Reputation: 261
I have a function that that finds the angle between the unit circle vector [1,0]
and a vector on the unit circle.
import numpy as np
def angle(a):
b = [0,1]
if a[1] >= 0:
return round(np.degrees(np.arccos(np.dot(a, b)/ (np.linalg.norm(a) * np.linalg.norm(b)))), 2)
else:
return 180 + round(np.degrees(np.arccos(np.dot(a, b)/ (np.linalg.norm(a) * np.linalg.norm(b)))), 2)
print(angle(np.array([1,0])))
90.0
print(angle(np.array([-4,2])))
63.43 # This value should be 150
print(angle(np.array([-1,0])))
90.0 # This value should be 180
print(angle(np.array([0,-1])))
360.0 # This value should be 270
a
is always a 2D vector?Upvotes: 0
Views: 2202
Reputation: 11181
One way to define a function that expects inputs is to leave both as separate args (this also fixes some bugs and simplifies the logic to get your angle values):
def angle(x, y):
rad = np.arctan2(y, x)
degrees = np.int(rad*180/np.pi)
if degrees < 0:
degrees = 360 + degrees
return degrees
Incidentally, atan2
has input order y, x
which is easy to mix up. An advantage to specifying them separately is you can help avoid that. If you want to keep the input as an array, something like this helps you validate the length:
def angle(a):
if len(a) != 2:
raise IndexError("vector a expected to be length 2")
x = a[0]
y = a[1]
rad = np.arctan2(y, x)
degrees = np.int(rad*180/np.pi)
if degrees < 0:
degrees = 360 + degrees
return degrees
Upvotes: 1
Reputation: 51
To establish a is always a 2D vector, you can check it's length : if len(a) == 2
. you can additionally check if it's a list or a tuple with : if type(a) in [list, tuple] and len(a) == 2:
EDIT : my bad just noticed it's actually numpy arrays, in that case : if isinstance(x, np.ndarray) and x.shape[0] == 2
EDIT 2 : from the comments : x.ndim == 2
sounds better.
Upvotes: 0
Reputation: 368
You have the x vector wrong. It should be
b = [1,0]
given that the first coordinate is the x axis and the second one is the y axis. If you put this correct b vector, all the computations work as expected.
Upvotes: 1