Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
612 views
in Technique[技术] by (71.8m points)

python - pyplot: Dotted line with FancyArrowPatch

I am using python and matplotlib.pyplot to generate a complex graphical output. I'd like to use a dotted linestyle in conjunction with FancyArrowPatch but failed to do so.

MWE:

import matplotlib.pyplot as plt
import matplotlib.patches as patches

style="Simple,head_width=4,head_length=8"
linestyle="dotted" # or "solid"
kw = dict(arrowstyle=style, linestyle=linestyle, color="b", connectionstyle="arc3,rad=1")
plt.gca().add_patch(patches.FancyArrowPatch((0,1), (1,1), **kw))
plt.savefig("MWE.pdf")

This generates the following image:

Zoom of MWE.pdf

However, I'd like to get something like:

GIMPed version using linestyle solid

Question: What do I have to change in my MWE to get the lower image?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As said in the comments, I doubt that it is possible, to easily change the linestyle of the FancyArrowPatch. This is really a patch in the sense of a polygon, consisting of 13 points which are connected by lines. If changing the linestyle you cannot change it for only part of the patch.

An option might indeed to split the patch into the arrow head and the tail. For the tail you would only take part of it and create a new line along those points. This line can be given its own linestyle. The head may stay a filled patch, for which you may choose a different linestyle.

You may get the path of the original arrow by arrow.get_path(). Note that this will fix the coordinates, i.e. all transforms of the arrow will be lost. Hence you need to make sure to do this only once the final axes limits and figure size have been set, and that if changing any of them later on will squeeze the arrow in an undesired manner.

import matplotlib.pyplot as plt
import matplotlib.path
import matplotlib.patches as patches


style="Simple,head_width=40,head_length=80"
kw = dict(arrowstyle=style, linestyle=None, lw=1,color="b",connectionstyle="arc3,rad=0.2")
arrow = patches.FancyArrowPatch((0,1), (1,1), **kw)

plt.gca().add_patch(arrow)
plt.gca().axis([0,1.03,0,1.1])

def split_arrow(arrow, color_tail="C0",color_head="C0", 
                ls_tail="-", ls_head="-",lw_tail=1.5, lw_head=1.5):    
    v1 = arrow.get_path().vertices[0:3,:]
    c1 = arrow.get_path().codes[0:3]
    p1 = matplotlib.path.Path(v1,c1)
    pp1 = patches.PathPatch(p1, color=color_tail, linestyle=ls_tail, 
                            fill=False, lw=lw_tail)
    arrow.axes.add_patch(pp1)

    v2 = arrow.get_path().vertices[3:8,:]
    c2 = arrow.get_path().codes[3:8]
    c2[0] = 1
    p2 = matplotlib.path.Path(v2,c2)
    pp2 = patches.PathPatch(p2, color=color_head, lw=lw_head, linestyle=ls_head)
    arrow.axes.add_patch(pp2)
    arrow.remove()

split_arrow(arrow, color_tail="crimson",color_head="limegreen", 
                ls_tail="--", lw_tail=3)

plt.show()

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...