Skip to content

坐标处理

用途和范围

本文档描述在 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 标志可选 |

这些模块在坐标级别操作,遍历位置数组以执行变换或过滤操作。它们依赖基础模块进行几何访问和验证。

模块依赖结构

SVG
100%

Clean Coords:冗余坐标删除

@turf/clean-coords 中的 cleanCoords 函数从 GeoJSON 几何体中删除重复和共线坐标,在保留几何形状的同时减小文件大小和处理开销。

核心算法

实现使用基于段的方法来检测冗余点:

SVG
100%

该算法维护三个索引(a、b、c)并在测试中间点 b 是否在线上时扩展段 a-c。这持续到找到不共线的点为止,此时段被提交。

实现细节

cleanLine 函数实现核心逻辑:

SVG
100%

关键实现方面:

  1. 共线性测试:使用 booleanPointOnLine(points[b], lineString([points[a], points[c]])) 确定是否可以删除点 b packages/turf-clean-coords/index.ts121

  2. 几何特定处理

  3. 多边形起点优化:清理后,检查起点/终点是否与第一个和最后一个内部点共线,如果冗余则删除 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 模块将坐标值四舍五入到指定的小数位数,可用于减小文件大小、规范化精度和确保坐标相等比较。

模块依赖

SVG
100%

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] 格式之间转换。

模块结构

SVG
100%

flip 函数在通过 coordEach 遍历坐标并反转每个位置数组之前,选择性地克隆输入几何体。

使用模式

与其他坐标处理模块一样,flip 支持不可变(默认)和可变操作:

// 不可变(创建新对象)
const flipped = flip(feature);

// 可变(就地修改)
flip(feature, { mutate: true });

坐标处理 Workflow

坐标处理操作通常在数据流水线中链接在一起:

SVG
100%

常见用例

|| 用例 | 操作 | 用途 | || --- | --- | --- | || 布尔操作预处理 | 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 中的 coordEachgeomEach 进行几何遍历:

SVG
100%

@turf/meta 模块提供优化的迭代原语,可高效处理 FeatureCollections、GeometryCollections 和嵌套的 Multi* 几何体。

与其他模块集成

Clean Coords 消费者

几个模块依赖 cleanCoords 进行预处理:

SVG
100%

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 });