pyplot: Dotted line with FancyArrowPatch

后端 未结 2 1419
孤城傲影
孤城傲影 2020-12-18 11:34

I am using python and matplotlib.pyplot to generate a complex graphical output. I\'d like to use a dotted linestyle in conjunction wit

相关标签:
2条回答
  • 2020-12-18 12:04

    An alternative implementation is to split the arrow into two parts:

    • arrow shaft (dotted line)
    • arrow head (not dotted)

    I used this workaround to draw a dotted line phasor.

    0 讨论(0)
  • 2020-12-18 12:21

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

    0 讨论(0)
提交回复
热议问题