点在多边形内的判断

判断点在多边形内

凸多边形

凸多边形考虑叉积,因为在凸多边形中,我们假设围绕多边形走一圈,如果点在多边形内,那么这个点一直在我们的同一侧。按照这个性质,我们顺时针或者逆时针处理多边形上的点,叉积运算,算参考的和多边形上连续的两个点,如何叉积的结果符号发生变化,那么不再多边形内。

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;
}
不疯魔不成活
原文地址:https://www.cnblogs.com/gzr2018/p/11250887.html