(三维)我正在寻找一种计算两个向量之间的有符号角度的方法,除了那些向量之外没有其他信息。正如在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)
答案 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 ×之间选择任意方式为你的正常人做。也许选择一个字典缩小的那个?
(但你可能想解释一下你实际想要解决的问题:也许有一个解决方案不涉及计算任意三向量之间的一致有符号角度。)