Numpy's arctan2(y, x) will compute the counterclockwise angle (a value in radians between -ฯ and ฯ) between the origin and the point (x, y).
You could do this for your points A and B, then subtract the second angle from the first to get the signed clockwise angular difference. This difference will be between -2ฯ and 2ฯ, so in order to get a positive angle between 0 and 2ฯ you could then take the modulo against 2ฯ. Finally you can convert radians to degrees using np.rad2deg.
import numpy as np
def angle_between(p1, p2):
ang1 = np.arctan2(*p1[::-1])
ang2 = np.arctan2(*p2[::-1])
return np.rad2deg((ang1 - ang2) % (2 * np.pi))
For example:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
If you don't want to use numpy, you could use math.atan2 in place of np.arctan2, and use math.degrees (or just multiply by 180 / math.pi) in order to convert from radians to degrees. One advantage of the numpy version is that you can also pass two (2, ...) arrays for p1 and p2 in order to compute the angles between multiple pairs of points in a vectorized way.
Numpy's arctan2(y, x) will compute the counterclockwise angle (a value in radians between -ฯ and ฯ) between the origin and the point (x, y).
You could do this for your points A and B, then subtract the second angle from the first to get the signed clockwise angular difference. This difference will be between -2ฯ and 2ฯ, so in order to get a positive angle between 0 and 2ฯ you could then take the modulo against 2ฯ. Finally you can convert radians to degrees using np.rad2deg.
import numpy as np
def angle_between(p1, p2):
ang1 = np.arctan2(*p1[::-1])
ang2 = np.arctan2(*p2[::-1])
return np.rad2deg((ang1 - ang2) % (2 * np.pi))
For example:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
If you don't want to use numpy, you could use math.atan2 in place of np.arctan2, and use math.degrees (or just multiply by 180 / math.pi) in order to convert from radians to degrees. One advantage of the numpy version is that you can also pass two (2, ...) arrays for p1 and p2 in order to compute the angles between multiple pairs of points in a vectorized way.
Use the inner product and the determinant of the two vectors. This is really what you should understand if you want to understand how this works. You'll need to know/read about vector math to understand.
See: https://en.wikipedia.org/wiki/Dot_product and https://en.wikipedia.org/wiki/Determinant
from math import acos
from math import sqrt
from math import pi
def length(v):
return sqrt(v[0]**2+v[1]**2)
def dot_product(v,w):
return v[0]*w[0]+v[1]*w[1]
def determinant(v,w):
return v[0]*w[1]-v[1]*w[0]
def inner_angle(v,w):
cosx=dot_product(v,w)/(length(v)*length(w))
rad=acos(cosx) # in radians
return rad*180/pi # returns degrees
def angle_clockwise(A, B):
inner=inner_angle(A,B)
det = determinant(A,B)
if det<0: #this is a property of the det. If the det < 0 then B is clockwise of A
return inner
else: # if the det > 0 then A is immediately clockwise of B
return 360-inner
In the determinant computation, you're concatenating the two vectors to form a 2 x 2 matrix, for which you're computing the determinant.
Difficulty calculating angle between two points
Angles between two n-dimensional vectors in Python - Stack Overflow
Determining the angle between three points.
math - python code to calculate angle between three point using their 3D coordinates - Stack Overflow
I have a function called angle_between which calculates the angle between two 2D coordinates and returns it in degrees, its supposed to work with any coordinates given but when y1 and y2 are close and x2 is less than x1, it flips polarity which makes it turn wildly, not sure how to fix it atm and any help would be appreciated.
Pastebin: https://pastebin.com/FyejNCb1
Note: all of the other answers here will fail if the two vectors have either the same direction (ex, (1, 0, 0), (1, 0, 0)) or opposite directions (ex, (-1, 0, 0), (1, 0, 0)).
Here is a function which will correctly handle these cases:
import numpy as np
def unit_vector(vector):
""" Returns the unit vector of the vector. """
return vector / np.linalg.norm(vector)
def angle_between(v1, v2):
""" Returns the angle in radians between vectors 'v1' and 'v2'::
>>> angle_between((1, 0, 0), (0, 1, 0))
1.5707963267948966
>>> angle_between((1, 0, 0), (1, 0, 0))
0.0
>>> angle_between((1, 0, 0), (-1, 0, 0))
3.141592653589793
"""
v1_u = unit_vector(v1)
v2_u = unit_vector(v2)
return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
import math
def dotproduct(v1, v2):
return sum((a*b) for a, b in zip(v1, v2))
def length(v):
return math.sqrt(dotproduct(v, v))
def angle(v1, v2):
return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2)))
Note: this will fail when the vectors have either the same or the opposite direction. The correct implementation is here: https://stackoverflow.com/a/13849249/71522
Your original code is pretty close. Adomas.m's answer is not very idiomatic numpy:
import numpy as np
a = np.array([32.49, -39.96,-3.86])
b = np.array([31.39, -39.28, -4.66])
c = np.array([31.14, -38.09,-4.49])
ba = a - b
bc = c - b
cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
angle = np.arccos(cosine_angle)
print np.degrees(angle)
I guess numpy is quite enough:
from numpy import *
from numpy.linalg import norm
a = array([32.49, -39.96,-3.86])
b = array([31.39, -39.28, -4.66])
c = array([31.14, -38.09,-4.49])
f = b-a
e = b-c
abVec = norm(f)
bcVec = norm(e)
abNorm = f / abVec;
bcNorm = e / bcVec;
res = abNorm[0] * bcNorm[0] + abNorm[1] * bcNorm[1] + abNorm[2] * bcNorm[2];
angle = arccos(res)*180.0/ pi
print angle
also the res can be calculated with dot:
res = abNorm[0] * bcNorm[0] + abNorm[1] * bcNorm[1] + abNorm[2] * bcNorm[2];
res = dot(abNorm, bcNorm)