据我所知,在matplotlib中无法做到这一点,因为行的笔划宽度不能直接与数据坐标相关联. (正如您所提到的,您可以将回调连接到绘制事件并完成此操作.但是,这会导致很大的性能损失.)
但是,一个快速的解决方法是通过缓冲街道路径使用匀称来生成多边形.
作为一个简单的例子:
import shapely.geometry
import descartes
import matplotlib.pyplot as plt
lines = ([(0, 0), (1, 0), (0, 1)],
[(0, 0), (1, 1)],
[(0.5, 0.5), (1, 0.5)],
)
lines = shapely.geometry.MultiLineString(lines)
# "0.05" is the _radius_ in data coords, so the width will be 0.1 units.
poly = lines.buffer(0.05)
fig, ax = plt.subplots()
patch = descartes.PolygonPatch(poly, fc='gray', ec='black')
ax.add_artist(patch)
# Rescale things to leave a bit of room around the edges...
ax.margins(0.1)
plt.show()
如果您确实想要采用回调路由,可以执行以下操作:
import matplotlib.pyplot as plt
def main():
lines = ([(0, 0), (1, 0), (0, 1)],
[(0, 0), (1, 1)],
[(0.5, 0.5), (1, 0.5)],
)
fig, ax = plt.subplots()
artists = []
for verts in lines:
x, y = zip(*verts)
line, = ax.plot(x, y)
artists.append(line)
scalar = StrokeScalar(artists, 0.1)
ax.callbacks.connect('xlim_changed', scalar)
ax.callbacks.connect('ylim_changed', scalar)
# Rescale things to leave a bit of room around the edges...
ax.margins(0.05)
plt.show()
class StrokeScalar(object):
def __init__(self, artists, width):
self.width = width
self.artists = artists
# Assume there's only one axes and one figure, for the moment...
self.ax = artists[0].axes
self.fig = self.ax.figure
def __call__(self, event):
"""Intended to be connected to a draw event callback."""
for artist in self.artists:
artist.set_linewidth(self.stroke_width)
@property
def stroke_width(self):
positions = [[0, 0], [self.width, self.width]]
to_inches = self.fig.dpi_scale_trans.inverted().transform
pixels = self.ax.transData.transform(positions)
points = to_inches(pixels) * 72
return points.ptp(axis=0).mean() # Not quite correct...
main()