Я хотел бы создать matplotlib.patches.PathPatch
подобный патч с шириной линии, указанной в единицах данных (не точках).
Я знаю, что для патчей с правильной формой, такой объект можно имитировать c, рисуя два фрагмента разных размеров друг на друге. Тем не менее, этот подход становится намного более вычислительно сложным для произвольных фигур (необходимо вычислить параллельную линию для произвольной формы). Кроме того, я хотел бы сохранить методы объекта PathPath
, поэтому в конечном итоге я ищу класс, производный от PathPatch
или Patch
.
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch, Rectangle
fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)
origin = (0, 0)
width = 1
height = 2
lw = 0.25
outer = Rectangle((origin[0], origin[1]), width, height, facecolor='darkblue', zorder=1)
inner = Rectangle((origin[0]+lw, origin[1]+lw), width-2*lw, height-2*lw, facecolor='lightblue', zorder=2)
ax1.add_patch(outer)
ax1.add_patch(inner)
ax1.axis([-0.5, 1.5, -0.5, 2.5])
ax1.set_title('Desired')
path = outer.get_path().transformed(outer.get_patch_transform())
pathpatch = PathPatch(path, facecolor='lightblue', edgecolor='darkblue', linewidth=lw)
ax2.add_patch(pathpatch)
ax2.set_title('Actual')
plt.show()
Существует другой пост SO , производный от Line2D
для создания строки с ширинами в единицах данных.
class LineDataUnits(Line2D):
# https://stackoverflow.com/a/42972469/2912349
def __init__(self, *args, **kwargs):
_lw_data = kwargs.pop("linewidth", 1)
super().__init__(*args, **kwargs)
self._lw_data = _lw_data
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
_linewidth = property(_get_lw, _set_lw)
Я не совсем понимаю, как эта реализация работает (например, никакие методы Line2D
не кажутся перезаписанными) Тем не менее, я попытался скопировать этот подход (class LineDataUnits(Line2D)
-> class PathPatchDataUnits(PathPatch)
), но - что неудивительно - не могу заставить его работать (AttributeError: 'NoneType' object has no attribute 'set_figure'
).