Matplotlib set_clip_path 需要绘制补丁

16 投票
1 回答
5254 浏览
提问于 2025-04-20 01:12

我刚发现了一种很不错的方法,可以创建一个填充的等高线图,并且可以把它裁剪到任意的多边形区域。这个方法需要在Matplotlib的contourf()函数返回的QuadContourSet中的每个PathCollection实例上调用set_clip_path(patch)

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
import matplotlib.path as mpath

# some arbitrary data to plot
xx, yy = np.meshgrid(np.linspace(-5, 5, 20), np.linspace(-10, 10, 20), copy=False)
zz = np.sqrt(xx ** 2 + yy ** 2)

poly_verts = [
    (0, 0),
    (-4, 7),
    (-4, -7),
    (4, -7),
    (4, 7),
    (0, 0)
]
poly_codes = [mpath.Path.MOVETO] + (len(poly_verts) - 2) * [mpath.Path.LINETO] +
mpath.Path.CLOSEPOLY]

# create a Path from the polygon vertices
path = mpath.Path(poly_verts, poly_codes)

# create a Patch from the path
patch = mpatches.PathPatch(path, facecolor='none', edgecolor='k')

plt.figure()
ax = plt.gca()
cont = plt.contourf(xx, yy, zz, 50)

# add the patch to the axes
ax.add_patch(patch)  ## TRY COMMENTING THIS OUT
for col in cont.collections:
    col.set_clip_path(patch)

plt.show()

结果图

我对一个方面有点困惑:如果我把绘制补丁的那一行注释掉,那么裁剪就不起作用,最后得到的图就是一片空白。我猜想在PathCollection上调用set_clip_path方法时,补丁必须已经被添加到坐标轴上,但我不明白为什么会这样。虽然在创建补丁时设置edgecolor='none'是个不错的解决办法,但这样做有什么意思呢?

大家有什么想法吗?

1 个回答

8

如果这个补丁没有被添加到坐标轴上,它就不知道应该按照哪个转换来处理。通过把它添加到坐标轴上,你实际上是把这个补丁的转换设置为你添加它的那个坐标轴的数据转换。
我想如果你想象一下在一个图形上有多个坐标轴,这个需求就会变得清晰了。这样的话,mpatches.PathPatch 可能会被用在任何一个坐标轴上。

你确实可以通过把补丁的填充颜色和边框颜色设置为 "none" 来让它变得不可见。

patch = mpatches.PathPatch(path, facecolor='none', edgecolor='none')

或者完全让它不可见,

patch = mpatches.PathPatch(path, visible=False)

如果你真的想避免把补丁添加到坐标轴上,你可以手动设置所需的转换。

patch = mpatches.PathPatch(path, transform=ax.transData)

for col in cont.collections:
    col.set_clip_path(patch)

在这种情况下,就不需要把它添加到坐标轴上了。

撰写回答