CTHREEPO
CTHREEPO

Reputation: 37

Arrow pointing to a point on a curve

I am trying to plot arrows pointing at a point on a curve in python using matplotlib.

On this line i need to point vertical arrows at specific points. This is for indicating forces acting on a beam, so their direction is very important. Where the curve is the beam and the arrow is the force.

I know the coordinate of said point, exactly, but it is of cause changing with the input. This input should also dictate whether the arrow points upwards or downwards from the line. (negative and positive forces applied). I have tried endlessly with plt.arrow, but because the scale changes drastically and so does the quadrant in which the arrow has to be. So it might have to start at y < 0 and end in a point where y > 0. The problem is that the arrowhead length then points the wrong way like this --<. instead of -->.

So before I go bald because of this, I would like to know if there is an easy way to apply a vertical arrow (could be infinite in the opposite direction for all i care) pointing to a point on a curve, of which I can control whether it point upwards to the curve, or downwards to the curve.

Upvotes: 3

Views: 2497

Answers (2)

Paulina
Paulina

Reputation: 1

The inverted arrowhead is due to a negative sign of the head_length variable. Probably you are scaling it using a negative value. Using head_length= abs(value)*somethingelse should take care of your problem.

Upvotes: 0

xnx
xnx

Reputation: 25528

I'm not sure I completely follow you, but my approach would be to use annotate rather than arrow (just leave the text field blank). You can specify one end of the arrow in data coordinates and the other in offset pixels: but you do have to map your forces (indicating the length of the arrows) to number of pixels. For example:

import matplotlib.pyplot as plt
import numpy as np

# Trial function for adding vertical arrows to
def f(x):
    return np.sin(2*x)

x = np.linspace(0,10,1000)
y = f(x)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y, 'k', lw=2)
ax.set_ylim(-3,3)

def add_force(F, x1):
    """Add a vertical force arrow F pixels long at x1 (in data coordinates)."""
    ax.annotate('', xy=(x1, f(x1)), xytext=(0, F), textcoords='offset points',
                arrowprops=dict(arrowstyle='<|-', color='r'))

add_force(60, 4.5)
add_force(-45, 6.5)

plt.show()

enter image description here

Upvotes: 3

Related Questions