Python 计算两点之间的角度(顺时针方向)
我已经很久没有使用数学了,这应该是一个简单的问题来解决 假设我有两点A:(1,0)和B:(1,-1) 我想用一个程序(Python或任何编程语言)来计算a,原点(0,0)和B之间的顺时针角度。它将是这样的:Python 计算两点之间的角度(顺时针方向),python,math,angle,Python,Math,Angle,我已经很久没有使用数学了,这应该是一个简单的问题来解决 假设我有两点A:(1,0)和B:(1,-1) 我想用一个程序(Python或任何编程语言)来计算a,原点(0,0)和B之间的顺时针角度。它将是这样的: angle_clockwise(point1, point2) 请注意,参数的顺序很重要。由于角度计算将顺时针进行: def angle_between_points(p1, p2): d1 = p2[0] - p1[0] d2 = p2[1] - p1[1] if
angle_clockwise(point1, point2)
请注意,参数的顺序很重要。由于角度计算将顺时针进行:
def angle_between_points(p1, p2):
d1 = p2[0] - p1[0]
d2 = p2[1] - p1[1]
if d1 == 0:
if d2 == 0: # same points?
deg = 0
else:
deg = 0 if p1[1] > p2[1] else 180
elif d2 == 0:
deg = 90 if p1[0] < p2[0] else 270
else:
deg = math.atan(d2 / d1) / pi * 180
lowering = p1[1] < p2[1]
if (lowering and deg < 0) or (not lowering and deg > 0):
deg += 270
else:
deg += 90
return deg
- 如果我顺时针调用角度_(A,B),它返回45
- 如果我顺时针调用角度_(B,A),它返回315
angle_clockwise(point1, point2)
>>> import cmath
>>> a_phase = cmath.phase(complex(1,0))
>>> b_phase = cmath.phase(complex(1,-1))
>>> (a_phase - b_phase) * 180 / cmath.pi
45.0
>>> (b_phase - a_phase) * 180 / cmath.pi
-45.0
你可以检查一个数字是否小于0,如果你想要所有的正角度,也可以加360。Numpy's将计算原点和点之间的逆时针角度(一个介于-π和π之间的弧度值)(x,y)
您可以对点A
和B
执行此操作,然后从第一个角度减去第二个角度,以获得符号顺时针角度差。这个差在-2π和2π之间,所以为了得到0和2π之间的正角度,你可以取模与2π的比值。最后,可以使用将弧度转换为度
例如:
A = (1, 0)
B = (1, -1)
print(angle_between(A, B))
# 45.
print(angle_between(B, A))
# 315.
如果不想使用numpy,可以使用代替np.arctan2,并使用(或仅乘以
180/math.pi
)将弧度转换为度。numpy版本的一个优点是,您还可以为p1
和p2
传递两个(2,…)
数组,以便以矢量化方式计算多对点之间的角度。使用两个向量的内积和行列式。如果你想了解它是如何工作的,这确实是你应该了解的。你需要了解/阅读向量数学才能理解
见:和
从数学导入acos
从数学导入sqrt
从数学导入pi
def长度(v):
返回sqrt(v[0]**2+v[1]**2)
def dot_产品(v、w):
返回v[0]*w[0]+v[1]*w[1]
def行列式(v,w):
返回v[0]*w[1]-v[1]*w[0]
def内倾角(v,w):
cosx=点积(v,w)/(长度(v)*长度(w))
rad=acos(cosx)#弧度
返回弧度*180/pi#返回度
def角度_顺时针(A、B):
内=内倾角(A,B)
det=行列式(A,B)
如果det为0,则A为B的顺时针方向
返回360内部
在行列式计算中,将两个向量连接起来,形成一个2 x 2矩阵,然后计算行列式。这是一个不需要
cmath
的解决方案
import math
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
v1 = Vector(0, 1)
v2 = Vector(0, -1)
v1_theta = math.atan2(v1.y, v1.x)
v2_theta = math.atan2(v2.y, v2.x)
r = (v2_theta - v1_theta) * (180.0 / math.pi)
if r < 0:
r += 360.0
print r
导入数学
类向量:
定义初始化(self,x,y):
self.x=x
self.y=y
v1=向量(0,1)
v2=向量(0,-1)
v1_θ=数学atan2(v1.y,v1.x)
v2_θ=数学常数2(v2.y,v2.x)
r=(v2θ-v1θ)*(180.0/math.pi)
如果r<0:
r+=360.0
印刷机
Chris St Pierre:使用函数时:
A = (x=1, y=0)
B = (x=0, y=1)
这应该是从a
到B
的90度角。您的函数将返回270
在处理det符号时是否有错误,或者我是否遗漏了什么?一个顺时针计算角度的公式,用于测量:
f(E,N)=pi()-pi()/2*(1+sign(N))* (1-sign(E^2))-pi()/4*(2+sign(N))*sign(E)
-sign(N*E)*atan((abs(N)-abs(E))/(abs(N)+abs(E)))
公式给出了从0到2pi的角度,从北到北
正在为N和E的任何值工作。(N=N2-N1和E=E2-E1)
对于N=E=0结果未定义。验证的0°至360°解决方案
这是一个旧线程,但对我来说,其他解决方案没有很好地工作,所以我实现了自己的版本
我的函数将为屏幕上的两个点返回一个介于0和360(不包括360)之间的数字(即“y”从顶部开始并向底部增加),结果如指南针中所示,顶部为0°,顺时针增加:
def angle_between_points(p1, p2):
d1 = p2[0] - p1[0]
d2 = p2[1] - p1[1]
if d1 == 0:
if d2 == 0: # same points?
deg = 0
else:
deg = 0 if p1[1] > p2[1] else 180
elif d2 == 0:
deg = 90 if p1[0] < p2[0] else 270
else:
deg = math.atan(d2 / d1) / pi * 180
lowering = p1[1] < p2[1]
if (lowering and deg < 0) or (not lowering and deg > 0):
deg += 270
else:
deg += 90
return deg
点(p1、p2)之间的定义角度:
d1=p2[0]-p1[0]
d2=p2[1]-p1[1]
如果d1==0:
如果d2==0:#相同的点?
度=0
其他:
如果p1[1]>p2[1],则deg=0,否则为180
elif d2==0:
如果p1[0]0):
摄氏度+=270度
其他:
摄氏度+=90度
返回度
以弧度为单位,顺时针,从0到π*2
static angle(center:Coord, p1:Coord, p2:Coord) {
var a1 = Math.atan2(p1.y - center.y, p1.x - center.x);
var a2 = Math.atan2(p2.y - center.y, p2.x -center.x);
a1 = a1 > 0 ? a1 : Math.PI * 2 + a1;//make angle from 0 to PI * 2
a2 = a2 > 0 ? a2 : Math.PI * 2 + a2;
if(a1 > a2) {
return a1 - a2;
} else {
return Math.PI * 2 - (a2 - a1)
}
}
阅读并注意atan2在问题中是关于实现atan2的代码,而不是atan2的概念,为什么建议查看更多关于atan2的内容?“如果我顺时针调用angle_(B,A),它返回335”-当然你是指315(360-45)?哇。。。是的,我是说315。现在你知道我有多长时间没用数学了:最好不要用这么差的近似值pi@317070pi的固定值。最后可以使用r%360。在Python中,模数的工作原理与负数相同:)
arctan2(y,x)
计算x轴和向量之间的逆时针角度(x,y)
。要定义一个角度,你需要三个点或两个向量,而不仅仅是两个点。@Spirko OP要求的是从原点到点A的向量与从原点到点B的向量之间的顺时针角度。我们有三个点和两个向量,所以角度定义得很好。“这将介于-π和π之间”这不是真的-角度将在-2π和2π@Eric之间-你是对的-这只是指np.arctan2
的输出,而不是两个suc的差