Qt-QTransform-内存结构-仿射变换-工作原理-C++

news2024/11/13 8:18:21

文章目录

    • 1.概述
    • 2.内存结构
    • 3.矩阵乘法
    • 4.map函数
    • 5.QPaint-setWorldTransform
    • 6.总结

1.概述

QTransform是Qt中推荐的矩阵变换类。转换指定如何平移,缩放,剪切,旋转或投影坐标系,通常在渲染图形时使用。QTransform类支持矩阵乘法,加法和减法,并且可以流式传输和比较该类的对象。使用改对象时,需要清楚Qt视图使用的坐标系。逻辑视图和物理视图,都为x值向右增加; y值向下增加。QTransform类在此环境中使用。

在这里插入图片描述
QTransform实现的矩阵乘法,点向量在前,乘以矩阵,依次实现变换效果。
在这里插入图片描述

2.内存结构

QTransform内部是一个二维的矩阵数据,如下图所示,由如下参数构成。
在这里插入图片描述

初始化方法
a.直接使用参数构造。

QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33 = 1.0)

b.QTransform()

m11、m22、m33设置为1,其他元素设置为零。

c.[static] QTransform fromScale(qreal sx, qreal sy)

创建一个QTransform,矩阵对应于水平sx和垂直sy的缩放比例。 这与scale(sx,sy)相同,但速度稍快。

d.[static] QTransform fromTranslate(qreal dx, qreal dy)

创建一个QTransform,阵对应于dx沿x轴和平移dy沿y轴平移。 这与translate(dx,dy)相同,但速度稍快。

3.矩阵乘法

矩阵乘法是连续仿射变换的基础。矩阵乘法一行乘以一列为对应矩阵元素的值,QTransform内部实现的乘法运算如下:

/*!
    \fn QTransform QTransform::operator*(const QTransform &matrix) const
    Returns the result of multiplying this matrix by the given \a
    matrix.

    Note that matrix multiplication is not commutative, i.e. a*b !=
    b*a.
*/
QTransform QTransform::operator*(const QTransform &m) const
{
    const TransformationType otherType = m.inline_type();
    if (otherType == TxNone)
        return *this;

    const TransformationType thisType = inline_type();
    if (thisType == TxNone)
        return m;

    QTransform t(true);
    TransformationType type = qMax(thisType, otherType);
    switch(type) {
    case TxNone:
        break;
    case TxTranslate:
        t.affine._dx = affine._dx + m.affine._dx;
        t.affine._dy += affine._dy + m.affine._dy;
        break;
    case TxScale:
    {
        qreal m11 = affine._m11*m.affine._m11;
        qreal m22 = affine._m22*m.affine._m22;

        qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
        qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;

        t.affine._m11 = m11;
        t.affine._m22 = m22;
        t.affine._dx = m31; t.affine._dy = m32;
        break;
    }
    case TxRotate:
    case TxShear:
    {
        qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
        qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;

        qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
        qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;

        qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
        qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;

        t.affine._m11 = m11; t.affine._m12 = m12;
        t.affine._m21 = m21; t.affine._m22 = m22;
        t.affine._dx = m31; t.affine._dy = m32;
        break;
    }
    case TxProject:
    {
        qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
        qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
        qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;

        qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
        qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
        qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;

        qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
        qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
        qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;

        t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
        t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
        t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
    }
    }

    t.m_dirty = type;
    t.m_type = type;

    return t;
}

4.map函数

按矩阵变换修改几何位置数据。以变换点位置为基础。点的变换以左乘为基础。

QPoint QTransform::map(const QPoint &p) const
{
    qreal fx = p.x();
    qreal fy = p.y();

    qreal x = 0, y = 0;

    TransformationType t = inline_type();
    switch(t) {
    case TxNone:
        x = fx;
        y = fy;
        break;
    case TxTranslate:
        x = fx + affine._dx;
        y = fy + affine._dy;
        break;
    case TxScale:
        x = affine._m11 * fx + affine._dx;
        y = affine._m22 * fy + affine._dy;
        break;
    case TxRotate:
    case TxShear:
    case TxProject:
        x = affine._m11 * fx + affine._m21 * fy + affine._dx;
        y = affine._m12 * fx + affine._m22 * fy + affine._dy;
        if (t == TxProject) {
            qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
            x *= w;
            y *= w;
        }
    }
    return QPoint(qRound(x), qRound(y));
}

5.QPaint-setWorldTransform

修改绘图对象变换矩阵

void QPainter::setWorldTransform(const QTransform &matrix, bool combine )
{
    Q_D(QPainter);

    if (!d->engine) {
        qWarning("QPainter::setWorldTransform: Painter not active");
        return;
    }

    if (combine)
        d->state->worldMatrix = matrix * d->state->worldMatrix;        // combines
    else
        d->state->worldMatrix = matrix;                                // set new matrix

    d->state->WxF = true;
    d->updateMatrix();
}

6.总结

使用QTransform进行仿射变换时,一定要注意坐标空间,X向右为正,Y向下为正。否则容易出现各种莫名其妙的问题。一切线性变换皆为仿射变换,如果变换关系复杂,可以利用3个对应点来构建此仿射变换矩阵

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/988710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

业务自动化工具Automatisch

什么是 Automatisch ? Automatisch 是一种开源的 Zapier 替代业务自动化工具,可让您连接不同的服务,如 Twitter、Slack 等,以自动化您的业务流程。您可以使用 Automatisch 构建工作流程自动化,而无需花费时间和金钱。也…

【大虾送书第八期】揭秘分布式文件系统大规模元数据管理机制——以Alluxio文件系统为例

目录 ✨写在前面 ✨分布式文件系统元数据的常见类型 🍓文件(inode)元数据 🍓数据块(block)元数据 🍓MountTable 🍓Worker元数据 ✨分布式文件系统元数据的存储模式 🍓元数…

手写RPC框架--8.压缩报文

RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 压缩报文 对报文进行压缩a.报文压缩b.负载均衡c.使用模板方法优化负载均衡d.一致性hash-负载均衡算法d.1) 介绍d.2) 实现 e.实现心跳检测f.最短响应时间的负载均衡策略 对报文…

vue 将public文件下的图片引入.vue文件内

data() {return {publicPath:process.env.BASE_URL,} }<div :style"{backgroundImage: url(${publicPath}images/tradingRegular_images/rectBg.png)}">11 </div>

从一个向量类中理解Python 中的特殊方法(__init__、__getitem__、__len__、__repr__、__str__)

文章目录 前言一、init、getitem、len、repr、str解释二、向量案例1.实现属于我们自己的向量2.导入向量模块 前言 特殊方法是一种具有特殊命名约定的方法&#xff0c;用来定义类的行为与功能。当满足特定条件时&#xff0c;这些方法会被自动调用&#xff0c;从而实现一些内置的…

Splunk Enterprise for Mac:卓越的数据分析与管理工具

在当今的数字化时代&#xff0c;数据已经成为企业成功的核心驱动力。然而&#xff0c;如何有效地管理和分析这些数据&#xff0c;却常常让企业感到困惑。Splunk Enterprise for Mac 是一款领先的数据分析和管理工具&#xff0c;可以帮助你解决这一难题。 Splunk Enterprise fo…

Nginx(动静分离、分配缓冲区、资源缓存、防盗链、资源压缩、IP黑白名单、大文件传输配置、跨域配置、高可用、性能优化)

Nginx&#xff0c;负载均衡&#xff0c;Http反向代理服务器&#xff0c;支持大部分协议&#xff0c;如TCP、UDP、SMTP、HTTPS 环境搭建 Nginx反向代理-负载均衡 首先通过SpringBootFreemarker快速搭建一个WEB项目&#xff1a;springboot-web-nginx&#xff0c;然后在该项目中&…

适用于Linux的Windows子系统(在VScode中开发Linux项目)

目录 前言 一、VScode扩展安装 二、挂载项目 1.连接 2.挂载&#xff08;挂载之后项目终端就是Linux了&#xff09; 3.愉快的搬砖开始了 4.前端如何通过内网 IP 本地访问到 Ubuntu 上&#xff1f; 总结 前言 系列分为三章&#xff08;从安装到项目使用&#xff09;&…

云端AI:释放企业创新力,打造智慧企业

文章目录 1. 云端AI的基本概念1.1 云计算1.2 人工智能1.3 云端AI 2. 云端AI的重要性2.1 成本效益2.2 弹性扩展2.3 无缝整合2.4 实时更新 3. 云端AI的应用领域3.1 智能客服3.2 预测分析3.3 自动化生产 4. 云端AI的未来趋势4.1 边缘计算与云端AI的融合4.2 可解释性AI4.3 隐私和安…

ORACLE的分区(一)

目录 一、分区概念 二、表分区的优点 三、分区策略 一、分区概念 随着时间的发展&#xff0c;一个表的数据会越来越多&#xff0c;当数据量增大的时候我们一般采取建立索引优化索引的方式提高查询速度&#xff0c;但是数据量再次增大即使是索引也无法提高速度&#xff0c;这时…

从金蝶云星空到聚水潭通过接口配置打通数据

从金蝶云星空到聚水潭通过接口配置打通数据 源系统:金蝶云星空 金蝶K/3Cloud&#xff08;金蝶云星空&#xff09;是移动互联网时代的新型ERP&#xff0c;是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”&#xff0c;旨在帮助企业打造面…

代码随想录Day_59打卡

①、下一个更大元素Ⅱ 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&am…

REST风格【SpringBoot】

1.REST简介 行为动作 通常模块名使用复数&#xff0c;也就是加s 2.RESTful入门 Controller public class UserController {RequestMapping(value "/users", method RequestMethod.POST)public String save() {System.out.println("user save");return &…

pcie 总结

用户空间pci 常用命令 lspci 查看所有pci 设备 lspci -t 树形查看所有设备 lspci -s 00:1f.6 -vvv 查看某个设备所有信息 lspci -s 00:1f.6 -vvv -xxx 增加16进制看看 sudo cat /proc/iomen | grep PCI 查看所有地址映射 如何确定pcie io空间 内存空间大小 (1)读取出基地址…

视频监控/安防监控/AI视频分析/边缘计算/TSINGSEE青犀AI算法智慧仓储解决方案

随着全球经济与科学技术的双重推动&#xff0c;我国的仓储管理已经进入了高速发展时期&#xff0c;物流仓储也由简单的储藏仓库向智能化仓储转变。TSINGSEE青犀AI智慧仓储解决方案是利用先进的信息技术和物联网技术来提高仓储管理效率、降低成本的一种仓储管理模式。 方案功能 …

如何使用PyTorch训练LLM

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 像LangChain这样的库促进了上述端到端AI应用程序的实现。我们的教程介绍 LangChain for Data Engineering & Data Applications 概述了您可以使用 Langchain 做什么&#xff0c;包括 LangChain 解决的问题&#xf…

Facebook营销攻略:教你集中管理Facebook Business专页及广告

Facebook 在社交媒体间是无人不识的「霸主」&#xff0c;占据着主导地位&#xff0c;2020年 Facebook 创造了 859亿美元的收入&#xff0c;当中有大约600亿美元来自 Facebook 的应用程序&#xff0c;而 Facebook App 已被下载超过50亿次。作为全球最大型的社交媒体公司之一&…

2023年7月京东饮料行业数据分析(京东运营数据分析)

饮料消费已成为当下快消品行业里的主力军&#xff0c;随着社会群体喜好的改变、消费群体的不断扩大&#xff0c;可选择的饮料种类越来越多&#xff0c;我国饮料市场的体量也较为庞大。根据鲸参谋电商数据分析平台的数据显示&#xff0c;今年7月份&#xff0c;京东平台饮料的销量…

如何获得一个Oracle 23c免费开发者版

获取23c开发者版 简单介绍可参考这里。 获取数据库可以参考这篇文章Introducing Oracle Database 23c Free – Developer Release或这里。 Docker Image 这是最快的方法。在OCI上创建一个计算实例&#xff0c;然后就可以拉取image使用了。 docker的安装和配置不赘述了。 …

《DevOps实践指南》- 读书笔记(一)

DevOps实践指南 Part 1 DevOps 介绍精益运动敏捷宣言 1. 敏捷、持续交付和三步法1.1 制造业价值流1.2 技术价值流1.2.1 聚焦于部署前置时间1.2.2 关注返工指标——%C/A 1.3 三步工作法&#xff1a;DevOps 的基础原则 2. 第一步&#xff1a;流动原则2.1 使工作可见2.2 限制制品数…