点与多边形关系可以应用的地方:几何图形直接的碰撞检测
/**
* !#en Test whether the point is in the polygon
* !#zh 测试一个点是否在一个多边形中
* @method pointInPolygon
* @param {Vec2} point - The point
* @param {Vec2[]} polygon - The polygon, a set of points
* @return {boolean}
*/
function pointInPolygon(point, polygon) {
var inside = false;
var x = point.x;
var y = point.y;
// use some raycasting to test hits
// https://github.com/substack/point-in-polygon/blob/master/index.js
var length = polygon.length;
for (var i = 0, j = length - 1; i < length; j = i++) {
var xi = polygon[i].x, yi = polygon[i].y,
xj = polygon[j].x, yj = polygon[j].y,
intersect = (
(yi > y) !== (yj > y)) //排除不在线段之间的点 即不在yi 与 yj 之间的 点
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
解析:
1,函数参数: point 需要判断的点,polygon 是多边形顶点集合
2,多边形点表示多边形每条边的方式
var xi = polygon[i].x, yi = polygon[i].y,
xj = polygon[j].x, yj = polygon[j].y,
//多边形点:0、1、... i-2、i-1
//多边形边: (0,1)、(1,2)、(3,4)....(i-2,i-1),(i-1,0)
3,(yi > y) !== (yj > y))
(yi > y) !== (yj > y))
//排除不在线段之间的点 即不在yi 与 yj 之间的 点
//yi>y && y>=yj 或 yi<=y && y< yj 过顶点计算两次被排除,同时排除了共线问题
4,(x < (xj - xi) * (y - yi) / (yj - yi) + xi)
// (xj - xi) * (y - yi) / (yj - yi)
1,使用了直线两点式方程:(y-yi)/(yj-yi) = (x-xi)/(xj-xi)
=> (xj - xi) * (y - yi) / (yj - yi) = (x-xi)
2,即等于 point向右平行x轴的射线与线段(i,j)的交点
3,x的值:
(x-xi) = (xj - xi) * (y - yi) / (yj - yi)
=》 x = (xj - xi) * (y - yi) / (yj - yi) + xi
5,当线段(i,j) 取point的y值时,得到的x 如果x 大于point的x 则 point的x轴正方向的射线会与线段相交。如果小于 point的x 则不会
6,if (intersect) inside = !inside;
if (intersect) inside = !inside;
/**
* inside 奇数取反 等于 true 偶数依然是其默认值 false
*
* 奇数即为 在多边形内(包括在边上) inside 等于true
* 偶数在 多边形外 inside 等于 false
*/
参考资料: