/usr/lib/python3/dist-packages/descartes/patch.py is in python3-descartes 1.1.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | """Paths and patches"""
from matplotlib.patches import PathPatch
from matplotlib.path import Path
from numpy import asarray, concatenate, ones
class Polygon(object):
# Adapt Shapely or GeoJSON/geo_interface polygons to a common interface
def __init__(self, context):
if isinstance(context, dict):
self.context = context['coordinates']
else:
self.context = context
@property
def exterior(self):
return (getattr(self.context, 'exterior', None)
or self.context[0])
@property
def interiors(self):
value = getattr(self.context, 'interiors', None)
if value is None:
value = self.context[1:]
return value
def PolygonPath(polygon):
"""Constructs a compound matplotlib path from a Shapely or GeoJSON-like
geometric object"""
def coding(ob):
# The codes will be all "LINETO" commands, except for "MOVETO"s at the
# beginning of each subpath
n = len(getattr(ob, 'coords', None) or ob)
vals = ones(n, dtype=Path.code_type) * Path.LINETO
vals[0] = Path.MOVETO
return vals
if hasattr(polygon, 'geom_type'): # Shapely
ptype = polygon.geom_type
if ptype == 'Polygon':
polygon = [Polygon(polygon)]
elif ptype == 'MultiPolygon':
polygon = [Polygon(p) for p in polygon]
else:
raise ValueError(
"A polygon or multi-polygon representation is required")
else: # GeoJSON
polygon = getattr(polygon, '__geo_interface__', polygon)
ptype = polygon["type"]
if ptype == 'Polygon':
polygon = [Polygon(polygon)]
elif ptype == 'MultiPolygon':
polygon = [Polygon(p) for p in polygon['coordinates']]
else:
raise ValueError(
"A polygon or multi-polygon representation is required")
vertices = concatenate([
concatenate([asarray(t.exterior)[:, :2]] +
[asarray(r)[:, :2] for r in t.interiors])
for t in polygon])
codes = concatenate([
concatenate([coding(t.exterior)] +
[coding(r) for r in t.interiors]) for t in polygon])
return Path(vertices, codes)
def PolygonPatch(polygon, **kwargs):
"""Constructs a matplotlib patch from a geometric object
The `polygon` may be a Shapely or GeoJSON-like object with or without holes.
The `kwargs` are those supported by the matplotlib.patches.Polygon class
constructor. Returns an instance of matplotlib.patches.PathPatch.
Example (using Shapely Point and a matplotlib axes):
>>> b = Point(0, 0).buffer(1.0)
>>> patch = PolygonPatch(b, fc='blue', ec='blue', alpha=0.5)
>>> axis.add_patch(patch)
"""
return PathPatch(PolygonPath(polygon), **kwargs)
|