patch.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. """Paths and patches"""
  2. from matplotlib.patches import PathPatch
  3. from matplotlib.path import Path
  4. from numpy import asarray, concatenate, ones
  5. class Polygon(object):
  6. # Adapt Shapely or GeoJSON/geo_interface polygons to a common interface
  7. def __init__(self, context):
  8. if hasattr(context, 'interiors'):
  9. self.context = context
  10. else:
  11. self.context = getattr(context, '__geo_interface__', context)
  12. @property
  13. def geom_type(self):
  14. return (getattr(self.context, 'geom_type', None)
  15. or self.context['type'])
  16. @property
  17. def exterior(self):
  18. return (getattr(self.context, 'exterior', None)
  19. or self.context['coordinates'][0])
  20. @property
  21. def interiors(self):
  22. value = getattr(self.context, 'interiors', None)
  23. if value is None:
  24. value = self.context['coordinates'][1:]
  25. return value
  26. def PolygonPath(polygon):
  27. """Constructs a compound matplotlib path from a Shapely or GeoJSON-like
  28. geometric object"""
  29. this = Polygon(polygon)
  30. assert this.geom_type == 'Polygon'
  31. def coding(ob):
  32. # The codes will be all "LINETO" commands, except for "MOVETO"s at the
  33. # beginning of each subpath
  34. n = len(getattr(ob, 'coords', None) or ob)
  35. vals = ones(n, dtype=Path.code_type) * Path.LINETO
  36. vals[0] = Path.MOVETO
  37. return vals
  38. vertices = concatenate(
  39. [asarray(this.exterior)]
  40. + [asarray(r) for r in this.interiors])
  41. codes = concatenate(
  42. [coding(this.exterior)]
  43. + [coding(r) for r in this.interiors])
  44. return Path(vertices, codes)
  45. def PolygonPatch(polygon, **kwargs):
  46. """Constructs a matplotlib patch from a geometric object
  47. The `polygon` may be a Shapely or GeoJSON-like object with or without holes.
  48. The `kwargs` are those supported by the matplotlib.patches.Polygon class
  49. constructor. Returns an instance of matplotlib.patches.PathPatch.
  50. Example (using Shapely Point and a matplotlib axes):
  51. >>> b = Point(0, 0).buffer(1.0)
  52. >>> patch = PolygonPatch(b, fc='blue', ec='blue', alpha=0.5)
  53. >>> axis.add_patch(patch)
  54. """
  55. return PathPatch(PolygonPath(polygon), **kwargs)