Search code examples
pythonpolygonrectanglesshapely

Python - Check if Shapely Polygon is a rectangle


After operations like splitting on Polygon, I would like to verify that it is a rectangle.
I have tried simplify and then counting if number of coords is 5...

>>> from shapely.geometry import Polygon
>>> from shapely.ops import split
>>> 
>>> poly1 = Polygon([(0, 0), (0, 1), (0, 3), (2, 3), (2, 2), (2, 0), (0, 0)])
>>> 
>>> poly_check=poly1.simplify(0)
>>> if len(poly_check.exterior.coords)==5:
>>>     print 'Yes, it is a rectangle...'
>>> else:
>>>     print 'No, it is not a rectangle...'
>>> 
Yes, it is a rectangle...

But it does not work if the starting point is in the middle of an edge.

>>> #poly2 is actually a rectangle
>>> poly2 = Polygon([(0, 1), (0, 3), (2, 3), (2, 2), (2, 0), (0, 0), (0, 1)])
>>> 
>>> poly_check=poly2.simplify(0)
>>> if len(poly_check.exterior.coords)==5:
>>>     print 'Yes, it is a rectangle...'
>>> else:
>>>     print 'No, it is not a rectangle...'
>>> 
No, it is not a rectangle...

How can I check this ?

Thanks


Solution

  • Polygon is a rectangle if its area matches the area of its minimum bounded rectangle. It is a known shape index called rectangularity.

    if poly.area == poly.minimum_rotated_rectangle.area:
        return True
    

    EDIT: Taking into account the comment about floating point error below, you can either measure rectangularity directly and consider everything > .99 as rectangle or make the approximate comparison (e.g. rounding).

    if (poly.area / poly.minimum_rotated_rectangle.area) > .99:
        return True
    

    EDIT 2: It is better to just use math.isclose function to determine the equality of the two variables. The division in the previous comparison reduces the overall precision of the comparison, we avoid that here:

    import math
    
    if math.isclose(poly.minimum_rotated_rectangle.area, poly.area):
        return True