Искажение размера при вращении (пользовательский путь) маркера в matplotlib - PullRequest
0 голосов
/ 09 ноября 2018

Я использую путь для определения пользовательского маркера для графика, используя пакет matplotlib. Кроме того, мне нужно иметь возможность вращать маркер, чтобы показать направление.

Я следовал этому примеру , и маркер вращается. Однако в зависимости от угла размер маркера меняется.

Вот код, который я использую:

import matplotlib.pyplot as plt

from matplotlib.path import Path
from matplotlib import transforms
import matplotlib.patches as patches

fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1)

ax.set_xlim(-10, 10)
ax.set_ylim(-4, 4)

colors = ax.set_prop_cycle(color = ['#993F00', '#0075DC'])

triangle = Path([[-1.,-1.], [1., -1.], [0., 2.], [0.,0.],], [Path.MOVETO, Path.LINETO, Path.LINETO, 
    Path.CLOSEPOLY,])

print("First Triangle:", triangle, type(triangle))
#patch1 = patches.PathPatch(triangle, facecolor='orange', lw=2)
line1, = ax.plot(0, 0, marker=triangle, markersize=50, alpha=0.5)

R = transforms.Affine2D().rotate_deg(45)

triangle = triangle.transformed(R)
#patch2 = patches.PathPatch(triangle, facecolor='blue', lw=2)
line2, = ax.plot(0, 0, marker=triangle, markersize=50, alpha=0.5)

print("\n transform R", R)
print("\ntriangle after transform", triangle, type(triangle))

#ax.add_patch(patch1)
#ax.add_patch(patch2)

plt.show()

Закомментированные строки преобразуют путь в патчи (кстати, если кто-то захочет объяснить, что такое патч против пути, я был бы благодарен), чтобы показать, что преобразование на базовом пути работает нормально, оно просто деформируется размер, когда вы строите его.

Это вывод текущей программы:

link to imgur

Спасибо!

1 Ответ

0 голосов
/ 10 ноября 2018

Проблема в том, что Path, который берется в качестве ввода для маркера, нормализуется в поле (-0.5, 0.5)x(-0.5, 0.5).Это часто полезно, потому что позволяет подключать произвольно масштабированные пути и по-прежнему выводить маркеры одинакового размера.
Однако в этом случае концы треугольников будут иметь один и тот же coodinate (оба раза y = 0,5).в предварительно преобразованной системе).

Единственное решение, которое я могу найти, - это создать подкласс matplotlib.markers.MarkerStyle и заменить метод масштабирования на метод, который не изменяет путь.

Теперь проблема в том, что plot в настоящее время не принимает MarkerStyle экземпляров в качестве входных данных для своего аргумента marker.Следовательно, приведенное ниже решение работает только для scatter.

import matplotlib.pyplot as plt
from matplotlib.path import Path
from matplotlib import transforms
from matplotlib.markers import MarkerStyle

class UnsizedMarker(MarkerStyle):
    def _set_custom_marker(self, path):
        self._transform = transforms.IdentityTransform()
        self._path = path


fig = plt.figure(figsize=(10, 5))
ax = fig.add_subplot(1, 1, 1)

ax.set_xlim(-10, 10)
ax.set_ylim(-4, 4)

colors = ax.set_prop_cycle(color = ['#993F00', '#0075DC'])

triangle1 = Path([[-1.,-1.], [1., -1.], [0., 2.], [0.,0.],], 
                [Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY,])


m1 = UnsizedMarker(triangle1)
line1 = ax.scatter(0, 0, marker=m1, s=50**2, alpha=0.5)

R = transforms.Affine2D().rotate_deg(45)
triangle2 = triangle1.transformed(R)
m2 = UnsizedMarker(triangle2)
line2 = ax.scatter(0, 0, marker=m2, s=50**2, alpha=0.5)


plt.show()

enter image description here


Вне зависимости от этого, вопрос также состоит в том, чем является Patch против Path.Path - это объект, который хранит вершины и их соответствующие свойства.Его главная цель, которая делает это более полезным, чем простой контейнер из двух списков или координат, состоит в том, что у него есть методы для вычисления кривых Безье между точками.Однако сам путь не может быть добавлен к фигуре.

A Patch - художник matplotlib, то есть объект, который можно нарисовать на рисунке matplotlib.Matplotlib предоставляет несколько полезных патчей, таких как стрелки, прямоугольники, круги и т. Д. PathPatch - это такой патч, который создает визуализацию Path.Следовательно, это самый очевидный способ нарисовать путь на фигуре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...