如何找到范围从 0 rad 到 2 rad 的两个向量之间的角度,而不是 arccos 函数的内角

How can I find the angle between two vectors that can range from 0 rad to 2 rad, instead of the inside angle with the arccos function

我现在正在制作一个 python 脚本,它试图找到弧的长度,它给出了以下信息:

圆弧中心:x1,y1

圆弧起点:x2,y2

圆弧终点:x3,y3

方向,顺时针,逆时针

到目前为止,我已经能够成功计算出半径,并且我尝试使用以下公式计算角度:

但对于任何角度大于 1*pi 或 180 度的弧,它 returns 不正确(但正确)的内角。

知道半径和这三个点的正确方程是什么,我可以用它来找到从 0 rad/degrees 到 360 degrees/2pi 弧度的弧度值,要么顺时针或逆时针方向(可以是或,我需要能够计算这两种情况)

代码:

# code to find theta
aVector = np.array([x1 - x2, y1 - y2])
bVector = np.array([x1 - x3, y1 - y3])
aMag = np.linalg.norm(aVector)
bMag = np.linalg.norm(aVector)
theta = np.arcos(np.dot(aVector, bVector) / (aMag * bMag))

如你所见,我使用的是 arccos,令我沮丧的是它只能输出 0-180 度

Solution/Working代码:

# equation for angle using atan2
start = math.atan2(y2 - y1, x2 - x1)
end = math.atan2(y3 - y1, x3 - x1)
if gcodeAnalysis[tempLineNum][4] == "G3": # going CW
    start, end = end, start
tau = 2.0 * math.pi
theta = math.fmod(math.fmod(end - start, tau) + tau, tau)

工作价值:

X1 = 0.00048399999999998444
Y1 = 0.0002720000000007161
X2 = 0.378484
Y2 = -14.694728
X3 = 3.376
Y3 = -14.307

适当的result/value

Theta = 6.077209477545957

假设这条弧是逆时针完成的

如您所见,math.acos is [0, pi], making it rather useless for telling you the relative directions of the vectors. To get full circular information about a pair of angles, you can use math.atan2. While regular math.atan 的范围为 [-pi/2,pi/2],atan2 将输入分成两部分,returns 范围内的角度 (-pi, pi)。您可以计算相对于任何参考的角度,不一定相对于彼此:

start = math.atan2(y2 - y1, x2 - x1)
end = math.atan2(y3 - y1, x3 - x1)

现在您可以使用一些常用公式来计算任意方向的角度差。我已经在我制作的名为 haggis 的小型实用程序库中实现了其中的一些。你想要的具体功能是haggis.math.ang_diff_pos.

一、“人工”计算:

if direction == 'cw':
    start, end = end, start
tau = 2.0 * math.pi
angle = math.fmod(math.fmod(end - start, tau) + tau, tau)

如果你想使用我的功能,你可以

if direction == 'cw':
    start, end = end, start
angle = ang_diff_pos(start, end)

如果您发现自己同时处理许多点,那么所有这些操作都可以使用 numpy 轻松矢量化。

您可以使用两个向量的叉积来确定两个向量是否需要顺时针或逆时针旋转。

查看下面的代码:


import numpy as np
from numpy import linalg as LA


x1 = 0
y1 = 0
x2 = 2
y2 = 0
x3 = 2
y3 = -2
dir = 'ccw' # or ccw 

v1 = np.array([x2-x1,y2-y1])
v2 = np.array( [x3-x1,y3-y1])

# if the cross product is positive, then the two vector need to rotate counter clockwise
rot = np.cross(v1,v2)
vdir = 'ccw' if rot >0 else 'cw'

r = (v1[0]*v2[0]+v1[1]*v2[1])/(LA.norm(v1)*LA.norm(v2))

deg = np.arccos(r)/np.pi*180

if vdir != dir:
    deg = 360 -deg

print(deg)