【问题标题】:Check point within polygon多边形内的检查点
【发布时间】:2015-02-19 18:59:27
【问题描述】:
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。

【问题讨论】:

  • 你的测试点是什么(对于给定的例子)?此代码和该示例仅适用于查找测试点 (-8.0, -4.0) 和 (0, 6)。
  • 没错,负坐标在这里似乎不是问题。你了解算法的工作原理吗?
  • 浮点 x[3] = { -10, 0.17, 10 };浮动 y[3] = { -5.56, 1.85, 1.69 };测试点为 (2.5,-1.6) 返回 0。

标签: c++ polygon


【解决方案1】:

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)

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

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

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

【讨论】:

  • 非常感谢。解决了我的问题。
【解决方案2】:

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

你需要处理y上平行的线

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 2011-06-17
    • 1970-01-01
    相关资源
    最近更新 更多