在matplotlib

时间:2018-11-09 13:54:49

标签: python matplotlib

我正在使用路径使用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()

用注释掉的行将路径转换为补丁(顺便说一句,如果有人愿意解释什么是补丁与路径,我将不胜感激),以表明基础路径上的转换效果很好,只是扭曲了绘制时的大小。

这是当前程序的输出:

link to imgur

谢谢!

1 个答案:

答案 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()

enter image description here


与此无关,该问题还询问PatchPath是什么。 Path是存储顶点及其相应属性的对象。它的主要目的(比起具有两个列表或坐标的简单容器)使它更有用,它具有计算点之间贝塞尔曲线的方法。但是,路径本身不能添加到图形中。

Patch是matplotlib艺术家,即可以在matplotlib图形中绘制的对象。 Matplotlib提供了一些有用的补丁,例如箭头,矩形,圆形等。PathPatch就是这样的补丁,可创建Path的可视化效果。因此,这是在图中绘制路径的最明显方法。