检查多边形内的点

时间:2014-12-21 13:27:04

标签: c++ polygon

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;
}

此函数检查点是否在多边形内。如何处理负数的多边形坐标?例如,

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

我尝试检查多边形内的有效点,然后返回0.

2 个答案:

答案 0 :(得分:5)

iSurfer

有很好的实现

大多数情况下使用的两种方法(以及我所知道的两种方法)是交叉数蜿蜒数它们都不受多边形/点坐标的符号的影响。所以它必须是代码中的错误。

为了完整性,我要为交叉号码测试放置代码,这似乎是您在代码中尝试做的事情

// 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)

}
//===================================================================

交叉数测试可能出现的特殊情况是光线与多边形的边重叠。在这种情况下,如何计算交叉点会变得有些模糊。这就是为什么它不是我们计算的交叉点的实际数量,而是我们在光线定义的半平面上的数量。

绕组数测试在这方面更加稳健

答案 1 :(得分:0)

请注意,如果多边形N和N + 1具有相同的y值,则此测试可能无法计算vt。例如:确定一个点是否在轴线对齐的正方形内。

您需要处理与y平行的线