射线法Ray-casting Algorithm算法检查点point是否在多边形里面。
算法思想就是,对检查点,做向右的平行于x轴的射线,如果跟多边形有奇数个交点就在框内,有偶数个交点就在框外。
用法:insidePolygon([[x1,y1],[x2,y2],[x3,y3]...], [x , y])
参数说明:
polygon多边形坐标集合,格式为[[x1,y1],[x2,y2],[x3,y3]...]。
point 测试点坐标, 格式为[x , y]。
返回true点在内部,false在外部。
下面是javascript代码。
function insidePolygon(polygon, point){
var x = point[0], y = point[1];
var inside = false;
for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
var xi = polygon[i][0], yi = polygon[i][1];
var xj = polygon[j][0], yj = polygon[j][1];
var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect)inside = !inside;
}
return inside;
}
算法解释
函数参数:point 需要判断的点,polygon是多边形顶点集合
伪代码举例:
polygon包含的顺序为A1,A2,A3,A4,A5
polygon=[A1, A2, A3, A4, A5];
A1=[4, 5];
For循环遍历每个线段,这里例子是5个线段。
2.1 第一次循环是i=0,j=4;
var xi = polygon[0][0], yi = polygon[0][1];
var xj = polygon[4][0], yj = polygon[4][1];
![](https://img-blog.csdnimg.cn/img_convert/0eef336171ec83ebb55050bc7e9d9c71.png)
(图1)
2.2 第二次循环是i=1, j=0;
var xi = polygon[1][0], yi = polygon[1][1];
var xj = polygon[0][0], yj = polygon[0][1];
![](https://img-blog.csdnimg.cn/img_convert/f4fc58431e970f2c0156718d95a42936.png)
(图2)
依次类推,直到遍历完。
(yi > y) != (yj > y))
首选要判断任意点P的y值,是否在图2的A1 A2这个线段的y轴区间内。
如果在yi和yj线段内结果为true,反之false。
![](https://img-blog.csdnimg.cn/img_convert/72dc524da8281dea55373b43f78f338e.png)
4、x < (xj - xi) * (y - yi) / (yj - yi) + xi
4.1引入两点式直线方程:
![](https://img-blog.csdnimg.cn/img_convert/07a1e335158d0e7da566bf9b367026f9.png)
4.2 推导方程式
(x-xi)/(xj-xi) = (y-yi)/(yj-yi)
=> x-xi = (xj - xi) * (y - yi) / (yj - yi)
=> x = (xj - xi) * (y - yi) / (yj - yi) + xi
上面的方程式就是求A1A2所构成的直线上,在带入P点的y值后,计算对应的x的值。
![](https://img-blog.csdnimg.cn/img_convert/6bdf7077206745f41c7d10ac6cc02239.png)
绿色的x值为P的实际的x值,计算x值为上面公式推导出的x值。
如果x< 计算x值,说明点在线段的左侧。
5、var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi)
结果为true就说明P点在线段A1A2的左侧,同时在A1A2的y轴区间内。
也就证明,以P点为起点平行于x轴的射线,跟线段A1A2应该有个交点。
![](https://img-blog.csdnimg.cn/img_convert/8884f295376c9db99583375dd1a28ca0.png)
6、if (intersect) inside = !inside;
如果有奇数交点,inside =true。
如果有偶数个交点,inside=false