Core Graphics图形变换
2015-06-06 17:18
344 查看
简单的坐标变换:
Quarzd 2D提供了三个API进行坐标变换://1.位移变换 CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty);
对于变换后的坐标系而言,原点位于原坐标系的(tx,ty)处。也相当于在原有坐标系下,所有点的横纵坐标分别增加tx和ty。
//2.旋转变换 CGContextRotateCTM(CGContextRef c, CGFloat angle);
假设点A1经过坐标变换变到了A2,记坐标原点为O。则A1O = A2O(A2在以O为圆心,A1O长度为半径的圆上)且∠A1OA2 = angel。这里的旋转是顺时针旋转。如果想用逆时针旋转的话,使用-angel即可。
//3.缩放变换 CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy);
新坐标系下所有点的横纵坐标等于原横纵坐标分别乘以缩放因子sx和sy。
需要注意的是:这里的变换函数都是作用于上下文(context)的。但和前文所说修改绘图设置不同的是,这些API修改了坐标系统的状态,即使调用CGContextDrawPath方法也无法恢复设置。
坐标系统状态的保存与恢复
我们可以调用这一对方法来进行系统状态的保存和恢复。CGContextSaveGState(CGContextRef c);//保存当前绘图状态。 CGContextRestoreGState(CGContextRef c);//恢复系统绘图状态。
一个绘图上下文维护了一个绘图系统状态的栈。上下文被初始化时,这个栈为空,所以先调用CGContextSaveGState方法,将当前系统状态入栈,需要恢复时再调用CGContextRestoreGState出栈即可。这里的“状态”(State)不仅包含了当前坐标系统的状态,也包含了设置的填充风格、线条风格、阴影风格等各种状态。需要切记的是,如果还没有保存状态就调用了坐标变换的API,那么就再也无法恢复了。如果此时试图调用CGContextRestoreGState方法,将会对一个空栈执行出栈方法,从而引起报错。
*使用矩阵进行变换
Quartz 2D除了以上三个变换方法之外,还提供了更为一般的,利用矩阵处理坐标变换的方法。CGContextConcatCTM(CGContextRef c, CGAffineTransform transform); //Transform 是一个变换矩阵 - (CGAffineTransform)CGContextGetCTM(CGContextRef c); //获取当前上下文坐标系的变换矩阵
变换矩阵CGAffineTransform transform可以这样创建:
CGAffineTransform transform1 = CGAffineTransformMakeRotation(CGFloat angle); CGAffineTransform transform2 = CGAffineTransformMakeScale(CGFloat sx, CGFloat sy); CGAffineTransform transform3 = CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty);
这三个方法分别对应了旋转变换、缩放变换和平移变换的API,因此就不做解释了。
还可以创建一个更一般的变换矩阵:
CGAffineTransform transform = CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);
根据矩阵的运算规则和平移变换的变换规律,点A(x,y)经过transform矩阵作用后的点A’左边应为(ax+cy+tx,bx+dy+ty)。
根据高中数学知识,得出常见的几个变换矩阵:
CGAffineTransformMake(-1, 0, 0, 1, 0, 0);//关于X轴对称变换 CGAffineTransformMake(1, 0, 0, -1, 0, 0);//关于Y轴对称变换 CGAffineTransformMake(0, 1, 1, 0, 0, 0);//关于Y=X对称变换 CGAffineTransformMake(0, -1, -1, 0, 0, 0);//关于X轴对称变换 CGAffineTransformMake(1, 0, tan(α), 1, 0, 0);//水平倾斜α°角 CGAffineTransformMake(1, -tan(α), 0, 1, 0, 0);//竖直倾斜α°角
还可以对已有的矩阵进行修改
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy); CGAffineTransformRotate(CGAffineTransform t, CGFloat angle); CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);//追加平移变换效果,上两个方法类似 CGAffineTransformInvert(CGAffineTransform t);//获取一个变换矩阵的逆矩阵 CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);//拼接两个变换矩阵,相当于t1左乘t2
变换矩阵不仅可以作用于上下文的坐标系,还可以作用于CGPoint、CGSize、CGRect等。不仅如此,UIView自身有一个transform属性,支持设置变换矩阵,从而可以对UI控件本身进行坐标变换。
CGPoint newPoint = CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t); CGSize newSize = CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t); CGRect newRect = CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);
相关文章推荐
- 学术简历的撰写
- OC中UITabBarController控制器
- Xcode 升级后,常常遇到的遇到的警告、错误,解决方法(转)
- Flex 4.6 下载进度条 IPreLoaderDisplay生命周期
- 多播
- 最长单调递增子序列——动态规划
- Spring @EnableWebMvc
- BZOJ 1618: [Usaco2008 Nov]Buying Hay 购买干草( dp )
- <转载>C#IEnumerable和IEnumerator 详解
- 手机充电误区及该如何充电
- 堆优化的Dijkstra算法
- springMVC bootstarp 用户权限基础框架+即时通讯
- 数据库的查询
- css动画
- 黑马程序员——Java基础---深层拷贝(数组、ArrayList)
- [c++]复数的运算符重载
- 基于OpenCV的圆斑检测方法
- [网络编程] Linux网络编程经典书籍
- shell脚本(一)
- Android 在锁屏界面添加未读短信和电话提醒