先看一组数据
1 | 0 | 0 | ||||||||
0 | 1 | 0 | ||||||||
0 | 0 | 1 | ||||||||
transform.translate(150,150); | 163 | 150 | 163 | 150 | 49069 | |||||
1 | 0 | 0 | ||||||||
0 | 1 | 0 | ||||||||
150 | 150 | 1 | ||||||||
transform.rotate(-15.0); | 163 | 150 | 313 | 300 | 49069 | |||||
0.965926 | -0.258819 | 0 | ||||||||
0.258819 | 0.965926 | 0 | ||||||||
150 | 150 | 1 | ||||||||
transform.translate(-150,-150); | 163 | 150 | 346.268788 | 252.701403 | 49069.01532 | |||||
0.965926 | -0.258819 | 0 | ||||||||
0.258819 | 0.965926 | 0 | ||||||||
-33.7117 | 43.934 | 1 | ||||||||
163 | 150 | 162.557088 | 146.635403 | 49069.01532 |
|1 0 0 |
|0 1 0 |
|0 0 1 |矩阵是QTransform类对象transform的初始值,QTransform类对象的模型是这样的其中m31dx、m32dy是沿x、y轴的偏移量,也就是坐标系的偏移,可正可负。下面我们来分析transform和rotate函数都做了什么。
QTransform看起来像是变形的意思,但实际上是坐标系。
transform.translate(150,150);是把坐标系移动和150,150位置
transform.rotate(-15.0);把坐标系逆时针旋转15°
transform.translate(-150,-150);是把坐标系还原到0,0位置
这三行的代码的意图是让坐标系中的点绕150,150旋转-15°。那第三行为什么要回到原来的位置,因为图像中的点都平移了150,150,需要消减这个影响。那么这几函数内部都做了什么呢?看不懂的可以结合表格来看,其中0.258819为sin15°的值,0.965926为cos15°的值。
transform.translate(150,150)做的是这样的变换
|1 0 0| |1 0 0 |
|0 1 0|* |0 1 0 |
|150 150 0| |0 0 1 |
transform.rotate(-15.0);做的是这样的变换,先回到0,0位置,再平移后旋转
|1 0 0| |1 0 0 | |1 0 0| |0.965926 -0.258819 0|
|0 1 0|* |0 1 0 | * |0 1 0|*|-0.965926 0.258819 0|
|150 150 0| |0 0 1 | |-150 -150 0| |150 150 1|
最后一个transform.translate(-150,-150);由于我们只是绕150,150旋转而没有平移,所以要反向平移,
|1 0 0| |0.965926 -0.258819 0|
|0 1 0|*|0.258819 0.965926 0|
|-150 -150 0| |150 150 1|
当然此时的原点已经不是0,0了,而是-33.7117,43.934,可见0,0是按150,150旋转了-15°的,x变小y变大了。也就是0,0,1与结果矩阵的积,原坐标系的0,0在现坐标系中是-33.7117,43.934
值得注意的是,容易搞错和混乱的,矩阵乘法虽然不支持交换律,但是可以不按顺序相乘如ABC可以先算BC结果再与A相乘。因此要做什么变换可以先把Qtransform对象做好再map映射一下就可以了。在这个过程中要记住几个事
m11、m22控制缩放,m33一般是1,m13、m23一般是0,这里最容易搞乱的就是m31dx和m32dy这两个平移量。
|0.965926 -0.258819 0| //这里叫原点变换旋转矩阵吧
*|0.258819 0.965926 0|
|150 150 1|这个乘法的效果是平移了150,150后以150,150为轴旋转,或者先旋转后平移也能说的通而
|1 0 0| |0.965926 -0.258819 0|
*|0 1 0|* |0.258819 0.965926 0|
|150 150 0| |0 0 1| 是平移到150,150后坐标系以结果矩阵中m31dx和m32旋dy为中心旋转,上一个坐标变换竟然没办法分步完成!而Qt把我们认为本应该分步完成的以一个封装的形式完成就是transform.rotate(-15.0),它实际上是回到原点再执行乘原点变换旋转矩阵。
可以认为底层矩阵中
|m11 m12 m13|
|m21 m22 m23|
|m31 m32 m33| m32dx,m33dx就包含着坐标原点信息,无论是哪种仿射变换。我们大概率要考
dx dy
虑到它的存在,除非是按照原点做仿射变换的这种小概率事件。而且它是增量的哦,我们设置乘矩阵时m31dx=0,m32dy=0只能代表 一个不太需要的结果。最终的结果还是要印出QTransform对象的矩阵结果才行。
qDebug()<<transform.m11()<<transform.m12()<<transform.m13();
qDebug()<<transform.m21()<<transform.m22()<<transform.m23();
qDebug()<<transform.m31()<<transform.m32()<<transform.m33();
结果
0.965926 -0.258819 0
0.258819 0.965926 0
-33.7117 43.934 1就是绕0,0旋转-15度后平移 -33.7117,43.934,表现就是以绕150,150旋转-15度