两个三维向量之间的X角度是多少?

7

我有两个名为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角度,我知道听起来很模糊,但我不知道如何解释。 也许例如您在3D空间中拥有相机,如果您向上或向下看,则会旋转x轴。 但现在我需要获取两个向量之间的“上/下”角度。 如果我沿着y轴旋转该3D相机,则x轴不会更改。 因此,对于这2个向量,无论它们之间的“y角度”是多少,如果y角度发生变化,这两个向量之间的x角度将保持不变,因为它是“上下”角度,就像相机一样。
请帮忙吗? 我只需要一行数学/伪代码或解释。 :)

让我们使用yaw,pitch和roll来命名不同的旋转。根据我阅读的文本,“X角度”指的是“yaw”(相机的“pan”),而“Y角度”指的是“pitch”(相机的“tilt”)。通常,绕yaw轴的旋转会改变pitch和roll轴的位置。当您写道“无论y角度如何,x角度保持不变”时,似乎您正在绝对地定义yaw轴(始终指向“上”),但是其他两个相对。但是它们的定义不清楚。您能否使用这些术语重新表述问题? - MvG
3个回答

8
atan2(crossproduct.length,scalarproduct)

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

6

计算高度角

好的,我可能终于理解了你在下面评论中关于结果与 y 角无关以及它如何与两个向量相关的问题。似乎你并不真正关心 两个 向量和这两个向量之间的夹角,而是关心 差向量 和一个相对水平面成的角度。在水平坐标系(常用于天文学)中,该角度称为“高度”或“仰角”,与你的相机的“倾斜”密切相关,而“方位角”则与“平移”有关,在你修改后的问题中使用公式计算“方位角”。

我们仍然有一个二维问题。2D向量的一个坐标是差向量的 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-BB-A相反)的选择是为了“将A放在B上”得到正的y并且高度为正,这符合下面您的评论。方位角计算中的减号应替换您在问题中的代码中的+180,但现在范围是[-180, 180]而不是[0, 360]。只是提供另一种选择,可以选择您喜欢的任何一种。实际上,无论哪种方式,都会计算出B - A的方位角。对于这两个角度使用不同的顺序可能有些令人困惑,因此请考虑一下是否真的需要这样做,或者是否需要通过将高度的符号取反或将方位角更改为180°来更改这两个角之间的关系。

正交投影

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

如果您在问题中提到的这个x角度确实是围绕x轴旋转的角度,就像摄像机示例所示,那么您可能希望这样考虑:将x坐标设置为零,那么您将得到y-z平面上的2D向量。您可以将其视为对该平面的正交投影。现在您又回到了一个2D问题,可以在那里解决它。

个人建议只需两次调用atan2,一次用于每个向量,并减去所得到的角度:

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

上述公式中的 x=0 是隐含的,因为我只对 yz 进行操作。
目前我还没有完全理解你单个 atan2 调用背后的逻辑,但是,我需要这么长时间思考它的事实表明,如果没有很好的解释性注释,我不想维护它。
我希望我正确地理解了你的问题,这就是你正在寻找的东西。

谢谢,我已经纠正了我的atan2函数,我之前打错了。现在它应该可以得到两个向量之间的“y角度”。我会尝试使用你的版本来减去角度。我也理解了你的正交投影建议。如果经过多次尝试后仍然不行,我会再详细解释一下。 - Arundel
好的,这并没有解决我的问题,但我必须说我们已经接近了。所以再举个相机的例子:如果相机向上或向下旋转,x角度会改变。如果y角度改变,x角度不会改变。因此,无论向量之间的“y角度”(就像我的atan2函数一样)是什么,向量之间的x角度保持不变。如果:向量的y位置相同,则向量之间的x角度始终为0;如果:向量A在B的上方,则x角度始终为90度;如果:A在B的下方,则x角度始终为-90度。你知道的,这些值之间的所有内容。 - Arundel
@user1569781:听起来你想要投影到一个包含y轴但不一定包含z轴的平面上。因此,这个平面似乎是由y轴和你的两个向量定义的。但是怎么定义呢?你的其中一个向量是否像相机一样,所以你想要投影到由该向量和y轴张成的平面上?还是你正在寻找对称解决方案,如果交换AB会得到相同的结果? - MvG
@user1569781,再次阅读您的评论,我希望我已经弄对了。上面编辑过的解决方案是您要找的吗? - MvG
哇,非常感谢@MvG,确实是我想要的高度。我听说过方位角和高度这些术语,但不知道它们是如何工作的。很抱歉我试图解释得含糊不清,但最终它起作用了。非常感谢。我也感谢其他贡献信息的人们。:D 我希望其他人能从这个帖子中学到东西。如果你好奇我要用这个做什么:我已经用2D Gui制作了一个基本的3D游戏引擎,这些信息对于3D相机和3D场景非常有用。:) - Arundel

4

就像2D向量一样,你可以通过解决它们的点积的余弦值来计算它们的角度。

3D向量的点积
你不需要使用atan,你总是使用点积因为它是向量的基本运算,然后使用acos获得角度。

double angleInDegrees = acos ( cos(theta) ) * 180.0 / PI;

谢谢,但是有问题。当向量A与向量B平行(前方)时,我使用了这些向量:A<4,6,17>; B<4,6,-8>,它应该给出0度,因为y轴相同。但实际上它给出了约24.19度。当我尝试:A<4,6,17>; B<4,21,17>,它给出了约48.96度。应该是90度,因为向量B在A的顶部。你能看到哪里出了问题吗?Theta是整个公式还是如果不是怎么解决它? - Arundel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接