如何在Python中找到两个向量之间的顺时针角度?

6
我希望在Python中找到两个向量之间的顺时针角度,该角度应在(-90,90)范围内。 计算角度的方程/代码是什么?
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)

尝试余弦相似度? - cs95
2个回答

6

向量几何提供了(至少)两个有用的公式来找到两个向量之间的角度:

其中a·b可以使用以下方法计算

在哪里

由于我们的向量是二维的,因此可以将a3b3(在z轴方向上的分量)设为0。这进一步简化了公式:

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

这两个公式都属于θ,但解释不同。对于点积,角度是两个向量之间的夹角 -- 因此始终为0到π之间的值。
对于叉积,角度是从a到b逆时针方向的测量角度。由于你要寻找顺时针方向的角度,只需反转使用叉积公式得到的角度的符号即可。
在Python中,math.asin返回范围为[-pi/2, pi/2]的值,而math.acos返回范围为[0, pi]的值。由于你想要在范围[-pi/2, pi/2](以弧度为单位)内获得角度,因此叉积公式似乎是更有前途的候选者:
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]))

打印

     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

以上,t是从vector1vector2的角度,以逆时针方向在(0, 360)度范围内测量。 angle是从vector1vector2的角度,以顺时针方向测量,并在(-90, 90)度范围内。


4

在这种情况下,您想要找到范围在(-90,90)之间的角度。 更多信息,您可以获得范围在(-180,180)之间的角度。如下所示。

从unutbu的回答中 您可以获取目标角度θ的cos(theta),sin(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))

您可以得到 tan(theta) = sin(theta)/cos(theta)。

在Python中,numpy.arctan2返回范围在[-pi, pi]内的值。因此,

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

更简单(因为np.linalg.norm(a)*np.linalg.norm(b)很常见)。
cosTh = np.dot(a,b)
sinTh = np.cross(a,b)
print (np.rad2deg(np.arctan2(sinTh,cosTh)))   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接