给定n个几何形状的最大参与者相交面积

时间:2019-03-15 12:29:44

标签: java algorithm math

我在GeoJson中定义了n个几何形状,我想计算涉及最大数目的形状的交点。

我有以下限制;

  • 所有形状都不能相交(任何形状之间都没有相交,0参与者相交)
  • 所有形状可能相交(所有形状都有一个相交,n个参与者相交)
  • 与k个参与者可能存在多个交集(形状A B C相交,形状D E F相交,有2个3位参与者相交,不需要找到两者,找到第一个3位参与者时返回)

因此,作为起点,我虽然可以使用蛮力(尝试将给定形状的n,n-1,n-2组合相交)来做到这一点,但是时间复杂度将为O(n!)。我想知道算法是否可以优化?

编辑:

好吧,我忘了讲述数据类型。我将Esri/geometry库用于形状。具体来说,Polygon类实例。

2 个答案:

答案 0 :(得分:1)

这个问题感觉就像您可以构造无法有效解决的硬盒,特别是在形状不是凸形的情况下。您可以尝试以下两种方法:

1。迭代交叉点

保留L个(不相交)多边形的列表,其开头的计数为空。现在遍历给定的多边形P。对于p中的每个多边形Pl中的所有多边形L相交。如果pl之间有交集,则从l

中删除L
  • previous count of l +1添加set_intersection(l,p)
  • 将set_minus(l,p)添加为“先前计数为l”
  • 记住set_minus(p,l)并继续进行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)多边形,则可以在合理的时间内处理更大的多边形集。