高德地图(isPointInRing)、腾讯地图(isPointInPolygon)都有这么一个可以获取某个点是否在多边形内的方法,但是之前却是只知道使用方式,不知其原理,终于在这么一个下午,我想知其所以然!!!
/*
若是P在多边形内部,那么这条射线与多边形的交点必为奇数,若是P在多边形外部,则交点个数必为偶数(0也在内,暂不考虑临界条件)。
y轴垂直向上作为射线(以高德地图作为基础:lng对应x轴,lat对应y轴)。
因此,考虑多边形的每条边,求出交点的总个数,即可推断出他们的关系。
注意:
1)若是射线正好穿过P1或者P2,那么这个交点会被算做2次(此时此点当忽略,对2取余即默认忽略)。
2)若是p1、p2平行于y轴,则射线要么与其无交点,要么有无数个(或p1、p2为同一个点),这种状况也直接忽略。
3)若是p1、p2平行于x轴,而P0的横坐标在P1,P2的横坐标之间,则必然相交。
4)判断相交以前,先判断P是否在边(P1,P2)的上面,若是在可以直接得出在内部。
*/
// 判断点是否在多边形范围内-(高德地图格式的经纬度传参)
isInPolygon(dot, polygons) {
let counter = 0
let yinters
let p1, p2
let pointCount = polygons.length
p1 = polygons[0]
if(polygons.some(it => it[0] == dot[0] && it[1] == dot[1])) return true // 4)
for (let i = 1; i <= pointCount; i++) {
p2 = polygons[i % pointCount]
if (dot[0] > Math.min(p1[0], p2[0]) && dot[0] <= Math.max(p1[0], p2[0])) {
if (dot[1] <= Math.max(p1[1], p2[1])) {
if (p1[0] != p2[0]) { // 2)
yinters = (dot[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1]
if (p1[1] == p2[1] || // 3)
dot[1] <= yinters) { // p0位于线段下方
counter++
}
}
}
}
p1 = p2
}
return counter % 2 != 0
}