点在多边形内的判断
判断点在多边形内
凸多边形
凸多边形考虑叉积,因为在凸多边形中,我们假设围绕多边形走一圈,如果点在多边形内,那么这个点一直在我们的同一侧。按照这个性质,我们顺时针或者逆时针处理多边形上的点,叉积运算,算参考的和多边形上连续的两个点,如何叉积的结果符号发生变化,那么不再多边形内。
double det(point p1,point p2,point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool isinside(point p)
{
double pre,now;
for(int i=0;i<n;i++){
now=det(p,poly[i],poly[(i+1)%n]);
if(i>0){
if(pre*now<0){
return 0;
}
}
pre=now;
}
return true;
}
一般的多边形。
凹多边形不满足上面的性质,使用不能使用。计算机图形学中讲授过射线与多边形的交点个数,如果为偶数,则不再多边形内,否则在多边形内。射线与多边形变重合不考虑,与顶点相交特殊考虑,不考虑或者算一个。
这里我们作一条水平向右的射线。
首先,对于多边形的水平边不做考虑,其次,对于多边形的顶点和射线相交的情况,如果该顶点是其所属的边上纵坐标较大的顶点,则计数,否则忽略该点。最后,对于Q在多边形上的情形,直接判断Q是否属于多边形。
点积和叉积判断点在直线上,运用叉积判断点在多边形的哪一侧,这样判断和交点奇偶数等效,这样写较为减掉,写的时候最后手动模拟一下,验证正确性。
ll operator^(node p1, node p2) {
return p1.x*p2.x + p1.y*p2.y;
}
double det(node A, node B, node C) {
//a×b>0 则说明 b在a的左上方
//a×b<0 则说明b在a的右下方
return (B.x - A.x)*(C.y - A.y) - (B.y - A.y)*(C.x - A.x);
}
bool onSeg(node p, node l1, node l2) {
return det(p, l1, l2) == 0 && ((l1 - p)^(l2 - p))<=0;
}
//poly点顺或者逆时针
bool PointInPolygon(node p, vector<node>poly) {
int cnt = 0;
int len = poly.size();
for (int i = 0; i < poly.size(); i++) {
if (onSeg(p, poly[i], poly[(i + 1)%len]))return true;
ll k = det(poly[i], poly[(i + 1) % len], p);
ll d1 = poly[i].y - p.y;
ll d2 = poly[(i + 1) % len].y-p.y;
if (k > 0 && d1 <= 0 && d2 > 0)cnt++;
if (k < 0 && d2 <= 0 && d1>0)cnt--;
}
if (cnt != 0)return true;
return false;
}
不疯魔不成活