在同一平面内具有相同原点的两个3Dvector之间的夹angular
我需要的是两个vectorVa和Vb之间的符号旋转angular度,这两个vector位于相同的3D平面内并具有相同的原点,因此知道:
- 包含两个vector的平面是任意的,并不平行于XY或任何其他的基本平面
- Vn – 是一个正常的飞机
- 两个vector与法线都具有相同的原点O = {0,0,0}
- Va – 是测量Vn左旋的参考
angular度应该这样测量,所以如果平面是XY平面,Va将代表X轴单位vector。
我想我应该用Va作为X轴,Vb和Vn的叉积作为Y轴进行一种坐标空间变换,然后像atan2()那样使用一些2d方法。 有任何想法吗? 公式?
使用这两个vector的叉积来得到由这两个vector形成的平面的法线。 然后检查它与原始平面法线之间的点积,看它们是否面向相同的方向。
angle = acos(dotProduct(Va.normalize(), Vb.normalize())); cross = crossProduct(Va, Vb); if (dotProduct(Vn, cross) < 0) { // Or > 0 angle = -angle; }
我目前使用的解决scheme似乎在这里丢失。 假定平面法线被归一化( |Vn| == 1
),符号angular度就是:
atan2((Vb x Va) . Vn, Va . Vb)
它返回范围[-PI,+ PI](或任何可用的atan2实现返回)的angular度。
.
x
分别是点和叉积。
没有明确的分支,没有分割/向量长度计算是必要的。 使用Va x Vb
代替左边的旋转
为什么这个工作的解释:让alpha是vector(0°到180°)和我们正在寻找的angular度(0°到360°)之间的正交angular度与beta == alpha
或beta == 360° - alpha
Va . Vb == |Va| * |Vb| * cos(alpha) (by definition) == |Va| * |Vb| * cos(beta) (cos(alpha) == cos(-alpha) == cos(360° - alpha) Va x Vb == |Va| * |Vb| * sin(alpha) * n1 (by definition; n1 is a unit vector perpendicular to Va and Vb with orientation matching the right-hand rule) Therefore (again assuming Vn is normalized): n1 . Vn == 1 when beta < 180 n1 . Vn == -1 when beta > 180 ==> (Va x Vb) . Vn == |Va| * |Vb| * sin(beta)
最后
tan(beta) = sin(beta) / cos(beta) == ((Va x Vb) . Vn) / (Va . Vb)
你可以通过两步来做到这一点:
-
确定两个向量之间的angular度
theta = acos(Va,Vb的点积)。 假设Va,Vb被归一化。 这将给出两个向量之间的最小angular度
-
确定angular度的符号
查找vectorV3 = Va,Vb的叉积。 (顺序很重要)
如果(V3,Vn的点积)为负,则θ为负。 否则,theta是积极的。
您可以使用点积来获取angular度。 为了得到angular度的符号,取Vn * (Va x Vb)
的符号。 在XY平面的特殊情况下,这仅仅减小到Va_x*Vb_y - Va_y*Vb_x
。
将一个向量交叉到另一个向量并归一化以获得单位向量。
两个vector之间angular度的正弦等于叉积的大小除以两个vector的大小:
假设Vx是x轴,给定正常的Vn,可以通过叉积得到y轴,可以将vectorVb投影到Vx和Vy(通过点积可以得到Vb的投影长度) Vx和Vy),给定平面上的(x,y)坐标,可以使用atan2(y,x)来获取范围[-pi,+ pi]
高级客户提供了以下解决scheme(最初是对该问题的编辑):
SOLUTION: sina = |Va x Vb| / ( |Va| * |Vb| ) cosa = (Va . Vb) / ( |Va| * |Vb| ) angle = atan2( sina, cosa ) sign = Vn . ( Va x Vb ) if(sign<0) { angle=-angle }
设θ是vector之间的angular度。 令C = Va交叉乘积Vb。 然后
sinθ=长度(C)/(长度(Va)*长度(Vb))
要确定θ是正值还是负值,请记住C垂直于Va和Vb,指向由右手规则确定的方向。 所以特别是C与Vn平行。 在你的情况下,如果C指向与Vn相同的方向,那么theta是负数,因为你想要左旋。 可能是最简单的计算方法来快速检查Vn和C指向同一个方向是否只是他们的点积; 如果是肯定的,则指向相同的方向。
所有这一切都来自交叉产品的基本属性。
这是用于计算两个向量u,v之间的符号angular的Matlab代码,无论是2D还是3D。 代码是自我解释的。 符号约定是在ix和iy([1,0,0],[0,1,0])或iy和iz([0,1,0],[0, 0,1])
function thetaDEG = angDist2Vecs(u,v) if length(u)==3 %3D, can use cross to resolve sign uMod = sqrt(sum(u.^2)); vMod = sqrt(sum(v.^2)); uvPr = sum(u.*v); costheta = min(uvPr/uMod/vMod,1); thetaDEG = acos(costheta)*180/pi; %resolve sign cp=(cross(u,v)); idxM=find(abs(cp)==max(abs(cp))); s=sign(cp(idxM(1))); if s < 0 thetaDEG = -thetaDEG; end elseif length(u)==2 %2D use atan2 thetaDEG = (atan2(v(2),v(1))-atan2(u(2),u(1)))*180/pi; else error('u,v must be 2D or 3D vectors'); end