如何获得覆盖另一堆矩形的最小计数矩形?

时间:2012-07-26 11:10:58

标签: c++ algorithm merge computational-geometry

假设我有一堆矩形,其中一些是相交的,有些是孤立的。 E. g。


    +--------------- +                     +-------- +
    |                |                     |         |
    |                |                     |         |
    |       A        |                     |   C     |
    |         +---------------- +          |         |
    |         |      |          |          +---------+-------- +
    |         |      |          |          |                   |
    +---------|----- +  B       |          |       D           |
              |                 |          |                   |
              |                 |          +------------------ +
              +---------------- +

    +------------------ +          +-------- +
    |                   |          |         |
    |        E          |          |   X     |
    +-------------------+          |         |
    |                   |          +-------- +
    |                   |                       +------------ +
    |                   |                       |             |
    |        F          |                       |             |
    |                   |                       |     Y       |
    |                   |                       |             |
    +-------------------+                       +------------ +

矩形A,B相互交叉,C,D有一个相同的点,E,F有两个相同的点,X,Y是孤立的。

我有两个问题:

  1. 如何将这些矩形分成矩形,这些矩形覆盖A,B,C,D,E,F,X,Y也具有这样的最小数量:
  2. 
        +---------+----- +                     +-------- +
        |         |      |                     |         |
        |         |      |                     |         |
        |         |      |                     |         |
        |         |      +--------- +          |         |
        |         |      |          |          +---------+-------- +
        |         |      |          |          |                   |
        +---------+      |          |          |                   |
                  |      |          |          |                   |
                  |      |          |          +-------------------+
                  +------+----------+
    
        +------------------ +          +-------- +
        |                   |          |         |
        |                   |          |         |
        |                   |          |         |
        |                   |          +---------+
        |                   |                       +------------ +
        |                   |                       |             |
        |                   |                       |             |
        |                   |                       |             |
        |                   |                       |             |
        +-------------------+                       +-------------+
    
    
    1. 如何用大的矩形覆盖相交的矩形?像这样:
    2. 
          +---------------------------+          +-------------------+
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          |                   |
          |                           |          +-------------------+
          +---------------------------+
      
      
          +-------------------+          +---------+
          |                   |          |         |
          |                   |          |         |
          |                   |          |         |
          |                   |          +---------+
          |                   |                       +------------ +
          |                   |                       |             |
          |                   |                       |             |
          |                   |                       |             |
          |                   |                       |             |
          +-------------------+                       +-------------+
      
      

      对于Q1,我根本不知道.... 对于Q2,我用C ++编写了一些代码,但效率很低。我相信有更好的方法/算法。

       bool intersectRect(const Rect& rect1, const Rect& rect2) {
          /* if rect1 and rect2 intersect return true
             else return false
          */
      }
      Rect mergeIntersectRects(const set<Rect>& rects) {
          // suppose rects are all intersected. This function only return a smallest Rect that cover all rects.
      }
      set<Rect> mergeRectToRects(const set<Rect>& rectset, const Rect& rect) {
          set<Rect> _intersect_rects;
          set<Rect> _unintersect_rects;
          for(set<Rect>::const_iterator it = rectset.begin();
              it != rectset.end();
              ++it) {
              if(intersectRect(*it, rect))
                  _intersect_rects.insert(*it);
              else 
                  _unintersect_rects.insert(*it);
          }
          if(!_intersect_rects.empty()) {
              _intersect_rects.insert(rect);
              return mergeRectToRects(_unintersect_rects,
                                      mergeIntersectRects(_intersect_rects));
          }
          else {
              _unintersect_rects.insert(rect);
              return _unintersect_rects;
          }
      }
      

4 个答案:

答案 0 :(得分:3)

首先,我假设您的矩形都是轴对齐的。

对于Q1,一个选项是sweep the plane,同时保持沿扫描线的位于矩形内部的线段列表。当您在扫描过程中发现每个矩形顶点时,您可以检查它是否修改当前内部线段,如果是,则根据需要开始或结束矩形。

例如,假设您的扫描线从左向右移动:

                                                                     Current
                                                                     Interior
      |                                                                  
    +-|------------- +                     +-------- +                   *
    | |              |                     |         |                   |
    | |              |                     |         |                   |
    | |     A        |                     |   C     |                   |
    | |       +---------------- +          |         |                   |
    | |       |      |          |          +---------+-------- +         |
    | |       |      |          |          |                   |         |
    +-|-------|----- +  B       |          |       D           |         *
      |       |                 |          |                   |
      |       |                 |          +------------------ +
      |       +---------------- +
      |
    +-|---------------- +          +-------- +                           *
    | |                 |          |         |                           |
    | |      E          |          |   X     |                           |
    | |-----------------+          |         |                           |
    | |                 |          +-------- +                           |
    | |                 |                       +------------ +          |
    | |                 |                       |             |          |
    | |      F          |                       |             |          |
    | |                 |                       |     Y       |          |
    | |                 |                       |             |          |
    +-|-----------------+                       +------------ +          *
      |

当扫描线位于上图所示的位置时,有两个内部区段。即,内部A和内部(E U F)。当扫描线到达B的最左边时,我们输出一个矩形,用于位于左侧的A部分。然后,我们用(A U B)的内部替换段列表中A的内部。

                                                                     Current
                                                                     Interior
                |                                                        
    +---------+-|--- +                     +-------- +                   *
    |         | |    |                     |         |                   |
    |         | |    |                     |         |                   |
    |         | |    |                     |   C     |                   |
    |         | |-------------- +          |         |                   |
    |         | |    |          |          +---------+-------- +         |
    |         | |    |          |          |                   |         |
    +---------+ |--- +  B       |          |       D           |         |
              | |               |          |                   |         |
              | |               |          +------------------ +         |
              +-|-------------- +                                        *
                |
    +-----------|------ +          +-------- +                           *
    |           |       |          |         |                           |
    |           |       |          |   X     |                           |
    |           |-------+          |         |                           |
    |           |       |          +-------- +                           |
    |           |       |                       +------------ +          |
    |           |       |                       |             |          |
    |           |       |                       |             |          |
    |           |       |                       |     Y       |          |
    |           |       |                       |             |          |
    +-----------|-------+                       +------------ +          *
                |

对于Q2,可以在同一扫描期间通过跟踪首先将片段添加到列表的x坐标(例如“A的左侧”)以及最小和最大y来计算答案。 - 协调它在其生命周期中跨越(例如B的底部到A的顶部)。当段最终从列表中删除时(例如“B的右侧”),然后使用这四个坐标输出一个矩形。

在预处理步骤中按字典顺序对矩形顶点进行排序将为O(n * log n)。处理它们将是O(log n),因为您可以对已知的内部范围进行二分搜索。总运行时间应为O(n * log n)。

答案 1 :(得分:1)

Q1:这称为直线多边形的分区。 Rob的comment的答案有很好的描述。我发现paper中提及的answer很有用。

Q2:我想你不希望两个非交叉区域的覆盖相交。像3个矩形的覆盖,2个矩形产生L和矩形交叉覆盖L但不是任何L矩形。

如果是这样,那么可以逐步创建封面。这是一个简单的算法。

covers = {A}
for each rectangle R
  while there is a cover that intersects R, say C
    remove C from covers and set R = cover of R and C
  add R to covers

此代码在标准格式中效率不高。 covers结构的结构良好,效率很高。

答案 2 :(得分:0)

我使用@Damon建议的方法,但使用一些空间索引结构加速相邻矩形搜索,例如四叉树或网格。您需要其中两个,首先构建在输入矩形集上,以搜索要分割的交叉矩形,然后在第一步中获得的分割矩形集上构建,以搜索相邻的矩形进行合并。与天真的方法相比,这应该会大大加快速度。

答案 3 :(得分:0)

以下是算法:http://goo.gl/aWDJo

您可以阅读有关查找凸包算法的信息:http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf