平面上点与多边形包含关系的查询。
查询平面上一点是否在某多边形(可以为凸或凹多边形)范围内,或在其边上,或在范围之外,此方法作为GIS空间分析中的一种有广泛的应用。
具体方法之一是从此点开始沿任意方向作射线,计算此射线与多边形的边的相交个数,由于相交能说明点进出多边形的次数,若为偶数,则在多边形范围之外,为奇数则点被包含在多边形之内。为计算方便,常将射线方向定为与X或Y轴平行。
参考代码:
// 输入: 顶点 P
// 多边形的顶点数组 V[ ], 顶点个数为n+1 ,其中 V[n]=V[0]
// 返回的数值: 0表示在多边形之外, 1 表示在多边形之内
int CDEMAlgorithm::cn_PnPoly(Point P, Point* V,int n )//判断一个点和多边形的包含关系{
int cn = 0; // 记录相交个数
//对每条边进行循环
for (int i=0; i<n; i++) { // 由V[i] 和 V[i+1]顶点构成的边
if (((V[i].y <= P.y) && (V[i+1].y > P.y))||((V[i].y > P.y) && (V[i+1].y <= P.y))) { //说明要判断的这个顶点Y数值在多边形这条边的两个端点Y轴数值之间
double vt = (P.y - V[i].y) / (V[i+1].y - V[i].y); //计算系数,数值在0到1之间
if (P.x < V[i].x + vt * (V[i+1].x - V[i].x)) //说明此顶点在平行于X轴的平行线:y=P.y和与此条边的交点的右侧
++cn; //说明要判断的这个顶点与多边形这条边是相交的,计数器加1
}
} //循环结束
if (cn % 2 == 0) return 0;
else return 1; //若为偶数则说明在多边形的范围外,若为奇数说明在范围内
}
方法之二是判断此点与多边形边的左右邻接关系。这需要使用前面讲解的矢量XY数值交叉相乘从而判断夹角正弦的方法。
此图说明顶点一进一出多边形的情况。
由于多边形范围外的顶点将一进一出,有抵消,最后的计算结果为0就说明顶点在范围之外,其他返回的计算结果都表明在范围之内。
参考代码:
int CDEMAlgorithm::wn_PnPoly( Point P, Point* V, int n )//判断点和多边形范围的关系
{
int wn = 0; // 计数器
for (int i=0; i<n; i++) { //对每条边进行循环,其顶点为 V[i] 和 V[i+1]
if (V[i].y <= P.y) {
if (V[i+1].y > P.y) //P点的Y轴数值在一条上升边(Y轴数值增大)的范围内
if (isLeft( V[i], V[i+1], P) > 0) //调用前面章节讲解的isLeft()函数,来通过sina 的正负判断点P在此条边的左端
++wn; //如上图中靠右边的那种情况
}
else { //点的Y轴数值在一条下降边(Y轴数值减小)的范围内
if (V[i+1].y <= P.y)
if (isLeft( V[i], V[i+1], P) < 0) //通过sina 的正负可以判断点P在边的右端
--wn; //如上图中靠左边的那种情况
}
} //循环结束
return wn; //由于多边形范围外的顶点将一进一出,有抵消,最后的计算结果为0就说明顶点在范围之外,其他返回的计算结果都表明在范围之内。
}