31

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.

Georgy
  • 6,348
  • 7
  • 46
  • 58
Eric Bal
  • 805
  • 2
  • 9
  • 13
  • 3
    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 Nov 26 '14 at 15:34
  • does shapely can calculate corner of the intersection rectangle? – Eric Bal Nov 26 '14 at 15:43
  • 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 Nov 26 '14 at 15:53
  • 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 Nov 26 '14 at 22:38
  • @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 Nov 27 '14 at 02:41
  • Usually with a rectangle one only defines two points or four values since the other four are redundant. But, I'll just write am answer for (xmin,...) and let you go from there. – tom10 Nov 27 '14 at 03:09

2 Answers2

64

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.

tom10
  • 60,398
  • 8
  • 116
  • 129
  • thanks accepted, but does your code still works even if the blue polygon is at left side of the red polygon? – Eric Bal Nov 27 '14 at 05:30
  • 3
    @just: Yes, it works either way. Using the max and min approach is just an easy way of what would otherwise be a complicated set of conditionals to determine the relative positions. That is, read `max(a.xmin, b.xmin)` as the "righmost left corner", etc. Also, I changed my answer to now include the case when the rectangles don't intersect. – tom10 Nov 27 '14 at 14:58
  • How to get the percentage area of overlap? – Santhosh Dhaipule Chandrakanth Aug 05 '19 at 13:32
  • @SanthoshDhaipuleChandrakanth: It would be better to ask a separate question. For example, here it's not clear what you mean by percentage, specifically, the area of overlap is clear, by what area are you comparing that to -- the maximum area, the area of the two initial rectangles, etc? – tom10 Aug 14 '19 at 01:39
  • Just a note: Be sure to use the right points -- on Cartesian axes, the "top left" is x.min, but y.max. On a monitor, x.min, y.min is at the upper left and x.max, y.max is lower right. – Vorpal Swordsman May 06 '21 at 00:22
21

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

Georgy
  • 6,348
  • 7
  • 46
  • 58
  • 1
    @quant No, Shapely can be used only for planar geometry computations. – Georgy Jul 11 '20 at 09:43
  • According to your knowledge, is there something similar for higher dimensions ? – quant Jul 11 '20 at 09:47
  • 1
    @quant I've never worked with geometries of 3 or more dimensions. Googling gives the following links. Maybe they can be of any help: [3D Geometry Package for Python](https://stackoverflow.com/q/38637603/7851470), [Geometric Computing with Python](https://geometryprocessing.github.io/geometric-computing-python/#packages-description), [Open3D](http://www.open3d.org/docs/release/). – Georgy Jul 11 '20 at 09:54