算法简述
从目标点引出一条射线,计算该射线与多边形边的交点次数,奇数个交点则目标点在多边形内,否则在多边形外部。
论述
由于多边形为闭合曲线,因此,改多边形将平面分成了内部和外部两部分。要从内部前往外部或者从外部前往内部,一定要跨越多边形的边界。若要做到在平面中区域的切换,就必须经过跨越奇数次的边界。若将移动轨迹连成线,跨越的次数就是轨迹与边界相交的次数。因此,若已知一个点的位置,可以绘制一条容易描述的轨迹,使其能够移动到平面一个已知所属区域的位置,计算该轨迹与多边形边界相交次数即可判定该点在多边形的外部或者内部。为计算方便,一般将目标点沿射线移动到无穷远处,直线计算更简便并且能够确保终点在多边形外部。
只要边界交点能够求解得到,理论上能够利用这种方式判断任意闭合曲线的内部和外部。
算法实现
// 以x轴为方向引一条射线判断
public bool IsInPolygon(List<Vector2> vertices, Vector2 point)
{
bool isIn = false;
for(int i = 0, j = vertices.Count-1; i< vertices.Count; j = i++)
{
Vector2 beginPoint = vertices[j];
Vector2 endPoint = vertices[i];
if ((beginPoint.y > point.y) != (endPoint.y > point.y))
{
// 说明射线在线段两端点间,有可能有交点
// 求直线y=point.y与边的交点
float x = (beginPoint.x - endPoint.x) / (beginPoint.y - endPoint.y) * (point.y - endPoint.y) + endPoint.x;
// 这里假定向右引的射线,因此x>point.x才算与射线相交,若以小于号比较亦可
if (x > point.x)
{
isIn = !isIn;
}
}
}
return isIn;
}