如何获得两个2D矢量之间的“逆时针”角度?

时间:2016-10-27 14:01:05

标签: math

我有两个向量,我想得到这些向量之间的角度,我目前正在使用这个公式:

acos(dot(v1.unitVector, v2.unitVector))

以下是我得到的内容: enter image description here

我想要绿色角度而不是红色角度,但我不知道应该使用什么配方......

谢谢。

编辑:所以,母鸡的矢量仍处于某个位置(就像前两对矢量一样,没关系,但是无论何时它都像第三对一样,它不会给我一个正确的角度再)

4 个答案:

答案 0 :(得分:4)

使用点积,你总是得到一个与矢量顺序无关的角度和两种可能性中较小的一个。

对于你想要的,你需要由atan2函数实现的复数的参数函数。从a=ax+i*ayb=bx+i*by的角度是ab的共轭参数(向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)

可以得到完整的逆时针弧度的计算。