Qt 从 QTransform 逆向解出 Translate/Scale/Rotate(平移/缩放/旋转)分析
QTransform 用于图形绘制,它定义了如何平移(translate)、缩放(scale)、切变(shear)、旋转(rotate)或投射(project)坐标系。注意:QTransform 是作用于坐标系,不是直接作用于图形。实际运用中我们可以通过 QPainter 、 QGraphicsView、QGraphicsItem 实现图形的平移、缩放、旋转等操作,但是需要从当前图形对象中获取当前旋转的角度、缩放比例时无法找到合适的函数直接获取。有很多建议是从 QTransform 中获取,因为我们总是能通过 transform 获取到 QTransform ,而且QT帮助文档中也给出了对应矩阵的说明。通过实践发现
QTransform 的矩阵说明是指执行单一变换时矩阵中每个数值的含义,当执行了一系列的平移、缩放、旋转后,该矩阵已经经过多次运算,所包含的数值已经不是我们当时设置的值,也就是说这些值是平移、缩放、旋转相互作用后的数值。如果想得到当初我们设置的数值,就需要经过逆向的计算。
首先,我们需要了解 QTransform 矩阵是如何运算的。为了帮助我们快速了解矩阵的运算过程,我设计了一个小程序,每次平移、缩放、旋转后都会输出 QTransform 计算后的矩阵信息。参考项目地址

QTransform 的定义
QTransform 只是定义了一个变换矩阵,实际的图形变换是由 QPainter 中的绘制程序来实现。QPainter 使用的标准坐标系是:以左上角为原点,X 轴向右,Y 轴向下。QTransform 对象包含一个 3 x 3 矩阵。m31 (dx) 、 m32 (dy) 表示水平与垂直位移。m11 、 m22 表示水平与垂直缩放比。m21 、 m12 表示水平与垂直切变。m13 、 m23 表示水平与垂直投影, m33 是投影因子。 3 x 3 矩阵如下图所示

平面上的一个点通过 QTransform 变换到另外一个点的计算公式如下, (x, y) 为原始点, (x', y')是变换后的点。
x' = m11*x + m21*y + dx
y' = m22*y + m12*x + dy
if (!isAffine()) {
w' = m13*x + m23*y + m33
x' /= w'
y' /= w'
}
对于一个恒等矩阵(identity matrix),m11、m22、m33 的值为 1,其它值为0。恒等矩阵作用于图形时不会产生任何变化。m12、m21 控制切变,它们会扭曲坐标系。坐标系的旋转(Rotation)是通过同时设置切变(Shear)和缩放(scale)来实现的。坐标系的透视(Perspective)是通过同时设置投影(projection)和缩放(scale)实现的。
很显然,当我们设置了缩放,又设置了旋转,m11、m22 就不再仅表示缩放,m12、m21 就也再仅表示切变。如果要得到原始值,需要经过计算。
Transform 计算与组合
1. Transform 计算
当我们执行如下代码时,最终的 transform 是如何计算出来的呢?
const double a = qDegreesToRadians(45.0);
double sina = sin(a);
double cosa = cos(a);
QTransform scale(0.5, 0, 0, 1.0, 0, 0);
QTransform rotate(cosa, sina, -sina, cosa, 0, 0);
QTransform translate(1, 0, 0, 1, 50.0, 50.0);
QTransform transform = scale * rotate * translate;
变量 scale 表示的矩阵为:
变量 rotate 表示的矩阵为:
变量 translate 表示的矩阵为:
坐标系变换执行顺序如下:translate -> rotate -> scale

先计算 temp = rotate * translate:
再计算 transform = scale * temp : 
注意:后执行的变换在做矩阵乘法时要放在左边,即左乘
2. Transform 组合
坐标系的旋转会同时影响 m11 m12 m21 m22,坐标系透视会同时影响 m11 m13 m22 m23 m33,所以了解 Transform 的组合必须要了解坐标系的旋转与透视。我们可以先从看似互不影响的操作(实际顺序不同时产生影响)来看。
(1)translate 与 scale
当按照 translate -> scale 的顺序变换时,transform 矩阵中的值就是我们设置的值。

当安照 scale -> translate 的顺序变换时,transform 矩阵中dx dy的值受到 scale 的影响不再是我们设置的值。

这跟前面讲的矩阵的运算顺序有关。

(2)translate 与 rotate
当按照 translate -> rotate的顺序变换时,transform 矩阵中的值就是我们设置的值。

当按照 rotate -> translate 的顺序变换时,transform 矩阵中的dx dy的值受到 rotate 的影响不再是我们设置的值。

dx dy的计算如下图所示:

(3)scale 与 rotate
当按照 scale -> rotate的顺序变换时,transform 矩阵中的值的计算方式如下


当按照 rotate -> scale 的顺序变换时,transform 矩阵中的值的计算方式如下


(4)shear 与 translate
当按照 translate -> shear 的顺序变换时,transform 矩阵中的值的计算方式如下

当按照 shear -> translate 的顺序变换时,transform 矩阵中的值的计算方式如下

(5)shear 与 scale
当按照 scale -> shear 的顺序变换时,transform 矩阵中的值的计算方式如下

当按照 shear -> scale 的顺序变换时,transform 矩阵中的值的计算方式如下

(6)translate scale rotate
按照 translate -> scale -> rotate 的顺序变换时,transform 矩阵中的值的计算方式如下

按照 translate -> rotate -> scale 的顺序变换时,transform 矩阵中的值的计算方式如下

按照 rotate -> translate -> scale 的顺序变换时,transform 矩阵中的值的计算方式如下

按照 rotate -> scale -> translate 的顺序变换时,transform 矩阵中的值的计算方式如下

按照 scale -> rotate -> translate 的顺序变换时,transform 矩阵中的值的计算方式如下

按照 scale -> translate -> rotate 的顺序变换时,transform 矩阵中的值的计算方式如下

(7)shear translate scale rotate
按照 translate -> scale -> rotate -> shear 的顺序变换时,transform 矩阵中的值的计算方式如下

当 4 种变换混合在一起时,计算非常复杂,这里不再一一列举。可以看出当变换越多时,从transform 的矩阵中反推出原始值非常困难,如果使用过程中仅限于少数的变换,从上面的推导中是可以逆推出原始值的。另外,即使是同样的一组变换,执行顺序不同得到的结果也会不同,更直观的可以运行上面的程序仔细观察一下。
Qt 从 QTransform 逆向解出 Translate/Scale/Rotate(平移/缩放/旋转)分析的更多相关文章
- Canvas绘图之平移translate、旋转rotate、缩放scale
画布操作介绍 画布绘图的环境通过translate(),scale(),rotate(), setTransform()和transform()来改变,它们会对画布的变换矩阵产生影响. 函数 方法 描 ...
- 软件项目技术点(2)——Canvas之平移translate、旋转rotate、缩放scale
AxeSlide软件项目梳理 canvas绘图系列知识点整理 画布操作介绍 画布绘图的环境通过translate(),scale(),rotate(), setTransform()和transf ...
- 偏移:translate ,旋转:rotate,缩放 scale,不知道什么东东:lineCap 实例
<!DOCTYPE HTML> <head> <meta charset = "utf-8"> <title>canvas</ ...
- [转]Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法
转载:http://blog.csdn.net/harvic880925/article/details/39996643 前言:这几天做客户回访,感触很大,用户只要是留反馈信息,总是一种恨铁不成钢的 ...
- Animation 动画详解(一)——alpha、scale、translate、rotate、set的xml属性及用法
一.概述 Android的animation由四种类型组成:alpha.scale.translate.rotate,对应android官方文档地址:<Animation Resources&g ...
- 转:自定义控件三部曲之动画篇——alpha、scale、translate、rotate、set的xml属性及用法
第一篇: 一.概述 Android的animation由四种类型组成:alpha.scale.translate.rotate,对应android官方文档地址:<Animation Resour ...
- CSS动画:Transform中使用频繁的scale,rotate,translate动画
动画中,skew只是transform中的一种形式的动画,我们还可以学习scale,rotate,translate.这是目前使用比较频繁的属性动作. 1.scale动画的定义:(单位数值) scal ...
- QT信号槽详解
1 QT信号槽详解 1.1 信号和槽的定义 信号是触发信号,例如按钮的点击触发一个clicked信号,槽是用来接收信号,并处理信号,相当于信号响应函数.一个信号可以关联多个槽函数,信 ...
- android.view.animation(1) - alpha、scale、translate、rotate、set的xml属性和用法(转)
一.ScaleAnimation ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, floa ...
- 自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法
前言:这几天做客户回访,感触很大,用户只要是留反馈信息,总是一种恨铁不成钢的心态,想用你的app,却是因为你的技术问题,让他们不得不放弃,而你一个回访电话却让他们尽释前嫌,当最后把手机号留给他们以便随 ...
随机推荐
- 使用Servlet进行页面跳转的两种方式
最近在教学生学习JavaWeb相关的技术,刚好讲到Java当中的Servlet,一个服务端的小程序. 也在和学生讲使用Servlet如何进行页面跳转,一种方式是使用请求转发进行页面跳转,一种方式 是使 ...
- 【stras-one】星念漫画下载器
原文链接:[stras-one]星念漫画下载器 - Stars-One的杂货小窝 一款将在线漫画保存到本地的下载工具 应一位蓝奏云批量下载器的用户的要求,实现了这款漫画下载的工具开发, 一直没时间,鸽 ...
- 多线程系列(二十) -CompletableFuture使用详解
一.摘要 在上篇文章中,我们介绍了Future相关的用法,使用它可以获取异步任务执行的返回值. 我们再次回顾一下Future相关的用法. public class FutureTest { publi ...
- Android 开发Day2
我的是小刺猬版本,算是比较新的版本了,还有火烈鸟和蜻蜓版啥的 新建项目(project)点击加号新建就行了.这时我们会选择一个模板作为开发的辅助起点,看上哪个就选哪个就行了.推荐新手选空项目(Empt ...
- 使用CEF(五)— 在QT中集成CEF(2)基于CLion+CMake搭建环境
在前文<使用CEF(四)- 在QT中集成CEF(1):基本集成>中,我们使用VS+QT的插件搭建了一个基于QT+CEF的项目.时过境迁,笔者目前用的最多的就是CLion+CMake搭建C/ ...
- 记录--极致舒适的Vue可编辑表格
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 使用ElementPlus的Table啥都好,就是没有可编辑表格!!! 既然UI库不支持,那我们实现一个可编辑表格是很难的事么?难么?不难 ...
- 记录--Canvas实现打飞字游戏
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 打开游戏界面,看到一个画面简洁.却又富有挑战性的游戏.屏幕上,有一个白色的矩形框,里面不断下落着各种单词,而我需要迅速地输入这些单词.如果 ...
- C# 人脸比对服务,自带模型,离线部署
软件说明 基于以下开源项目,做了再次封装 GitHub - ViewFaceCore/ViewFaceCore: C# 超简单的离线人脸识别库.( 基于 SeetaFace6 ) 可以一键开启服务: ...
- KingbaseES 优化之sql优化方法
金仓数据库在sql层面提供了多种优化手段,但是这些的前提时需要保证我们的统计信息准确,优化器已经在正确信息下选择了它认为的最优的执行计划, 优化手段包括 •使用索引 索引解决的问题用于在进行表的扫描时 ...
- 美团一面:项目中使用过Redis吗?我说用Redis做缓存。他对我哦了一声
引言 Redis,作为一种开源的.基于内存且支持持久化的键值存储系统,以其卓越的性能.丰富灵活的数据结构和高度可扩展性在全球范围内广受欢迎.Redis不仅提供了一种简单直观的方式来存储和检索数据,更因 ...