我已经看到了多边形内点的算法。 到目前为止我学到的内容来自这个网站: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)
可以避免这种情况
我找不到弧形部分的复合多边形的任何类似实现。有人曾经做过类似的事情或有任何暗示吗?
答案 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坐标),并根据角度和弧方向评估弧是否继续向下。但是根据实施情况,这可能会有一些数值稳定性问题。第一个选项(分成单调部分)可能更容易实现。它推广到其他原语。