One critical piece of code on my application involves enumerating all rectangles on a 2-D surface. The rectangles do not intersect each other and I must be able to enumerate all rectangles within a given rectangular boundary.
I already have a function to return the rectangle for a given coordinate, if it exists
GetRectangle( int row, int col )
Here is how I would call the resulting code.
foreach( var rect in GetRectangles( row, col, rowCount, colCount ) ) {
//.. my processing code here
}
Obviously, I could call the function GetRectangle() for each of the points in the surface. I can also skip the width of the rectangle that was returned from the previous call as I know that they do not intersect. But, this is still not efficient enough.
Are you aware of such an algorithm?
UPDATE: The surface is not necessarily covered by rectangles but it can be for some special cases. So, the function GetRectangle( int row, int col ) might return null.
Think of the surface as a bitmap filled with random rectangles (which don’t intersect). The task is to return all rectangles on that surface that falls within (i.e. intersects) a given frame. Hope this will clarify the question.
Thanks
For best results, organize your collection of rectangles into a spatial lookup structure. In this case it sounds as though a R-tree would be a good bet. But if you can’t do that, and
GetRectangleis all you’ve got, then here is what I’d do:The plan is to maintain a list of integers xj for 0 ≤ j <
rowCount, where xj is the leftmost point on row j for which I have not yet found a rectangle covering it.Start by initializing xj := 0 for all j.
If xj =
colCountfor all j, we are done. Stop.Let J = min(j | xj = min(xi)). Then xJ is the topmost leftmost point that I have not yet found a rectangle that covers it.
Call
GetRectangle(xJ, J). If this does not return a rectangle, then the point is uncovered. Set xJ := xJ + 1 and go to step 2.Otherwise, we have a rectangle with top left corner at (xJ, J). Call its width w and height h. For J ≤ j < J + h, set xj := xj + w. Go to step 2.
Here’s an example run of this algorithm. The list of xj is shown by the numbers at the left, with the topmost leftmost highlighted in bold. The orange rectangle is the one that’s discovered at that step of the algorithm.
For efficient discovery of the minimum at step 3, you might want to keep the list of xj in a heap.