最小化随机矩形中的重叠

时间:2010-02-11 17:06:35

标签: algorithm language-agnostic ascii-art

我有许多可能重叠的矩形,在固定平面内随机大小和位置。由于这些矩形是随机的,有些可能不会重叠:

|-----
|    |    |----|
|----|    |    |
          |----|

有些可能只在一个角落重叠:

|-----|
|  |--|--|
|--|--|  |
   |-----|

有些可能包含在另一个矩形中:

|----------------|
|                |
|   |-----|      |
|   |     |      |
|   |-----|      |
|----------------|

有些可能会通过另一个矩形:

   |----------------|
   |                |
|--|-------------------|
|  |                |  |
|--|-------------------|
   |----------------|

我正在尝试找到一种算法,该算法为我提供了一组矩形,这些矩形表示与输入集相同的区域,但没有重叠。有些情况很明显 - 可以丢弃包含在较大矩形内的矩形,并且在角上重叠的矩形可以分成三个矩形,也可以将矩形分成另一个矩形。我正在寻找的是一种处理所有这些情况的通用算法。我不在乎它是否效率不高 - 输入集相当小(最多25个矩形)

找到重叠的矩形很容易,但很快就会变得更难,特别是考虑到一个矩形可能与多个其他矩形重叠时。

这是我的头脑。有什么建议吗?

更新

我刚才意识到了一件事:

我可以在添加矩形的时候运行这个算法,一个接一个地添加,或者在添加了所有矩形之后。在添加矩形时可能更容易,因为您只需要考虑一个矩形,但您仍需要考虑单个矩形与多个其他矩形重叠的情况。

5 个答案:

答案 0 :(得分:3)

矩形是否与x& y轴平行?我想他们是。

您可以尝试使用KD-Trees

或者如果你想要一些自产的东西而且不一定有效,你可以'矩形',然后如果需要合并矩形。

通过'rectangulation'我的意思是你首先找到一个更大的矩形,其中所有矩形都适合(基本上由最左边缘,右边缘,最底边缘,最顶边缘形成的矩形)。

现在延伸出矩形的所有边缘以切割大矩形。你现在有一个'矩形'。基本上所有这些意味着您对垂直边和水平边排序,并选择相邻的对以形成一个小矩形。对于每个小矩形,您现在可以检查它是否是有趣区域的一部分,如果不是(它在室内或室外完全),则拒绝它。

现在你有一个小矩形列表(可能是O(n ^ 2),在你的情况下可能是~2500),它构成你感兴趣的区域。如果数字足够小以供将来处理,你可以使用它们,或者你可以将它们合并在一起以减少矩形的数量。

要合并,你可以考虑一个矩形,并考虑4个可能的合并(相同高度的相邻矩形向右或向左,或相同宽度的相邻矩形到顶部或底部)。

您可以通过维护排序的边缘列表(水平和并行)以及一些哈希表来加快某些处理(不仅仅是在合并期间)。

答案 1 :(得分:1)

首先在合成中创建所有“原子”矩形的集合,即由矩形交叉点形成的区域,而不是自身细分的区域。每个实际矩形覆盖一个或多个原子矩形。然后运行组合优化算法,例如SETCOVER计算你需要覆盖它们的最小矩形数。

这里是该方法的说明。你有三个矩形(A,B,C)。它们创建了5个原子区域(1-5):

 +---------+A
 |       1 |
 |    +----+-----+B
 |    |  2 | 3   |
 |    |  +-+---+C|
 |    |  |4|   | |
 +----+--+-+ 5 | |
      |  +-----+ |
      +--+-------+

矩形根据此表覆盖原子区域:

 A  {1,2,4}
 B  {2,3,4,5}
 C  {4,5}

SETCOVER问题现在是选择矩形{A,B,C}的最小子集,以便在将矩形覆盖的原子区域放在一起时覆盖所有原子区域。最小的解决方案是(显然)

 A {1,2,4} + B {2,3,4,5} = {1,2,3,4,5}

注意,这里的区域是非矩形的,例如区域3具有复杂的形状。您可以通过以下方法解决此问题:获取原始矩形的角点的所有不同的X坐标,并将它们视为网格的X坐标,并对Y坐标执行相同的操作;然后每个矩形都覆盖一组从不细分的网格方块,即:

 +---------+A       -
 |       1 |
 |    +----+-----+B -
 |    |  2 | 3   |
 |    |  +-+---+C|  -
 |    |  |4|   | | 
 +----+--+-+ 5 | |  -
      |  +-----+ |  -
      +--+-------+  -

 |    |  | |   | |

它为您提供以下5x5网格:

 AAA      A = rectangle A only
 A**BB    B = rectangle B only
 A*#CB    * = A and B
  BCCB    C = rectangles C and B
  BBBB    # = All

由此您可以轻松提取5个区域;事实上,它们已被标记为:(A,B,C,*,#)

答案 2 :(得分:1)

非常有趣的问题 - 我认为最好一次解决一对矩形问题,而不是一次看3个或更多。首先丢弃其他矩形内的那些。现在你只有3种交叉点 - 角重叠并通过重叠和部分重叠(矩形不会一直通过)。这些都创建了一组新的矩形,对吗?

将起始矩形从1编号为N.从矩形1开始循环,直到找到相交的矩形。创建新的矩形。删除两个相交的矩形,并将3个或更多新创建的矩形添加到您的集合中,然后重新开始。

结果将是一堆非重叠的矩形。这会创建最少的矩形吗?可能不是,但你没有说明最小化矩形的数量很重要。是否需要超过o(n ^ 2)时间?可能。

答案 3 :(得分:1)

如果您对算法应该生成的矩形数量没有任何限制,那么您的治疗肯定会轻率!

<强> 1。最简单的解决方案

创建一组由输入集的矩形覆盖的所有正方形(区域1)。一个正方形是一个矩形......你在那里!

<强> 2。极简主义解决方案?

好吧,那是轻率的,但我不认为你应该担心输入集。你的问题实际上是不同的:

  

选择一个形状复杂的连续区域,然后尝试用矩形覆盖它,最大限度地减少它们的数量,使它们不重叠。

当然,您的区域可能不是连续的,但它只是意味着您有几个可以独立工作的连续区域。

现在,我承认我不知道这个问题的最佳解决方案,我可以设想各种方法,我不知道他们的表现或结果。 KD-Tree应该会产生一个解决方案,但不知道它是否是极简主义的!

答案 4 :(得分:0)

如果你还没有一组矩形,你可以从另一个方向接近它 - 从一个大的矩形开始并细分它直到你有一个你可以使用的集合 - 这将确保你没有重叠。

从整个矩形开始

--------
|      |
|      |
|      |
|      |
|      |
--------

以随机点分割并存储两个矩形。

--------
|      |
|------|
|      |
|      |
|      |
--------

在随机点分割随机矩形

--------
|      |
|------|
| |    |
| |    |
| |    |
--------

重复一遍。 。

--------
|      |
|------|
| |    |
| |----|
| |    |
--------

当你有所需数量的矩形时停止。

你可以通过更仔细地选择你每次将要分割的矩形等来使这种产生你想要的“随机性”