计算两个向量之间的顺时针角度的直接方法

新手上路,请多包涵

我想找出 2 个向量(2D,3D)之间的顺时针角度。

点积的经典方式给了我内角(0-180 度),我需要使用一些 if 语句来确定结果是我需要的角度还是它的补角。

你知道计算顺时针角度的直接方法吗?

原文由 Mircea Ispas 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

2D案例

就像 点积 与角度的余弦成正比一样, 行列式 与其正弦成正比。所以你可以这样计算角度:

 dot = x1*x2 + y1*y2      # dot product between [x1, y1] and [x2, y2]
det = x1*y2 - y1*x2      # determinant
angle = atan2(det, dot)  # atan2(y, x) or atan2(sin, cos)

该角度的方向与坐标系的方向相匹配。在 左手坐标系中,即 x 指向右和 y 下,这在计算机图形学中很常见,这意味着你会得到一个顺时针角度的正号。如果坐标系的方向是数学的, y 向上,你会得到逆时针角度,这是数学中的惯例。更改输入的顺序将更改符号,因此如果您对符号不满意,只需交换输入即可。

3D案例

在 3D 中,两个任意放置的向量定义了它们自己的旋转轴,垂直于两者。该旋转轴没有固定方向,这意味着您也无法唯一固定旋转角度的方向。一个常见的约定是让角度始终为正,并以适合正角度的方式定位轴。在这种情况下,归一化向量的点积足以计算角度。

 dot = x1*x2 + y1*y2 + z1*z2    #between [x1, y1, z1] and [x2, y2, z2]
lenSq1 = x1*x1 + y1*y1 + z1*z1
lenSq2 = x2*x2 + y2*y2 + z2*z2
angle = acos(dot/sqrt(lenSq1 * lenSq2))

编辑:请注意,出于数字原因,一些评论和替代答案建议不要使用 acos ,特别是如果要测量的角度很小。

平面嵌入 3D

一种特殊情况是您的向量不是任意放置的,而是位于具有已知法线向量 n 的平面内。然后旋转轴也将在方向 n 上,并且 n 的方向将固定该轴的方向。在这种情况下,您可以调整上面的 2D 计算,包括 n行列式 中,使其大小为 3×3。

 dot = x1*x2 + y1*y2 + z1*z2
det = x1*y2*zn + x2*yn*z1 + xn*y1*z2 - z1*y2*xn - z2*yn*x1 - zn*y1*x2
angle = atan2(det, dot)

其工作的一个条件是法线向量 n 具有单位长度。如果没有,您将不得不对其进行标准化。

作为三重产品

正如 @Excrubulent 在建议的编辑中指出的那样,这个决定因素也可以表示为 三重乘积

 det = n · (v1 × v2)

这在某些 API 中可能更容易实现,并且对这里发生的事情给出了不同的看法:叉积与角度的正弦成正比,并且垂直于平面,因此是 n 的倍数。因此,点积将基本上测量该向量的长度,但附加了正确的符号。

原文由 MvG 发布,翻译遵循 CC BY-SA 4.0 许可协议

对于 2D 情况,atan2 可以轻松计算 (1, 0) 向量(X 轴)与您的向量之一之间的角度。公式为:

 Atan2(y, x)

所以你可以很容易地计算出两个角度相对于X轴的差异

angle = -(atan2(y2, x2) - atan2(y1, x1))

为什么不将其用作默认解决方案? atan2 不够高效。最佳答案的解决方案更好。在 C# 上的测试表明,这种方法 的性能降低了 19.6% (100 000 000 次迭代)。这不是关键但令人不快。

因此,另一个可能有用的信息:

以度为单位的外部和内部之间的最小角度:

 abs(angle * 180 / PI)

以度为单位的全角:

 angle = angle * 180 / PI
angle = angle > 0 ? angle : 360 - angle

或者

angle = angle * 180 / PI
if (angle < 0) angle = 360 - angle;

原文由 Oko Lenmi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题