matplotlib:绘制看起来像 pyplot.arrow 的弯曲箭头? [英] matplotlib: Draw curved arrow that looks just like pyplot.arrow?

查看:73
本文介绍了matplotlib:绘制看起来像 pyplot.arrow 的弯曲箭头?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 pyplot.arrow 做一些直线箭头,例如,

I use pyplot.arrow do draw some straight arrows, e.g.,

import matplotlib.pyplot as plt
import numpy as np

v={}
for i in range (1,4):
    v[i]=np.array([np.cos(-2*np.pi/3*i),np.sin(-2*np.pi/3*i)])

plt.arrow(.85*(.05*v[2]+.95*v[1])[0],.85*(.05*v[2]+.95*v[1])[1],.85*.9*(v[2]-v[1])[0],.85*.9*(v[2]-v[1])[1],width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")
plt.arrow(.85*(.05*v[3]+.95*v[2])[0],.85*(.05*v[3]+.95*v[2])[1],.85*.9*(v[3]-v[2])[0],.85*.9*(v[3]-v[2])[1],width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")
plt.arrow(.85*(.05*v[1]+.95*v[3])[0],.85*(.05*v[1]+.95*v[3])[1],.85*.9*(v[1]-v[3])[0],.85*.9*(v[1]-v[3])[1],width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")

plt.axes().set_xlim(-.5,1)
plt.axes().set_ylim(-np.sqrt(3)/2,np.sqrt(3)/2)
plt.axes().set_aspect(1)
plt.show()

现在我还想绘制一些具有圆形曲率而不是直线的箭头.我看到我可以使用 connectionstyle ="arc3,rad = .5" pyplot.annotate() patches.FancyArrowPatch 实现此目标,或者所以.

Now I want to also draw some arrows that have circular curvature instead of being straight. I see that I can achieve this with pyplot.annotate() or patches.FancyArrowPatch with connectionstyle="arc3,rad=.5" or so.

但是这些箭头看起来与 pyplot.arrow 完全不同,并且不适合我的其他图形.而且我不知道如何将 connectionstyle 之类的东西传递给 pyplot.arrow.有没有办法绘制与我从 pyplot.arrow 得到的箭头完全一样的弯曲箭头?

But these arrows look completely different from the pyplot.arrows and do not fit with the rest of my figures. And I don't know how I could pass something like connectionstyle to pyplot.arrow. Is there a way to draw curved arrows that look exactly like those that I get from pyplot.arrow?

推荐答案

这就是我最终使用的内容;这有点骇人听闻,只是在 Arc 的末端绘制了直的 arrow 头:

Here's what I ended up using; it's a bit of a hack and just draws straight arrow heads at the ends of an Arc:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Arc
def circarrow(self,diameter,centX,centY,startangle,angle,**kwargs):
    startarrow=kwargs.pop("startarrow",False)
    endarrow=kwargs.pop("endarrow",False)

    arc = Arc([centX,centY],diameter,diameter,angle=startangle,
          theta1=np.rad2deg(kwargs.get("head_length",1.5*3*.001)) if startarrow else 0,theta2=angle-(np.rad2deg(kwargs.get("head_length",1.5*3*.001)) if endarrow else 0),linestyle="-",color=kwargs.get("color","black"))
    self.axes().add_patch(arc)

    if startarrow:
        startX=diameter/2*np.cos(np.radians(startangle))
        startY=diameter/2*np.sin(np.radians(startangle))
        startDX=+.000001*diameter/2*np.sin(np.radians(startangle)+kwargs.get("head_length",1.5*3*.001))
        startDY=-.000001*diameter/2*np.cos(np.radians(startangle)+kwargs.get("head_length",1.5*3*.001))
        self.arrow(startX-startDX,startY-startDY,startDX,startDY,**kwargs)

    if endarrow:
        endX=diameter/2*np.cos(np.radians(startangle+angle))
        endY=diameter/2*np.sin(np.radians(startangle+angle))
        endDX=-.000001*diameter/2*np.sin(np.radians(startangle+angle)-kwargs.get("head_length",1.5*3*.001))
        endDY=+.000001*diameter/2*np.cos(np.radians(startangle+angle)-kwargs.get("head_length",1.5*3*.001))
        self.arrow(endX-endDX,endY-endDY,endDX,endDY,**kwargs)

import types
plt.circarrow = types.MethodType(circarrow,plt)

该函数被称为circarrow,并且作为参数传递直径、中心的两个坐标、弧开始的角度以及弧应该通过的总角度作为传递给 pyplot arrow 的任何参数.要在弧的开始处绘制箭头,请指定 startarrow = True ,而 endarrow = True 将在弧的末尾启用箭头.

The function is called circarrow, and as arguments you pass the diameter, the two coordinates of the center, the angle at which the arc starts and the total angle the arc should pass over, as well as any parameters that are passed to pyplot arrow. To draw an arrowhead at the beginning of the arc you specify startarrow=True, while endarrow=True will enable an arrowhead at the end of the arc.

这是一个示例图片,您还可以看到箭头样式与直箭头一致:

Here's an example image, where you can also see that the arrow style is consistent with the straight arrows:

plt.plot(0,0,"o",markersize=10,color="black",mfc="none")

plt.circarrow(.85,0,0,0.05*120,.9*120,startarrow=True,width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")
plt.circarrow(.85,0,0,1.05*120,.9*120,startarrow=True,endarrow=True,width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")
plt.arrow(-.2,-.33,.6,+.33,width=0,head_width=.03,head_length=.045,length_includes_head=True,color="black")

plt.axes().set_xlim(-.5,.5)
plt.axes().set_ylim(-.5,.5)
plt.axes().set_aspect(1)
plt.show()

示例图片

这篇关于matplotlib:绘制看起来像 pyplot.arrow 的弯曲箭头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆