In [1]:
import numpy as np
import shapely.geometry
import shapely.geometry.polygon
import shapely.geometry.multilinestring
import matplotlib.pyplot as plt
from matplotlib import patches, transforms, collections, cm
from matplotlib.path import Path
%matplotlib inline
%load_ext autoreload
%autoreload 2
In [2]:
def mpl_to_shapely(mpl, **kwargs):
if isinstance(mpl, transforms.Bbox):
return shapely.geometry.box(mpl.x0, mpl.y0, mpl.x0+mpl.width, mpl.y0+mpl.height)
def shapely_to_mpl(shape, **kwargs):
"""Convert shapely to mpl Polygon.
If PolygonCollection try instead to convert largest polygon.
"""
if isinstance(shape, shapely.geometry.polygon.Polygon):
# return mpl Polygon if possible
if isinstance(shape.boundary, shapely.geometry.linestring.LineString):
return patches.Polygon(zip(*shape.exterior.xy),
**kwargs)
elif isinstance(shape.boundary, shapely.geometry.multilinestring.MultiLineString):
verts = []
codes = []
for geom in shape.boundary.geoms:
nverts = zip(*geom.xy)
ncodes = [Path.MOVETO]
ncodes.extend([Path.LINETO for i in range(len(nverts)-2)])
ncodes.append(Path.CLOSEPOLY)
verts.extend(nverts)
codes.extend(ncodes)
path = Path(verts, codes)
return patches.PathPatch(path, **kwargs)
elif isinstance(shape, shapely.geometry.multipolygon.MultiPolygon):
# MultiPolygon instead of Polygon --> convert largest polygon in collection
polygon = sorted(shape.geoms, key=lambda x: x.area)[-1]
return patches.Polygon(zip(*polygon.exterior.xy),
**kwargs)
elif isinstance(shape, shapely.geometry.multilinestring.MultiLineString):
lines = [zip(*line.xy) for line in shape.geoms]
return collections.LineCollection(lines,
**kwargs)
In [3]:
fig, ax = plt.subplots()
imdata = np.random.randn(10, 10)
ax.imshow(imdata, extent=(0, 1, 0, 1), aspect='auto', cmap=cm.coolwarm)
box = shapely.geometry.box(0.3, 0.3, 0.7, 0.7)
text = ax.text(0.5, 0.5, 'Text', fontsize='xx-large', fontweight='bold', color='k', ha='center', va='center')
renderer = ax.figure.canvas.get_renderer()
bbox = text.get_window_extent(renderer)
bbox_points = bbox.transformed(ax.transAxes.inverted()).get_points()
pad = 0.01
bbox_points[0] -= pad
bbox_points[1] += pad
bbox_points = ax.transData.inverted().transform(ax.transAxes.transform(bbox_points))
bbox_shapely = shapely.geometry.box(*bbox_points.flatten())
patch = shapely_to_mpl(box-bbox_shapely, edgecolor='k', facecolor='none', lw=1.0, alpha=1.0, hatch=r'//')
ax.add_patch(patch)
print patch.get_path()
plt.xticks([])
plt.yticks([])
Out[3]:
In [4]:
bbox.get_points()
Out[4]:
In [5]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import patches, cm
from matplotlib.path import Path
fig, ax = plt.subplots()
imdata = np.random.randn(10, 10)
ax.imshow(imdata, extent=(0, 1, 0, 1), aspect='auto', cmap=cm.coolwarm)
text = ax.text(0.5, 0.5, 'Text', fontsize='xx-large', fontweight='bold',
color='k', ha='center', va='center')
renderer = fig.canvas.get_renderer()
bbox = text.get_window_extent(renderer).transformed(ax.transData.inverted())
bboxrect = patches.Rectangle((bbox.x0, bbox.y0), bbox.width, bbox.height)
bbpath = bboxrect.get_path().transformed(bboxrect.get_patch_transform())
patch = patches.Rectangle((0.3, 0.3), 0.4, 0.4)
path = patch.get_path().transformed(patch.get_patch_transform())
path = Path.make_compound_path(path, bbpath)
patch = patches.PathPatch(path, facecolor='none', hatch=r'//')
ax.add_patch(patch)
print patch.get_path()
In [6]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Rectangle
from matplotlib.transforms import Bbox
# This is in PIXELS
# first tuple : coords of box' bottom-left corner, from the figure's bottom-left corner
# second tuple : coords of box' top-right corner, from the figure's bottom-left corner
clip_box = Bbox(((0,0),(200,200)))
circle = Circle((0,0), 1, clip_on=True)
plt.axis('equal')
plt.axis((-2,2,-2,2))
plt.axes().add_artist(circle)
ax = plt.gca()
text = plt.text(0, 0, 'hi')
renderer = fig.canvas.get_renderer()
bbox = text.get_window_extent(renderer).transformed(ax.transData.inverted())
print bbox
rect = Rectangle([bbox.x0, bbox.y0], bbox.width, bbox.height, color = [0,0,0], fill = False)
# You have to call this after add_artist()
circle.set_clip_box(bbox.transformed(ax.transData))
#circle.set_clip_path(rect)
In [ ]: