Check point within polygon

此生再无相见时 提交于 2019-12-04 11:33:07

问题


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) && (y < yp[j])) ||
        ((yp[j] <= y) && (y < yp[i]))) &&
        (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
       c = !c;
   }
   return c;
}

This function checks if a point is within a polygon. How do I deal with a polygon coordinate that is negative? For example,

float x[3] = { 0.16, 1.2, -10 };
float y[3] = { 1.8, 10, -5.5 };

I tried checking a valid point within the polygon and it returns 0.


回答1:


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




回答2:


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



来源:https://stackoverflow.com/questions/27589796/check-point-within-polygon

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!