点线面之间的关系判断
这类函数统一以 boolean 开头,返回 true 或 false。
语义看着直白,真正容易出错的是边界:落在多边形边线上的点算不算在内部,
不同函数的答案并不一致。
按输入的几何组合选函数
| 函数 | 输入组合 | 回答的问题 |
|---|---|---|
booleanPointInPolygon | 点 + 面 | 点是否在面内 |
booleanPointOnLine | 点 + 线 | 点是否落在线段上 |
booleanContains | 面 + 点/线/面 | 前者是否完全包含后者 |
booleanWithin | 点/线/面 + 面 | 前者是否完全位于后者内部 |
booleanIntersects | 任意两种 | 是否存在任何公共部分 |
booleanDisjoint | 任意两种 | 是否完全没有公共部分 |
booleanTouches | 任意两种 | 是否只有边界接触,内部不相交 |
booleanOverlap | 同类型 | 是否部分重叠但不完全包含 |
点在面内:边界算内部
函数名在 7.x 里正式写法是 booleanPointInPolygon,
pointInPolygon 是同一实现的别名。默认情况下,
落在边线或顶点上的点返回 true。
需要严格排除边界时传 ignoreBoundary: true。
var poly = turf.polygon([[[116.35, 39.86], [116.45, 39.86], [116.45, 39.94],
[116.35, 39.94], [116.35, 39.86]]]);
var onEdge = turf.point([116.35, 39.90]);
console.log(turf.booleanPointInPolygon(onEdge, poly)); // true
console.log(turf.booleanPointInPolygon(onEdge, poly, { ignoreBoundary: true })); // false
判断范围时这个差异会带来实际后果:按行政边界统计站点数量,
边界上的点可能被相邻两个区各算一次。要么统一 ignoreBoundary: true,
要么在数据层面给每个点指定唯一归属。
面可以带洞,也可以是多面。带洞时落在洞里的点返回 false,
这部分由函数内部处理,不需要自己拆环。
包含与位于:一对反向关系
booleanContains(poly, point) 与
booleanWithin(point, poly) 在很多情况下答案相同,
但参数顺序固定:包含关系的「大」在前,「小」在后。
两者都要求「小」完全落在「大」内部,线只要有一个顶点在外,
就返回 false。
因此用 booleanWithin(line, poly) 判断一条道路是否完全在园区内,
结果通常偏严格:道路穿过边界一点点就会失败。需要「大部分在内」这种语义时,
自己按长度加权计算更合适。
相交、相离、接触
booleanIntersects只要有任何公共部分就为 true,包括只贴着一个角。booleanDisjoint是它的取反,两者对同一输入必然一真一假。booleanTouches更严格:只有边界接触、内部不相交才为 true, 比如两个相邻的行政区块。
var x = turf.polygon([[[116.40, 39.88], [116.48, 39.88], [116.48, 39.96],
[116.40, 39.96], [116.40, 39.88]]]);
console.log(turf.booleanIntersects(poly, x)); // true,有重叠
console.log(turf.booleanDisjoint(poly, x)); // false
console.log(turf.booleanTouches(poly, x)); // false,重叠不在边界
批量判断怎么不卡
一万个点对一个面逐个调用,看起来是线性复杂度,实际开销主要在两件事: 每次调用都要遍历面的所有顶点,以及频繁构造 Feature 对象。 两个改动能显著降低耗时:
- 先用外包矩形粗筛。点不在面的 bbox 内,可以直接判 false,不必进入多边形判断。
- 面只读取一次,复用同一个引用;点用坐标数组循环,最后再包装成 Feature。
var box = turf.bbox(poly);
function inside(coords) {
if (coords[0] < box[0] || coords[0] > box[2] ||
coords[1] < box[1] || coords[1] > box[3]) return false;
return turf.booleanPointInPolygon(turf.point(coords), poly);
}
var hits = points.filter(function (p) { return inside(p); });
更高数量级时,把面拆成网格索引,或者把判断放到后端与空间数据库里做。 前端 Turf 的定位是几十万次以内的交互式判断。
常见错误
用点在面内判断落在线上
点与线的关系要用 booleanPointOnLine,它还提供
ignoreEndPoint 选项来排除端点。反过来,用点线判断去处理面,
结果是 false 而不是报错,很容易被误读成「不相交」。
忽略坐标顺序
从后端拿到的坐标常是 [lat, lng]。面与点的顺序如果一边反了,
判断会稳定地返回 false,看起来像「数据没问题但永远不在范围内」。
拿细长面做包含判断
细长面(比如道路中心线两侧各 1 米形成的面)在浮点误差下容易出现 「点明明在图上却判 false」。把半径放大到米级以上,或者改用点到线距离判断。
经纬志(2026)。《点线面之间的关系判断》。https://www.jingweizhi.com/turf/tutorial/relations.html(访问日期 2026-11-03)。