Extract points/coordinates from a polygon in Shapely
Asked Answered
N

10

121

How do you get/extract the points that define a shapely polygon? Thanks!

Example of a shapely polygon

from shapely.geometry import Polygon

# Create polygon from lists of points
x = [list of x vals]
y = [list of y vals]

polygon = Polygon(x,y)
Neri answered 9/12, 2013 at 15:40 Comment(0)
N
140

The trick is to use a combination of the Polygon class methods:

from shapely.geometry import Polygon

# Create polygon from lists of points
x = [0.0, 0.0, 1.0, 1.0, 0.0]
y = [0.0, 1.0, 1.0, 0.0, 0.0]

poly = Polygon(zip(x,y))

# Extract the point values that define the perimeter of the polygon
xx, yy = poly.exterior.coords.xy

# Note above return values are of type `array.array` 
assert x == xx.tolist()
assert y == yy.tolist()

If you would like them as coordinate pairs

assert tuple(poly.exterior.coords) == tuple(zip(x,y))

or as a numpy array

assert np.array_equal(np.array(poly.exterior.coords), np.asarray(tuple(zip(x,y))))
Neri answered 9/12, 2013 at 16:56 Comment(1)
This gives the x and y coords as separate lists. For list as individual (x,y) tuples use the poly.exterior.coords per @pnklein 's answer below, or use sh.get_coordinates(poly) to get np array of arrays[x,y]Lenis
H
77

It took me a while to learn that a Polygon has an exterior boundary and possibly several interior boundaries. I am posting here because some of the answers don't reflect that distinction, though to be fair the original post did not use as an example a polygon with interior boundaries.

The points forming the exterior boundary are arranged in a CoordinateSequence, which can be obtained as

polygon.exterior.coords

You can find the length of this object using len(polygon.exterior.coords) and can index the object like a list. To get the first vertex, for example, use polygon.exterior.coords[0]. Note that the first and last points are the same; if you want a list consisting of the vertices without that repeated point, use polygon.exterior.coords[:-1].

You can convert the CoordinateSequence (including the repeated vertex) to a list of points thus:

list(polygon.exterior.coords)

Similarly, the CoordinateSequence consisting of the vertices forming the first interior boundary is obtained as polygon.interiors[0].coords, and the list of those vertices (without the repeated point) is obtained as polygon.interiors[0].coords[:-1].

Haplite answered 8/8, 2018 at 20:0 Comment(1)
How would you get all coordinates subtended by the polygon? So any points lying inside the Polygon, how to get those coordinates?Lanellelanette
T
36

You can use the shapely mapping function:

>>> from shapely.geometry import Polygon, mapping
>>> sh_polygon = Polygon(((0,0), (1,1), (0,1)))
>>> mapping(sh_polygon)
{'type': 'Polygon', 'coordinates': (((0.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0)),)}
Tenorio answered 16/11, 2016 at 11:34 Comment(2)
Nice. This is nice as it would allow for easily generalizing a routine which requires this.Neri
and this also gives the bounding box should you need itKristin
A
14

I used this:

list(zip(*p.exterior.coords.xy))

Polygon created with: p = Polygon([(0,0),(1,1),(1,0),(0,0)]) returns:

[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)]
Aspic answered 27/11, 2017 at 20:14 Comment(0)
A
8

If you really want the shapely point objects that make up the polygon, and not just tuples of coordinates, you can do that this way:

points = MultiPoint(polygon.boundary.coords)
Acetic answered 27/5, 2018 at 4:45 Comment(0)
G
3

Update (2017-06-09):

As the last answer seems not to work anymore with newest version of shapely, I propose this update.

shapely provides the Numpy array interface (as the doc says: http://toblerity.org/shapely/project.html )

So, let poly be a shapely polygon geometry:

In [2]: type(poly)
Out[2]: shapely.geometry.polygon.Polygon

This command will do the conversion to a numpy array:

In [3]: coordinates_array = np.asarray(poly.exterior.coords)

Hint:
One must need to give the exterior.coords for a polygon because giving the direct geometry seems not to work either:

In [4]: coordinates_array = np.asarray(poly)
Out[4]: array(<shapely.geometry.polygon.Polygon object at 0x7f627559c510>, dtype=object)    
Ganiats answered 9/6, 2017 at 21:13 Comment(0)
B
2

You can convert a shapely Polygon to a NumPy array using NumPy.array. I find using NumPy arrays more useful than the arrays returned by coords.xy, since the coordinates are paired, rather than in two one-dimensional arrays. Use whichever is more useful to your application.

import numpy as np
x = [1, 2, 3, 4]
y = [9, 8, 7, 6]
polygon = Polygon(x,y)
points = np.array(polygon)

# points is:
[[ 1 9]
 [ 2 8]
 [ 3 7]
 [ 4 6]]
Baste answered 27/4, 2016 at 1:0 Comment(3)
Good thinking. Thanks! I think I was using this when I had an un-ordered group of points, and by using coords.xy I was able to pull out an ordered list of external points, or perhaps the external points of a grid... I'll play with this when I have time and report back :)Neri
The above code doesn't work with shapely=1.5.13=py35_0. Polygon(x,y) is not accepted. np.array(some_actual_polygon) also does not behave as shown.Corie
We get this warning in from Shapely 2.0 onwards.C:\ProgramData\Anaconda3\envs\gis\lib\site-packages\IPython\core\interactiveshell.py:3457: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead. exec(code_obj, self.user_global_ns, self.user_ns). Therefore using points = np.array(polygon.coors)Pardner
R
2

You can use any of the two following methods.

1)

p = Polygon([(1,0),(1,1),(0,1),(0,0)])
for x,y in p.exterior.coords:
   print(x,y)

The above code prints the following. Note that (1,0) is printed twice, since exterior.coords returns an ordered sequence that completes the polygon.

1.0 0.0
1.0 1.0
0.0 1.0
0.0 0.0
1.0 0.0

2)

p.exterior.coords.xy

It outputs the following

(array('d', [1.0, 1.0, 0.0, 0.0, 1.0]), array('d', [0.0, 1.0, 1.0, 0.0, 0.0]))
Rolfe answered 8/1, 2018 at 17:56 Comment(3)
Those two methods are the same, and the same as my answer from 2013-12-09.Neri
@Neri yeah the second one is the same as yours. The first one though I felt is a more intuitive way to unpack the xy pairs.Rolfe
The question was how to obtain the coordinates, not how to unpack tuples. I'm responding to this because this does answer does not add additional information for how to obtain the coords, and it is not the first to repeat an already existing answer, like this one. Your suggestion would best be made in the form of a comment on an existing answer. Answers like this create unnecessary cruft for people to go through to find the critical information.Neri
R
1

With Holes

x, y = [0,0,4,4,0], [0,4,4,0,0]
shell = [(0,0), (0,4), (4,4), (4,0), (0,0)]
holes = [
    [(1,1), (1,2), (2,2), (2,1), (1,1)],
    [(2,2), (2,3), (3,3), (3,2), (2,2)],
]

assert list(zip(x, y)) == shell

polygon = Polygon(shell, holes)

shell = polygon.exterior.coords[:]
holes = [hole.coords[:] for hole in polygon.interiors]

assert polygon == Polygon(shell, holes)
Roadwork answered 23/4 at 9:33 Comment(1)
Or for a numpy array coords[:] with coords._coords.Roadwork
V
-2
d0=[]
for n in range(0,len(gdf1['geometry'])):
    try:
        k=(len(gdf1['geometry'][n].geoms))    
        ce+=1
    except:
        d0.append(n)
Veach answered 27/5, 2022 at 3:57 Comment(2)
You might want to add an explanation what the code does and why it is better than the other answers.Deluge
This appears to compose a list of geometries in gdf that are not muli-polygons, which is not applicable to the question asked. For this problem, I might rather use DataFrame.apply(), as is proposed in this SO question thread.Neri

© 2022 - 2024 — McMap. All rights reserved.