揭密QTransform &QTransform::translate(qreal dx, qreal dy)算法

translate,在Qt是平移的意思,看起来没什么难的,但是如果结合旋转rotate和缩放scale往往会让人摸不着头脑。

先介绍一下qt的QTransform的算法,这里主要是translate、rotate、scale。

这三个算法本质上是矩阵变换但是与学校里学的矩阵变换不同,它是“前乘”

众所周知矩阵的乘法不支持交换律(但是支持结合律)所以有了前乘和后乘的概念,所谓的前乘就是在已知的矩阵前面乘以一个矩阵,后乘就是在已知矩阵后面乘以一个矩阵。

结果是不一样,即便是偶尔一样也是小概率事件 。这里本来应该是2*2的矩阵与一个1*2或2*1的矩阵相乘的但是这两个矩阵都增维了,有疑问的可以看看增广矩阵

现在来看看那三个算法,如果只加一个的话没有什么问题,与我们学的一样,都是后乘。

 QTransform &QTransform::translate(qreal dx, qreal dy):dx传150,dy传150

QTransform &QTransform::scale(qreal sx, qreal sy):sx传0.8,sy传1 

QTransform &QTransform::rotate(qreal angle, Qt::Axis axis = Qt::ZAxis) :angle传-30,axis默认

那么我们先平移再旋转/缩放是怎么样的算法呢?经过我的多少实现,其实数学好的人的显而易见的,它是前乘。例如先旋转后平移是这样算的。

 这里Qt做了封装,所以与学校学的算法不太一样,这里的过是这样的:

QTransform qTransform;

qTransform.rotate(-30);

qTransform.translate(150,150);

qTransform.map(x,y);

这里与红括号矩阵乘法有所不用,这是先把后两个乘完了,再前乘|x,y,1|,矩阵乘法支持结合律。那么在这个基础上再在x轴上缩放0.8要怎么做呢?

qTransform.scale(0.8,1);

qTransform.map(x,y);

在矩乘法上执行的过程如下

 肉眼可见,是先以0,0缩放,再平移150,150,再以0,0旋转-30°但是结果是与反过程相同的

 主意,这里从来没有出现过旋转半径的不同,从来都是绕0,0旋转后平移,不信的话可以亲手乘一乘,150从来没有参与cos/sin的相乘,都只是影响了平移的两个位置,m31,m32。

结论,Qt的scale/translate/scale几个算法的堆叠是前乘,好有趣,明明是后加的变换却是在前面乘个矩阵,这是Qt的QTransform类封装好的,只是为了更简洁罢了。现在来看看对于绕点旋转/平稳是怎么理解的,这里只举绕点旋转的例子。

qTransform.translate(150,150);//平移150

qTransform.rotate(-30);//以0,0旋转-30°

qTransform.translate(-150,-150);//平移-150,-150

qTransform.map(x,y)

先平移150,再前乘-30再前乘-150,-150,本行第一个逗号前的平移也是乘 

-150,-150是最后的变换所以放在最前面,其它的也是类似的,每变换一次就在前面乘个矩阵。

那么它执行了什么呢?我先平移了-150,-150,再绕0,0旋转-30°,再平移150,150 

好像是按150,150旋转了-30度,事实上也的确如此,两个平移的路径是平行的,可以衍生出新的点的x,y相对于150,150的变化与左上角x,y与0,0的变化是相同的。也就证明了最终点是按150,150旋转了-30。这里一定要注意,按某点旋转一定是先划归到与0,0的旋转的框架,千万不要先旋转了再想办法,谁要是这么做我把他脑袋给拧下来。

好了,同学们,剩下的平移、旋转、缩放自由组合的验算由你们自己完成,看看是不是这么算的。Qtransform对象是可以相乘的可以实现translate/rotate/scale算法,且更灵活。自己拿excel算一算。

最后,无论什么变换,学校学的也好,Qt中的也好,本质上都是乘矩阵,只是顺序不,但算法相同 

有的文章说,QTransform是坐标轴,但是从更有效的角度看,理解成变换更好一点 

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值