0

I would like to plot three vectors, b, d, and d-b. Of course, this means that the tail of d-b touches the head of b. I'm using this SO to plot arrows. However, I clearly don't understand the API, since the figure I get is baffling. The arrows look roughly like they're in the right directions, but the magnitudes are way off. Not sure what I'm doing wrong here.

enter image description here

import numpy as np
import matplotlib.pyplot as plt


b = np.array([4, 1])
d = np.array([-3, 3])
m = d-b

o = np.array([
    [0, 0, b[0]],
    [0, 0, b[1]]
])
v = np.array([
    [b[0], b[1]],
    [d[0], d[1]],
    [m[0], m[1]]
])

fig, ax = plt.subplots()
ax.quiver(*o, v[:, 0], v[:, 1])
plt.show()
jds
  • 7,910
  • 11
  • 63
  • 101

2 Answers2

1

According to this and the matplotlib documentation here, you need to use angles='xy', scale_units='xy', scale=1 to get the right units.

See code below:

import numpy as np
import matplotlib.pyplot as plt


b = np.array([4, 1])
d = np.array([-3, 3])
m = d-b
print(np.linalg.norm(d))
o = np.array([
    [0, 0, b[0]],
    [0, 0, b[1]]
])
v = np.array([
    [b[0], b[1]],
    [d[0], d[1]],
    [m[0], m[1]]
])

fig, ax = plt.subplots()
ax.quiver(*o, v[:, 0], v[:, 1],angles='xy', scale_units='xy', scale=1)
ax.set_xlim([-4,4])
ax.set_ylim([-4,4])
plt.show()

And the output:

enter image description here

jylls
  • 4,395
  • 2
  • 10
  • 21
1

It's more convenient to store coordinates of vectors like so:

S = np.stack([*o, v[:, 0], v[:, 1]])
>>> S
array([[ 0,  0,  4],
       [ 0,  0,  1],
       [ 4, -3, -7],
       [ 1,  3,  2]])

Now you can access coords of starting points and directions in this way:

>>> S[:2], S[2:]
(array([[0, 0, 4],
        [0, 0, 1]]),
 array([[ 4, -3, -7],
        [ 1,  3,  2]]))

As well as coords of ending points:

>>> S[:2] + S[2:]
array([[ 4, -3, -3],
       [ 1,  3,  3]])

So you can get all the points on a plane:

>>> pts = np.hstack([S[:2], S[:2] + S[2:]])
array([[ 0,  0,  4,  4, -3, -3],
       [ 0,  0,  1,  1,  3,  3]])

For later part, look into an answer of jylls and use:

plt.quiver(*S, angles='xy', scale_units='xy', scale=1)

Finally, as you've got a nice plot, you might be interested how to specify boundaries for your plot. You can do it like so:

x_min, y_min = np.min(pts, axis=1)
x_max, y_max = np.max(pts, axis=1)
plt.xlim([x_min, x_max])
plt.ylim([y_min, y_max])
plt.show()

enter image description here

mathfux
  • 5,759
  • 1
  • 14
  • 34