Quartz 2D编程指南 - 变换

本文介绍了 Quartz 2D 的坐标空间概念,详细讲解了用户空间与设备空间之间的转换,以及如何通过变换函数实现平移、旋转和缩放等操作。此外,还解释了 UIView 类中的关键方法,如 loadView、viewDidLoad 和 viewDidUnload 等的作用和调用时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Quartz 2D 绘制模型定义了两种独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的本地分辨率)。用户坐标空间用浮点数表示坐标,与设备空间的像素分辨率没有关系。当我们需要一个点或者显示文档时, Quartz会将用户空间坐标系统映射到设备空间坐标系统。因此,我们不需要重写应用程序或添加额外的代码来调整应用程序的输出以适应不同的设备。
我们可以通过操作CTM(current transformation matrix)来修改默认的用户空间。在创建图形上下文后,CTM是单位矩阵,我们可以使用 Quartz的变换函数来修改CTM,从而修改用户空间中的绘制操作。
本章内容包括:
  • 变换操作函数概览
  • 如何修改CTM
  • 如何创建一个仿射变换
  • 如何选择两个相同的变换
  • 如何获取user-to-device-space变换
Quartz变换函数
我们可能使用 Quartz内置的变换函数方便的平移、旋转和缩放我们的绘图。只需要短短几行代码,我们便可以按顺序应用变换或结合使用变换。图5-1显示了缩放和旋转一幅 图片的效果。我们使用的每个变换操作都更新了CTM。CTM总是用于表示用户空间和设备空间的当前映射关系。这种映射确保了应用程序的输出在任何显示器或打印机上看上去都很棒。

 
Quartz 2D API提供了5个函数,以允许我们获取和修改CTM。我们可以旋转、平移、缩放CTM。我们还可以联结一个仿射变换矩阵。
有时我们可以不想操作用户空间,直到我们决定将变换应用到CTM时, Quartz为此允许我们创建应用于此的仿射矩阵。我们可以使用另外一组函数来创建仿射变换,这些变换可以与CTM联结在一起。
我们可以不需要了解矩阵的数学含义而使用这些函数。
修改CTM
我们在绘制图像前操作CTM来旋转、缩放或平移page,从而变换我们将要绘制的对象。以变换CTM之前,我们需要保存图形状态,以便绘制后能恢复。我们同样能用仿射矩阵来联结CTM。在本节中,我们将介绍与CTM函数相关的四种操作--平移、旋转、缩放和联结。
假设我们提供了一个可用的图形上下文、一个指向可绘制图像的矩形的指针和一个可用的CGImage对象,则下面一行代码绘制了一个图像。该行代码可以绘制如图5-2所示的图片。在阅读了本节余下的部分后,我们将看到如何将变换应用于图像。
复制代码
  1. CGContextDrawImage (myContext, rect, myImage);


 
平移变换根据我们指定的x, y轴的值移动坐标系统的原点。我们通过调用CGContextTranslateCTM函数来修改每个点的x, y坐标值。如图5-3显示了一幅图片沿x轴移动了100个单位,沿y轴移动了50个单位。具体代码如下:
复制代码
  1. CGContextTranslateCTM (myContext, 100, 50);


 
旋转变换根据指定的角度来移动坐标空间。我们调用CGContextRotateCTM函数来指定旋转角度(以弧度为单位)。图5-4显示了图片以原点(左下角)为中心旋转45度,代码所下所示:
复制代码
  1. CGContextRotateCTM (myContext, radians(–45.));


 
由于旋转操作使图片的部分区域置于上下文之外,所以区域外的部分被裁减。我们用弧度来指定旋转角度。如果需要进行旋转操作,下面的代码将会很有用
复制代码
  1. #include <math.h>
  2. static inline double radians (double degrees) {return degrees * M_PI/180;}
缩放操作根据指定的x, y因子来改变坐标空间的大小,从而放大或缩小图像。x, y因子的大小决定了新的坐标空间是否比原始坐标空间大或者小。另外,通过指定x因子为负数,可以倒转x轴,同样可以指定y因子为负数来倒转y轴。通过调用CGContextScaleCTM函数来指定x, y缩放因子。图5-5显示了指定x因子为0.5,y因子为0.75后的缩放效果。代码如下:
复制代码
  1. CGContextScaleCTM (myContext, .5, .75);


 
联合变换将两个矩阵相乘来联接现价变换操作。我们可以联接多个矩阵来得到一个包含所有矩阵累积效果矩阵。通过调用CGContextConcatCTM来联接CTM和仿射矩阵。
另外一种得到累积效果的方式是执行两个或多个变换操作而不恢复图形状态。图5-6显示了先平移后旋转一幅图片的效果,代码如下:

复制代码
  1. CGContextTranslateCTM (myContext, w,h);
  2. CGContextRotateCTM (myContext, radians(-180.));


 
图5-7显示了平移、缩放和旋转一幅图片,代码如下:

复制代码
  1. CGContextTranslateCTM (myContext, w/4, 0);
  2. CGContextScaleCTM (myContext, .25,  .5);
  3. CGContextRotateCTM (myContext, radians ( 22.));


 
变换操作的顺序会影响到最终的效果。如果调换顺序,将得到不同的结果。调换上面代码的顺序将得到如图5-8所示的效果,代码如下:

复制代码
  1. CGContextRotateCTM (myContext, radians ( 22.));
  2. CGContextScaleCTM (myContext, .25,  .5);
  3. CGContextTranslateCTM (myContext, w/4, 0);


 
创建仿射变换
仿射变换操作在矩阵上,而不是在CTM上。我们可以使用这些函数来构造一个之后用于CTM(调用函数CGContextConcatCTM)的矩阵。仿射变换函数使用或者返回一个CGAffineTransform数据对象。我们可以构建简单或复杂的仿射变换。
仿射变换函数能实现与CTM函数相同的操作--平移、旋转、缩放、联合。表5-1列出了仿射变换函数及其用途。注意每种变换都有两个函数。
表5-1 仿射变换函数
函数
用途
CGAffineTransformMakeTranslation
通过指定x, y值来创建一个平移矩阵
CGAffineTransformTranslate
在已存在的矩阵中使用平移
CGAffineTransformMakeRotation
通过指定角度来创建一个旋转矩阵
CGAffineTransformRotate
在已存在的矩阵中使用旋转
CGAffineTransformMakeScale
通过指定x, y缩放因子来创建一个缩放矩阵
CGAffineTransformScale
在已存在的矩阵中使用缩放
Quartz同样提供了一个仿射变换函数(CGAffineTransformInvert)来倒置矩阵。倒置操作通常用于在变换对象中提供点的倒置变换。当我们需要恢复一个被矩阵变换的值时,可以使用倒置操作。将值与倒置矩阵相乘,就可得到原先的值。我们通常不需要倒置操作,因为我们可以通过保存和恢复图形状态来倒置CTM的效果。
在一些情况下,我们可能不需要变换整修空间,而只是一个点或一个大小。我们通过调用CGPointApplyAffineTransform在CGPoint结构上执行变换操作。调用CGSizeApplyAffineTransform在CGSize结构上执行变换操作。调用CGRectApplyAffineTransform在CGRect结构上执行变换操作。CGRectApplyAffineTransform返回一个最小的矩形,该矩形包含了被传递给CGRectApplyAffineTransform的矩形对象的角点。如果矩形上的仿射变换操作只有缩放和平移操作,则返回的矩形与四个变换后的角组成的矩形是一致的。
可以通过调用函数CGAffineTransformMake来创建一个新的仿射变换,但与其它函数不同的是,它需要提供一个矩阵实体。


评价仿射变换
我们可以通过调用CGAffineTransformEqualToTransform函数来决定一个仿射变换是否与另一个相同。如果两个变换相同,则返回true;否则返回false。
函数CGAffineTransformIsIdentity用于确认一个变换是否是单位变换。单位变换没有平移、缩放和旋转操作。 Quartz常量CGAffineTransformIdentity表示一个单位变换。
获取用户空间到设备空间的变换
当使用 Quartz 2D时,我们只是在用户空间下工作。 Quartz为我们处理用户空间和设备空间的转换。如果我们的应用程序需要获取 Quartz转换用户空间和设备空间的仿射变换,我们可以调用函数CGContextGetUserSpaceToDeviceSpaceTransform。
Quartz提供了一系列的函数来转换用户空间和设备空间的几何体。我们会发现这些函数使用赶来比使用CGContextGetUserSpaceToDeviceSpaceTransform函数返回的仿射变换更好用。
  • 点:函数CGContextConvertPointToDeviceSpace和CGContextConvertPointToUserSpace将一个CGPoint数据结构从一个空间变换到另一个空间。
  • 大小:函数CGContextConvertSizeToDeviceSpace和CGContextConvertSizeToUserSpace将一个CGSize数据结构从一个空间变换到另一个空间。
  • 矩形:函数CGContextConvertRectToDeviceSpace和CGContextConvertRectToUserSpace将一个CGPoint数据结构从一个空间变换到另一个空间。

posted @ 2012-05-16 21:31 wtq 阅读(425) 评论(0)  编辑
posted @ 2012-05-16 20:48 wtq 阅读(1694) 评论(0)  编辑

原文链接地址:http://www.cocoachina.com/bbs/read.php?tid=38766

UIView的一些基本方法理解
UIView的一些基本方法理解:loadView、viewDidLoad、viewDidUnload、viewWillAppear、viewWillDisappear

经常使用UIView以及它的子类,一般对于init:,viewDidLoad:,dealloc:等方法应该是比较熟悉和了解的。
对于其它几个基本方法就不那么常用了,为了更好地编程使用这些方法,在此集中收集整理一下各方法调用的时机和作用:

init:方法
在init方法中实例化必要的对象(遵从LazyLoad思想)
init方法中初始化ViewController本身



loadView:方法
这是当没有正在使用nib视图页面,子类将会创建自己的自定义视图层。绝不能直接调用
如果手工维护views,必须重载重写该方法。
当view需要被展示而它却是nil时,viewController会调用该方法。
loadView和IB构建view
你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。 如果设备内存不足的时候, view 控制器会收到didReceiveMemoryWarning的消息。 默认的实现是检查当前控制器的view是否在使用。 如果它的view不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法将被再次调用来创建一个新的view。

viewDidLoad:方法
在视图加载后被调用:
如果是在代码中创建的视图加载器,他将会在loadView方法后被调用;
如果是从nib视图页面输出,他将会在视图设置好后后被调用。
重载重写该方法以进一步定制view
在iPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引
viewDidLoad后调用数据Model


viewDidUnload:方法
当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc)
内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式
在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其release掉了)
在该方法中释放其他与view有关的对象、其他在运行时创建(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nil(IBOutlet只需要将其置为nil,系统release view时已经将其release掉了)
一般认为viewDidUnload是viewDidLoad的镜像,因为当view被重新请求时,viewDidLoad还会重新被执行
viewDidUnload中被release的对象必须是很容易被重新创建的对象(比如在viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象


dealloc:方法
viewDidUnload和dealloc方法没有关联,dealloc还是继续做它该做的事情


viewWillAppear: 方法
Called when the view is about to made visible. Default does nothing
视图即将可见时调用。默认情况下不执行任何操作


viewDidAppear: 
Called when the view has been fully transitioned onto the screen. Default does nothing
视图已完全过渡到屏幕上时调用


viewWillDisappear:
Called when the view is dismissed, covered or otherwise hidden. Default does nothing
视图被驳回时调用,覆盖或以其他方式隐藏。默认情况下不执行任何操作


viewDidDisappear:
Called after the view was dismissed, covered or otherwise hidden. Default does nothing
视图被驳回后调用,覆盖或以其他方式隐藏。默认情况下不执行任何操作
 

posted @ 2012-05-16 14:31 wtq 阅读(171) 评论(0)  编辑

描述:在使用UISplitViewController时 ,如何修改导航视图控制器的标题呢?如图

         

    修改方法:在导航视图控制器 初始化时,设置导航视图控制器本身的title,比如:self.title = @"    ";

标题基于SpringBoot+Vue的学生交流互助平台研究AI更换标题第1章引言介绍学生交流互助平台的研究背景、意义、现状、方法与创新点。1.1研究背景与意义分析学生交流互助平台在当前教育环境下的需求及其重要性。1.2国内外研究现状综述国内外在学生交流互助平台方面的研究进展与实践应用。1.3研究方法与创新点概述本研究采用的方法论、技术路线及预期的创新成果。第2章相关理论阐述SpringBoot与Vue框架的理论基础及在学生交流互助平台中的应用。2.1SpringBoot框架概述介绍SpringBoot框架的核心思想、特点及优势。2.2Vue框架概述阐述Vue框架的基本原理、组件化开发思想及与前端的交互机制。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue在学生交流互助平台中的整合方式及优势。第3章平台需求分析深入分析学生交流互助平台的功能需求、非功能需求及用户体验要求。3.1功能需求分析详细阐述平台的各项功能需求,如用户管理、信息交流、互助学习等。3.2非功能需求分析对平台的性能、安全性、可扩展性等非功能需求进行分析。3.3用户体验要求从用户角度出发,提出平台在易用性、美观性等方面的要求。第4章平台设计与实现具体描述学生交流互助平台的架构设计、功能实现及前后端交互细节。4.1平台架构设计给出平台的整体架构设计,包括前后端分离、微服务架构等思想的应用。4.2功能模块实现详细阐述各个功能模块的实现过程,如用户登录注册、信息发布与查看、在线交流等。4.3前后端交互细节介绍前后端数据交互的方式、接口设计及数据传输过程中的安全问题。第5章平台测试与优化对平台进行全面的测试,发现并解决潜在问题,同时进行优化以提高性能。5.1测试环境与方案介绍测试环境的搭建及所采用的测试方案,包括单元测试、集成测试等。5.2测试结果分析对测试结果进行详细分析,找出问题的根源并
内容概要:本文详细介绍了一个基于灰狼优化算法(GWO)优化的卷积双向长短期记忆神经网络(CNN-BiLSTM)融合注意力机制的多变量多步时间序列预测项目。该项目旨在解决传统时序预测方法难以捕捉非线性、复杂时序依赖关系的问题,通过融合CNN的空间特征提取、BiLSTM的时序建模能力及注意力机制的动态权重调节能力,实现对多变量多步时间序列的精准预测。项目不仅涵盖了数据预处理、模型构建与训练、性能评估,还包括了GUI界面的设计与实现。此外,文章还讨论了模型的部署、应用领域及其未来改进方向。 适合人群:具备一定编程基础,特别是对深度学习、时间序列预测及优化算法有一定了解的研发人员和数据科学家。 使用场景及目标:①用于智能电网负荷预测、金融市场多资产价格预测、环境气象多参数预报、智能制造设备状态监测与预测维护、交通流量预测与智慧交通管理、医疗健康多指标预测等领域;②提升多变量多步时间序列预测精度,优化资源调度和风险管控;③实现自动化超参数优化,降低人工调参成本,提高模型训练效率;④增强模型对复杂时序数据特征的学习能力,促进智能决策支持应用。 阅读建议:此资源不仅提供了详细的代码实现和模型架构解析,还深入探讨了模型优化和实际应用中的挑战与解决方案。因此,在学习过程中,建议结合理论与实践,逐步理解各个模块的功能和实现细节,并尝试在自己的项目中应用这些技术和方法。同时,注意数据预处理的重要性,合理设置模型参数与网络结构,控制多步预测误差传播,防范过拟合,规划计算资源与训练时间,关注模型的可解释性和透明度,以及持续更新与迭代模型,以适应数据分布的变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值