matplotlib 如何在数据单位中创建具有虚线间距和宽度的线条?

pftdvrlh  于 2023-03-03  发布在  其他
关注(0)|答案(1)|浏览(133)

我尝试将matplotlib.lines.Line2D子类化,创建宽度和虚线间距与绘制数据坐标相同的线,我对this answer进行了扩展,尝试支持虚线(虚线间距也是数据单位),目前代码如下:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

class LineDataUnits(Line2D):
    """
    A Line2D object, but with the linewidth and dash properties defined in data coordinates.
    """
    def __init__(self, *args, **kwargs):
        _lw_data = kwargs.pop("linewidth", 1)
        _dashes_data = kwargs.pop("dashes", (1,))
        super().__init__(*args, **kwargs)
        self._lw_data = _lw_data
        self._dashes_data = _dashes_data
        self._dashOffset = 0

    def _get_lw(self):
        if self.axes is not None:
            ppd = 72./self.axes.figure.dpi
            trans = self.axes.transData.transform
            return ((trans((1, self._lw_data))-trans((0, 0)))*ppd)[1]
        else:
            return 1

    def _set_lw(self, lw):
        self._lw_data = lw

    def _get_dashes(self):
        if self.axes is not None:
            ppd = 72./self.axes.figure.dpi
            trans = self.axes.transData.transform
            return tuple([((trans((1, dash_data))-trans((0, 0)))*ppd)[1] for dash_data in self._dashes_data])
        else:
            return tuple((1, 0))

    def _set_dashes(self, dashes):
        self._dashes_data = dashes

    _linewidth = property(_get_lw, _set_lw)
    _dashSeq = property(_get_dashes, _set_dashes)

if __name__ == "__main__":
    fig, ax = plt.subplots()
    line1 = Line2D([0, 10], [3, 3], linewidth=10, color="blue", dashes=(3, 3), dash_capstyle="round")
    line2 = LineDataUnits([0, 10], [6, 6], linewidth=0.5, color="red", dashes=(1, 1), dash_capstyle="round")
    print("dash_capstyle:", line2.get_dash_capstyle())
    ax.add_line(line1)
    ax.add_line(line2)
    ax.set_xticks(range(10))
    ax.grid()
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    plt.show()

生成以下图形:

当我放大和缩小时,虚线间距在数据单元中似乎保持不变,但是如图所示,它们的值计算不正确。此外,在该类中设置dash_capstyle参数似乎没有效果。
任何帮助都将不胜感激。

9vw9lbht

9vw9lbht1#

经过更多的试验,我设法让它正常工作。首先,即使用虚线绘制线,Line2D仍然将其_linestyle参数设置为“-”(实线),这导致cap style参数被忽略。其次,在从数据单位到点的转换中出现了一个错误。通过以下更改,它现在工作得很好。

# in __init__()
    super().__init__(*args, **kwargs):
+   self.set_linestyle("--")
    self._lw_data = _lw_data

# in _get_dashes()
-   return tuple([((trans((1, dash_data))-trans((0, 0)))*ppd)[1] for dash_data in self._dashes_data])
+   dpu = (trans((1, 1)) - trans((0, 0)))[0]
+   return tuple([u*dpu*ppd for u in self._dashes_data])

相关问题