Finding out if a rectangle is obscured by rectangles above it?
I have a collection of rectangles, and a reference rectangle. I want to find out if the reference rectangle is completely obscured by the rectangles above it (all of those in the collection). For example :
The obvious solution is to create a matrix of bools or a bitmap and simply blit all the rectangles and check if there's anything that isn't covered, but that's not an option. This would have to be done lots of times per sec开发者_开发知识库ond.
I came up with this idea : for every rectangle, intersect it with every other rectangle (and limit them to the reference rectangle), resulting in a collection of smaller rectangles that don't intersect, like this :
Then simply add all their areas and subtract from the area of the reference rectangle. However I'm not sure exactly how to do this best. Any other ideas, suggestions or examples are welcome.
Thank you.
Let n be the number of covering rectangles. This problem can be solved in time O(n log n) using a plane sweep ( http://en.wikipedia.org/wiki/Sweep_line_algorithm ) and an augmented bottom-up splay tree ( http://en.wikipedia.org/wiki/Splay_tree ).
Clip all covering rectangles to the reference.
By sorting, reduce the problem to one where all x-coordinates of the covering rectangles are integers in [0, 2n). Transform the y-coordinates similarly.
Create a 2n-node splay tree. The value of node j is how many rectangles intersect the sweep line in the open interval (j, j + 1). For O(log n)-time updates, don't store j's value in j but rather the difference between j's value and j's parent's value (the root stores its true value). Rotations are slightly more complicated: the rotation
y x / \ / \ x c -> a y / \ / \ a b b c
involves updating
b.diff += x.diff; // if b exists x.diff += y.diff; y.diff -= x.diff;
Each node also tracks its subtree minimum. For compatibility with the value representation previously described, node j stores the difference of its subtree minimum and its value. During a rotation:
y.diffmin = min(0, b.diffmin + b.diff, c.diffmin + c.diff);
At the end of a splay operation, update the root the same way. Omit b or c if they don't exist.
Sweep the line. For x in [0, 2n), find all rectangles whose left-hand side is at x and update the tree as follows. For a rectangle from y0 to y1, splay y1 and increment the diff of its left child (and recompute diffmin), then splay y0 and decrement the diff of its left child.
After all left-hand sides have been processed, check the tree min. If it's zero, then the reference is not covered.
Process the right-hand sides in much the same way (swap increment and decrement in the description).
精彩评论