如何使用 matplotlib 在形状上画一个洞

How to draw a hole on shape with matplolib

我用 imshow 画了一个实心圆 plt.circle :

sun_back = ax.imshow(np.linspace(0, 1, 100).reshape(-1, 1), cmap='plasma', vmin=0, vmax=100, 
                     extent=[..., ..., ..., ...])

sun_back.set_clip_path(plt.Circle((0, 10), 20, transform=ax.transData))

然后我知道如何在上面画一条线,但我不想要实线,我想在这个圆上打一个洞,但我不知道如何用一个形状“钻”两个 zorder。

与图片不同,我希望黑条与背景颜色相同,但是这个是动态的,所以我不能用代码改变颜色。它需要是透明的。

谢谢

matplotlib中只能创建多个路径的union但是这里需要圆形和矩形的区别。因此,除非您想自己进行数学运算,否则我建议您使用 shapely 来计算剪辑对象之间的差异。 difference 给你一个多边形:

cp_shape = circle.difference(rect1).difference(rect2).difference(rect3) 

然后您可以将该多边形的所有多边形的外部转换为路径,并使用 make_compound_path 将它们组合成一个剪辑路径:

clip_path = mp.Path.make_compound_path(*[mp.Path(np.array(p.exterior.xy).T) for p in cp_shape])

示例:

import matplotlib.pyplot as plt
import matplotlib.path as mp
import numpy as np
import shapely.geometry as sg

fig,ax = plt.subplots()
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
ax.patch.set_color('r')
sun_back = ax.imshow(np.broadcast_to(np.linspace(100, 0, 100), (100, 100)).T, 
                     cmap='plasma',
                     extent=[0,200,0,200]
                     )

circle = sg.Point(100,100).buffer(70)
rect1 = sg.box(30,50,170,58)
rect2 = sg.box(30,65,170,70)
rect3 = sg.box(30,75,170,78)
cp_shape = circle.difference(rect1).difference(rect2).difference(rect3)
clip_path = mp.Path.make_compound_path(*[mp.Path(np.array(p.exterior.xy).T) for p in cp_shape])

sun_back.set_clip_path(clip_path, transform=ax.transData)