Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given a set of rectangles, do any overlap?

Tags:

Given a set of rectangles represented as tuples (xmin, xmax, ymin, ymax) where xmin and xmax are the left and right edges, and ymin and ymax are the bottom and top edges, respectively - is there any pair of overlapping rectangles in the set?

A straightforward approach is to compare every pair of rectangles for overlap, but this is O(n^2) - it should be possible to do better.

Update: xmin, xmax, ymin, ymax are integers. So a condition for rectangle 1 and rectangle 2 to overlap is xmin_2 <= xmax_1 AND xmax_2 >= xmin_1; similarly for the Y coordinates.

If one rectangle contains another, the pair is considered overlapping.

like image 542
gcbenison Avatar asked May 18 '15 15:05

gcbenison


People also ask

How do you know if rectangles overlap?

Problem Statement Its top and bottom edges are perpendicular to the X-axis, while its left and right edges are perpendicular to the Y-axis. If the area of their intersection is positive, two rectangles overlap.

How do you check if two rectangles overlap in Python?

If we have two (axis-aligned) rectangles, we have to check whether they overlap or not. So, if the input is like R1 = [0,0,2,2], R2 = [1,1,3,3], then the output will be True. otherwise, return True.

What is overlap area?

The OverlapArea function is a Spatial Numeric measurement that calculates the total area (or length or count) of overlap between features in the current layer and features in the target layer.


2 Answers

You can do it in O(N log N) approach the following way.

Firstly, "squeeze" your y coordinates. That is, sort all y coordinates (tops and bottoms) together in one array, and then replace coordinates in your rectangle description by its index in a sorted array. Now you have all y's being integers from 0 to 2n-1, and the answer to your problem did not change (in case you have equal y's, see below).

Now you can divide the plane into 2n-1 stripes, each unit height, and each rectangle spans completely several of them. Prepare an segment tree for these stripes. (See this link for segment tree overview.)

Then, sort all x-coordinates in question (both left and right boundaries) in the same array, keeping for each coordinate the information from which rectangle it comes and whether this is a left or right boundary.

Then go through this list, and as you go, maintain list of all the rectangles that are currently "active", that is, for which you have seen a left boundary but not right boundary yet.

More exactly, in your segment tree you need to keep for each stripe how many active rectangles cover it. When you encounter a left boundary, you need to add 1 for all stripes between a corresponding rectangle's bottom and top. When you encounter a right boundary, you need to subtract one. Both addition and subtraction can be done in O(log N) using the mass update (lazy propagation) of the segment tree.

And to actually check what you need, when you meet a left boundary, before adding 1, check, whether there is at least one stripe between bottom and top that has non-zero coverage. This can be done in O(log N) by performing a sum on interval query in segment tree. If the sum on this interval is greater than 0, then you have an intersection.

 squeeze y's
 sort all x's
 t = segment tree on 2n-1 cells
 for all x's
     r = rectangle for which this x is
     if this is left boundary
         if t.sum(r.bottom, r.top-1)>0   // O(log N) request
              you have occurence
         t.add(r.bottom, r.top-1, 1)  // O(log N) request
     else
         t.subtract(r.bottom, r.top-1)  // O(log N) request

You should implement it carefully taking into account whether you consider a touch to be an intersection or not, and this will affect your treatment of equal numbers. If you consider touch an intersection, then all you need to do is, when sorting y's, make sure that of all points with equal coordinates all tops go after all bottoms, and similarly when you sort x's, make sure that of all equal x's all lefts go before all rights.

like image 191
Petr Avatar answered Nov 14 '22 17:11

Petr


Why don't you try a plane sweep algorithm? Plane sweep is a design paradigm widely used in computational geometry, so it has the advantage that it is well studied and a lot of documetation is available online. Take a look at this. The line segment intersection problem should give you some ideas, also the area of union of rectangles.

Read about Bentley-Ottman algorithm for line segment intersection, the problem is very similar to yours and it has O((n+k)logn) where k is the number of intersections, nevertheless, since your rectangles sides are parallel to the x and y axis, it is way more simpler so you can modify Bentley-Ottman to run in O(nlogn +k) since you won't need to update the event heap, since all intersections can be detected once the rectangle is visited and won't modify the sweep line ordering, so no need to mantain the events. To retrieve all intersecting rectangles with the new rectangle I suggest using a range tree on the ymin and ymax for each rectangle, it will give you all points lying in the interval defined by the ymin and ymax of the new rectangle and thus the rectangles intersecting it.

If you need more details you should take a look at chapter two of M. de Berg, et. al Computational Geometry book. Also take a look at this paper, they show how to find all intersections between convex polygons in O(nlogn + k), it might prove simpler than my above suggestion since all data strcutures are explained there and your rectangles are convex, a very good thing in this case.

like image 26
Javier Cano Avatar answered Nov 14 '22 19:11

Javier Cano