如何求两个三维向量之间的夹角(要求值域在[0,2PI]之间)?

Tomcat4 2005-08-31 06:52:13
设两个规范化后三维向量n1(x1,y1,z1),n1(x2,y2,z2),按照计算机图形学书上计算两条直线的夹角的公式:
angle = arccos(dot(n1,n2))
由此得到的夹角值的范围是[0,PI]之间,由于我现在处理的是向量,它们之间的夹角的实际值域应该在[0,2PI]之间,请问如何计算得到两个向量的夹角在[0,2PI]之间?
...全文
9845 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
HUNTON 2005-09-07
  • 打赏
  • 举报
回复 1
定义:平面上的三点P1(x1,y1),P2(x2,y2),P3(x3,y3)的面积量:
|x1 x2 x3|
S(P1,P2,P3) = |y1 y2 y3| = (x1-x3)*(y2-y3) - (y1-y3)(x2-x3)
|1 1 1 |
当P1P2P3逆时针时S为正的,当P1P2P3顺时针时S为负的。

所以你只要算S(N2,0,N1)的值,
如果大于或等于0,angle = arccos(dot(n1,n2)),
小于0,则angle = 2PI - arccos(dot(n1,n2))
alphapaopao 2005-09-06
  • 打赏
  • 举报
回复
hehe
条条大路通罗马。
你的 dot 用 arccos 的时候,要注意数值稳定性问题 , 参见 http://www.alphasun.org/alphasun/techarticle/angle/Angle.htm
Tomcat4 2005-09-05
  • 打赏
  • 举报
回复
问题已经按照诸位的解释而解决,虽然有DOT得到的角度在[0,PI]之间,但是可以有n1×n2得到旋转轴的方向,所以仍然能够实现正确的旋转。谢谢!
寻开心 2005-09-02
  • 打赏
  • 举报
回复
问题主要就在于sin的数值获取不到
|a×b|=|a|*|b|*sin(theta)
但是|v|运算返回的数值永远是正数,因此asin的结果只能是0到PI/2的范围的,这才是问题的关键
kenshu111 2005-09-02
  • 打赏
  • 举报
回复
我认为再求一下arcsin()就可以知道是0-2PI之间的哪个180度半区间
寻开心 2005-09-02
  • 打赏
  • 举报
回复 1
在指定的N的时候,旋转才有0到2Pi的说法
在用a×b生成的N的时候,旋转角度只能是0到Pi
寻开心 2005-09-02
  • 打赏
  • 举报
回复 1
补充说明一下,在本人的blog当中的算法公式是:

theta = atan2 ( (a×b) *N, a*b )
这里面,N是a,b所在平面的单位法向量(这个方向也许和a×b相同,也许相反的)
也就是把a旋转theta到达b方向时候的转轴

当a和b是任意的空间向量,而N是未知的时候,一般取a×b作为旋转轴
那么这个时候,不需要上面的公式,只需要计算
theta = acos(a*b/|a|/|b|)
结果是0到Pi
而事实上,按照a×b作为转轴旋转的时候,角度只会是0到Pi之间的
syy64 2005-09-02
  • 打赏
  • 举报
回复
还请大侠们对上面的函数,提提意见和建议,以使它更加完善,这在我们的工作中用处很大。
alphapaopao 2005-09-02
  • 打赏
  • 举报
回复
楼上的可以构造一个旋转矩阵,或者叫方向余弦阵
syy64 2005-09-02
  • 打赏
  • 举报
回复
不在一条直线上的空间三点可以决定一个平面,可以不用求夹角;

// 功能:根据空间的三点(不在一条直线上,三点决定一个平面,
// 且三点以逆时针排序)来决定一个坐标系,
// 第一点与第二点 的连线作为X轴,平面的法线作为Z轴,第一点作为原点,
// 返回三个坐标轴的九个方向余弦。 2004.2.5. 2004.2.26.改
void CoordAxis(CPoint3DArray& pt, bool bCounterClock, double dAxisCos[][3])
{
// pt-->空间三点的坐标数组,点序以逆时针排序;
// bCounterClock-->点序的方向,逆时针是true;
// dAxisCos[][3]-->九个方向余弦,其中:
// dAxisCos[0][0]-->X轴的α方向余弦;
// dAxisCos[0][1]-->Y轴的α方向余弦;
// dAxisCos[0][2]-->Z轴的α方向余弦;
// dAxisCos[1][0]-->X轴的β方向余弦;
// dAxisCos[1][1]-->Y轴的β方向余弦;
// dAxisCos[1][2]-->Z轴的β方向余弦;
// dAxisCos[2][0]-->X轴的γ方向余弦;
// dAxisCos[2][1]-->Y轴的γ方向余弦;
// dAxisCos[2][2]-->Z轴的γ方向余弦;
int i;
double dArea, dAreaX, dAreaY, dAreaZ;
CPoint3D vXAxisVector, vYAxisVector, vZAxisVector;
CPoint3DArray ptt;

vXAxisVector = Vector(pt[1], pt[0]);
vXAxisVector = Normalize(vXAxisVector); // Use our function we created to normalize the normal (Makes it a length of one)
if(!bCounterClock)
{
dArea = 0.0;
dAreaX = 0.0;
dAreaY = 0.0;
dAreaZ = 0.0;
ptt.SetSize(4);
for(i=0;i<3;i++)ptt[i] = pt[i];
ptt[3] = ptt[0];
for(i=0;i<3;i++)dAreaZ += (ptt[i+1].x-ptt[i].x)*(ptt[i+1].y+ptt[i].y)*0.5;
for(i=0;i<3;i++)dAreaY += (ptt[i+1].x-ptt[i].x)*(ptt[i+1].z+ptt[i].z)*0.5;
for(i=0;i<3;i++)dAreaX += (ptt[i+1].y-ptt[i].y)*(ptt[i+1].z+ptt[i].z)*0.5;
dArea = dAreaZ;
if(fabs(dAreaY)>fabs(dArea))dArea = dAreaY;
if(fabs(dAreaX)>fabs(dArea))dArea = dAreaX;
vZAxisVector = Normal(pt);
if(dArea>0.0)
{
vZAxisVector = CPoint3D(0.0,0.0,0.0)-vZAxisVector;
}
}
else
vZAxisVector = Normal(pt);
vZAxisVector = Normalize(vZAxisVector); // Use our function we created to normalize the normal (Makes it a length of one)
vYAxisVector = Cross(vZAxisVector, vXAxisVector); // Take the cross product of our 2 vectors to get a perpendicular vector

// Now we have a normal, but it's at a strange length, so let's make it length 1.

vYAxisVector = Normalize(vYAxisVector); // Use our function we created to normalize the normal (Makes it a length of one)
dAxisCos[0][0] = vXAxisVector.x;
dAxisCos[0][1] = vYAxisVector.x;
dAxisCos[0][2] = vZAxisVector.x;
dAxisCos[1][0] = vXAxisVector.y;
dAxisCos[1][1] = vYAxisVector.y;
dAxisCos[1][2] = vZAxisVector.y;
dAxisCos[2][0] = vXAxisVector.z;
dAxisCos[2][1] = vYAxisVector.z;
dAxisCos[2][2] = vZAxisVector.z;
}

以上函数仅供参考。
寻开心 2005-09-01
  • 打赏
  • 举报
回复
http://blog.csdn.net/happy__888/archive/2005/04/28/367008.aspx
Tomcat4 2005-09-01
  • 打赏
  • 举报
回复
alphapaopao(炮炮[www.alphasun.org]图形学) 请继续...
Tomcat4 2005-09-01
  • 打赏
  • 举报
回复
可考虑将两向量所决定的平面置平?
这需要旋转这个平面,在旋转的时候仍然需要求这个平面与XOY(假设为旋转后的平面)之间的夹角,好像还是不好解决啊?

syy64(太平洋) 说的考虑哪个向量作为其实向量,这个在计算向量夹角的时候的确应该考虑,但是从公式angle = arccos(dot(n1,n2))中并没有看出这两个向量的顺序会影响这个angle的值啊?高手有没有办法解决啊?

alphapaopao 2005-09-01
  • 打赏
  • 举报
回复
三维空间两个矢量,如果不借助一个辅助平面,则无法定义一个在 [0, 2*PI) 之间的夹角。

搂住明白上面的话之后,我再往下讲。
syy64 2005-09-01
  • 打赏
  • 举报
回复
主要是考虑哪个作为起始向量,可考虑将两向量所决定的平面置平,在平面上求夹角应该比较容易。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧