复合多边形内的点

Point inside compound polygon

我见过很多点在多边形内的算法。 到目前为止我所学到的来自这个网站:http://alienryderflex.com/polygon/

最好的算法通常是这样的:

var inside = false;
for (int i = poly.Count - 1, j = 0; j < poly.Count; i = j++)
{
    var p1 = poly.Vertices[i];
    var p2 = poly.Vertices[j];

    if ((p1.Y < testY != p2.Y < testY) && //at least one point is below the Y threshold and the other is above or equal
        (p1.X >= testX || p2.X >= testX)) //optimisation: at least one point must be to the right of the test point
    {
        if (p1.X + (testY - p1.Y) / (p2.Y - p1.Y) * (p2.X - p1.X) > testX)
            inside = !inside;
    }
}

但是复合多边形线段可以是直线也可以是圆弧。弧段由法线 2 点和用于查找弧的中心和半径的凸起定义。 2个点用于求圆弧的起点和终点角度。

使用测试点 Y 和 Math.Asin((testY - arc.Center.Y) / arc.Radius) 我可以找到测试线与圆相交的角度。当测试线与圆相交时,有2个交点。之后我测试角度以了解交点是否在弧上。

到目前为止,我的结果还不错,只是当测试点发生时与顶点完全相同 y。它将被计算在 2 个相邻的段中。对于普通段,if (p1.Y < testY != p2.Y < testY)
可以避免这种情况

对于圆弧部分的复合多边形,我找不到任何类似的实现。有人曾经做过类似的事情或有任何提示吗?

用这条线

p1.Y < testY != p2.Y < testY

您只计算从底部接近查询线(或穿过它)的线段。这正是您需要为弧线做的。

为此,可能需要将弧分成单调部分(相对于 y-axis)。在您的示例中,下弧已经是单调的。上弧应一分为二(沿着穿过其中心的垂直线)。然后每个段都有 minYmaxY,您可以应用上面的公式:

minY < testY != maxY < testY

或者,您可以检查交点是否在圆弧末端(等于y-coordinate),并根据角度和圆弧方向评估圆弧是否继续向下。但是根据实施情况,这可能会出现一些数值稳定性问题。第一个选项(拆分成单调部分)可能更容易实现。并且它推广到其他原语。