I have few polygons or boxes. Ones intersect each other but some are isolated. For example I have free figures:
import shapely.geometry as sg
import shapely.ops as so
import matplotlib.pyplot as plt
r1 = sg.Polygon([(0,0),(0,1),(1,1),(1,0),(0,0)])
r2 = sg.box(0.5,0.5,1.5,1.5)
r3 = sg.box(4,4,5,5)
First two are intersected and r3 is on some distance from them. I unite them via cascaded_union:
new_shape = so.cascaded_union([r1, r2, r3])
Then I try to plot it (one united figure of r1 and r2 and one distanced box r3)
xs, ys = new_shape.exterior.xy
fig, axs = plt.subplots()
axs.fill(xs, ys, alpha=0.5, fc='r', ec='none')
plt.show()
Instead of plot I receive an AttributeError: 'MultiPolygon' object has no attribute 'exterior'.
Is there a pythonic way to display a multipolygon or to iterate through it and draw its parts?
4 Answers 4
Shapely Polygon
object has attribute exterior
. Shapely MultiPolygon
object has Polygon
object sequence. You should iterate over those polygons. You can do that using attribute geoms
of MultiPolygon
.
Use this way:
import shapely.geometry as sg
import shapely.ops as so
import matplotlib.pyplot as plt
r1 = sg.Polygon([(0,0),(0,1),(1,1),(1,0),(0,0)])
r2 = sg.box(0.5,0.5,1.5,1.5)
r3 = sg.box(4,4,5,5)
new_shape = so.unary_union([r1, r2, r3])
fig, axs = plt.subplots()
axs.set_aspect('equal', 'datalim')
for geom in new_shape.geoms:
xs, ys = geom.exterior.xy
axs.fill(xs, ys, alpha=0.5, fc='r', ec='none')
plt.show()
-
cascaded_union
is deprecated. See here.petezurich– petezurich2022年11月27日 12:56:16 +00:00Commented Nov 27, 2022 at 12:56
An alternative, shorter way of plotting using @Kadir Şahbaz's answer:
Edit: Per @petezurich's comment, cascaded_union
is superseded by unary_union
as of 1.8.0
new_shape = so.unary_union([r1, r2, r3])
# Plot each polygon shape directly
for geom in new_shape.geoms:
plt.plot(*geom.exterior.xy)
# Set (current) axis to be equal before showing plot
plt.gca().axis("equal")
plt.show()
-
1
cascaded_union
is deprecated. See here.petezurich– petezurich2022年11月27日 12:55:43 +00:00Commented Nov 27, 2022 at 12:55
Look at Plot shapefile with islands with matplotlib for example.
As with polygons you can use matplotlib paths and patches and there is a Python module dedicated to plot polygons from shapefiles using these functions Descartes.
new_shape= so.unary_union([r1, r2, r3])
from descartes import PolygonPatch
import matplotlib.pyplot as plt
BLUE = '#6699cc'
GRAY = '#999999'
fig = plt.figure()
ax = fig.gca()
ax.add_patch(PolygonPatch(new_shape, fc=GRAY, ec=BLUE, alpha=0.5, zorder=2 ))
ax.axis('scaled')
plt.show()
You can use GeoPandas' .plot()
function:
import shapely.geometry as sg
import shapely.ops as so
import matplotlib.pyplot as plt
import geopandas as gpd
r1 = sg.Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)])
r2 = sg.box(0.5, 0.5, 1.5, 1.5)
r3 = sg.box(4, 4, 5, 5)
new_shape = so.cascaded_union([r1, r2, r3])
gpd.GeoSeries(new_shape).plot()
plt.show()
-
This is the easiest solution, I'd wager.Lupilum– Lupilum2023年05月15日 08:20:31 +00:00Commented May 15, 2023 at 8:20