经纬志
首页 / Turf.js / 教程

坐标处理

先看结论

真实数据里总有重复顶点、多余小数、方向反了的环。这一组函数不改几何形状, 只做规整:降精度、去冗余、统一方向、翻转坐标顺序。

最后验证 2026-11-03 · Turf.js 7.x · 更新 2026-10-29 · 引用本文

降精度:truncate 与 round

truncate 按小数位截断,不四舍五入;round 四舍五入。 经纬度保留 6 位约等于 0.1 米,5 位约 1 米,超出业务需要的位数只是浪费带宽。

var raw = turf.point([116.39126345678, 39.90735912345], { id: 7 });

var cut = turf.truncate(raw, 6);
var rnd = turf.round(raw, 6);

console.log(turf.getCoord(cut));   // [116.391263, 39.907359]
console.log(turf.getCoord(rnd));   // [116.391263, 39.907359]

// 批量处理整个数据集
var cleaned = turf.truncate(turf.featureCollection([raw]), 6, { mutate: true });

截断会引入最多 1 个精度单位的偏移。做面积、距离计算前先截断, 可以消除同一位置不同精度的重复记录;但截断后再求和,结果会有细微差异。

去冗余:cleanCoords

重复顶点、共线的中间点都不影响形状,却会增加体积与渲染开销。 cleanCoords 把它们去掉。抽取自 GPS 轨迹的数据尤其需要。

var messy = turf.lineString([
  [116.391263, 39.907359],
  [116.391263, 39.907359],     // 重复
  [116.400000, 39.907359],     // 共线
  [116.410000, 39.907359],
  [116.410000, 39.920000]
]);

console.log('原始', messy.geometry.coordinates.length);

var clean = turf.cleanCoords(messy);
console.log('清理后', clean.geometry.coordinates.length);

统一环方向:rewind

GeoJSON 规范建议外环逆时针、内环顺时针。方向不一致的面在 intersect、dissolve 里可能被当成「洞」处理, 结果多出一块空白。

var fixed = turf.rewind(polygon);            // 按规范方向重排
var flipped = turf.rewind(polygon, { reverse: true });   // 全部反向

console.log(turf.rewind(polygon) === polygon);   // false,默认返回新对象

翻转经纬度:flip

后端返回 [纬度, 经度] 时,flip 一次性把整份数据换过来。 它只处理坐标数组,属性不动。

var wrongOrder = turf.point([39.907359, 116.391263]);

var right = turf.flip(wrongOrder, { mutate: true });
console.log(turf.getCoord(right));   // [116.391263, 39.907359]

flip 用错比不用更危险。数据本来是对的,多翻一次就全错, 而且地图上仍能画出形状(只是位置在南极附近)。 翻转只能在数据入口做一次,不要放在渲染流程里。

遍历坐标:coordEach

需要自定义清洗规则时,coordEach 是底层入口。 直接遍历坐标数组,比先拆成 Feature 再处理的分配开销小得多。

var minLng = Infinity, maxLng = -Infinity;
var bad = 0;

turf.coordEach(bigCollection, function (coord, index) {
  if (coord[0] < -180 || coord[0] > 180 ||
      coord[1] < -90  || coord[1] > 90) {
    bad++;
    return;
  }
  if (coord[0] < minLng) minLng = coord[0];
  if (coord[0] > maxLng) maxLng = coord[0];
});

console.log('越界坐标', bad, '经度范围', minLng, maxLng);

coordEach 的回调第一个参数是坐标,第二个是坐标序号, 后面还带要素与几何的层级索引;单部件几何里最后几项没有区分意义。

按方位角推算

destination 从一点出发,沿给定方位角走给定距离,得到新点; bearing 反过来算两点之间的方位角。方位角以正北为 0,顺时针增加。

var origin = turf.point([116.391263, 39.907359]);

var north = turf.destination(origin, 5, 0,   { units: 'kilometers' });
var east  = turf.destination(origin, 5, 90,  { units: 'kilometers' });

console.log(turf.bearing(origin, north));   // 0
console.log(turf.bearing(origin, east));    // 90

// 以原点为中心,画一圈等距采样点
var ring = [];
for (var deg = 0; deg < 360; deg += 30) {
  ring.push(turf.getCoord(turf.destination(origin, 3, deg, { units: 'kilometers' })));
}
console.log(ring.length);
函数作用是否返回新对象
truncate按小数位截断,不四舍五入是,除非传 mutate
round按小数位四舍五入是,除非传 mutate
cleanCoords删重复顶点与共线中间点是,除非传 mutate
rewind统一环的方向是
flip交换经纬度顺序是,除非传 mutate
coordEach遍历所有坐标,不复制数据否,只做回调
destination按方位角与距离推算新点是,返回新的 Point

注意事项

truncate 的精度上限

精度参数只接受 0 到 6 位。写 8 会被夹到 6, 以为保留了原始精度,实际已经被截短。

cleanCoords 会删掉必要顶点

共线判断有浮点容差。对精度要求高的面(例如小于 1 米的宗地), 清理后面积可能变化。这类数据只去重复点,不做共线清理。

rewind 与自相交

rewind 只调整顶点顺序,不修复自相交。自相交的面在重排后 可能被判成「洞」,看起来像是凭空缺了一块。先用 turf.kinks 定位问题。

引用本文

经纬志(2026)。《坐标处理》。https://www.jingweizhi.com/turf/tutorial/coordinates.html(访问日期 2026-11-03)。