| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- """Plot single geometries using Matplotlib.
- Note: this module is experimental, and mainly targeting (interactive)
- exploration, debugging and illustration purposes.
- """
- import numpy as np
- import shapely
- def _default_ax():
- import matplotlib.pyplot as plt
- ax = plt.gca()
- ax.grid(True)
- ax.set_aspect("equal")
- return ax
- def _path_from_polygon(polygon):
- from matplotlib.path import Path
- from shapely.ops import orient
- if isinstance(polygon, shapely.MultiPolygon):
- return Path.make_compound_path(
- *[_path_from_polygon(poly) for poly in polygon.geoms]
- )
- else:
- polygon = orient(polygon)
- return Path.make_compound_path(
- Path(np.asarray(polygon.exterior.coords)[:, :2]),
- *[Path(np.asarray(ring.coords)[:, :2]) for ring in polygon.interiors],
- )
- def patch_from_polygon(polygon, **kwargs):
- """Get a Matplotlib patch from a (Multi)Polygon.
- Note: this function is experimental, and mainly targeting (interactive)
- exploration, debugging and illustration purposes.
- Parameters
- ----------
- polygon : shapely.Polygon or shapely.MultiPolygon
- The polygon to convert to a Matplotlib Patch.
- **kwargs
- Additional keyword arguments passed to the matplotlib Patch.
- Returns
- -------
- Matplotlib artist (PathPatch)
- """
- from matplotlib.patches import PathPatch
- return PathPatch(_path_from_polygon(polygon), **kwargs)
- def plot_polygon(
- polygon,
- ax=None,
- add_points=True,
- color=None,
- facecolor=None,
- edgecolor=None,
- linewidth=None,
- **kwargs,
- ):
- """Plot a (Multi)Polygon.
- Note: this function is experimental, and mainly targeting (interactive)
- exploration, debugging and illustration purposes.
- Parameters
- ----------
- polygon : shapely.Polygon or shapely.MultiPolygon
- The polygon to plot.
- ax : matplotlib Axes, default None
- The axes on which to draw the plot. If not specified, will get the
- current active axes or create a new figure.
- add_points : bool, default True
- If True, also plot the coordinates (vertices) as points.
- color : matplotlib color specification
- Color for both the polygon fill (face) and boundary (edge). By default,
- the fill is using an alpha of 0.3. You can specify `facecolor` and
- `edgecolor` separately for greater control.
- facecolor : matplotlib color specification
- Color for the polygon fill.
- edgecolor : matplotlib color specification
- Color for the polygon boundary.
- linewidth : float
- The line width for the polygon boundary.
- **kwargs
- Additional keyword arguments passed to the matplotlib Patch.
- Returns
- -------
- Matplotlib artist (PathPatch), if `add_points` is false.
- A tuple of Matplotlib artists (PathPatch, Line2D), if `add_points` is true.
- """
- from matplotlib import colors
- if ax is None:
- ax = _default_ax()
- if color is None:
- color = "C0"
- color = colors.to_rgba(color)
- if facecolor is None:
- facecolor = list(color)
- facecolor[-1] = 0.3
- facecolor = tuple(facecolor)
- if edgecolor is None:
- edgecolor = color
- patch = patch_from_polygon(
- polygon, facecolor=facecolor, edgecolor=edgecolor, linewidth=linewidth, **kwargs
- )
- ax.add_patch(patch)
- ax.autoscale_view()
- if add_points:
- line = plot_points(polygon, ax=ax, color=color)
- return patch, line
- return patch
- def plot_line(line, ax=None, add_points=True, color=None, linewidth=2, **kwargs):
- """Plot a (Multi)LineString/LinearRing.
- Note: this function is experimental, and mainly targeting (interactive)
- exploration, debugging and illustration purposes.
- Parameters
- ----------
- line : shapely.LineString or shapely.LinearRing
- The line to plot.
- ax : matplotlib Axes, default None
- The axes on which to draw the plot. If not specified, will get the
- current active axes or create a new figure.
- add_points : bool, default True
- If True, also plot the coordinates (vertices) as points.
- color : matplotlib color specification
- Color for the line (edgecolor under the hood) and points.
- linewidth : float, default 2
- The line width for the polygon boundary.
- **kwargs
- Additional keyword arguments passed to the matplotlib Patch.
- Returns
- -------
- Matplotlib artist (PathPatch)
- """
- from matplotlib.patches import PathPatch
- from matplotlib.path import Path
- if ax is None:
- ax = _default_ax()
- if color is None:
- color = "C0"
- if isinstance(line, shapely.MultiLineString):
- path = Path.make_compound_path(
- *[Path(np.asarray(mline.coords)[:, :2]) for mline in line.geoms]
- )
- else:
- path = Path(np.asarray(line.coords)[:, :2])
- patch = PathPatch(
- path, facecolor="none", edgecolor=color, linewidth=linewidth, **kwargs
- )
- ax.add_patch(patch)
- ax.autoscale_view()
- if add_points:
- line = plot_points(line, ax=ax, color=color)
- return patch, line
- return patch
- def plot_points(geom, ax=None, color=None, marker="o", **kwargs):
- """Plot a Point/MultiPoint or the vertices of any other geometry type.
- Parameters
- ----------
- geom : shapely.Geometry
- Any shapely Geometry object, from which all vertices are extracted
- and plotted.
- ax : matplotlib Axes, default None
- The axes on which to draw the plot. If not specified, will get the
- current active axes or create a new figure.
- color : matplotlib color specification
- Color for the filled points. You can use `markeredgecolor` and
- `markerfacecolor` to have different edge and fill colors.
- marker : str, default "o"
- The matplotlib marker for the points.
- **kwargs
- Additional keyword arguments passed to matplotlib `plot` (Line2D).
- Returns
- -------
- Matplotlib artist (Line2D)
- """
- if ax is None:
- ax = _default_ax()
- coords = shapely.get_coordinates(geom)
- (line,) = ax.plot(
- coords[:, 0], coords[:, 1], linestyle="", marker=marker, color=color, **kwargs
- )
- return line
|