我正在使用路径使用matplotlib包为图定义自定义标记。另外,我需要能够旋转标记以显示方向。
我跟随this example,并且标记旋转。但是,根据角度,标记的大小会发生变化。
这是我正在使用的代码:
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()
用注释掉的行将路径转换为补丁(顺便说一句,如果有人愿意解释什么是补丁与路径,我将不胜感激),以表明基础路径上的转换效果很好,只是扭曲了绘制时的大小。
这是当前程序的输出:
谢谢!
答案 0 :(得分:3)
问题在于,将作为标记输入的Path
标准化为框(-0.5, 0.5)x(-0.5, 0.5)
。这通常很有用,因为它允许插入任意缩放的路径,并且仍然可以输出相同大小的标记。
但是,在这种情况下,它将导致三角形的尖端共享相同的y 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()
与此无关,该问题还询问Patch
与Path
是什么。
Path
是存储顶点及其相应属性的对象。它的主要目的(比起具有两个列表或坐标的简单容器)使它更有用,它具有计算点之间贝塞尔曲线的方法。但是,路径本身不能添加到图形中。
Patch
是matplotlib艺术家,即可以在matplotlib图形中绘制的对象。 Matplotlib提供了一些有用的补丁,例如箭头,矩形,圆形等。PathPatch
就是这样的补丁,可创建Path
的可视化效果。因此,这是在图中绘制路径的最明显方法。