Check point within polygon

后端 未结 2 1501
情歌与酒
情歌与酒 2021-02-09 05:24
int pnpoly(int npol, float *xp, float *yp, float x, float y)
{
   int i, j, c = 0;
   for (i = 0, j = npol-1; i < npol; j = i++) {
     if ((((yp[i] <= y) &&am         


        
相关标签:
2条回答
  • 2021-02-09 05:40

    Note that if your polygon N and N+1 have the same y value then this test can fail computing vt. For example: determining if a point is inside an axis aligned square.

    You need to deal with lines parallel on y

    0 讨论(0)
  • 2021-02-09 05:50

    There are pretty good implementations from the iSurfer

    The two methods used in most cases (and the two I know of) are crossing number and winding number. Both of them are not affected by the signs of the polygon/point coordinates. So it must be a bug in your code.

    For completeness I'm placing the code for a crossing number test which seems to be what you're trying to do in your code

    // a Point is defined by its coordinates {int x, y;}
    
    // isLeft(): tests if a point is Left|On|Right of an infinite line.
    //    Input:  three points P0, P1, and P2
    //    Return: >0 for P2 left of the line through P0 and P1
    //            =0 for P2  on the line
    //            <0 for P2  right of the line
    //    See: Algorithm 1 "Area of Triangles and Polygons"
    inline int isLeft( Point P0, Point P1, Point P2 )
    {
        return ( (P1.x - P0.x) * (P2.y - P0.y) - (P2.x -  P0.x) * (P1.y - P0.y) );
    }
    //===================================================================
    
    // cn_PnPoly(): crossing number test for a point in a polygon
    //      Input:   P = a point,
    //               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
    //      Return:  0 = outside, 1 = inside
    // This code is patterned after [Franklin, 2000]
    int cn_PnPoly( Point P, Point* V, int n )
    {
        int    cn = 0;    // the  crossing number counter
    
        // loop through all edges of the polygon
        for (int i=0; i<n; i++) {    // edge from V[i]  to V[i+1]
           if (((V[i].y <= P.y) && (V[i+1].y > P.y))     // an upward crossing
            || ((V[i].y > P.y) && (V[i+1].y <=  P.y))) { // a downward crossing
                // compute  the actual edge-ray intersect x-coordinate
                float vt = (float)(P.y  - V[i].y) / (V[i+1].y - V[i].y);
                if (P.x <  V[i].x + vt * (V[i+1].x - V[i].x)) // P.x < intersect
                     ++cn;   // a valid crossing of y=P.y right of P.x
            }
        }
        return (cn&1);    // 0 if even (out), and 1 if  odd (in)
    
    }
    //===================================================================
    

    A special case that can arise with the crossing number number test, is when the ray overlaps an edge of the polygon. In that case it becomes somewhat fuzzy how to count intersections. That's why it's not the actual number of intersections we count, but the number we crossed over semiplanes defined by the ray.

    The winding number test is more robust to this respect

    0 讨论(0)
提交回复
热议问题