Is there a way to draw a arrow inside a circle elegantly

Viewed 197

I am trying to plot a unit vector in a unit circle.

here is the code

vunit = 1/np.sqrt(2)
vec1 = [vunit,vunit]
thetas = np.arange(-np.pi, np.pi, .05)
coordinates = np.vstack((np.cos(thetas),np.sin(thetas)))

plt.figure(figsize = (6,6))
plt.xlim(-3,3)
plt.ylim(-3,3)
plt.scatter(coordinates[0,:],coordinates[1,:],s=.1)
plt.arrow(0, 0, vec1[0], vec1[1], head_width=0.15, color='r')

enter image description here

everything is OK, except the head of arrow is outside the circle.

so, I modify the vec1 ugly

vec1 = [vunit-.1,vunit-.1]

enter image description here

the figure looks better and I can modify the vec1 more finely, but the fix seem to be ugly. is there a way to have the arrow inside the circle elegantly

2 Answers

Use length_includes_head=True:

import numpy as np
import matplotlib.pyplot as plt

vunit = 1/np.sqrt(2)
vec1 = [vunit,vunit]
thetas = np.arange(-np.pi, np.pi, .05)
coordinates = np.vstack((np.cos(thetas),np.sin(thetas)))

plt.figure(figsize = (6,6))
plt.xlim(-3,3)
plt.ylim(-3,3)
plt.scatter(coordinates[0,:],coordinates[1,:],s=.1)
plt.arrow(0, 0, vec1[0], vec1[1], head_width=0.15, color='r', length_includes_head=True)
plt.show()

enter image description here

One might use a FancyArrowPatch instead of a FancyArrow (which is the object produced by plt.arrow).
The difference here is marginal, but for other cases, and hence consistency, FancyArrowPatch offers a lot of nice features that are not present for FancyArrow. One main difference is observed when zooming the plot; the FancyArrow's head is defined in data coordinates, it will hence look skewed when shown in non equal aspect plots.

enter image description here

So here is the complete code with FancyArrowPatch, where we get the head tip at the end coordinate via shrinkB argument.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch

vunit = 1/np.sqrt(2)
vec1 = [vunit,vunit]
thetas = np.arange(-np.pi, np.pi, .05)
coordinates = np.vstack((np.cos(thetas),np.sin(thetas)))

plt.figure(figsize = (6,6))
plt.xlim(-3,3)
plt.ylim(-3,3)
plt.scatter(coordinates[0,:],coordinates[1,:],s=.1)

arrow = FancyArrowPatch(posA=(0,0), posB=vec1, 
                        arrowstyle='-|>', mutation_scale=20, 
                        shrinkA=0, shrinkB=0, color='r')
plt.gca().add_patch(arrow)

plt.show()

enter image description here

Related