目录
综述
今天听了闫令琪老师的lecture3:Transformation
就我所学习的内容做了一下作业0,将我的解决方法与遇到的问题粘贴于此。
问题描述
给定一个点 P=(2,1), 将该点绕原点先逆时针旋转 45◦,再平移 (1,2), 计算出变换后点的坐标。
用到的库和命名空间
#include <iostream>
#include <Eigen/Core>
#include <cmath>
using namespace std;
using namespace Eigen;
解决思路
方法一:齐次坐标进行计算
第一个方法是使用齐次坐标来进行计算。
齐次坐标中(T表示转置矩阵):
定义2D点:2D point = (x,y,1)T
定义2D向量:2D vector=(x,y,0)T
使用齐次坐标矩阵计算变换后的坐标方法是(详细请看视频):
这一步就是进行了仿射变换。
第一步:在代码中使用eigen定义上图中第一个3×3的矩阵如下:
// 定义一个3*3的矩阵affine,作为仿射矩阵
// 根据题意,先旋转45°后水平方向移动1,垂直方向移动2,得到仿射矩阵如下
// [cos45°,-sin45°,1]
// [sin45°, cos45°,2]
// [ 0 , 0 ,1]
Matrix3f affine;
// C++中cos,sin,asin,acos这些三角函数操作的是弧度,而非角度,需要把角度转化为弧度.弧度 = 角度 * Pi / 180;
affine << cos(45 * acos(-1) / 180), -sin(45 * acos(-1) / 180), 1,
sin(45 * acos(-1) / 180), cos(45 * acos(-1) / 180), 2,
0, 0, 1;
第二步:将P点以矩阵的形式定义出来(使用齐次坐标)
// 定义一个三行一列的矩阵p,作为p点,p点如下
// [ 2 ]
// [ 1 ]
// [ 1 ]
MatrixXf p(3, 1);
p << 2,
1,
1;
第三步:获得结果(注意,仿射矩阵必须写在点矩阵左边,才是将仿射矩阵应用于点矩阵之上)
cout << "********result********" << endl;
cout << affine * p << endl;
结果如图:
方法二:先进行线性计算,再进行平移计算
仿射变换Affine Transformation实际上就是先进行线性变换再进行平移。
不使用齐次坐标情况下,我们可以如下计算:
第一步:将线性变化矩阵表示出来
Matrix2f linear;
linear << cos(45 * acos(-1) / 180), -sin(45 * acos(-1) / 180),
sin(45 * acos(-1) / 180), cos(45 * acos(-1) / 180);
第二步:定义P点(这里取名为p2)
MatrixXf p2(2, 1);
p2 << 2,
1;
第三步:定义平移矩阵
MatrixXf translation(2,1);
translation << 1,
2;
第四步:获得结果
cout << "********result********" << endl;
cout << (linear * p2) + translation << endl;
结果如图:
和齐次坐标计算结果是完全一样的。
编码中遇到的问题
问题一:不会定义3行1列的矩阵
使用Eigen中的Matrix2d,Matrix3d,必须分别输入足够的数字,因为这固定是2×2矩阵、3×3矩阵。
定义3行1列矩阵方法如下:
MatrixXf p(3, 1);
由此,就必须输入3个数字了。
以此类推,定义m行n列矩阵就是MatrixXf 矩阵名(m, n);
问题二:相同数字类型的矩阵才能做运算
我一开始定义点是MatrixXd,线性、平移矩阵是Matrix3f和MatrixXd。因为有float类型有decimal类型不能共通进行计算。
所以我最后全部定义成float类型就可以了。
完整代码
// Program1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Eigen/Core>
#include <cmath>
using namespace std;
using namespace Eigen;
int main()
{
cout << "--------------------method1--------------------" << endl;
/* 方法一 */
// 定义一个三行一列的矩阵p,作为p点,p点如下
// [ 2 ]
// [ 1 ]
// [ 1 ]
MatrixXf p(3, 1);
p << 2,
1,
1;
cout << "********p********" << endl;
cout << p << endl;
// 定义一个3*3的矩阵affine,作为仿射矩阵
// 仿射矩阵如下
// [cos45°,-sin45°,1]
// [sin45°, cos45°,2]
// [ 0 , 0 ,1]
Matrix3f affine;
// C++中cos,sin,asin,acos这些三角函数操作的是弧度,而非角度,需要把角度转化为弧度.弧度 = 角度 * Pi / 180;
affine << cos(45 * acos(-1) / 180), -sin(45 * acos(-1) / 180), 1,
sin(45 * acos(-1) / 180), cos(45 * acos(-1) / 180), 2,
0, 0, 1;
cout << "********affine********" << endl;
cout << affine << endl;
// 让affine应用于p上,即是结果
cout << "********result********" << endl;
cout << affine * p << endl;
cout << "--------------------method2--------------------" << endl;
/* 方法二 先线性变换再平移 */
MatrixXf p2(2, 1);
p2 << 2,
1;
cout << "********p2********" << endl;
cout << p2 << endl;
Matrix2f linear;
linear << cos(45 * acos(-1) / 180), -sin(45 * acos(-1) / 180),
sin(45 * acos(-1) / 180), cos(45 * acos(-1) / 180);
cout << "********linear********" << endl;
cout << linear << endl;
MatrixXf translation(2,1);
translation << 1,
2;
cout << "********translation********" << endl;
cout << translation << endl;
cout << "********result********" << endl;
cout << (linear * p2) + translation << endl;
return 0;
}