当前位置: 首页 > news >正文

使用 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() 指定的变换;

如果使用 setTransform() 指定旋转角度 A,再使用 setRotation() 指定旋转角度 B,那么 QGraphicsItem 旋转的角度就是 A + B。使用 rotation() 获取的角度值是 B;角度 A 只能从 transform() 中推算。然后使用 resetTransform() 复位的是 transform(),rotation() 中的角度仍然保留,那么此时 QGraphicsItem 旋转的角度就是 B 。也就是说三种变换方式数值的变换相互不影响。

对于有父子关系的 QGraphicsItem 父项目的变换将累加到子项目(即使在父项目中使用的是setRotation()方式进行的变换,叠加到子项目时只能从transform中获取该角度,并不会影响到子项目的 rotation()),子项目通过方法 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 变换,该方法推算出来的角度不是原来设置的角度。

http://www.jsqmd.com/news/826535/

相关文章:

  • 使用 Taotoken 后模型 API 响应延迟与稳定性效果实测观察
  • 1987年5月31日中午11-13点出生性格、运势和命运
  • 6541616
  • Arm Neoverse CMN-650架构解析与寄存器编程实战
  • Java后端无人机飞手接单平台开发低空经济服务系统架构解析
  • 探索GitHub导航菜单:平台功能、解决方案、资源及GlycemicGPT项目全揭秘
  • Claude Code :自动保存 + 免打扰模式
  • 【c++面向对象编程】第22篇:输入输出运算符重载:<< 与 >> 的友元实现
  • 从LVDS到JESD204B:为什么你的多通道采集系统必须升级?一次讲透协议优势与选型
  • GESP学习,如何判断孩子是否适合跳级
  • Mochi语言解析:轻量级编程语言的设计原理与应用实践
  • Anthropic 发布了一份 Calude原生创业手册
  • 从goated-skills项目看软件工程师的硬核技能进阶之路
  • 使用HIP编写GPU 算子向量加法
  • Anolis OS Linux Dirty Frag 漏洞安全声明
  • 终极炉石传说游戏优化插件:HsMod完整配置与使用指南
  • oracle的26版本及以下 Null的判断及空串判定
  • PNP、NPN、源型、漏型,一次全搞懂
  • BallonsTranslator:3分钟搞定漫画翻译的终极AI辅助工具
  • 从计数器到计时器:使用Spectator构建可观测性系统的实践指南
  • [GESP202512 C++ 三级] 判断题第 9 题
  • ±0.03mm的精度怎么保证?翌东塑胶用AI赋能质量管控升级
  • Minecraft服务器技能数据自动化管理:mcpskills-cli命令行工具实战指南
  • 02 Transformer 基础:Self-Attention 原理详解
  • 思源宋体TTF完全指南:7种字重免费解决中文排版难题
  • AI 智能体 “寒武纪”——OpenClaw 狂飙迭代,引领开源 Agent 商业化落地浪潮
  • 2026年山东大学软件学院创新项目实训博客(五)
  • 62-260515 AI 科技日报 (Qwen3.6 模型推理速度再提升,MTP加速至1.8倍)
  • 开源智能体框架xbrain:模块化设计与工程实践指南
  • 基于DB-GPT-Hub的文本到SQL微调实战:从原理到企业级部署