32
votes

enter image description here

I want to calculate the overlapped area "THE GRAY REGION" between red and blue rectangles.

Each rectangle is defined by its four corner coordinates. The resulted unit of the overlapped area is unit square.

I could not imagine how can I do it?

Any creative comments would be appreciated.

2
So what is your problem exactly? If you know all the corners points, you can easily calculate the corner of the intersection rectangle. The corner coordinates and the min and max functions should be all you need. - cel
does shapely can calculate corner of the intersection rectangle? - Eric Bal
I don't know that. Yet, I'm pretty sure you can figure out how you can calculate those corners on your own. Just look at the upper left corner: To be in the intersection you have to have an x_coord at least as large as the maximum of red and blue's left ends and a y_coord at most the minimum of red and blue's upper ends... you have similar arguments for each of the four corner points. - cel
This is easy, but the main problem is notation. How do you define a rectangle in your code? For example, a tuple with values like: (xmin, ymin, xmax, ymax), etc? - tom10
@tom10 Each corner of rectangle is defined as (x,y) coordinate values, which can be used for getting (xmin, ymin, xmax, ymax) as you said. - Eric Bal

2 Answers

64
votes

This type of intersection is easily done by the "min of the maxes" and "max of the mins" idea. To write it out one needs a specific notion for the rectangle, and, just to make things clear I'll use a namedtuple:

from collections import namedtuple
Rectangle = namedtuple('Rectangle', 'xmin ymin xmax ymax')

ra = Rectangle(3., 3., 5., 5.)
rb = Rectangle(1., 1., 4., 3.5)
# intersection here is (3, 3, 4, 3.5), or an area of 1*.5=.5

def area(a, b):  # returns None if rectangles don't intersect
    dx = min(a.xmax, b.xmax) - max(a.xmin, b.xmin)
    dy = min(a.ymax, b.ymax) - max(a.ymin, b.ymin)
    if (dx>=0) and (dy>=0):
        return dx*dy

print area(ra, rb)
#  0.5 

If you don't like the namedtuple notation, you could just use:

dx = max(a[0], b[0]) - min(a[2], b[2])

etc, or whatever notation you prefer.

22
votes

As this question has a tag, here is a solution using it. I will use the same rectangles as in the tom10 answer:

from shapely.geometry import Polygon

polygon = Polygon([(3, 3), (5, 3), (5, 5), (3, 5)])
other_polygon = Polygon([(1, 1), (4, 1), (4, 3.5), (1, 3.5)])
intersection = polygon.intersection(other_polygon)
print(intersection.area)
# 0.5

This is much more concise than the version in the accepted answer. You don't have to construct your own Rectangle class as Shapely already provides the ready ones. It's less error-prone (go figure out the logic in that area function). And the code itself is self-explanatory.


References:
Docs for object.intersection(other) method