合并重叠的轴对齐矩形

时间:2018-02-01 07:58:45

标签: algorithm computational-geometry rectangles

我有一组轴对齐的矩形。当两个矩形重叠(部分或完全)时,它们将合并到它们的公共边界框中。此过程以递归方式工作。

检测所有重叠并使用union-find形成组,您最终合并 将无效,因为两个矩形的合并覆盖了更大的区域并可以创建新的重叠。 (在下图中,合并了两个重叠的矩形后,会出现新的重叠。)

enter image description here

在我的情况下,矩形的数量是中等的(比如N <100),可以使用强力解决方案(尝试所有对,如果发现重叠,则从头开始合并并重新启动)。无论如何,我想降低复杂性,在最坏的情况下可能是O(N³)。

有任何建议如何改善这个?

3 个答案:

答案 0 :(得分:1)

我认为R-Tree会在这里完成工作。 R-Tree索引矩形区域,允许您在O(log n)中插入,删除和查询(例如,交叉查询)低维度的“普通”查询。

我们的想法是连续处理您的矩形,对于您执行以下操作的每个矩形:

  1. 对当前R-Tree执行交叉查询(空中的 开始)

  2. 如果有结果,则从R-Tree中删除结果,     将当前矩形与所有结果矩形合并并插入     新合并的矩形(最后一步跳转到第1步。)。

  3. 如果没有结果,只需在R-Tree中插入矩形
  4. 总共会执行

    • O(n)在步骤1中交叉查询。(O(n log n))
    • O(n)在步骤3中插入步骤(O(n log n))
    • 在步骤2中最多n次删除和n次插入步骤。这是因为每次执行步骤2时,将矩形数减少至少1(O(n log n))

    理论上你应该使用 O(n log n),但是最后的合并步骤(使用大矩形)可能选择性低,需要的时间超过O(log n),但是根据数据分布,这不应该破坏整个运行时间。

答案 1 :(得分:0)

使用平衡的标准化四叉树。

规范化:收集所有x坐标,对它们进行排序,并用排序数组中的索引替换它们。 y坐标也一样。

平衡:构建四叉树时始终在中间坐标处分割。

因此,当你得到一个矩形时,你想要用树的一些id标记树中正确的节点。如果您在下面找到任何其他矩形(这意味着它们将重叠),请将它们聚集在一组中。完成后,如果向量不为空(您找到重叠的矩形),那么我们创建一个新的矩形来表示子矩形的并集。如果计算的矩形大于您刚插入的矩形,则使用新计算的矩形再次应用算法。重复此操作直到它不再生长,然后移动到下一个输入矩形。

对于性能,四叉树中的每个节点都存储与该节点重叠的所有矩形,并将其标记为终端节点。

复杂性:初始标准化为O(NlogN)。插入和检查重叠将为O(log(N)^2)。您需要对原始N矩形以及重叠执行此操作。每次找到重叠时,都会消除至少一个原始矩形,这样您最多可以找到(N-1)个重叠。总的来说,你需要2N的操作。总的来说,复杂性将是O(N(log(N)^2))

这比其他方法更好,因为您不需要检查任何到任何矩形的重叠。

答案 2 :(得分:0)

这可以使用平面扫描和空间数据结构的组合来解决:我们沿扫描线合并交叉矩形,并将扫描线后面的任何矩形放到空间数据结构中。每当我们得到一个新合并的矩形时,我们会检查与这个新矩形相交的任何矩形的空间数据结构,如果找到则合并它。

如果扫描线后面的任何矩形(R)与扫描线下的某个矩形(S)相交,则最靠近扫描线的R的两个角中的任何一个都在S内。这意味着空间数据结构应存储点(两点)对于每个矩形)并回答有关位于给定矩形内的任何点的查询。实现这种数据结构的一种显而易见的方法是分段树,其中每个叶子包含在相应的y坐标处具有顶侧和底侧的矩形,并且每个其他节点指向包含最右边的矩形的其后代之一(其右侧最接近于扫线)。

要使用这样的分段树,我们应该压缩(标准化)矩形角的y坐标。

  1. 压缩y坐标
  2. 按左侧x坐标对矩形进行排序。
  3. 将扫描线移动到下一个矩形,如果它通过某些矩形的右侧,则将它们移动到分段树。
  4. 检查当前矩形是否与扫描线相交。如果没有,请转到第3步。
  5. 检查在步骤4中找到的矩形的并集是否与段树中的任何内容相交并递归合并,然后转到步骤4.
  6. 当步骤3到达列表末尾时,获取扫描线下的所有矩形和段树中的所有矩形,并解压缩它们的坐标。
  7. 最坏情况时间复杂度由段树确定:O(n log n)。空间复杂度为O(n)。