我在GeoJson
中定义了n个几何形状,我想计算涉及最大数目的形状的交点。
我有以下限制;
因此,作为起点,我虽然可以使用蛮力(尝试将给定形状的n,n-1,n-2组合相交)来做到这一点,但是时间复杂度将为O(n!)。我想知道算法是否可以优化?
编辑:
好吧,我忘了讲述数据类型。我将Esri/geometry库用于形状。具体来说,Polygon类实例。
答案 0 :(得分:1)
这个问题感觉就像您可以构造无法有效解决的硬盒,特别是在形状不是凸形的情况下。您可以尝试以下两种方法:
1。迭代交叉点
保留L
个(不相交)多边形的列表,其开头的计数为空。现在遍历给定的多边形P
。对于p
中的每个多边形P
与l
中的所有多边形L
相交。如果p
和l
之间有交集,则从l
和
L
previous count of l +1
添加set_intersection(l,p)L
的下一个条目当您遍历L
的所有元素时,请将p
的其余部分添加到L中,计数为1。
最终,您将获得一个不相交的多边形列表,其数量等于参与者多边形的数量。
2。空间分解
围绕所有多边形构建一个边界框。然后迭代分割该空间(类似于KD-Tree)。对于每个一半(矩形),从与该矩形相交的P中计算多边形的数量。进行最佳优先(始终评估计数最高的矩形)。当您处于KD树的某个级别时,请停止并通过蛮力或迭代交集进行评估。
两种方法都将受益于使用多边形周围最小边界矩形的过滤器。
答案 1 :(得分:0)
将维护未处理(非空)交叉点的列表以及创建交叉点的面索引。最初,它是用单个多边形填充的。始终会取出大多数多边形和所涉及多边形的最小索引之间的交集,并将其与索引较高的所有多边形相交(以避免一次又一次地查看同一多边形子集)。这样可以进行有效的修剪:
这是类似Python的表示法的算法:
def findIntersectionFromMostMembers(polygons):
unprocessedIntersections = [(polygon, {i}) for i, polygon in enumerate(polygons)]
unprocessedIntersections.reverse() # make polygon_0 the last element
intersectionFromMostMembers, indicesMost = (polygons[0], {0})
while len(unprocessedIntersections) > 0:
# last element has most involved polygons and least maximal polygon index
# -> highest chance of being extended to best intersection
intersection, indices = unprocessedIntersections.pop() # take out unprocessed intersection from most polygons
if len(indices) + n - max(indices) - 1 <= len(indicesMost):
continue # pruning 1: this intersection cannot beat best found solution so far
for i in range(max(indices)+1, n): # pruning 2: only look at polyong with higher indices
intersection1 = intersection.intersect(polygons[i])
if not intersection1.isEmpty(): # pruning 3: empty intersections do not need to be considered any further
unprocessedIntersections.insertSorted(intersection1, indices.union({i}), key = lambda(t: len(t[1]), -max(t[1])))
if len(indices)+1 > len(indicesMost):
intersectionFromMostMembers, indicesMost = (intersection1, indices.union({i}))
return intersectionFromMostMembers, indicesMost
性能很大程度上取决于平均有多少个共同的多边形。共有相同区域的(<< n
多边形越少,修剪3越有效。多边形共有的区域越多,修剪1的效果就越好。修剪2确保没有任何多边形子集被考虑两次。最坏的情况似乎是当恒定比例的n
(例如n/2
)多边形具有某些公共区域时。直到n=40
,该算法才会在合理的时间内终止(几秒钟或最多几分钟)。如果大多数多边形的非空交集仅涉及几个(任何常量<< n
)多边形,则可以在合理的时间内处理更大的多边形集。