欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

上期讲到
绕任一向量旋转矩阵计算思考与实现
点击前往
点击前往

问题提出

之前讲到绕任一向量旋转矩阵实现,原来的向量都是从原点出发,现在把出发点改变成任意一点。

除了需要计算旋转矩阵,还可以支持2个旋转矩阵的乘法操作。就是2个旋转矩阵依次作用以后的一个综合结果。

问题分析

从某点出发沿某一方向旋转实现

从原点出发的旋转是已经实现的,我的思路是把坐标系统一平移一个(-x0, -y0,-z0),然后作用旋转矩阵,最后再平移回去。

用公式表示, RT1表示旋转矩阵,O1表示出发点。

P ′ = R T 1 ⋅ ( P − O 1 ) + O 1 ( 1 ) P' = RT1\cdot(P-O1)+O1 (1) P′=RT1⋅(P−O1)+O1(1)

既我们只要用一个旋转矩阵RT加一个出发点O就可以表示这个旋转动作。那么如果是2个旋转动作叠加怎么去用一个旋转动作来表示呢。

旋转相乘

有一种方法是用奇次矩阵来表示一个平移和旋转的组合,然后矩阵可以相乘,但是这种方式需要用到4*4的矩阵效率上没有3*3的矩阵来得高。

我这边通过公式推导得到一种新的表示方法。

首先对式子(1)进行展开再合并同类项得到

P ′ = R T 1 ⋅ P + ( I − R T 1 ) ⋅ O 1 P'=RT1\cdot P+(I-RT1)\cdot O1 P′=RT1⋅P+(I−RT1)⋅O1

( I − R T 1 ) ⋅ O 1 是一个常量, (I-RT1)\cdot O1 是一个常量, (I−RT1)⋅O1是一个常量,

即只要一个表示形如 R T ⋅ P + Q ( Q 是一个常量 ) 的形式, 即只要一个表示形如 RT\cdot P+Q(Q是一个常量)的形式, 即只要一个表示形如RT⋅P+Q(Q是一个常量)的形式,

就可用一个矩阵加一个出发点的形式来表示。 就可用一个矩阵加一个出发点的形式来表示。 就可用一个矩阵加一个出发点的形式来表示。

出发点 O = ( I − R T ) − 1 Q 出发点O=(I-RT)^{-1}Q 出发点O=(I−RT)−1Q

现在有第二个旋转RT2,O2作用于P’ 得到

P ′ ′ = R T 2 ⋅ P ′ + ( I − R T 2 ) ⋅ O 2 P''=RT2\cdot P' + (I-RT2)\cdot O2 P′′=RT2⋅P′+(I−RT2)⋅O2

= R T 2 ⋅ R T 1 ⋅ P + R T 2 ⋅ ( I − R T 1 ) ⋅ O 1 + ( I − R T 2 ) ⋅ O 2 =RT2\cdot RT1 \cdot P + RT2\cdot (I-RT1)\cdot O1 + (I-RT2)\cdot O2 =RT2⋅RT1⋅P+RT2⋅(I−RT1)⋅O1+(I−RT2)⋅O2

上式中 , R T = R T 2 ⋅ R T 1 上式中, RT = RT2\cdot RT1 上式中,RT=RT2⋅RT1

O = ( I − R T ) − 1 ⋅ [ R T 2 ⋅ ( I − R T 1 ) ⋅ O 1 + ( I − R T 2 ) ⋅ O 2 ] O = (I-RT)^{-1}\cdot [RT2\cdot (I-RT1)\cdot O1 + (I-RT2)\cdot O2] O=(I−RT)−1⋅[RT2⋅(I−RT1)⋅O1+(I−RT2)⋅O2]

这样,我们就得了两个刚体变换的综合变换。

但是上面的方法有一个问题,当(I-RT)不可逆时,那么该公式失效。
我的理解是,当(I-RT)不可逆时,O并不是没有解,而是有很多个解。

那么我们要另选他法。

再观察(1)式,其实我们并不需要求出O,只要求出Q就可以了。

R T = R T 2 ⋅ R T 1 , Q = R T 2 ⋅ Q 1 + Q 2 RT = RT2\cdot RT1, Q=RT2\cdot Q_1 + Q_2 RT=RT2⋅RT1,Q=RT2⋅Q1​+Q2​

这个方法与奇次矩阵相比,计算量小很多。

代码实现

  • 代码链接点击前往
  • 代码链接点击前往
  • 代码链接点击前往

namespace acamcad {const double pi = acos(-1);using Point = Eigen::Vector3d;class RigidRTMatrix {private:Eigen::Matrix3d mat;Eigen::Vector3d trans;public:RigidRTMatrix(Point start, Point end, double theta) {cout << "generate RigidRTMatrix 2" << endl;Eigen::Vector3d v = end - start;cout << "v:" << v << endl;cout << "angle:" << theta << endl;assert(!v.isZero());// Point::Zero();v.normalize();Eigen::Vector3d X(1,0,0);Eigen::Vector3d m = v.cross(X);// todo m=0时特殊处理if (m.isZero()) {if (v.dot(X) > 0) m = { 0,1,0 }; // 直接等于Y轴else m = { 0,-1,0 }; // 等于Y轴的反轴}auto RY = GetRY(m);// 将v 旋转至ZOX 平面。auto vZOX = RY * v;auto RX = GetRX(vZOX);auto Xrotate = GetXRotate(theta);mat = RY.transpose() * RX.transpose() * Xrotate * RX * RY;cout << "mat create :" << mat << endl;trans = (Eigen::Matrix3d::Identity() - mat) * start; // 存储总体位移}RigidRTMatrix() {}// 给定YOX平面上的单位M向量,将其旋转到Y轴上。Eigen::Matrix3d GetRY(Eigen::Vector3d m) {assert(!m.isZero());m.normalize();Eigen::Matrix3d RY;RY.setIdentity();RY(1, 1) = m.y();RY(1, 2) = m.z();RY(2, 1) = -m.z();RY(2, 2) = m.y();return RY;}// 给定ZOX平面上的单位M向量,将其旋转到X轴上。Eigen::Matrix3d GetRX(Eigen::Vector3d m) {assert(!m.isZero());m.normalize();Eigen::Matrix3d RX;RX.setIdentity();RX(0, 0) = m.x();RX(0, 2) = m.z();RX(2, 0) = -m.z();RX(2, 2) = m.x();return RX;}// 给定ZOX平面上的单位M向量,将其旋转到X轴上。Eigen::Matrix3d GetXRotate(double theta) {double rad = theta / 180 * pi;Eigen::Matrix3d X;X.setIdentity();X(1, 1) = cos(rad);X(1, 2) = -sin(rad);X(2, 1) = sin(rad);X(2, 2) = cos(rad);return X;}double angleMod(double theta) {while (theta < -180)theta += 360;while (theta > 180)theta -= 360;return theta;}Point Trans(Point &a) {return mat * a + trans;}friend static RigidRTMatrix operator*(RigidRTMatrix& a, RigidRTMatrix& b) {RigidRTMatrix multi;multi.mat = a.mat * b.mat;multi.trans = a.mat * b.trans + a.trans;return multi;}};
}

代码测试


可以看出一个点依次作用与用一次综合矩阵的效果是一样的。


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。

欢迎添加我的公众号,进群交流。

从某一点出发沿任意一方向旋转矩阵计算思考与实现相关推荐

  1. python n维向量向任意方向旋转,求旋转矩阵

    本来想做绕轴旋转,绕轴旋转是在垂直于轴向量的空间里旋转,但是n维空间里与某个向量垂直的空间为n-1维,而旋转只在二维空间里有定义.所以这里就改成了,向任意方向旋转. 计算单位向量 X = ( x 1 ...

  2. java图像处理之实现任意角度图像旋转

    原理及步骤: 1.旋转角度:图像顺时针或逆时针旋转的角度,以θ表示,需要用户输入: 2.旋转中心:一般以图像中心作为旋转中心,周围像素围绕其旋转: 3.画布大小:由于图像旋转后产生的图像宽和高与原始图 ...

  3. matlab中如何转动三维图_MATLAB小技巧之:绕任意空间轴旋转三维图形

    x=1:0.1:10; y=sin(x); c=cosd(15); s=sind(15); X=x*c-y*s; Y=x*s+y*c; plot(x,y) hold on plot(X,Y) 这就是新 ...

  4. 怎么对Revit族三个方向旋转

    对revit族三个方向旋转 做原始族: 放到基于面的族模板上: 创建公制常规模型, 左视图方向如下: 注意: 使用工作平面; 先画角度, 再标注角度, 创建 "绕X轴旋转角度" 参 ...

  5. unity物体自身轴旋转_unity3D实现物体任意角度自旋转

    本文实例为大家分享了unity3D实现物体任意角度自旋转的具体代码,供大家参考,具体内容如下 主要涉及函数: Input.GetAxis("Mouse x") 可取得鼠标横向(x轴 ...

  6. 物体绕任意向量的旋转——四元数法、旋转矩阵法、欧拉角法的比较

    3D空间中的旋转可用旋转矩阵.欧拉角或四元数等形式来表示,他们不过都是数学工具,其中在绕任意向量的旋转方面,旋转矩阵和四元数两种工具用的较多,欧拉角由于存在万向节死锁等问题,使用存在限制. (本文假设 ...

  7. element icon图标方向旋转

    element icon图标方向旋转 style="transform:rotate(90deg)"

  8. Camera中onPreviewFrame()方法的视频方向旋转

    1.旋转90度 private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) {byte [] y ...

  9. 基于exif信息进行图片方向旋转修正

    基于exif信息进行图片方向旋转修正 在处理标注数据的时候,发现标注框不吻合经过分析发现标注软件在读取图片时,读取了图片的exif信息,并对图片进行了旋转,所以标注的坐标时旋转后的坐标. 解决方法有两 ...

最新文章

  1. 【干货】智能电视UI设计那些事儿
  2. Python即时网络爬虫项目: 内容提取器的定义(Python2.7版本)
  3. DOM 事件深入浅出(二)
  4. linux 高级IO函数之sendfile splice tee
  5. SQL Server 2005 Express数据库为“只读”
  6. 苹果手机型号对应表及尺寸
  7. post 请求下载文件
  8. Python数据分析与展示(一)(基于北理MOOC)
  9. js获取 当前URL中的参数
  10. 基于Key过期失效实现 ‘N分钟内请勿重复提交“ 功能
  11. 计算机设置u盘启动,③、设置U盘启动教程
  12. 提取文件原生ico图标
  13. webpack的source-map的详解
  14. 百度BML-飞桨服务器以及Jetson nano部署实战案例(下)
  15. centos安装部分开发软件
  16. ANSYS ICEM CFD二维结构网络生成实例——流动传热
  17. Android基于安卓手机个人理财系统
  18. “网络吸血鬼” Leech
  19. postman接口批量测试
  20. uniapp开发app真机调试连接电脑服务器请求失败解决方法

热门文章

  1. C++ bitset的使用
  2. Java 9 与 Java 10
  3. win10环境下Android SDK下载安装及配置教程----Android SDK安装
  4. python中类的self到底是什么
  5. VSCode全配置(c++、unity、html...等配置和好用设置,持续更新)
  6. python中ipaddr库用法详解
  7. matlab进行数值积分的主要函数使用方法
  8. 记一次失败的《将视频中的音频转换成文字》的经历
  9. 【Java】装箱拆箱
  10. 别让假装努力毁了你,最强的68道软件测试基础问答题你能答的溜嘛?