指向复合多边形内部

时间:2016-01-19 15:26:42

标签: c# point polygons point-in-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)
可以避免这种情况     enter image description here

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

1 个答案:

答案 0 :(得分:2)

使用此行

class TypedProperty(object):
    def __init__(self,name,type,default=None):
        self.name = "_" + name
        self.type = type
        self.default = default if default else type()
    def __get__(self,instance,cls):
        return getattr(instance,self.name,self.default)
    def __set__(self,instance,value):
        if not isinstance(value,self.type):
            raise TypeError("Must be a %s" % self.type)
        setattr(instance,self.name,value)

class Foo(object):
    name = TypedProperty("name",str)
    num = TypedProperty("num",int,42)

f = Foo()
f.name = 'blah'

您只计算从底部接近查询行的段(或跨越它)。这正是你需要为弧做的事情。

为此,可能希望将弧分成单调部分(相对于y轴)。在您的示例中,较低的弧已经是单调的。上弧应分成两部分(沿着中心的垂直线)。然后,每个细分受众群都有class TypedProperty2(object): def __init__(self, val, typ): if not isinstance(val, typ): raise TypeError() self.value = val self.typ = typ def __get__(self, instance, owner): return self.value def __set__(self, instance, val): if not isinstance(val, self.typ): raise TypeError() self.value = val p1.Y < testY != p2.Y < testY ,您可以应用以上公式:

minY

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