空间三维点绕任意空间直线旋转
来源:互联网 发布:revit是什么软件 编辑:程序博客网 时间:2024/05/20 07:59
绕任意轴旋转的情况比较复杂,主要分为两种情况,一种是平行于坐标轴的,一种是不平行于坐标轴的,对于平行于坐标轴的,我们首先将旋转轴平移至与坐标轴重合,然后进行旋转,最后再平移回去。
- 将旋转轴平移至与坐标轴重合,对应平移操作
- 旋转,对应操作
- 步骤1的逆过程,对应操作
整个过程就是
对于不平行于坐标轴的,可按如下方法处理。(该方法实际上涵盖了上面的情况)
- 将旋转轴平移至原点
- 将旋转轴旋转至YOZ平面
- 将旋转轴旋转至于Z轴重合
- 绕Z轴旋转θ度
- 执行步骤3的逆过程
- 执行步骤2的逆过程
- 执行步骤1的逆过程
假设用v1(a1, b2, c2)和v2(a2, b2, c2)来表示旋转轴,θ表示旋转角度。为了方便推导,暂时使用右手系并使用列向量,待得出矩阵后转置一下即可,上面步骤对应的流程图如下。
步骤1是一个平移操作,将v1v2平移至原点,对应的矩阵为
步骤2是一个旋转操作,将p(p = v2 -v1)旋转至XOZ平面,步骤3也是一个旋转操作,将p旋转至与Z轴重合,这两个操作对应的图如下。
做点p在平面YOZ上的投影点q。再过q做Z轴垂线,则r是p绕X轴旋转所得,且旋转角度为α,且
,
于是旋转矩阵为
现在将r绕Y轴旋转至与Z轴重合,旋转的角度为-beta(方向为顺时针),且
,
于是得到旋转矩阵为
最后是绕Z轴旋转,对应的矩阵如下
如果旋转轴是过原点的,那么第一步和最后一步的平移操作可以省略,也就是把中间五个矩阵连乘起来,再转置一下,得到下面的绕任意轴旋转的矩阵
即
对应的函数代码如下。
void RotateArbitraryAxis(D3DXMATRIX* pOut, D3DXVECTOR3* axis, float theta){ D3DXVec3Normalize(axis, axis); float u = axis->x; float v = axis->y; float w = axis->z; pOut->m[0][0] = cosf(theta) + (u * u) * (1 - cosf(theta)); pOut->m[0][1] = u * v * (1 - cosf(theta)) + w * sinf(theta); pOut->m[0][2] = u * w * (1 - cosf(theta)) - v * sinf(theta); pOut->m[0][3] = 0; pOut->m[1][0] = u * v * (1 - cosf(theta)) - w * sinf(theta); pOut->m[1][1] = cosf(theta) + v * v * (1 - cosf(theta)); pOut->m[1][2] = w * v * (1 - cosf(theta)) + u * sinf(theta); pOut->m[1][3] = 0; pOut->m[2][0] = u * w * (1 - cosf(theta)) + v * sinf(theta); pOut->m[2][1] = v * w * (1 - cosf(theta)) - u * sinf(theta); pOut->m[2][2] = cosf(theta) + w * w * (1 - cosf(theta)); pOut->m[2][3] = 0; pOut->m[3][0] = 0; pOut->m[3][1] = 0; pOut->m[3][2] = 0; pOut->m[3][3] = 1;
如果旋转轴是不过原点的,那么第一步和最后一步就不能省略,将所有七个矩阵连乘起来,得到如下变换矩阵
对应如下这个超长的矩阵,在这里(u, v, w) = (a2, b2, c2) - (a1, b1, c1),且是单位向量,a, b, c分别表示(a1, b1, c1)
将上面的过程写成函数,该函数接受四个参数,第一个参数是一个输出参数,用来保存得到的旋转矩阵,第二个和第三个参数是旋转轴的两个端点,最后一个参数是旋转角度θ,注意,在函数中我们已经将上面的矩阵转置了,因为上面是按照列向量计算的。
void RotateArbitraryLine(D3DXMATRIX* pOut, D3DXVECTOR3* v1, D3DXVECTOR3* v2, float theta){ float a = v1->x; float b = v1->y; float c = v1->z; D3DXVECTOR3 p = *v2 - *v1; D3DXVec3Normalize(&p, &p); float u = p.x; float v = p.y; float w = p.z; float uu = u * u; float uv = u * v; float uw = u * w; float vv = v * v; float vw = v * w; float ww = w * w; float au = a * u; float av = a * v; float aw = a * w; float bu = b * u; float bv = b * v; float bw = b * w; float cu = c * u; float cv = c * v; float cw = c * w; float costheta = cosf(theta); float sintheta = sinf(theta); pOut->m[0][0] = uu + (vv + ww) * costheta; pOut->m[0][1] = uv * (1 - costheta) + w * sintheta; pOut->m[0][2] = uw * (1 - costheta) - v * sintheta; pOut->m[0][3] = 0; pOut->m[1][0] = uv * (1 - costheta) - w * sintheta; pOut->m[1][1] = vv + (uu + ww) * costheta; pOut->m[1][2] = vw * (1 - costheta) + u * sintheta; pOut->m[1][3] = 0; pOut->m[2][0] = uw * (1 - costheta) + v * sintheta; pOut->m[2][1] = vw * (1 - costheta) - u * sintheta; pOut->m[2][2] = ww + (uu + vv) * costheta; pOut->m[2][3] = 0; pOut->m[3][0] = (a * (vv + ww) - u * (bv + cw)) * (1 - costheta) + (bw - cv) * sintheta; pOut->m[3][1] = (b * (uu + ww) - v * (au + cw)) * (1 - costheta) + (cu - aw) * sintheta; pOut->m[3][2] = (c * (uu + vv) - w * (au + bv)) * (1 - costheta) + (av - bu) * sintheta; pOut->m[3][3] = 1;}
- 空间三维点绕任意空间直线旋转
- HDU 2898 空间点关于直线旋转
- [转载]空间点绕任意轴旋转变换公式
- 空间点绕任意轴旋转变换公式
- 空间点绕向量旋转
- 空间向量绕任意轴旋转推导
- 3D 空间中物体绕任意轴旋转公式
- 定义空间的三维点Point3d
- 空间三维罪接近点对问题
- 点到空间直线的距离
- 空间直线的点向式
- 计算空间点到直线的距离
- 利用三维旋转矩阵在空间中旋转平面
- 三维坐标点绕任意轴旋转的新坐标计算
- 三维坐标点绕任意轴旋转的新坐标计算
- 点分直线,直线分平面,平面分空间
- 点分直线,直线分平面,平面分空间
- 空间两点绕某一固定点旋转公式
- Android学习 (十) 让TextView里面文字居中的方式
- 云片网--发送短信验证码服务端接口
- matlab 曲线交叉点
- android 关联自定义文件,文件管理器中打开自定文件类型
- Maven教程-简介安装配置创建
- 空间三维点绕任意空间直线旋转
- CString、CStringA 和 CStringW
- postgresql数据库存储过程、索引、触发器相关SQL梳理
- android开发之MediaPlayer+Service MP3播放器
- Charles 从入门到精通
- kafka系列(七)使用Kafka-Connect导入导出数据
- 1线程同步-底层支持
- TODO-3:css relative and absolute
- 利用link标签rel="alternate stylesheet"属性实现界面动态换肤