【计算机图形学】Transformation C++ 编程

综述

今天听了闫令琪老师的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;
}


Guess you like

Origin blog.csdn.net/passer__jw767/article/details/121064268