matplotlib:绘制看起来像 pyplot.arrow 的弯曲箭头? [英] matplotlib: Draw curved arrow that looks just like 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.arrow
s 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屋!