在同一平面内具有相同原点的两个3Dvector之间的夹angular

我需要的是两个vectorVa和Vb之间的符号旋转angular度,这两个vector位于相同的3D平面内并具有相同的原点,因此知道:

  1. 包含两个vector的平面是任意的,并不平行于XY或任何其他的基本平面
  2. Vn – 是一个正常的飞机
  3. 两个vector与法线都具有相同的原点O = {0,0,0}
  4. 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 == alphabeta == 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) 

你可以通过两步来做到这一点:

  1. 确定两个向量之间的angular度

    theta = acos(Va,Vb的点积)。 假设Va,Vb被归一化。 这将给出两个向量之间的最小angular度

  2. 确定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的大小:

http://mathworld.wolfram.com/CrossProduct.html

假设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