坐标处理
用途和范围
本文档描述在 GeoJSON 几何体内操作坐标数据的 Turf.js 模块。坐标处理操作修改位置值本身——删除重复项、控制精度、转换坐标顺序——而不会显著改变几何形状或执行空间分析。
有关改变形状和大小的几何变换(旋转、缩放、平移),请参阅 Measurements and Transformations。有关距离和方位计算,请参阅 Distance and Bearing。
坐标处理模块概述
Turf.js 为坐标处理提供三个主要模块:
|| 模块 | 包 | 主要功能 | 可变性 | ||--------------|---------------------------------|--------------------------------------------------------|---------------------------------------| || clean-coords | @turf/clean-coords | 从几何体中删除冗余坐标 | 通过 mutate 标志可选 | || truncate | @turf/truncate | 将坐标精度四舍五入到指定小数位 | 通过 mutate 标志可选 | || flip | @turf/flip | 交换经度和纬度坐标 | 通过 mutate 标志可选 |
这些模块在坐标级别操作,遍历位置数组以执行变换或过滤操作。它们依赖基础模块进行几何访问和验证。
模块依赖结构
Clean Coords:冗余坐标删除
@turf/clean-coords 中的 cleanCoords 函数从 GeoJSON 几何体中删除重复和共线坐标,在保留几何形状的同时减小文件大小和处理开销。
核心算法
实现使用基于段的方法来检测冗余点:
该算法维护三个索引(a、b、c)并在测试中间点 b 是否在线上时扩展段 a-c。这持续到找到不共线的点为止,此时段被提交。
实现细节
cleanLine 函数实现核心逻辑:
关键实现方面:
共线性测试:使用
booleanPointOnLine(points[b], lineString([points[a], points[c]]))确定是否可以删除点 b packages/turf-clean-coords/index.ts121几何特定处理:
- Point/MultiPoint:Point 无操作,从 MultiPoint 删除重复项 packages/turf-clean-coords/index.ts60-71
- LineString:直接应用段算法 packages/turf-clean-coords/index.ts42-44
- Polygon/MultiPolygon:对闭合环和最少 4 个点进行额外验证 packages/turf-clean-coords/index.ts142-167
多边形起点优化:清理后,检查起点/终点是否与第一个和最后一个内部点共线,如果冗余则删除 packages/turf-clean-coords/index.ts149-158
验证和边界情况
实现处理通过问题解决识别的几种边界情况:
|| 问题 | 问题描述 | 解决方案 | ||-------|--------------------------------------------------------------|-------------------------------------------------------------------------| || #2305 | 具有转向点的南北线被错误清理 | 修复段比较逻辑以保留方向变化 | || #2740 | 过度激进地删除有效中间点 | 优化共线性测试以区分转向点和通过点 | || #2406 | 冗余时未删除多边形起点 | 添加起点/终点共线性后处理检查 | || #918 | 所有相同点的退化多边形导致挂起 | 添加验证以对少于 4 个点的多边形抛出错误 |
使用模式
// cleanCoords(geojson, options?)
// options: { mutate?: boolean }该函数接受任何 GeoJSON Geometry 或 Feature 并返回相同类型的清理坐标。mutate 选项控制是就地修改输入还是返回新对象 packages/turf-clean-coords/index.ts27-32
Truncate:精度控制
@turf/truncate 模块将坐标值四舍五入到指定的小数位数,可用于减小文件大小、规范化精度和确保坐标相等比较。
模块依赖
truncate 函数使用 @turf/meta 中的 coordEach 遍历几何体中的所有坐标,对每个位置值应用精度四舍五入。
与 Clean Coords 集成
截断通常在坐标清理之前应用以规范化精度:
// 模式:先截断再清理
const normalized = cleanCoords(
truncate(lineString([[0, 0], [1.1, 1.123], [2.12, 2.32], [3, 3]]),
{ precision: 0 }
)
);
// 结果:[[0, 0], [3, 3]] - 截断后删除中间点此模式确保浮点精度差异不会阻止冗余坐标检测。
Flip:坐标顺序变换
@turf/flip 模块交换位置数组中的坐标顺序,通常用于在 [longitude, latitude] 和 [latitude, longitude] 格式之间转换。
模块结构
flip 函数在通过 coordEach 遍历坐标并反转每个位置数组之前,选择性地克隆输入几何体。
使用模式
与其他坐标处理模块一样,flip 支持不可变(默认)和可变操作:
// 不可变(创建新对象)
const flipped = flip(feature);
// 可变(就地修改)
flip(feature, { mutate: true });坐标处理 Workflow
坐标处理操作通常在数据流水线中链接在一起:
常见用例
|| 用例 | 操作 | 用途 | || --- | --- | --- | || 布尔操作预处理 | cleanCoords() | 删除可能导致交集失败的伪影 | || 文件大小优化 | truncate() → cleanCoords() | 降低精度然后删除结果重复项 | || 坐标系统转换 | flip() | 在 [lon,lat] 和 [lat,lon] 格式之间切换 | || 几何验证 | cleanCoords() | 确保多边形具有有效的环结构 |
性能特征
Clean Coords 复杂度
cleanLine 算法具有以下特征:
时间复杂度:O(n),其中 n 是坐标数
- 每个坐标在索引 c 推进时访问一次
- 每次测试
booleanPointOnLine是 O(1) - 最坏情况:没有点被删除,所有点都被测试
空间复杂度:O(n) 用于输出数组
- 最佳情况:O(2) 用于高度冗余的直线
- 最坏情况:O(n) 当没有点可以删除时
迭代策略
所有坐标处理模块使用 @turf/meta 中的 coordEach 或 geomEach 进行几何遍历:
@turf/meta 模块提供优化的迭代原语,可高效处理 FeatureCollections、GeometryCollections 和嵌套的 Multi* 几何体。
与其他模块集成
Clean Coords 消费者
几个模块依赖 cleanCoords 进行预处理:
@turf/simplify:在应用 Ramer-Douglas-Peucker 算法之前和之后调用
cleanCoords以确保有效的几何结构 packages/turf-simplify/package.json73-80@turf/boolean-equal:使用
cleanCoords在比较之前规范化几何体,确保坐标顺序和冗余不会影响相等性测试 packages/turf-boolean-equal/package.json158-177
Truncate 消费者
truncate 模块在代码库中广泛用于测试夹具生成和坐标规范化:
- 用于测试套件以创建可预测的坐标值进行断言
- 在缓冲区操作之前应用以防止浮点精度问题
- 通常与网格生成配对以确保单元边界精确对齐
错误处理和验证
Clean Coords 验证
cleanCoords 函数对多边形几何体执行严格验证:
// 来自 cleanLine 函数
if (newPoints.length < 4) {
throw new Error("invalid polygon, fewer than 4 points");
}
if (!equals(newPoints[0], newPoints[newPoints.length - 1])) {
throw new Error("invalid polygon, first and last points not equal");
}这些检查确保清理后的多边形保持 GeoJSON 有效性:
- 最少 4 个点(3 个唯一顶点 + 闭合点)
- 第一个和最后一个坐标必须相同(闭合环)
输入验证
所有坐标处理函数验证输入类型:
if (!geojson) throw new Error("geojson is required");
var type = getType(geojson);@turf/invariant 中的 getType 函数确保输入是有效的 GeoJSON 结构,然后处理开始。
可变模式
所有三个坐标处理模块遵循一致的可变模式:
|| 模块 | 默认行为 | 可变标志 | 返回值 | || --- | --- | --- | --- | || cleanCoords | 不可变 | options.mutate | 新几何体或可变输入 | || truncate | 不可变 | options.mutate | 新几何体或可变输入 | || flip | 不可变 | options.mutate | 新几何体或可变输入 |
不可变默认值确保函数式编程模式正确工作,而可变选项在不需要原始数据时为大型几何体提供性能优化:
// 不可变 - 对函数链安全
const result = cleanCoords(truncate(flip(input)));
// 可变 - 内存优化
truncate(input, { mutate: true });
flip(input, { mutate: true });
cleanCoords(input, { mutate: true });