7

Assume I have a pile of rectangles, some of which intersect, some isolate. E. g.


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

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

Rect A, B intersect with each other, C, D have one same point, E, F have two same points, X, Y are isolated.

I have two questions:

  1. How to partion these rectangles into rectangles which cover A, B, C, D, E, F, X, Y exactly also have minimum count like this:

    +---------+----- +                     +-------- +
    |         |      |                     |         |
    |         |      |                     |         |
    |         |      |                     |         |
    |         |      +--------- +          |         |
    |         |      |          |          +---------+-------- +
    |         |      |          |          |                   |
    +---------+      |          |          |                   |
              |      |          |          |                   |
              |      |          |          +-------------------+
              +------+----------+

    +------------------ +          +-------- +
    |                   |          |         |
    |                   |          |         |
    |                   |          |         |
    |                   |          +---------+
    |                   |                       +------------ +
    |                   |                       |             |
    |                   |                       |             |
    |                   |                       |             |
    |                   |                       |             |
    +-------------------+                       +-------------+

  1. How to cover intersected rectangles with big ones? Like this:

    +---------------------------+          +-------------------+
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          |                   |
    |                           |          +-------------------+
    +---------------------------+


    +-------------------+          +---------+
    |                   |          |         |
    |                   |          |         |
    |                   |          |         |
    |                   |          +---------+
    |                   |                       +------------ +
    |                   |                       |             |
    |                   |                       |             |
    |                   |                       |             |
    |                   |                       |             |
    +-------------------+                       +-------------+

For Q1, I've no idea at all.... For Q2, I wrote some code in C++ but have poor efficiency. I believe there're better methods/algorithm.

 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;
    }
}
Andrew Durward
  • 3,771
  • 1
  • 19
  • 30
zhangailin
  • 926
  • 2
  • 10
  • 20
  • 1
    This doesn't look terribly difficult, what have you got so far ? As your question stands, it seems that you expect SO to do ALL the work ! – High Performance Mark Jul 26 '12 at 11:15
  • Do you have any advice for calculating the rectangles ? May be some algorithm ? Question a and b are two questions actually – zhangailin Jul 26 '12 at 11:29
  • 2
    What I'd do is split a rectangle in 4 whenever another one touches or intersects, accumulating a lot of sub-rectangles. Then iterate over the list and for each item find the largest adjacent one, if any. Collapse them into one larger rectangle. Unluckily that's O(N^2) and thus probably not the most efficient algorithm, but so what. N and N^2 are kind of the same if N is a reasonable number (i.e. not in the thousands or ten thousands). It's dead simple to implement and almost impossible to get wrong. – Damon Jul 26 '12 at 11:30
  • Yes your method is simple enough but the number of rectangles is huge. The worst case may be 50000000 currently – zhangailin Jul 26 '12 at 11:43
  • possible duplicate of [Algorithm for finding the fewest rectangles to cover a set of rectangles](http://stackoverflow.com/questions/5919298/algorithm-for-finding-the-fewest-rectangles-to-cover-a-set-of-rectangles) – Rob Kennedy Jul 26 '12 at 12:02

4 Answers4

3

First, I'm assuming that your rectangles are all axis-aligned.

For Q1, one option would be to sweep the plane while maintaining a list of line segments along the sweep line that lie in the interior of the rectangles. As you discover each rectangle vertex during the sweep you can check to see if it modifies the current interior segments and if so, start or end a rectangle as necessary.

For example, let's say your sweep line moves left to right:

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

When the sweep line is in the position shown above, there are two interior segments. Namely, that inside A and that inside (E U F). When the sweep line reaches the leftmost edge of B, we output a rectangle for the portion of A lying to the left. We then replace the interior of A in the segment list with the interior of (A U B).

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

For Q2, the answer could be computed during the same sweep by keeping track of the x-coordinate at which a segment was first added to the list (e.g. "left side of A") as well as the min and max y-coordinates that it spans during its lifetime (e.g. bottom of B to top of A). When the segment is finally removed from the list (e.g. "right side of B"), then output a rectangle using these four coordinates.

Sorting the rectangle vertices lexicographically in a preprocessing step would be O(n * log n). Processing them would be O(log n) since you can do a binary search on the known interior ranges. The total runtime should be O(n * log n).

Andrew Durward
  • 3,771
  • 1
  • 19
  • 30
1

Q1: this is called partition of rectilinear polygon. Answer from Rob's comment has very good description. I found paper mentioned in the answer useful.

Q2: I suppose that you don't want two covers of non-intersecting regions to intersect. Like cover for 3 rectangle, 2 rectangle producing L and rectangle intersection cover of L but not any L rectangle.

If it is like that, than it is possible to incrementally create covers. Here is a simple algorithm for it.

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

This code is not efficient in standard form. With good structure for covers structure, it can be efficient.

Community
  • 1
  • 1
Ante
  • 5,350
  • 6
  • 23
  • 46
0

I'd use the method suggested by @Damon but speed up neighbouring rectangle search with some spatial indexing structure, for example a quadtree or a grid. You'd need two of them, first built over the set of input rectangles, to search for intersecting rectangles to split, and second built over the set of split rectangles obtained in first step, to search adjacent rectangles to merge. That should speed things up considerably compared to the naive approach.

yuri kilochek
  • 12,709
  • 2
  • 32
  • 59
0

Here's the algorithm: http://goo.gl/aWDJo

You can read about finding the convex hull algorithms: http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf

Nickon
  • 9,652
  • 12
  • 64
  • 119