如何有效地计算二维点的三个矢量之间的全(2pi)角

2024-10-06 08:41:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有三个形状为[n,2]的numpy数组,其中包含点列表。我们把它们叫做a,b,c。我想找出ab和bc之间的全角度。使用acos网我只有π弧度,但我想要完整的2pi规模。我考虑过使用atan2,但不确定如何计算atan2所需的y和x向量-我尝试过使用向量范数,但它们本质上是正的。有没有什么方法可以让我完全使用numpy函数来提高效率?你知道吗


Tags: 方法numpy范数列表ab数组向量角度
2条回答

毫不奇怪,这里可以使用angle函数。它需要一个复杂的参数x + y i

这种方法的优点是相对角度容易获得。有了atan2这就有点棘手了。你知道吗

def get_angle(a,b,yx=False):
    # make sure inputs are contiguous float
    # swap x and  if requested
    a,b = map(np.ascontiguousarray, (a[...,::-1],b[...,::-1]) if yx else (a,b), (float,float))
    # view cast to complex, prune excess dimension
    A,B = (z.view(complex).reshape(z.shape[:-1]) for z in (a,b))
    # to get the relative angle we must either divide 
    # or (probably cheaper) multiply with the conjugate  
    return np.angle(A.conj()*B)

a,b,c = np.random.randn(3,20,2)
# let's look at a roundtrip as a test
get_angle(a,b)+get_angle(b,c)+get_angle(c,a)
# array([ 0.00000000e+00,  1.66533454e-16,  4.44089210e-16, -2.22044605e-16,
#         0.00000000e+00,  0.00000000e+00,  0.00000000e+00, -4.44089210e-16,
#         0.00000000e+00, -1.66533454e-16,  2.22044605e-16,  0.00000000e+00,
#         0.00000000e+00,  2.22044605e-16,  6.28318531e+00,  8.32667268e-17,
#         2.22044605e-16, -6.28318531e+00, -2.22044605e-16,  6.28318531e+00])
# some zeros, some 2pi and some -2pi ==> looks ok

# Let's also check the sum of angles of triangles abc:
get_angle(a-c,b-c)+get_angle(b-a,c-a)+get_angle(c-b,a-b)
# array([-3.14159265, -3.14159265,  3.14159265, -3.14159265, -3.14159265,
#         3.14159265, -3.14159265, -3.14159265,  3.14159265, -3.14159265,
#        -3.14159265,  3.14159265, -3.14159265, -3.14159265,  3.14159265,
#         3.14159265, -3.14159265, -3.14159265,  3.14159265,  3.14159265])

单独使用arccos方法只能给出向量之间的绝对角度,而不是顺时针还是逆时针。您可以通过检查ab的垂线的点积是否为负来增强这一点,表示逆时针角度。你知道吗

import numpy as np

def dot(a, b):
  return np.sum(a * b, axis=-1)

def mag(a):
  return np.sqrt(np.sum(a*a, axis=-1))

def angle(a, b):
  cosab = dot(a, b) / (mag(a) * mag(b)) # cosine of angle between vectors
  angle = np.arccos(cosab) # what you currently have (absolute angle)

  b_t = b[:,[1,0]] * [1, -1] # perpendicular of b

  is_cc = dot(a, b_t) < 0

  # invert the angles for counter-clockwise rotations
  angle[is_cc] = 2*np.pi - angle[is_cc]
  return angle

print(angle(
  np.array([[1, 0], [1, 0]]),
  np.array([[0, 1], [0, -1]])
))

将打印[pi/2, 3pi/2]的浮点值。你知道吗

此函数的输出范围为[0, 2*pi]。你知道吗

相关问题 更多 >