我有两个向量,我想得到这些向量之间的角度,我目前正在使用这个公式:
acos(dot(v1.unitVector, v2.unitVector))
我想要绿色角度而不是红色角度,但我不知道应该使用什么配方......
谢谢。
编辑:所以,母鸡的矢量仍处于某个位置(就像前两对矢量一样,没关系,但是无论何时它都像第三对一样,它不会给我一个正确的角度再)
答案 0 :(得分:4)
使用点积,你总是得到一个与矢量顺序无关的角度和两种可能性中较小的一个。
对于你想要的,你需要由atan2
函数实现的复数的参数函数。从a=ax+i*ay
到b=bx+i*by
的角度是a
次b
的共轭参数(向b
向后旋转a
的角度,比例未考虑),坐标为
(ax-i*ay) * (bx+i*by) = ax*bx+ay*by + i*(ax*by-ay*bx)
所以角度是
atan2( ax*by-ay*bx, ax*bx+ay*by ).
答案 1 :(得分:0)
除了接受的答案之外,atan2
的问题在于,如果您想象矢量a
是静态的而矢量b
沿逆时针方向旋转,则会看到返回值范围从0到π,但是突然变成负数,并从-π变为0,如果您对从0到2π的角度感兴趣,则效果不佳。
为解决该问题,下面的函数可以方便地映射atan2
的结果,并返回0到2π之间的值,就像人们期望的那样:
const TAU = Math.PI * 2;
/**
* Gives the angle in radians from vector a to vector b in anticlockwise direction,
* ranging from 0 to 2π.
*
* @param {Vector} a
* @param {Vector} b
* @returns {Number}
*/
static angle(a, b) {
let angle = Math.atan2(a.x * b.y - a.y * b.x, a.x * b.x + a.y * b.y);
if (angle < 0) {
angle += TAU;
}
return angle;
}
它是用JavaScript编写的,但很容易移植到其他语言。
答案 2 :(得分:0)
Lutz已经正确回答了这个问题,但我要补充一点,我强烈建议将现代矢量数学代码基于Geometric Algebra(几何代数),从而大大提高抽象水平。
使用GA,您只需将两个向量U和V相乘即可得到转子。转子内部看起来像A + Bxy,其中A = U点V = | U | V | cos(角度),Bxy = U楔形V = | U || V | sin(角度)xy(这与复数同构) )。然后,您可以返回转子的带符号CCW角atan2(B,A)。
因此,对于运算符重载,您只需键入(u * v).Angle。最终的计算结果相同,但是您认为和使用的抽象级别要高得多。
答案 3 :(得分:0)
也许这更合适:
atan2( ax*by-ay*bx, ax*bx+ay*by ) % (PI*2)
可以得到完整的逆时针弧度的计算。