Qt坐标系统之三个坐标系和两个变换

news2024/11/15 8:25:39

前言

Qt坐标系统由QPainter类控制。它和QPaintDeviceQPaintEngine类一起构成Qt绘图系统的基础。QPainter用于执行绘图操作,QPaintDeviceQPainter用来绘制的一个二维空间的抽象,QPaintEngine提供在不同设备绘图的接口。
Qt 的坐标分为逻辑坐标物理坐标。在我们绘制时,提供给QPainter的都是逻辑坐标。所谓物理坐标,就是绘制底层QPaintDevice的坐标。单单只有逻辑坐标,我们是不能在设备上进行绘制的。要想在设备上绘制,必须提供设备认识的物理坐标。Qt 使用viewport-window机制将我们提供的逻辑坐标转换成绘制设备使用的物理坐标,方法是,在逻辑坐标物理坐标之间提供一层“窗口”坐标。视口是由任意矩形指定的物理坐标窗口则是该矩形的逻辑坐标表示。默认情况下,物理坐标逻辑坐标一致的,都等于设备矩形。

正文

简述

三个坐标系

  • 逻辑坐标系(Logical Coordinate System
    也称为用户坐标系,是在编程时最常使用的坐标系。
    坐标原点(0,0)通常位于窗口的左上角,X轴向右增长,Y轴向下增长。
    通过逻辑坐标系来指定图形元素(如线条、矩形等)的位置和大小。
  • 窗口坐标系(Window Coordinate System
    是逻辑坐标系经过变换(如缩放、旋转等)后得到的坐标系。
    用于在绘制过程中表示图形元素在窗口中的实际位置。窗口决定了我是看你的一部分还是整体。
    QPainter内部使用的一个坐标系,用于将逻辑坐标转换为绘图设备(如屏幕、打印机等)上的物理坐标。
  • 物理坐标系(Physical Coordinate System
    也称为设备坐标系,代表了绘图设备(如屏幕、打印机等)上的实际坐标系统。
    物理坐标系的原点、坐标轴方向以及单位(通常是像素)由绘图设备决定。
    QPainter最终会将图形元素绘制到物理坐标系中。

也就是说我们在绘制图像的时候一般是先在逻辑坐标系上构建想法,然后调用相关代码进行绘制,然后编译器编译时会将我们绘制在逻辑坐标系上的图形转换到窗口坐标系,最后转换到物理坐标系
默认情况下这三种坐标系是等同的。
它们之间的转换关系

Logical Coordinate System—>Window Coordinate System—>Physical Coordinate System
逻辑坐标setWindow()变换窗口坐标setViewport()变换物理坐标

两个变换

  • setWindow() 变换
    用于设置窗口坐标系的范围。相当于给逻辑坐标系加一个方框,然后我只能看到这个方框里面的东西
    通过调用setWindow(xMin, yMin, xMax, yMax),可以指定窗口坐标系的左下角和右上角坐标。
    这个变换主要影响逻辑坐标系到窗口坐标系的映射关系,进而影响图形元素在窗口中的实际位置
  • setViewport() 变换
    用于设置物理坐标系中用于绘图的矩形区域(即视口(如屏幕))。
    通过调用setViewport(x, y, width, height),可以指定视口在物理坐标系中的位置和大小。
    这个变换主要影响窗口坐标系到物理坐标系的映射关系,进而影响图形元素在物理设备上的实际绘制位置。

例子

首先调用resize(300,300), 然后绘制窗口的两条对角线(注意我们现在所使用的就是逻辑坐标系)
在这里插入图片描述

使用setWindow()

在这里插入图片描述

可以看到窗口大小本身并没有变化,但是线段更细了(上面两条挨着的是新绘制的),我就添加了一行代码painter.setWindow(0,0,600,600);这行代码的意思是我设置了一个新的逻辑坐标系,在该逻辑坐标系下,窗口原点位于该逻辑坐标系的(0,0)位置,窗口的宽和高分别为600(原逻辑坐标系宽高为300,所以显得扩大了2倍;由于扩大了两倍,原先两个点相当于现在的一个点所以显得细了);然后我下面继续调用绘图时就会在这个新的逻辑坐标系下进行绘制,所以说300像素在新的逻辑坐标系中只能是中间的位置。

  • 如果设置painter.setWindow(0,0,600,600);painter.setWindow(0,0,150,150);会发生什么呢?
    在这里插入图片描述

可以看到窗口大小本身并没有变化,但是线条显得更加粗了;这是由于在新的逻辑坐标系中窗口的大小被设置成了150x150;原先在逻辑坐标中是300x300,相当于压缩了,原先的两个点相当于现在的一个点。

  • 如果将painter.setWindow(0,0,600,600);改成painter.setWindow(20,30,520,180);会发生什么呢?
    在这里插入图片描述
    为什么会这样呢?新画的对角线为什么会超出边界呢?此时的窗口坐标系的取值如何计算?其实这也很好理解,我有一条对角线,取它的两个端点(0,0),(75,75)这是它的逻辑坐标,它的窗口坐标怎么计算呢?
    对于(0,0):

((30 + 0 * 520/300),(20 + 0 * 180/300) = (30, 20 )

对于(75,75):

((30 + 75 * 520/300),(20 + 75 * 180/300) = (159.75, 65)

对于此时窗口坐标系的取值

横坐标的取值范围为[30, 490],纵坐标的取值范围为[20,160]
对于线段上的点总归有些计算完窗口坐标后会超出坐标取值范围,使得其不在窗口上

使用setViewport()

还是使用刚才的例子,不过有些变化
在这里插入图片描述
可以看到窗口大小本身并没有变化,但是线条显得更加粗了;这是因为painter.setViewport(0,0,600,600);意思是将绘图操作的视口设置为一个从 (0,0) 开始,宽度和高度都是 600 个单位(由于没有修改相应的窗口坐标,窗口坐标范围不变);这个代码相当于把整个物理坐标系翻倍了。也就是单位逻辑坐标变大了。原来逻辑坐标画1个像素点,现在相当于画2个。

  • 如果设置painter.setViewport(0,0,600,600);painter.setViewport(0,0,150,150);会发生什么呢?

在这里插入图片描述
可以看到窗口大小本身并没有变化,但是线条显得更加细了;这是因为painter.setViewport(0,0,150,150);意思是将绘图操作的视口设置为一个从 (0,0) 开始,宽度和高度都是 150 个单位(由于没有修改相应的窗口坐标,窗口坐标范围不变);这个代码相当于把整个物理坐标系缩小2倍了。也就是单位逻辑坐标变小了。比如(75,75)转换成窗口坐标后为

((0 + 75 * 150/300),(0 + 75 * 150/300)) = (37.5, 37.5)
而37.5在300*300的窗口坐标中只占了1/8

  • 如果设置painter.setViewport(0,0,600,600);painter.setViewport(20,30,540,120);会发生什么呢?

在这里插入图片描述
我们将物理坐标原点修改为 (20, 30),长540,高是 120 的矩形时,窗口坐标范围不变,也就是说,我们将物理宽 540px 映射成窗口宽 300px,物理高 120px 映射成窗口高 300px。那么坐标如何计算呢?
比如还是(0,0)与(75,75)
对于(0,0):

((20 + 0 * 540/300),(30 + 0 * 120/300) = (20, 30 )

对于(75,75):

((20 + 75 * 540/300),(30 + 75 * 120/300) = (155, 165)

对于此时窗口坐标系的取值

横坐标的取值范围为[20, 520],纵坐标的取值范围为[30,90]

遗留小问题,如果将paintEvent中的内容改成

	QPainter painter(this);
    painter.setViewport(0, 0, 150, 150);
    painter.fillRect(0, 0, 150, 150, Qt::green);

那么将会有多少窗口被填充?
答案是1/16

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

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

相关文章

深度学习-局部最小值与鞍点【Datawhale X 李宏毅苹果书 AI夏令营】

在网络优化时,有时会出现随时参数不断更新,训练的损失可能不会再下降,但训练结果并不满意。为什么会出现这样的情况呢? 假设排除数据集优劣的问题,可能需要进一步考虑的是为什么网络不再有新的最优值了,在…

【记录】MICCAI BraTs 2020数据集

简介 本文 MICCAI 竞赛中公布的用于脑肿瘤分割 BraTS 2020数据集,根据官方统计,该数据集中共含有660例数据,训练集369、验证集125,测试集166。不过仅有训练集中给出了详细的分割标签,验证集虽然公布了 但是仅为了验证,没有给出具体的Ground Truth。所以如果进行实验主要还…

昇腾 - AscendCL C++应用开发 图像文件的解码时硬件对图像的宽度和高度的处理方式

昇腾 - AscendCL C应用开发 图像文件的解码时硬件对图像的宽度和高度的处理方式 flyfish 假如是这样的 输入图片格式(YUV分量比例) jpeg(420) 输出图片格式 YUV420SP NV12 8bit 输出图片宽、高对齐要求 宽2对齐 高2对齐 输出图片宽Stride、高St…

CMake构建学习笔记2-zlib库的构建

文章目录 1. 概述2. 详论2.1 设置构建目录2.2 配置构建2.3 构建项目2.4 安装项目2.5 清理构建目录 3. 总结 1. 概述 Zlib是一个数据压缩库,它提供了在内存中对数据进行压缩和解压缩的功能。这个库非常泛用,除了直接使用这个库之外,很多依赖库…

学历不高能进大厂么?

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

《终身学习——10个你必须掌握的未来生存法则》读书笔记

无论你遵守与否,大自然的法则是无法改变的,你若无视“重力法则”,从屋顶跳下,那给你善后的就不是“重力警察”了。同理,如果你不遵循成长法则,也不会有“成长警察”找你麻烦,你只会发现自己的成…

结合 curl 与住宅代理实现高效数据抓取

引言 什么是 curl?有哪些功能? 基本 curl 命令有哪些? 为什么要使用 curl 处理 HTTP 请求? 如何使用 curl 和住宅代理进行网络抓取? 总结 引言 在当今数据驱动的商业环境中,数据的获取和分析能力是企…

HttpMessageNotReadableException

项目本身用的全是JSON,但是对接MES的时候他们用的XML,就添加了对XML的支持,然后发现AGV发送任务的接口报下面的错误了。 Error while extracting response for type [class java.lang.String] and content type [application/json;charsetut…

77 智能卡ATR TA1通信速率计算

1 前言 智能卡读卡器在读卡前期会以默认标准通信速率9600与卡片交互,期间可通过卡片返回的ATR值中TA1字段获取卡片支持的最大通信速率,然后读卡器通过PPS指令与卡片协商更改通信速率,最后以协商的速率进行通信。 起初默认9600波特率是比较慢的…

图片高清修复怎么做?4种高清修复方法分享给你

照片已经成为我们记录生活、珍藏回忆的重要方式。然而,随着时间的推移,不少珍贵的照片可能因保存不当或拍摄技术限制而变得模糊不堪。想要将这些模糊的照片变清晰成为当下的急迫需求。不过不用担心,下面就来给大家分享4种高清修复图片方法&am…

TCP系列相关内容

一、TCP上传文件 loop——本地回环测试地址。 void *memset(void *s,int c,size_t n)——给一个变量设定一个值。 1、“粘包”问题 两次分别发送的数据,被一起接收形成该现象。 原因:TCP流式套接字,数据与数据间没…

超低排放验收流程的全方位指南

近年来,随着环保要求的不断升级,朗观视觉超低排放验收成为了众多工业企业必须面对的关键环节。本文将详细介绍超低排放验收流程的安装要求、最新政策、国家标准以及企业应对的解决方案,帮助企业更好地理解和应对这一重要课题。 一、超低排放验…

校园一卡通_q7e7o

TOC springboot576校园一卡通_q7e7o--论文 第一章 概述 1.1 研究背景 近些年,随着中国经济发展,人民的生活质量逐渐提高,对网络的依赖性越来越高,通过网络处理的事务越来越多。随着校园一卡通的常态化,如果依然采用…

JS中Promise用法(简要说明)

文章目录 1、下方自定义名词约定2、官方流程图3、构造函数Promise <状态>fulfilled 用法代码图示 4、构造函数Promise <状态>rejected 用法代码图示 5、第3和4结合使用&#xff0c;可以将promise状态settled为2种情况之一代码图示&#xff08;图中if和else都是调…

移动硬盘直接拔下来有什么影响吗?数据丢失如何恢复

在日常的工作与生活中&#xff0c;移动硬盘成为了我们不可或缺的数据存储和传输设备。然而&#xff0c;很多人或许都曾有过这样的经历&#xff1a;在数据传输或使用中&#xff0c;由于一时疏忽或赶时间&#xff0c;直接拔下了正在工作的移动硬盘。这样的行为&#xff0c;虽然看…

冷却液温度传感器检测诊断

检测发动机冷却液温度&#xff0c;向ECU输入温度信号&#xff0c;作为燃油喷射和点火正时的修正信号&#xff0c;同时也是其他控制系统的控制信号。 冷却液温度传感器安装位置 冷却液温度传感器&#xff08;俗称水温传感器&#xff09;一般安装在缸体水道上&#xff0c;缸盖水…

docker命令实现容器管理

容器镜像分类 1.系统类镜像 2.应⽤镜像 搜索镜像 下载镜像 默认下载最新版本 1.安装docker环境 #配置变量 2.启动并且使⽤ 2.配置远程管理 帮助和指令

JVM的五个 invoke 指令详解

文章目录 概述invoke 指令概览1. invokespecial2. invokevirtual3. invokestatic4. invokeinterface5. invokedynamic 总结 概述 Java 虚拟机 (JVM) 是 Java 语言的核心组件之一&#xff0c;负责执行 Java 字节码。在 JVM 中&#xff0c;invoke 指令用于执行方法调用。本文将详…

K8s 集群巡检

K8s 集群巡检 上次发文 K8s 无备份&#xff0c;不运维&#xff0c;文章开篇&#xff0c;插入了一张 K8s 集群巡检的图片&#xff0c;好多小伙伴私信留言&#xff0c;问我要开源地址。由于其通用性不高&#xff0c;大多数公司需要结合自身的架构情况进行不同的巡检&#xff0c;…

互联网应用主流框架整合之Redis配置

在实际的商用系统中&#xff0c;Redis常用的机制包括备份、回收策略、主从复制、哨兵模式、集群模式等&#xff0c;在保证性能的同时还要保证其高可用 首先要熟悉一下Redis的配置文件&#xff0c;如果实在linux系统中&#xff0c;配置文件是redis.conf&#xff0c;而在windows…