巧用 QLineF 从 QTransform 提取角度

我们在对 QGraphicsItem 进行变换时,QT 提供了很多便捷的方法。但当我们想获取当前变换的角度时却有些困难,因为 QTransform 没有提供获取角度的方法。在文章Qt 从 QTransform 逆向解出 Translate/Scale/Rotate(平移/缩放/旋转)分析分析过,使用 QTransform 进行多种变换组合后,由于组合顺序不能预知、组合数量不能预知,很难从 QTransform 矩阵中推算出当前变换的角度。即使推算出来,由于切变、缩放等变换的影响,推算出的角度也不准确。结合 QLineF 可以有个简便的方式来倒推变换角度。

一、从 QGraphicsItem 的变换说起

对 QGraphicsItem 进行变换有三种方式:

1. 使用 setRotation() 或 setScale();
2. 使用 setTransform();
3. 使用 setTransformations();

如果同时使用多种方式,变换效果将进行叠加。变换按照固定的顺序进行:

  • 第一步:应用 transform() 指定的变换;
  • 第二步:应用 transformations() 指定的变换;
  • 第三步:应用 rotation(), transformOriginPoint() 指定的变换;
  • 第四步:应用 scale(), transformOriginPoint() 指定的变换;

如果 transform() 中指定旋转角度 A,rotation() 指定旋转角度 B,那么 QGraphicsItem 旋转的角度就是 A + B。然后使用 resetTransform() 复位 transform(),那么 QGraphicsItem 旋转的角度就是 B 。也就是说三种变换方式数值的变换相互不影响。

对于有父子关系的 QGraphicsItem 父项目的变换将累加到子项目,子项目通过方法 sceneTransform() 获取所有累加的变换,通过 scenePos() 获取子项目在 scene 上的坐标。

二、解析 QGraphicsItem 当前旋转的角度

  1. 直接作用于 QGraphicsItem 的角度

不考虑父节项目对 QGraphicsItem 的影响,或者 QGraphicsItem 没有父项目时,计算 QGraphicsItem 当前旋转的角度,需要分别考虑 setRotation()、setTransform() 和 setTransformations() 设置的角度,分别计算后再进行累加即可。如果 QGraphicsItem 没有父项目,可以使用 sceneTransform() 获取所有累加变换后的 transform,从 transform 推算角度。

  1. 有父项目的 QGraphicsItem 的角度

考虑父项目对 QGraphicsItem 的变换影响,直接使用 sceneTransform() 获取所有累加变换后的 transform,再推算角度。

三、使用 QLineF 从 transform 提取角度

QLineF 提供的方法 angleTo() 可以帮助我们方便的计算2条直线间的夹角。要从 transform 中计算角度,可以先构建一条直线,然后使用 QTransform 的 map() 方法对直线进行变换。变换后的直线与原直线间的夹角就是 transform 旋转的角度。示例代码如下:

复制代码
QTransform trans = item->sceneTransform();
QLineF line1{{0,0},{1,0}};
QLineF line2 = trans.map(line1);
qreal angle = line2.angleTo(line1)

注意:如果 transform 中执行过 shear 变换,该方法推算出来的角度不是原来设置的角度。

相关推荐
爱编程的化学家9 小时前
代码随想录算法训练营第十一天--二叉树2 || 226.翻转二叉树 / 101.对称二叉树 / 104.二叉树的最大深度 / 111.二叉树的最小深度
数据结构·c++·算法·leetcode·二叉树·代码随想录
眠りたいです9 小时前
基于脚手架微服务的视频点播系统-数据管理与网络通信部分的预备工作
c++·qt·ui·微服务·云原生·架构·媒体
烦躁的大鼻嘎10 小时前
【Linux】深入Linux多线程架构与高性能编程
linux·运维·服务器·开发语言·c++·ubuntu
野生的编程萌新10 小时前
【C++深学日志】C++编程利器:缺省参数、函数重载、引用详解
c语言·开发语言·c++
愚润求学10 小时前
【贪心算法】day10
c++·算法·leetcode·贪心算法
智者知已应修善业10 小时前
【矩阵找最大小所在位置】2022-11-13
c语言·c++·经验分享·笔记·算法·矩阵
小柯J桑_10 小时前
C++之特殊类设计
java·开发语言·c++
bikong711 小时前
Qt/C++,windows多进程demo
c++·windows·qt
努力学习的小廉11 小时前
我爱学算法之—— 位运算(上)
c++·算法
青草地溪水旁11 小时前
设计模式(C++)详解—原型模式(1)
c++·设计模式·原型模式