Is point inside polygon?

白昼怎懂夜的黑 提交于 2019-12-02 10:13:10

A simple way to test whether a point is inside a polygon is to count the number of intersections between the edges of the polygon and a ray originating from the test point. Because you can pick the ray to be whatever you want, it's usually convenient to pick it to be parallel to the X axis. The code for that looks something like this:

public static bool IsInPolygon( this Point testPoint, IList<Point> vertices )
{
    if( vertices.Count < 3 ) return false;
    bool isInPolygon = false;
    var lastVertex = vertices[vertices.Count - 1];
    foreach( var vertex in vertices )
    {
        if( testPoint.Y.IsBetween( lastVertex.Y, vertex.Y ) )
        {
            double t = ( testPoint.Y - lastVertex.Y ) / ( vertex.Y - lastVertex.Y );
            double x = t * ( vertex.X - lastVertex.X ) + lastVertex.X;
            if( x >= testPoint.X ) isInPolygon = !isInPolygon;
        }
        else
        {
            if( testPoint.Y == lastVertex.Y && testPoint.X < lastVertex.X && vertex.Y > testPoint.Y ) isInPolygon = !isInPolygon;
            if( testPoint.Y == vertex.Y && testPoint.X < vertex.X && lastVertex.Y > testPoint.Y ) isInPolygon = !isInPolygon;
        }

        lastVertex = vertex;
    }

    return isInPolygon;
}

public static bool IsBetween( this double x, double a, double b )
{
    return ( x - a ) * ( x - b ) < 0;
}

There's some extra code stuffed in there to deal with some literal corner cases (if the test ray hits a vertex directly, that needs some special treatment).

Given 4 points that define the vertices of a polygon, in order, clockwise or counterclockwise. To determine if a points is inside first workout if the polygon is concave by getting the cross product of each pair of lines.

The polygon is p1,p2,p3,p4 each have a x and y.

To get the cross product get 3 points, p1,p2,p3 where p2 is the vertex where the two lines join.

cross = (p2.x-p1.x) * (p3.y-p2.y) - (p2.y-p1.y) * (p3.x-p2.x);

Do for {p1,p2,p3}, {p2,p3,p4},{p3,p4,p1}, and {p4,p1,p2}

If the cross is the same sign for all verts (note 0 is both negative and positive) then the polygon is concave.

If not all the same only one can be different. You need to split the polygon into two 3 sided polygons by joining the different point with the one opposite.

Eg is cross of p2,p3,p4 is negative and the rest positive then you have two polygons p1,p2,p3 and p3,p4,p1

Now you have either one or two polygons.

Calculate the cross for the point you are testing against each line

cross = (p2.x-p1.x) * (testPoint.y-p1.y) - (p2.y-p1.y) * (testPoint.x-p1.x);

Do for each line {p1,p2}, {p2,p3}, {p3,p4},{p4,p1}

If the sign is the same for all the line segments then the point is inside the polygon. If you have two polygons, you only need to satisfy the same sign condition for one polygon

Solved it this way:

public static bool IsPointInPolygon4(PointF[] polygon, PointF testPoint)
    {
        bool result = false;
        int j = polygon.Count() - 1;
        for (int i = 0; i < polygon.Count(); i++)
        {
            if (polygon[i].Y < testPoint.Y && polygon[j].Y >= testPoint.Y || polygon[j].Y < testPoint.Y && polygon[i].Y >= testPoint.Y)
            {
                if (polygon[i].X + (testPoint.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) * (polygon[j].X - polygon[i].X) < testPoint.X)
                {
                    result = !result;
                }
            }
            j = i;
        }
        return result;
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!