6

我有两个名为 A 和 B 的 3D 向量,它们都只有一个 3D 位置。我知道如何使用 atan2 函数找到沿 0-360 度范围内的单位圆的角度,方法是:

编辑:(我的 atan2 函数没有意义,现在它应该找到 2 个向量之间的“y 角”):

toDegrees(atan2(A.x-B.x,A.z-B.z))+180

但这给了我两个向量之间的 Y 角。我需要找到它们之间的 X 角。它与使用 x、y 和 z 位置值有关。不仅仅是 x 和 z,因为这给出了两个向量之间的 Y 角。我需要 X 角,我知道这听起来很模糊,但我不知道如何解释。例如,如果您向上或向下看而不是旋转 x 轴,也许您在 3D 空间中有一个相机。但现在我需要得到两个向量之间的“上/下”角度。如果我沿 y 轴旋转该 3D 相机,x 轴不会改变。因此,对于 2 个向量,无论它们之间的“y 角”是多少,如果 y 角发生变化,两个向量之间的 x 角将保持不变,因为它是“上/下”角,就像在 camara 中一样.

请帮忙?我只需要一行数学/伪代码或解释。:)

4

3 回答 3

7
atan2(crossproduct.length,scalarproduct)

使用 atan2 而不是 arccos 或 arcsin 的原因是准确性。arccos 在接近 0 度时表现非常糟糕。参数中的小计算错误将导致结果中不成比例的大错误。arcsin 在接近 90 度时也有同样的问题。

于 2012-09-02T19:46:35.603 回答
6

计算高度角

好的,我可能终于明白了你在下面关于结果独立于y角的评论,以及它与两个向量的关系。您似乎对两个向量以及这两个向量之间的角度并不真正感兴趣,而是对差分向量以及一个向量与水平面形成的角度感兴趣。在水平坐标系中(通常在天文学中使用),该角度将被称为“高度”或“仰角”,而不是您在(编辑的)问题中使用公式计算的“方位角”。“高度”与相机的“<a href="http://en.wikipedia.org/wiki/Tilt_%28camera%29" rel="noreferrer">倾斜”密切相关,而“方位角”与​​“ <a href="http://en.wikipedia.org/wiki/Panning_%28camera%29" rel="noreferrer">平移”。

我们仍然有一个二维问题。二维向量的一个坐标是差向量的y坐标。另一个坐标是向量在水平面上投影后的长度,即sqrt(x*x + z*z)。最终的解决方案是

x = A.x - B.x
y = A.y - B.y
z = A.z - B.z
alt = toDegrees(atan2(y, sqrt(x*x + z*z)))
az = toDegrees(atan2(-x, -z))

根据您在下面的评论,选择顺序(A - B而不是B - A)使得“A 高于 B”产生y正的高度,因此产生正的高度。上面方位角计算中的减号应该替换+ 180您问题代码中的,除了现在的范围是 [-180, 180] 而不是您的 [0, 360]。只是给你一个选择,选择你喜欢的。实际上,您计算B - A任一方式的方位角。您对这两个角度使用不同的顺序这一事实可能会有些混乱,因此请考虑这是否真的是您想要的,或者您是否想要反转高度的符号或将方位角更改 180°。


正交投影

作为参考,我将在下面包含我的原始答案,对于那些实际上正在寻找围绕某个固定 x 轴的旋转角度的人,就像原始问题所建议的那样。

如果您在问题中提到的这个x 角度确实是围绕x轴的旋转角度,如相机示例所示,那么您可能想这样考虑:将x坐标设置为零,您最终会得到yz平面中的二维向量。您可以将其视为在所述平原上的正交投影。现在你又回到了一个二维问题,可以在那里解决它。

就个人而言,我只需调用atan2两次,每个向量调用一次,然后减去结果角度:

toDegrees(atan2(A.z, A.y) - atan2(B.z, B.y))

x=0式中隐含的只是因为我只对yand进行操作z

我还没有完全理解你的单次atan2调用背后的逻辑,但我必须考虑这么久的事实表明我不想维护它,至少在没有很好的解释性评论的情况下不会。

我希望我正确理解了您的问题,这就是您要寻找的东西。

于 2012-09-02T21:40:37.277 回答
4

就像 2D Vectors 一样,您可以通过求解其点积的 cos 来计算它们的角度

3d 向量的点积
您不需要atan,您总是选择点积,因为它是向量的基本运算,然后使用acos来获取角度。

double angleInDegrees = acos ( cos(theta) ) * 180.0 / PI;
于 2012-09-01T18:01:23.307 回答