从三个 x,y 点 return 0-360 度计算角度的更多 pythonic 方法 "up" 为 0?
more pythonic way to calculate angle from three x,y points return 0-360 degrees with "up" as 0?
我正在使用所有正值的笛卡尔系统。我需要计算两点 (x,y,z) 之间的平面偏转。我主要对 return 相对于 "north" 参考向量顺时针旋转 0-360 值感兴趣,尽管我已经编写了函数(我认为)以便我可以将参考向量分配给任何方向。下面的代码似乎 return 我想要的,但 if 语句似乎有点 hack。有没有更简洁的方法来纯粹在计算中处理它?
我试过 arctan2,结果相似。
import numpy as np
# define 'origin' point where coords are X,Y,Z
p1 = [10000,10000,0]
# create function to compute angle
def ang(p1,p2):
"""
p1 is [x,y,z] 'from'
p2 is [x,y,z] 'to'
"""
# set reference point relative to p1
p0 = [p1[0],p1[1]+1000,0] # 1000 unit offset is arbitrary
# assign X,Y points to variables as arrays
a = np.array(p0[0:2])
b = np.array(p1[0:2]) # the origin
c = np.array(p2[0:2])
# create vectors
ba: ndarray = a - b # subtract the origin
bc: ndarray = c - b # subtract the origin
# calculate angle
cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
angle = np.arccos(cosine_angle)
# adjust for hemisphere
if bc[0] < 0:
return(360 - np.degrees(angle))
else:
return(np.degrees(angle))
test_lst = [[10000, 20000,0],[20000, 20000,0],[20000,10000,0],[20000,0,0],[10000,0,0],[0,0,0],[0,10000,0],[0,20000,0]]
for i in test_lst:
a = ang(p1,i)
print(a)
使用 if 语句(这就是我想要的):
expected | returned
0.0 | 0.0
45.0 | 45.0
90.0 | 90.0
135.0 | 135.0
180.0 | 180.0
225.0 | 225.0
270.0 | 270.0
315.0 | 315.0
没有 if 语句:
expected | returned
0.0 | 0.0
45.0 | 45.0
90.0 | 90.0
135.0 | 135.0
180.0 | 180.0
225.0 | 135.0
270.0 | 90.0
315.0 | 45.0
这不是关于 Python,而是关于数学是如何工作的。 arccos
(还有 arcsin
等)函数 return 一个非唯一值,因为可能的 sine/cosine 值的 [-1, 1]
范围映射到一个间隔是 180 度宽。 arctan2
,其中 return 的角度在 -180 到 180 度范围内,被引入(到 C 中,作为 atan2
)来解决同样的问题。幸运的是,在 Python:
中将 [-180, 180]
转换为 [0, 360]
是一种简单的方法
angle = np.arctan2(...)
return np.degrees(angle) % 360.0 # the modulo operator does this job well
我正在使用所有正值的笛卡尔系统。我需要计算两点 (x,y,z) 之间的平面偏转。我主要对 return 相对于 "north" 参考向量顺时针旋转 0-360 值感兴趣,尽管我已经编写了函数(我认为)以便我可以将参考向量分配给任何方向。下面的代码似乎 return 我想要的,但 if 语句似乎有点 hack。有没有更简洁的方法来纯粹在计算中处理它?
我试过 arctan2,结果相似。
import numpy as np
# define 'origin' point where coords are X,Y,Z
p1 = [10000,10000,0]
# create function to compute angle
def ang(p1,p2):
"""
p1 is [x,y,z] 'from'
p2 is [x,y,z] 'to'
"""
# set reference point relative to p1
p0 = [p1[0],p1[1]+1000,0] # 1000 unit offset is arbitrary
# assign X,Y points to variables as arrays
a = np.array(p0[0:2])
b = np.array(p1[0:2]) # the origin
c = np.array(p2[0:2])
# create vectors
ba: ndarray = a - b # subtract the origin
bc: ndarray = c - b # subtract the origin
# calculate angle
cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
angle = np.arccos(cosine_angle)
# adjust for hemisphere
if bc[0] < 0:
return(360 - np.degrees(angle))
else:
return(np.degrees(angle))
test_lst = [[10000, 20000,0],[20000, 20000,0],[20000,10000,0],[20000,0,0],[10000,0,0],[0,0,0],[0,10000,0],[0,20000,0]]
for i in test_lst:
a = ang(p1,i)
print(a)
使用 if 语句(这就是我想要的):
expected | returned
0.0 | 0.0
45.0 | 45.0
90.0 | 90.0
135.0 | 135.0
180.0 | 180.0
225.0 | 225.0
270.0 | 270.0
315.0 | 315.0
没有 if 语句:
expected | returned
0.0 | 0.0
45.0 | 45.0
90.0 | 90.0
135.0 | 135.0
180.0 | 180.0
225.0 | 135.0
270.0 | 90.0
315.0 | 45.0
这不是关于 Python,而是关于数学是如何工作的。 arccos
(还有 arcsin
等)函数 return 一个非唯一值,因为可能的 sine/cosine 值的 [-1, 1]
范围映射到一个间隔是 180 度宽。 arctan2
,其中 return 的角度在 -180 到 180 度范围内,被引入(到 C 中,作为 atan2
)来解决同样的问题。幸运的是,在 Python:
[-180, 180]
转换为 [0, 360]
是一种简单的方法
angle = np.arctan2(...)
return np.degrees(angle) % 360.0 # the modulo operator does this job well