判断任意点是否在给定的凸凹多边形内部(一种高效算法,附C++代码)

给定一个多边形和一个点“p”,找出“p”是否位于多边形内部。位于边界上的点也被视为内部点。

例子:

实施步骤:

1.在每个点的右边画一条水平线,并将其延伸到无穷远

2.计算该线与多边形边相交的次数。

3.如果相交数为奇数或点位于多边形的边上,则点位于多边形内部。若没有一个条件是true的,那个么这个点就在外面。

如何处理上图中的点“g”?

        注意,如果点位于直线上或与给定多边形的一个顶点相同,则应返回true。为了处理这个问题,在检查从“p”到极值的射线是否相交后,我们检查“p”是否与多边形当前边的顶点共线。如果它是共线的,那么我们检查点“p”是否位于多边形的当前边,如果是,返回true,否则返回false。

实现代码

#include <bits/stdc++.h>
using namespace std;
 
struct Point {
    int x, y;
};
 
struct line {
    Point p1, p2;
};
 
bool onLine(line l1, Point p)
{
    // Check whether p is on the line or not
    if (p.x <= max(l1.p1.x, l1.p2.x)
        && p.x >= min(l1.p1.x, l1.p2.x)
        && (p.y <= max(l1.p1.y, l1.p2.y)
            && p.y >= min(l1.p1.y, l1.p2.y)))
        return true;
 
    return false;
}
 
int direction(Point a, Point b, Point c)
{
    int val = (b.y - a.y) * (c.x - b.x)
              - (b.x - a.x) * (c.y - b.y);
 
    if (val == 0)
 
        // Collinear
        return 0;
 
    else if (val < 0)
 
        // Anti-clockwise direction
        return 2;
 
    // Clockwise direction
    return 1;
}
 
bool isIntersect(line l1, line l2)
{ 
    // Four direction for two lines and points of other line
    int dir1 = direction(l1.p1, l1.p2, l2.p1);
    int dir2 = direction(l1.p1, l1.p2, l2.p2);
    int dir3 = direction(l2.p1, l2.p2, l1.p1);
    int dir4 = direction(l2.p1, l2.p2, l1.p2);
 
    // When intersecting
    if (dir1 != dir2 && dir3 != dir4)
        return true;
 
    // When p2 of line2 are on the line1
    if (dir1 == 0 && onLine(l1, l2.p1))
        return true;
 
    // When p1 of line2 are on the line1
    if (dir2 == 0 && onLine(l1, l2.p2))
        return true;
 
    // When p2 of line1 are on the line2
    if (dir3 == 0 && onLine(l2, l1.p1))
        return true;
 
    // When p1 of line1 are on the line2
    if (dir4 == 0 && onLine(l2, l1.p2))
        return true;
 
    return false;
}
 
bool checkInside(Point poly[], int n, Point p)
{
 
    // When polygon has less than 3 edge, it is not polygon
    if (n < 3)
        return false;
 
    // Create a point at infinity, y is same as point p
    line exline = { p, { 9999, p.y } };
    int count = 0;
    int i = 0;
    do {
 
        // Forming a line from two consecutive points of
        // poly
        line side = { poly[i], poly[(i + 1) % n] };
        if (isIntersect(side, exline)) {
 
            // If side is intersects exline
            if (direction(side.p1, p, side.p2) == 0)
                return onLine(side, p);
            count++;
        }
        i = (i + 1) % n;
    } while (i != 0);
 
    // When count is odd
    return count & 1;
}
 
// Driver code
int main()
{
    Point polygon[]
        = { { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } };
    Point p = { 5, 3 };
    int n = 4;
 
    // Function call
    if (checkInside(polygon, n, p))
        cout << "Point is inside.";
    else
        cout << "Point is outside.";
   
    return 0;
}

输出

Point is inside.

时间复杂度:O(n),其中n是给定多边形中的顶点数。

辅助空间:O(1),因为没有占用额外的空间。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论.

本文内容来源于How to check if a given point lies inside or outside a polygon? - GeeksforGeeks

猜你喜欢

转载自blog.csdn.net/subin0403/article/details/134947324
今日推荐