【问题标题】:Winding Number Algorithm Not Yielding Expected Result绕组数算法未产生预期结果
【发布时间】:2020-08-10 20:14:47
【问题描述】:

因此,我实现了在 http://geomalgorithms.com/a03-_inclusion.html 上找到的绕组数和交叉数算法的一个非常未优化的版本,但是我遇到了一个绕组数算法无法产生预期结果的情况。

我创建了一个多边形和三个点,如图here 所示。对于 P0 和 P2,两种算法的行为都是可预测的。但是,对于点 P1(多边形边界内的“零空间”包含的点),交叉数算法成功,而绕组数算法无法识别该点不包含在多边形中。

这是实现的算法:

int wn_PnPoly(Vector2 P, Vector2[] V)
{
    int n = V.Length - 1;
    int wn = 0;    // the  winding 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)
        {          // start y <= P.y
            if (V[i + 1].y > P.y)      // an upward crossing
                if (isLeft(V[i], V[i + 1], P) > 0)  // P left of  edge
                    ++wn;            // have  a valid up intersect
        }
        else
        {                        // start y > P.y (no test needed)
            if (V[i + 1].y <= P.y)     // a downward crossing
                if (isLeft(V[i], V[i + 1], P) < 0)  // P right of  edge
                    --wn;            // have  a valid down intersect
        }
    }
    return wn;
}

float isLeft(Vector2 P0, Vector2 P1, Vector2 P2)
    {
        return ((P1.x - P0.x) * (P2.y - P0.y)
                - (P2.x - P0.x) * (P1.y - P0.y));
    }

我在这里遗漏了什么明显的东西吗?为什么在这种情况下交叉数算法成功而绕组数失败?

【问题讨论】:

    标签: algorithm polygon point-in-polygon


    【解决方案1】:

    这两种方法不是同一个标准。

    非零缠绕规则中,线段的方向很重要。该算法检查线段是从左侧还是从右侧穿过出射光线,并计算每种情况发生的频率。仅当

    crossing-numbereven-odd rule 只计算一条线被交叉的频率。每次你越过一条线,你要么从内到外,反之亦然,所以偶数的交叉意味着该点在外面。

    如果你在你的例子中从 P1 开始,你穿过两条线,所以奇偶规则告诉你 P1 不在多边形中。但是这两条线具有相同的方向:如果您的整体形状以顺时针方式绘制,则两条线都是从上到下绘制的。在您链接的文章中,多边形围绕 P1 绕了两次。根据缠绕规则,P1 是多边形的一部分。您的程序显示了正确的行为。

    矢量图形程序和格式区分这两个规则。例如 SVG 有一个 fill-rule 属性,您可以在其中设置行为。 Postscript 有filleofill 运算符,分别用于使用缠绕规则和奇偶规则填充路径。默认值通常是绕线规则,因此设计人员必须注意正确定位路径。

    【讨论】:

    • 我现在看到我错过了双绕组的概念。但是,我注意到另一个我不确定如何处理的边缘情况:一个点 (10,5) 将存在于多边形的最右边。两种算法都没有考虑到这个点包含在多边形内,但直觉上它应该是。是否有关于如何改进算法的鲁棒性的材料,包括适应多边形是贝塞尔样条的情况?
    • 这也是期望的行为:奇偶规则打折 (10, 5),因为它穿过两条线,而缠绕规则打折它,因为两条线在不同方向上穿过射线.如果你顺时针画大外正方形,你也会顺时针通过左上角的内正方形,但你会逆时针通过右下角的内正方形。
    • 真正的边缘情况是你的光线和线条共线的地方,例如(3, 8),或者它们只是在多边形的一个节点处相交。当您必须处理浮点数时,它会变得更加棘手。路径也可以包含曲线,但请记住,光线可能有多个点与贝塞尔曲线相交。这些问题是所有矢量图形的基础,因此“多边形中的点”、“多边形渲染”、“多边形裁剪”等可能是提供给您的搜索引擎的有用术语。
    • 这篇论文 - The Point in Polygon Problem for Arbitrary Polygons - 很好地讨论了定义多边形内部的奇偶和基于缠绕数的方法之间的关系。用于计算多边形内点的精炼算法也很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多