Qt坐标系统之坐标变换矩阵(QTransform类)

Qt坐标系统之坐标变换矩阵(QTransform类)

本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址:
https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q
《C++语法详解》网盘地址:https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

若对C++语法不熟悉,建议参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。

注:本小节需要一些数学知识和计算机图形学方面的知识
12.12.1 基本数学知识

1、齐次坐标

二维空间中的点可使用(x, y)表示,但在计算机图形学中使用齐次坐标表示点更为方便,齐次坐标把点表示为三元组,即在(x,y)基础上增加一维表示为(x, y, w),其中w是一个非零值
每个点有很多个不同的齐次坐标表示(只要其中一个是另一个的倍数即可),比如(1, 2, 5),(2,4, 10),(4, 8, 20);都表示同一个点,通常会使用w去除齐次坐标,从而一个点被表示为(x/w, y/w, 1),这样,每一个二维坐标点都可以使用三维的齐次坐标来表示,同理,三维坐标点(x,y,z);可使用四维的齐次坐标表示为(x, y, z, 1);比如(2,5,9)的齐次坐标为(2,5,9,1);
使用齐次坐标后,所有的坐标变换公式都可以使用如下矩阵相乘的形式来表示,
Qt坐标系统之坐标变换矩阵(QTransform类)_第1张图片

2、坐标变换公式
以下各式中,dx和dy表示平移距离,Sx和Sy表示缩放系数,θ表示绕原点逆时针旋转的角度,P1(x1, y1)为坐标变换后的点,P(x,y)为变换前的点。
Qt坐标系统之坐标变换矩阵(QTransform类)_第2张图片

Qt坐标系统之坐标变换矩阵(QTransform类)_第3张图片

Qt坐标系统之坐标变换矩阵(QTransform类)_第4张图片

3、坐标的复合变换
坐标的复合变换是指多个坐标变换序列的组合。
①、连续平移变换(其结果是平移相加)
把点P平移至点P1再平移至P2,则其平移公式的推导步骤为
在这里插入图片描述
由以上推导过程可见,对复合的坐标变换序列,只需计算其变换矩阵即可,以上规则同样适用于其他更复杂的复合变换,对于之后的变换,将只写出变换矩阵的计算。
下面为坐标平移复合变换后的计算过程。
Qt坐标系统之坐标变换矩阵(QTransform类)_第5张图片

Qt坐标系统之坐标变换矩阵(QTransform类)_第6张图片

5、总结
由以上讲解可知,只要给出变换矩阵,便可对其进行坐标变换,因此在计算机编程中,通常只需给出一个变换矩阵,然后给矩阵各元素赋予需要的值便可对其进行各种坐标变换。
6、其他
对于三维空间的坐标变换,其原理与二维类似,其坐标变换矩阵为
Qt坐标系统之坐标变换矩阵(QTransform类)_第7张图片

12.12.2 使用QPainter类中的基本变换函数进行坐标变换

默认情况下,QPainter是在自已所关联的绘制设备的坐标系(通常为像素)上运行的,绘制设备默认坐标系的原点位于左上角,X轴向右增长,Y轴向下增长。
2、QPainter类中的基本坐标变换函数如下
Qt坐标系统之坐标变换矩阵(QTransform类)_第8张图片
3、QPainter类中与绘制状态有关的函数如下
Qt坐标系统之坐标变换矩阵(QTransform类)_第9张图片

示例12.20:使用QPainter类中的基本坐标变换函数变换坐标

void paintEvent(QPaintEvent *e){
    QPainter pr(this);
    QBrush bs(QColor(1,111,1));    pr.setBrush(bs);    QRectF r(0,11,22,55);
pr.drawRect(r);
    pr.translate(50,10);		pr.drawRect(r);  	//变换1:平移(50,10)
pr.save();									//保存状态
//变换2:平移(50,50),缩放2倍(Y向),逆时针旋转60度
pr.translate(50,50);    pr.scale(1,2);    pr.rotate(-60);    pr.drawRect(r);
QTransform t=pr.transform();					//获取变换2的变换矩阵
qDebug()<

运行结果(见图12-55)
Qt坐标系统之坐标变换矩阵(QTransform类)_第10张图片

现以变换2计算其变换矩阵
注意:在使用QPainter类中的基本坐标变换函数进行复合坐标变换时,其变换矩阵应按相反的顺序进行计算。因此计算变换2的矩阵时应按旋转、缩放、平移的顺序进行计算,如下所示
Qt坐标系统之坐标变换矩阵(QTransform类)_第11张图片

12.12.3 使用变换矩阵(QTransform类)进行坐标变换

1、QPainter类中与QTransform类有关的函数如下
Qt坐标系统之坐标变换矩阵(QTransform类)_第12张图片

2、QTransform类
QTransform类主要用于创建一个3*3的变换矩阵,该矩阵用于坐标系的2D变换。该类取代了QMatrix类(此类已过时)。QTransform类通过操控变换矩阵来实现坐标变换。另外QTransform类还可对矩阵进行操作,比如可进行矩阵的加、乘等运算,还可对矩阵类型进行判断(比如是否是满秩矩阵等)。
QTransform类除了可通过操控其矩阵进行坐标变换外,还可使用QTransform类中内置的基本变换函数(比如QTransform::scale()、QTransform::scale()等)对坐标进行变换,这些函数的使用方法与QPainter类中的相应函数是相同的。简单的坐标变换完全可使用QPainter类中的基本坐标变换函数来完成,使用QTransform类可以把多个坐标变换组织在一起,然后在需要时使用。
QTransform类的变换矩阵如下
Qt坐标系统之坐标变换矩阵(QTransform类)_第13张图片

注:公式18~22其实就是使用的如下矩阵乘法计算出来的(读者可自行计算),在没有投影变换的情形下,w1直接取整数值1即可。因此在使用QTransform类进行坐标变换时,也可使用如下的矩阵形式计算变换后的坐标值。
在这里插入图片描述
把QTransform类的变换矩阵与坐标变换矩阵相对比,可得出如下规律m31和m32用于平移,m11和m22用于缩放,m21和m12用于错切(shear),m13和m23用于投影变换,m33是一个额外的投影因子,设置m11,m12,m21,m22可实现旋转变换。注:投影变换是一个比较复杂的变换,包括透视投影(图12-56为透视投影的一个简图)和平行投影,关于投影变换的内容请参阅《计算机图形学》课程。
Qt坐标系统之坐标变换矩阵(QTransform类)_第14张图片

12.12.4 QTransform类中的函数

1、构造函数
Qt坐标系统之坐标变换矩阵(QTransform类)_第15张图片
2、设置和获取变换矩阵的元素
Qt坐标系统之坐标变换矩阵(QTransform类)_第16张图片
3、QTransform内置的基本坐标变换函数
Qt坐标系统之坐标变换矩阵(QTransform类)_第17张图片
4、对变换矩阵的判断
Qt坐标系统之坐标变换矩阵(QTransform类)_第18张图片
5、构建变换矩阵
Qt坐标系统之坐标变换矩阵(QTransform类)_第19张图片
6、与线性代数有关的函数
Qt坐标系统之坐标变换矩阵(QTransform类)_第20张图片
7、使用变换矩阵转换图形坐标
以下函数用于转换坐标,比如QPoint p1=matrix.map(point);表示把点使用变换矩阵matrix进行转换,然后返回该点的副本。等效于p1= point*matrix;具体应用见示例12.22
Qt坐标系统之坐标变换矩阵(QTransform类)_第21张图片

8、下面为重新实现的操作符函数
Qt坐标系统之坐标变换矩阵(QTransform类)_第22张图片

示例12.21:使用QTransform类(变换矩阵)进行坐标变换(见图12-57)

注意:变换矩阵应按设计的相反顺序计算,比如若设计为平移T、旋转R、缩放S,则矩阵计算应为S∙R∙T
void paintEvent(QPaintEvent *e){
    QPainter pr(this);    QBrush bs(QColor(1,111,1));    pr.setBrush(bs);
QRectF r(0,55,22,55);
//变换1(平移、旋转)
    QTransform t(1,0,0,1,20,0); 	//x方向平移20
    t.rotate(-60);       		//使t再逆时针旋转60度。
    pr.setTransform(t);  		//设置变换矩阵为t
qDebug()<

Qt坐标系统之坐标变换矩阵(QTransform类)_第23张图片

示例12.22:QTransform::map()函数的使用(见图12-58)
void paintEvent(QPaintEvent *e){
QPainter pr(this);    QBrush bs(QColor(1,111,1));   
pr.setBrush(bs);
    QRectF r(0,55,22,55);   QLineF n(50,0,50,555);
    pr.drawLine(n);    		pr.drawRect(r);
    QTransform t;    		t.translate(50,0);	//x方向平移50
    QRectF r1=t.mapRect(r);   				//使用t转换r的坐标。
QLineF n1=t.map(n);     					//使用t转换n的坐标
//n1也可使用如下等效语句创建,更简洁
//QLineF n1=n*t;   						//注意t*n是错误的
    pr.drawRect(r1);	pr.drawLine(n1);}   	//绘制转换后的图形

Qt坐标系统之坐标变换矩阵(QTransform类)_第24张图片

示例12.23:使用变换矩阵计算变换后的坐标值(见图12-59)
void paintEvent(QPaintEvent *e){
    QPainter pr(this);    QBrush bs(QColor(1,111,1));    pr.setBrush(bs);
    QRect r(0,55,22,55);
    pr.drawRect(r);
    QTransform t;    t.translate(50,0);    t.rotate(-60);
    QPolygon g1=t.mapToPolygon(r);    pr.drawPolygon(g1);
qDebug()<

Qt坐标系统之坐标变换矩阵(QTransform类)_第25张图片

本文作者:黄邦勇帅(原名:黄勇)

Qt坐标系统之坐标变换矩阵(QTransform类)_第26张图片

你可能感兴趣的:(Qt)