15

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

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

4 回答 4

19

相关数学公式:

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

对于 3-D 向量之间的稳健角度,您的实际计算应该是:

  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),但没有几何理由偏爱它。

于 2012-04-13T16:54:49.837 回答
3

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

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

有符号角度(a,b)== -有符号角度(b,a)

我认为没有某种参考向量是不可能的。

于 2012-04-13T01:05:27.400 回答
2

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

作为参考,我将得到的角度反馈到旋转函数中。我没有考虑到这样一个事实,即这自然会使用与 signed_angle 相同的轴(输入向量的叉积),并且正确的旋转方向将遵循该轴所面向的任何方向。

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

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

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

于 2012-04-19T05:11:36.203 回答
-2

如果您想要的只是一个一致的结果,那么任何在a × bb × a之间为您的法线选择的任意方式都可以。也许选择字典顺序较小的那个?

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

于 2012-04-13T10:49:19.690 回答