Math 同一平面内具有相同原点的两个三维向量之间的有符号角度
我需要的是位于同一3D平面内且具有相同原点的两个向量Va和Vb之间的有符号旋转角,知道:Math 同一平面内具有相同原点的两个三维向量之间的有符号角度,math,vector,3d,geometry,Math,Vector,3d,Geometry,我需要的是位于同一3D平面内且具有相同原点的两个向量Va和Vb之间的有符号旋转角,知道: 包含两个向量的平面是任意平面,不平行于XY或任何其他基数平面 是一个平面法线吗 两个向量和法线具有相同的原点O={0,0,0} Va-是测量Vn处左手旋转的参考 角度的测量方式应确保,如果平面为XY平面,则Va代表其X轴单位矢量 我想我应该执行一种坐标空间转换,使用Va作为X轴,Vb和Vn的叉积作为Y轴,然后使用一些2d方法,比如atan2()之类的。有什么想法吗?公式?将一个向量交叉到另一个向量中,并进行
我想我应该执行一种坐标空间转换,使用Va作为X轴,Vb和Vn的叉积作为Y轴,然后使用一些2d方法,比如atan2()之类的。有什么想法吗?公式?将一个向量交叉到另一个向量中,并进行规格化以得到单位向量 两个矢量之间角度的正弦等于叉积的大小除以两个矢量的大小:
您可以使用符号获取要签名的角度。要获得角度的符号,请取
Vn*(Va x Vb)
的符号。在XY平面的特殊情况下,这将减少到仅Va_x*Vb_y-Va_y*Vb_x
让θ为向量之间的角度。设C=Va为叉积Vb。然后
sinθ=长度(C)/(长度(Va)*
长度(Vb))
要确定θ是正的还是负的,请记住C垂直于Va和Vb,指向由θ确定的方向。特别是,C与Vn是平行的。在你的例子中,如果C指向与Vn相同的方向,那么θ是负的,因为你想要左手旋转。快速检查Vn和C点是否在同一方向的最简单计算方法可能是只取它们的点积;如果是正数,则它们指向同一方向
angle = acos(dotProduct(Va.normalize(), Vb.normalize()));
cross = crossProduct(Va, Vb);
if (dotProduct(Vn, cross) < 0) { // Or > 0
angle = -angle;
}
所有这些都来自于向量的基本性质。使用两个向量的叉积来获得由两个向量构成的平面的法线。然后检查该点积与原始平面法线之间的点积,以查看它们是否朝向同一方向
angle = acos(dotProduct(Va.normalize(), Vb.normalize()));
cross = crossProduct(Va, Vb);
if (dotProduct(Vn, cross) < 0) { // Or > 0
angle = -angle;
}
angle=acos(点积(Va.normalize(),Vb.normalize());
交叉=交叉积(Va,Vb);
if(点积(Vn,cross)<0{//或>0
角度=-角度;
}
您可以通过两个步骤完成此操作:
假设Vx是x轴,给定法线Vn,你可以通过叉积得到y轴,你可以将向量Vb投影到Vx和Vy上(通过点积你可以得到Vb到Vx和Vy的投影长度),给定平面上的(x,y)坐标,你可以使用atan2(y,x)得到范围[-pi,+pi]内的角度高级客户提供了以下解决方案(最初是对问题的编辑):
解决方案:
新浪=| Va x Vb |/(| Va |*| Vb |)
cosa=(Va.Vb)/(|Va |*| Vb |)
角度=atan2(新浪、cosa)
符号=Vn。(Va x Vb)
如果(sign我当前使用的解决方案似乎在这里丢失了。
假设平面法线已归一化(|Vn |==1
),则符号角度仅为:
对于从Va到Vb的右手旋转:
atan2((Va x Vb.Vn,Va.Vb)
对于从Va到Vb的左手旋转:
atan2((vbx Va.Vn,Va.Vb)
返回范围[-PI,+PI](或可用atan2实现返回的任何值)内的角度
和x
分别是点积和叉积
无需显式分支和除法/向量长度计算
解释为什么这样做:让alpha是向量之间的直接角度(0°到180°)和beta是我们正在寻找的角度(0°到360°),使用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)
这是一个Matlab代码,用于计算二维或三维两个向量u,v之间的有符号角度。该代码是自解释的。符号约定是在ix和iy([1,0,0],[0,1,0])或iy和iz([0,1,0],[0,0,1])之间输出正+90°
函数thetaDEG=angDist2Vecs(u,v)
如果长度(u)==3
%3D,可以使用十字来解析符号
uMod=sqrt(总和(u.^2));
vMod=sqrt(总和(v.^2));
uvPr=总和(u.*v);
Costeta=最小值(uvPr/uMod/vMod,1);
thetaDEG=acos(costheta)*180/pi;
%解析符号
cp=(交叉(u,v));
idxM=find(abs(cp)=max(abs(cp));
s=符号(cp(idxM(1));
如果s<0
thetaDEG=-thetaDEG;
结束
elseif长度(u)=2
%2D使用atan2
数据=(atan2(v(2),v(1))-atan2(u(2),u(1)))*180/pi;
其他的
错误('u,v必须是二维或三维向量');
结束
还有-是的,我知道“acos(Va.Vb)”但是,由于余弦的性质,它总是给出积极的结果。你能解释一下Va吗?它平行于Vn吗?Vn是平面的法向量,所以它垂直于Va和Vb-Vn最初是已知的。这个问题的任务被简化了。在这种特殊情况下,Vn是唯一一个最初与r一起已知的向量然后将旋转矩阵R.Va计算为Vn和基数向量之一的叉积:Va=normalize(vnx{0,1,0});不需要除以(|Va | | Vb |)
对于sin
和cos
。atan2
的工作方式是分母抵消。我猜这是针对二维向量,而需要针对三维向量。两个三维向量所属的平面与XY不平行,因此仅使用x和y分量
tan(beta) = sin(beta) / cos(beta) == ((Va x Vb) . Vn) / (Va . Vb)
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