I'm trying to clip a cloud of points by several polygons, but I don't know if this is possible with plt.axis.set_clip_path()
.
Since set_clip_path()
requires a Path or a Patch as arguments, how could you create a geometry formed by several Polygons? It would be something like a plt.MultiPolygon()
, but that doesn't exist. I've tried to create a matplotlib.PatchCollection
with all the Polygons, but that does not work.
Here is the desired goal (from upper to lower figure):
Here is how I'd like the code to look like:
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
import numpy as np
fig, ax = plt.subplots()
points = np.array([np.random.random(100)*400,
np.random.random(100)*100]).T
A = plt.Polygon( np.array([( 0, 0),(50,100),(100, 0)]), color='w', ec='k' )
B = plt.Polygon( np.array([(120 , 0),(170 , 100), (220, 0)]), color='w', ec='k' )
C = plt.Polygon( np.array([(240 , 0),(290 , 100), (340, 0)]), color='w', ec='k' )
[ax.add_patch(i) for i in (A,B,C)]
ax.scatter(points[:,0], points[:,1], zorder=3).set_clip_path([A,B,C])
You can concatenate the vertices
and the codes
of all polygons, and use them to create a "compound path". Matplotlib's path tutorial contains an example creating a histogram from just one compound path.
import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib.patches import PathPatch
import numpy as np
points = np.array([np.random.random(100) * 400,
np.random.random(100) * 100]).T
A = plt.Polygon(np.array([(0, 0), (50, 100), (100, 0)]), color='w', ec='k')
B = plt.Polygon(np.array([(120, 0), (170, 100), (220, 0)]), color='w', ec='k')
C = plt.Polygon(np.array([(240, 0), (290, 100), (340, 0)]), color='w', ec='k')
fig, ax = plt.subplots()
all_polys = [A, B, C]
[ax.add_patch(i) for i in all_polys]
vertices = np.concatenate([i.get_path().vertices for i in all_polys])
codes = np.concatenate([i.get_path().codes for i in all_polys])
dots = ax.scatter(points[:, 0], points[:, 1], zorder=3)
dots.set_clip_path(PathPatch(Path(vertices, codes), transform=ax.transData))
plt.show()