我需要的是位于同一 3D 平面内且具有相同原点的两个向量 Va 和 Vb 之间的有符号旋转角,知道:
- 包含这两个向量的平面是任意的,并且不平行于 XY 或任何其他基本平面
- Vn - 是平面法线
- 两个向量与法线具有相同的原点 O = { 0, 0, 0 }
- Va - 是测量 Vn 处左手旋转的参考 角度
应以这种方式测量,因此如果平面是 XY 平面,Va 代表它的 X 轴单位向量。
我想我应该通过使用 Va 作为 X 轴和 Vb 和 Vn 的叉积作为 Y 轴来执行一种坐标空间变换,然后只使用一些 2d 方法,例如 atan2() 或其他方法。有什么想法吗?公式?
What I need is a signed angle of rotation between two vectors Va and Vb lying within the same 3D plane and having the same origin knowing that:
- The plane contatining both vectors is an arbitrary and is not parallel to XY or any other of cardinal planes
- Vn - is a plane normal
- Both vectors along with the normal have the same origin O = { 0, 0, 0 }
- Va - is a reference for measuring the left handed rotation at Vn
The angle should be measured in such a way so if the plane would be XY plane the Va would stand for X axis unit vector of it.
I guess I should perform a kind of coordinate space transformation by using the Va as the X-axis and the cross product of Vb and Vn as the Y-axis and then just using some 2d method like with atan2() or something. Any ideas? Formulas?
发布评论
评论(10)
令 theta 为向量之间的角度。令 C = Va 叉积 Vb。然后
要确定 theta 是正值还是负值,请记住 C 垂直于 Va 和 Vb,指向由 右手定则。特别是,C 与 Vn 平行。在您的情况下,如果 C 指向与 Vn 相同的方向,则 theta 为负,因为您想要左手旋转。快速检查 Vn 和 C 是否指向同一方向的最简单计算方法可能就是取它们的点积;如果为正,则它们指向同一方向。
所有这些都源自叉积的基本属性。
Let theta be the angle between the vectors. Let C = Va cross product Vb. Then
To determine if theta is positive or negative, remember that C is perpendicular to Va and Vb pointing in the direction determined by the right-hand rule. So in particular, C is parallel to Vn. In your case, if C points in the same direction as Vn, then theta is negative, since you want left-handed rotation. Probably the easiest computational way to quickly check if Vn and C point in the same direction is to just take their dot product; if it is positive they point in the same direction.
All this follows from elementary properties of the cross product.
假设Vx是x轴,给定法线Vn,通过叉积可以得到y轴,可以将向量Vb投影到Vx和Vy(通过点积可以得到Vb投影到Vy上的长度) Vx 和 Vy),给定平面上的 (x, y) 坐标,可以使用 atan2(y, x) 获取 [-pi, +pi] 范围内的角度
Suppose Vx is the x-axis, given the normal Vn, you can get the y-axis by cross product, you can project the vector Vb to Vx and Vy (by the dot product you can get the length of the projection of Vb onto Vx and Vy), given the (x, y) coordinate on the plane, you can use atan2(y, x) to get the angle in the range [-pi, +pi]
这是 Matlab 代码,用于计算 2D 或 3D 中两个向量 u,v 之间的符号角。该代码是不言自明的。符号约定是在 ix 和 iy ([1,0,0],[0,1,0]) 或 iy 和 iz ([0,1,0],[0, 0,1])
This is the Matlab code to compute the signed angle between two vectors u,v either in 2D or in 3D. The code is self explanatory. The sign convention is such that a positive +90° is output between ix and iy ([1,0,0],[0,1,0]) or iy and iz ([0,1,0],[0,0,1])
我目前使用的解决方案似乎在这里缺失。
假设平面法线已归一化 (
|Vn| == 1
),则带符号的角度很简单:对于从 Va 到 Vb 的右手旋转:
atan2((Va x Vb) . Vn, Va . Vb)
对于从 Va 到 Vb 的左手旋转:
atan2((Vb x Va) . Vn, Va . Vb)
返回范围内的角度[-PI, +PI] (或任何可用的 atan2 实现返回的内容)。
.
和x
分别是点积和叉积。不需要显式分支,也不需要除法/向量长度计算。
解释其原理:设 alpha 为向量之间的直角(0° 到 180°),beta 为我们要查找的角度(0° 到 360°),其中
beta == alpha
或beta == 360° - alpha
最后
The solution I'm currently using seems to be missing here.
Assuming that the plane normal is normalized (
|Vn| == 1
), the signed angle is simply:For the right-handed rotation from Va to Vb:
atan2((Va x Vb) . Vn, Va . Vb)
For the left-handed rotation from Va to Vb:
atan2((Vb x Va) . Vn, Va . Vb)
which returns an angle in the range [-PI, +PI] (or whatever the available atan2 implementation returns).
.
andx
are the dot and cross product respectively.No explicit branching and no division/vector length calculation is necessary.
Explanation for why this works: let alpha be the direct angle between the vectors (0° to 180°) and beta the angle we are looking for (0° to 360°) with
beta == alpha
orbeta == 360° - alpha
Finally
使用两个向量的叉积来获得两个向量形成的平面的法线。然后检查其与原始平面法线之间的点积,看看它们是否面向同一方向。
Use cross product of the two vectors to get the normal of the plane formed by the two vectors. Then check the dotproduct between that and the original plane normal to see if they are facing the same direction.
您可以分两步完成此操作:
确定两个向量之间的角度
theta = acos(Va、Vb 的点积)。假设 Va、Vb 已归一化。这将给出两个向量之间的最小角度
确定角度的符号
求向量 V3 = Va、Vb 的叉积。 (顺序很重要)
如果(V3、Vn 的点积)为负,则 theta 为负。否则,theta 为正。
You can do this in two steps:
Determine the angle between the two vectors
theta = acos(dot product of Va, Vb). Assuming Va, Vb are normalized. This will give the minimum angle between the two vectors
Determine the sign of the angle
Find vector V3 = cross product of Va, Vb. (the order is important)
If (dot product of V3, Vn) is negative, theta is negative. Otherwise, theta is positive.
您可以使用点积获得角度向上签名。要获取角度的符号,请取
Vn * (Va x Vb)
的符号。在 XY 平面的特殊情况下,这会简化为Va_x*Vb_y - Va_y*Vb_x
。You can get the angle up to sign using the dot product. To get the sign of the angle, take the sign of
Vn * (Va x Vb)
. In the special case of the XY plane, this reduces to justVa_x*Vb_y - Va_y*Vb_x
.高级客户提供了以下解决方案(最初是对问题的编辑):
Advanced Customer provided the following solution (originally an edit to the question):
将一个向量与另一个向量交叉并标准化以获得单位向量。
两个向量之间角度的正弦等于叉积的大小除以两个向量的大小:
http://mathworld.wolfram.com/CrossProduct.html
Cross one vector into the other and normalize to get the unit vector.
The sine of the angle between the two vectors equals the magnitude of the cross product divided by the magnitudes of the two vectors:
http://mathworld.wolfram.com/CrossProduct.html
对于使用 Python 的用户,Adrian Leonhard 提供的解决方案现已在 scikit-spatial 库(最新版本即将推出)。查找
Vector
的angle_signed_3d
下面是两个例子:
For those using Python, the solution provided by Adrian Leonhard is now implemented in the scikit-spatial library (the latest version will be available soon). Look for the
angle_signed_3d
of theVector
class.Here are two examples: