3

Sounds like a simple question, and the Shapely doc says all I need to do to create a simple polygon with a hole is to pass two lists of coordinate tuples:

exterior = [(2, 8), (7, 8), (7, 3), (2, 3), (2, 8)]
interior = [(4, 7), (4, 5), (6, 5), (6, 7), (4, 7)]
pgn = Polygon(exterior, holes=interior)

However, I get the following error:

AttributeError: 'tuple' object has no attribute '_ndim'

I also tried passing a Polygon as the interior ring.

interior=Polygon([(4, 7), (4, 5), (6, 5), (6, 7), (4, 7)])
pgn = Polygon(exterior, holes=interior)

>>> TypeError: object of type 'Polygon' has no len()

What is the correct way to use this constructor? Looks like the holes parameter should not be a tuple or a Polygon, so what should it be?

1 Answer 1

6

A polygon can have multiple holes in it, so the holes argument is a list of list of coordinate tuples:

>>> exterior = [(2, 8), (7, 8), (7, 3), (2, 3), (2, 8)]
>>> interior = [(4, 7), (4, 5), (6, 5), (6, 7), (4, 7)]

This fails:

>>> pgn = Polygon(exterior, holes=interior)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rowlings/.local/lib/python2.7/site-packages/shapely/geometry/polygon.py", line 240, in __init__
    ret = geos_polygon_from_py(shell, holes)
  File "/home/rowlings/.local/lib/python2.7/site-packages/shapely/geometry/polygon.py", line 506, in geos_polygon_from_py
    N = exemplar._ndim
AttributeError: 'tuple' object has no attribute '_ndim'

because interior isn't a list of interior polygons, its just one. So make it a list with one member:

>>> pgn = Polygon(exterior, holes=[interior])
>>> pgn
<shapely.geometry.polygon.Polygon object at 0x7fb3639bc250>

Docs:

The second is an optional unordered sequence of ring-like sequences specifying the interior boundaries or “holes” of the feature.

The "source code" links are great working examples of the shapely API, eg this:

ext = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]
int = [(1, 0), (0.5, 0.5), (1, 1), (1.5, 0.5), (1, 0)][::-1]
polygon = Polygon(ext, [int])

in https://shapely.readthedocs.io/en/latest/code/polygon.py

2
  • Ah, that's it! Knew I would be missing something simple. I might suggest adding an example to their docs to make it easier for the next person who has this problem.
    – jon_two
    Mar 5, 2020 at 15:03
  • The reason why you need [::-1] at the end of the interior sequence is because ring coordinate pairs should be ordered counter-clockwise while hole sequences should be clockwise. Jan 19, 2023 at 19:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.