我正在使用matplotlib.patheffects
使用虚线绘制路径。我的目标是将每条路径划分为沿路径均匀间隔的N个段。由于破折号需要以像素长度指定而不是数据坐标,我使用的是ax.transData.transform_point()
,而且我在大多数情况下都能使用,但是在需要缩小图形的情况下,破折号不适当地扩展。
以下是演示此问题的代码示例:
import sys
import matplotlib.pyplot as plt
import matplotlib.patheffects as PathEffects
from matplotlib.patches import PathPatch
from matplotlib.path import Path
import numpy as np
MIN=1 if len(sys.argv) <= 1 else int(sys.argv[1])
MAX=MIN if len(sys.argv) <=2 else int(sys.argv[2])
SCALE=4 if len(sys.argv) <=3 else int(sys.argv[3])
COUNT=MAX-MIN+1
fig = plt.figure(1, figsize=(COUNT*SCALE,SCALE))
for i in range(MIN, MAX+1):
ax = plt.subplot(1, COUNT, i-MIN+1)
ax.set_xlim(0, i)
ax.set_ylim(0, i)
path = Path([(0,0), (0,i) ,(i,i)], [Path.MOVETO, Path.CURVE3, Path.CURVE3])
pp = PathPatch(path, fill=False)
def path_length(path):
QI_SAMPLES=1000
v = path.vertices
v = [ax.transData.transform_point(p) for p in v ]
if len(v) > 2:
v = [ quad_interpolate( i/(1.0 * QI_SAMPLES), v[0], v[1], v[2])
for i in range(0, QI_SAMPLES)]
dv = np.diff(v, axis=0)
return np.sum(np.sqrt(np.sum(dv**2, axis=-1)))
def quad_interpolate(i, A, B, C):
(ax, ay) = A
(bx, by) = B
(cx, cy) = C
ii = 1.-i
i2 = i*i
ii2 = ii*ii
rx = ax*ii2 + 2*bx*ii*i + cx*i2
ry = ay*ii2 + 2*by*ii*i + cy*i2
return (rx, ry)
ax.add_patch(pp)
length = path_length(path)
dash_length = length/(2*i)
space_length = length/(2*i)
offset=-(space_length/2)
pe = [PathEffects.withStroke(linewidth=3,
dashes=[offset, (dash_length, space_length)],
foreground="b")]
pp.set_path_effects(pe)
plt.show()
命令行参数是(最小段)(最大段)(子图刻度)。您可能必须使用不同的命令行参数运行它以根据您的显示大小触发问题 - 在我的系统上,使用“1 8 3”运行显示:
以“1 8 4”运行时显示:
正如你所看到的,第二个情节并不完全正确 - 第八个情节只有七个破折号,而其他情节也有点破灭。
我怎样才能使短划线长度可靠地转换到底层轴的坐标空间而不管刻度?或者是否有其他方法可以沿路径获取虚线,而不依赖于以像素长度指定它们?
更新:以下是绘制线条而不是曲线的内容。好:
为:
正如评论中指出的那样,即使是“好”的情节也略显偏离,因为子图不是很正方形。但是ax.transData.transform_point
变换不应该解决这个问题吗?