Matplotlib 线段宽度的右对齐

Matplotlib 中Text有horizontalAlignment 和 verticalAlignment属性对应文字的水平对齐和垂直对齐方式,但是对于线段(plot),找遍全网却没有找到令线段宽度根据中法线左右对齐的解决方法。

好在通过查阅Matplotlib的Transformations教程,找到了使用ScaledTranslation另线段偏移(offset)的方法(https://matplotlib.org/3.2.2/tutorials/advanced/transforms_tutorial.html#using-offset-transforms-to-create-a-shadow-effect)。

通过简单的三角计算可以实现目标(图1)。

图1

直接上代码:

def segmentOffset(fig, x, y, linewidth, lr="left"):
    import numpy as np
    import matplotlib.transforms as transforms

    r = {"left": (-1, 1), "right": (1, -1)}[lr]
    delta = np.squeeze(np.diff([x, y]))
    del_p = np.hypot(*delta)
    dpi_scale = np.diag(fig.dpi_scale_trans.get_matrix())
    dx, dy = delta[::-1] * linewidth / dpi_scale[:2] / del_p / 2.0 * r
    offset = transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
    return offset

示例和图

fig, ax = plt.subplots(figsize=(5, 5))
x = [1, 4]
y = [1, 5]
plt.axis("equal")
lw = 10
ax.plot(x, y, color="k", ls=":", lw=2)
ax.plot(x, y, color="g", lw=lw, alpha=0.5, label="origin")
ax.plot(
    x,
    y,
    color="r",
    lw=lw,
    alpha=0.5,
    label="offset_left",
    transform=ax.transData + segmentOffset(fig, x, y, lw, lr="left"),
)
ax.legend()
图2

为什么要弄这个,因为之前在描最大风暴潮沿岸分布的时候,内部线的线宽在拐角地形处会盖过外边的线段。图3,图4

图3 线宽10,中对齐
图4 线宽5,右对齐(left offset),空白是因为网格边界和实际大陆边界有点差异。

还是有瑕疵但这也算性价比较高的解决方案了。

《Matplotlib 线段宽度的右对齐》上有1条评论

发表评论

电子邮件地址不会被公开。