How do I plot Shapely polygons and objects using Matplotlib?

PythonMatplotlibShapely

Python Problem Overview


I want to use Shapely for my computational geometry project. I need to be able to visualize and display polygons, lines, and other geometric objects for this. I've tried to use Matplotlib for this but I am having trouble with it.

from shapely.geometry import Polygon
import matplotlib.pyplot as plt

polygon1 = Polygon([(0,5),
                    (1,1),
                    (3,0),
                    ])

plt.plot(polygon1)
plt.show()

I would like to be able to display this polygon in a plot. How would I change my code to do this?

Python Solutions


Solution 1 - Python

Use:

import matplotlib.pyplot as plt

x,y = polygon1.exterior.xy
plt.plot(x,y)

Or, more succinctly:

plt.plot(*polygon1.exterior.xy)

Solution 2 - Python

A little late but I find the most convenient way to do this is with Geopandas as suggested above but without writing to a file first.

from shapely.geometry import Polygon
import matplotlib.pyplot as plt
import geopandas as gpd

polygon1 = Polygon([(0,5),
                    (1,1),
                    (3,0),
                    ])

 p = gpd.GeoSeries(polygon1)
 p.plot()
 plt.show()

Polygon Plotted using Geopandas

Checkout the docs for Geopandas.GeoSeries

Solution 3 - Python

If your data is in a .shp file, I would recommend geopandas:

import geopandas as gpd
import matplotlib.pyplot as plt

shapefile = gpd.read_file("path/to/shapes.shp")
shapefile.plot()
plt.show()

Solution 4 - Python

Geometries can be Point, LineString, Polygon, and their collection versions MultiPoint, MultiLineString, MultiPolygon.

Point

Just pass the coordinates to pyplot:

points = (point1, point2, point3, point3D)
xs = [point.x for point in points]
ys = [point.y for point in points]

fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.scatter(xs, ys)

LineString

Just pass the x and y collections to pyplot. They are obtained using xy attribute. This attribute returns something like:

(array('d', [3.0, 2.0, 9.0]), array('d', [6.0, -1.0, 4.0]))

and can be used this way:

ax.plot(line.xy[0], line.xy[1])
ax.plot(*line.xy) # Equivalent

Polygon

For Polygon, the currently accepted answer indeed works only for degraded polygons, that is polygons without holes. Here is a version working for any polygon with usual keywords for colors and other attributes. It's not my design, it's just adapted from GeoPandas source

import numpy as np
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.collections import PatchCollection


# Plots a Polygon to pyplot `ax`
def plot_polygon(ax, poly, **kwargs):
    path = Path.make_compound_path(
        Path(np.asarray(poly.exterior.coords)[:, :2]),
        *[Path(np.asarray(ring.coords)[:, :2]) for ring in poly.interiors])

    patch = PathPatch(path, **kwargs)
    collection = PatchCollection([patch], **kwargs)
    
    ax.add_collection(collection, autolim=True)
    ax.autoscale_view()
    return collection

It is used this way:

from shapely.geometry import Polygon
import matplotlib.pyplot as plt


# Input polygon with two holes
# (remember exterior point order is ccw, holes cw else
# holes may not appear as holes.)
polygon = Polygon(shell=((0,0),(10,0),(10,10),(0,10)),
                  holes=(((1,3),(5,3),(5,1),(1,1)),
                         ((9,9),(9,8),(8,8),(8,9))))

fig, ax = plt.subplots()
plot_polygon(ax, polygon, facecolor='lightblue', edgecolor='red')

enter image description here

Collections

For Multi- collections, just call the plot function on each element.

Solution 5 - Python

I was tired of Matplotlib's janky API for creating these plot images, so I made my own library. The Python module is called WKTPlot, and uses Bokeh to make interactive plots of your data. I have examples on how to plot WKT string data as well as data from Shapefiles.

It supports all most shapely geometric types:

  • Point

  • MultiPoint

  • LineString

  • MultiLineString

  • LinearRing

  • Polygon

  • MultiPolygon

  • GeometryCollection

Solution 6 - Python

It might be an overkill, but as an alternative to other good comments I would add an option of installing QGIS - a free software for working with geometries. All you need to do is to save your geometries as a shape file (.shp), geoJSON or any other format and open it with QGIS. If you're planning a big project it maybe more convenient at the end than using matplotlib.

Solution 7 - Python

Here is a solution using matplotlib patches that also accounts for holes:

import numpy as np
import shapely.geometry as sg
import matplotlib.pyplot as plt
import matplotlib.patches as patches


def add_polygon_patch(coords, ax, fc='blue'):
    patch = patches.Polygon(np.array(coords.xy).T, fc=fc)
    ax.add_patch(patch)


border = [(-10, -10), (-10, 10), (10, 10), (10, -10)]  # Large square
holes = [
    [(-6, -2), (-6, 2), (-2, 2), (-2, -2)],  # Square hole
    [(2, -2), (4, 2), (6, -2)]               # Triangle hole
]
region = sg.Polygon(shell=border, holes=holes)

fig, ax = plt.subplots(1, 1)

add_polygon_patch(region.exterior, ax)
for interior in region.interiors:
    add_polygon_patch(interior, ax, 'white')
        
ax.axis('equal')
plt.show()

Polygon region with polygon holes from a

Solution 8 - Python

You can also 'follow along' with the source code in the Shapely User Manual: (click on 'Source code).

The 'source code' provided here is not the actual Shapely source code, but the code used in the User Manual to create the examples. Using this 'example code' from the Shapely User Manual allows you to quickly create images in the same friendly style.

Screenshot from https://shapely.readthedocs.io/en/latest/manual.html#linestrings november 2021

You'll need the 'figures' module, which is just one short, quite simple, python file from: https://github.com/Toblerity/Shapely/blob/main/docs/code/figures.py. (Taken from per https://gis.stackexchange.com/questions/362492/shapely-examples-use-figures-what-is-this-library)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionebeb9View Question on Stackoverflow
Solution 1 - Pythonap21View Answer on Stackoverflow
Solution 2 - PythonMicah JohnsonView Answer on Stackoverflow
Solution 3 - PythonMitchell TracyView Answer on Stackoverflow
Solution 4 - PythonminsView Answer on Stackoverflow
Solution 5 - PythonnightwuffleView Answer on Stackoverflow
Solution 6 - PythonMarat SeroglazovView Answer on Stackoverflow
Solution 7 - PythonadamconkeyView Answer on Stackoverflow
Solution 8 - PythonIdeogramView Answer on Stackoverflow