1

I have a series of x,y coordinates and associated heading angles for multiple aircraft. I can plot the paths flown, and I would like to use a special marker to mark a particular location along the path that also shows the aircraft's heading when it was at that location.

Using matplotlib.pyplot I've used an arrowhead with no base to do this, but having to define the head and tail locations ended up with inconsistent arrowhead lengths when plotting multiple aircraft. I also used a custom three-sided symbol with the tuple (numsides, style, angle) as well as the wedge and bigvee symbols, but they never look very good.

From Custom arrow style for matplotlib, pyplot.annotate Saullo Castro showed a nice custom arrow (arrow1) that I'm wondering whether it can be used or converted in such a way as to just simply plot it at a given x,y and have its orientation defined by a heading angle.

I can plot the custom arrow with the following. Any ideas on how to rotate it to reflect a heading?

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)

Thanks in advance.

1 Answers1

1

So I made the polygon a little simpler and also found that the rotation could be done by using 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)

I first tried to overlay the polygon on a line plotted from the x,y coordinates. However, the scales of the x and y axes were not equal (nor did I want them to be), so the polygon ended up looking all warped and stretched when rotated. I got around this by first adding a new axis with equal x/y scaling:

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

I could at least then rotate all I wanted and not have the warp issue. But then I needed to figure out how to basically connect the two axes so that I could plot the polygon on the new axis at a point referenced from the original axis. The way I figured to do this was by using transformations to go from the data coordinates on the original axis, converting them to display coordinates, and then inverting them back to data coordinates except this time at the data coordinates on the new axis:

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

It felt a little like some sort of Rube Goldberg machine to do it this way, but it did what I wanted.

In the end, I decided I didn't like this approach and went with keeping it simpler and using a fancy arrowhead instead of a polygon. Such is life...