首页 文章

没有参考平面的两个矢量之间的有符号角度

提问于
浏览
11

(在三个维度上)我正在寻找一种计算两个向量之间的有符号角度的方法,除了那些向量之外没有其他信息 . 正如在this question中所回答的那样,在给定矢量垂直的平面的法线的情况下计算有符号角度是很简单的 . 但是如果没有这个 Value 我就无法做到这一点 . 它使用上面的答案遇到了以下矛盾:

signed_angle(x_dir, y_dir) == 90
signed_angle(y_dir, x_dir) == 90

我希望第二个结果是否定的 . 这是因为交叉积 cross(x_dir, y_dir)cross(y_dir, x_dir) 的方向相反,给定以下具有规范化输入的伪代码:

signed_angle(Va, Vb)
    magnitude = acos(dot(Va, Vb))
    axis = cross(Va, Vb)
    dir = dot(Vb, cross(axis, Va))
    if dir < 0 then
        magnitude = -magnitude
    endif
    return magnitude

我不相信dir永远不会消极 .

我已经看到了建议的atan2解决方案的相同问题 .

我正在寻找一种方法:

signed_angle(a, b) == -signed_angle(b, a)

4 回答

  • 18

    相关的数学公式:

    dot_product(a,b) == length(a) * length(b) * cos(angle)
      length(cross_product(a,b)) == length(a) * length(b) * sin(angle)
    

    对于三维向量之间的强大角度,您的实际计算应该是:

    s = length(cross_product(a,b))
      c = dot_product(a,b)
      angle = atan2(s, c)
    

    如果单独使用 acos(c) ,则角度较小时会出现严重的精度问题 . 计算 s 并使用 atan2() 为所有可能的情况提供稳健的结果 .

    由于 s 始终是非负的,因此得到的角度范围为0到pi . 总会有一个等效的负角 (angle - 2*pi) ,但没有几何理由可以选择它 .

  • 3

    没有参考平面的两个矢量之间的有符号角度

    angle = acos(dotproduct(normalized(a), normalized(b)));
    

    signed_angle(a,b)== -signed_angle(b,a)

    我认为如果没有某种参考向量,这是不可能的 .

  • 1

    谢谢大家 . 在回顾了这里的评论并回顾我想要做的事情之后,我意识到我可以用给定的标准公式来完成我需要做的事情 . 我刚刚在单位测试中挂了我的签名角度功能 .

    作为参考,我将得到的角度反馈回旋转功能 . 我没有考虑到这样的事实,即它将自然地使用与signed_angle(输入矢量的叉积)相同的轴,并且正确的旋转方向将跟随轴所面向的方向 .

    更简单地说,这两者都应该“做正确的事”并向不同的方向旋转:

    rotate(cross(Va, Vb), signed_angle(Va, Vb), point)
    rotate(cross(Vb, Va), signed_angle(Vb, Va), point)
    

    第一个参数是旋转轴,第二个参数是旋转的数量 .

  • -2

    如果你想要的只是一致的结果,那么你的正常情况下任意选择 a × bb × a 的方式都可以 . 也许选择一个字典缩小的那个?

    (但你可能想解释一下你实际想要解决的问题:也许有一个解决方案不涉及计算任意3向量之间的一致有符号角度 . )

相关问题