可以在matplotlib中使用自定义箭头或多边形作为标记绘制位置和方向吗?

1 投票
1 回答
809 浏览
提问于 2025-04-17 21:01

我有一系列飞机的x,y坐标和对应的航向角。我可以绘制出它们飞行的路径,现在我想用一个特殊的标记来标记路径上的某个特定位置,同时显示飞机在那个位置时的航向。

我使用了matplotlib.pyplot中的一个没有底座的箭头来实现这个目的,但在绘制多架飞机时,由于需要定义箭头的头部和尾部位置,导致箭头的长度不一致。我还尝试了一个自定义的三边形符号,使用了元组(numsides, style, angle),以及楔形和大V形符号,但效果都不是很好。

这个链接中,Saullo Castro展示了一个不错的自定义箭头(arrow1),我在想是否可以用它,或者将其转换成一种方式,简单地在给定的x,y位置绘制,并让它的方向由航向角来定义。

我可以用以下代码绘制这个自定义箭头。有没有什么想法可以让它旋转以反映航向呢?

a1 = np.array([[0,0],[0,1],[-1,2],[3,0],[-1,-2],[0,-1],[0,0]], dtype=float)
polB = patches.Polygon(a1, closed=True, facecolor='grey')
ax.add_patch(polB)

提前谢谢你。

1 个回答

1

我把多边形简化了一下,发现可以用mpl.transforms.Affine2D().rotate_deg_around()来实现旋转:

    a2 = np.array([[newX,newY+2],[newX+1,newY-1],[newX,newY],[newX-1,newY-1],[newX,newY+2]], dtype=float)
    polB = patches.Polygon(a2, closed=True, facecolor='gold')
    t2 = mpl.transforms.Affine2D().rotate_deg_around(newX,newY,heading) + newax.transData
    polB.set_transform(t2)
    newax.add_patch(polB)

我最开始尝试把多边形叠加在一个由x和y坐标绘制的线条上。但是,x轴和y轴的比例不一样(我也不想让它们一样),所以当我旋转多边形时,它看起来就变得扭曲和拉伸了。为了解决这个问题,我先添加了一个新的坐标轴,使得x和y的比例相等:

    newax = fig.add_axes(ax.get_position(), frameon=False)
    newax.set_xlim(-20,20)
    newax.set_ylim(-20,20) 

这样我就可以随意旋转,而不会出现扭曲的问题。不过,我还需要想办法把这两个坐标轴连接起来,这样我才能在新的坐标轴上绘制多边形,并且这个位置是参考原始坐标轴的。我想到的办法是使用变换,把原始坐标轴上的数据坐标转换为显示坐标,然后再把它们反转回数据坐标,不过这次是在新的坐标轴上的数据坐标:

    inTrans = ax.transData.transform((x, y))
    inv = newax.transData.inverted()
    newTrans = inv.transform((inTrans[0], inTrans[1]))
    newX = newTrans[0]
    newY = newTrans[1]

这样做感觉有点像是一个复杂的鲁布·戈德堡机器,但最终达到了我想要的效果。

最后,我决定不喜欢这种方法,选择了更简单的做法,使用一个花哨的箭头代替多边形。生活就是这样……

撰写回答