Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the clockwise angle between two vectors in python?

I want to find the clockwise angle between two vectors in python the angle should be in range of (-90,90)

what is the equation/code to calculate the angle ?

class Vect:
  def __init__(self, a, b):
    self.a = a
    self.b = b

  def findClockwiseAngle(self, other):
    ## how to compute ??
    pass


vector1 = Vect(a1,b1)  ## a1*i + b1*j
vector2 = Vect(a2,b2)  ## a2*i + b2*j
angle = vect1.findClockwiseAngle(vect2)
like image 944
thakee nathees Avatar asked Jan 01 '23 11:01

thakee nathees


2 Answers

Vector geometry provides (at least) two useful formulas for finding the angle between two vectors:

  • the dot product formula

where a · b can be computed using

  • and the cross-product formula:

where

and since our vectors are two dimensional, we can take a3 and b3 (the components in the z-axis direction) equal to 0. This simplifies the formula even further:

|a x b| = |a1 * b2 - a2 * b1| = |a| * |b| * sin(ϴ)

The ϴs is these two formulas, however, have different interpretations. With the dot product, the angle is the included angle between the two vectors -- and thus always a value between 0 and pi.

With the cross product, the angle is measured in the counterclockwise direction from a to to b. Since you are looking for the angle measured in the clockwise direction, you would simply reverse the sign of the angle obtained using the cross product formula.

In Python, math.asin returns values in the range [-pi/2, pi/2], whereas math.acos returns values in the range [0, pi]. Since you want angles in the range [-pi/2, pi/2] (in radians), the cross-product formula seems to be the more promising candidate:

import math

class Vect:

   def __init__(self, a, b):
        self.a = a
        self.b = b

   def findClockwiseAngle(self, other):
       # using cross-product formula
       return -math.degrees(math.asin((self.a * other.b - self.b * other.a)/(self.length()*other.length())))
       # the dot-product formula, left here just for comparison (does not return angles in the desired range)
       # return math.degrees(math.acos((self.a * other.a + self.b * other.b)/(self.length()*other.length())))

   def length(self):
       return math.sqrt(self.a**2 + self.b**2)

vector1 = Vect(2,0) 

N = 12
theta = [i * 2 * math.pi / N for i in range(N)]
result = []
for t in theta:
    vector2 = Vect(math.cos(t), math.sin(t))  ## a2*i + b2*j
    angle = vector1.findClockwiseAngle(vector2)
    result.append((math.degrees(t), angle))

print('{:>10}{:>10}'.format('t', 'angle'))    
print('\n'.join(['{:>10.2f}{:>10.2f}'.format(*pair) for pair in result]))

prints

     t     angle
  0.00     -0.00
 30.00    -30.00
 60.00    -60.00
 90.00    -90.00
120.00    -60.00
150.00    -30.00
180.00     -0.00
210.00     30.00
240.00     60.00
270.00     90.00
300.00     60.00
330.00     30.00

Above, t is the angle from vector1 to vector2 measured in the counterclockwise direction in the range (0, 360) degrees. angle is the angle from vector1 to vector2 measured in the clockwise direction and in the range (-90, 90) degrees.

like image 136
unutbu Avatar answered Mar 15 '23 19:03

unutbu


In this case, you want to find the angle in range of (-90,90). More infomation, you can get the angle in range of (-180,180). Shown bellow.

From unutbu'answer You can get cos(theta), sin(theta) of target angle theta.

cosTh1 = np.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b))
sinTh1 = np.cross(a,b)/(np.linalg.norm(a)*np.linalg.norm(b))

You can get tan(theta) = sin(theta)/cons(theta). In Python, numpy.arctan2 returns values in the range [-pi, pi]. So,

print (np.rad2deg(np.arctan2(sinTh1,cosTh1)),end=",")

More simple, (cause np.linalg.norm(a)*np.linalg.norm(b) is common.)

cosTh = np.dot(a,b)
sinTh = np.cross(a,b)
print (np.rad2deg(np.arctan2(sinTh,cosTh)))   
like image 35
johnInHome Avatar answered Mar 15 '23 21:03

johnInHome