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

时间:2012-04-13 01:00:08

标签: math vector 3d geometry

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

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 个答案:

答案 0 :(得分:19)

相关的数学公式:

  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),但没有几何理由可以选择它。

答案 1 :(得分:3)

  

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

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

  

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

我认为没有某种参考载体就不可能。

答案 2 :(得分:2)

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

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

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

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

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

答案 3 :(得分:-2)

如果你想要的只是一致的结果,那么在 a × b b ×之间选择任意方式为你的正常人做。也许选择一个字典缩小的那个?

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