iOS下的2D仿射变换机制(CGAffineTransform相关)

原创 2015年07月07日 09:53:11
仿射变换简介

仿射变换源于CoreGraphics框架,主要作用是绘制2D级别的图层,几乎所有iOS设备屏幕上的界面元素都是由CoreGraphics来负责绘制。而我们要了解的2D仿射变换是其下负责二维坐标到二维坐标的线性变换工作,它保持了二维图形的“平直性”(即:直线经过变换之后依然是直线,圆弧经过变换之后依然是圆弧)和“平行性”(即:二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变),只有依照向量产生的二维线条间的夹角会可能发生变化。仿射变换包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)。iOS中通常只用到平移、旋转和缩放,同时iOS中CGAffineTransform是一个结构体级别的数据类型,并没有封装成类作为仿射变换,我们通常是在一个view的transform属性中进行访问和设置。常见于手势触发的旋转、平移、缩放,或者动画的类似播放效果。

CGAffineTransform简介
CGAffineTransform结构体代表了一种用于仿射变换矩阵。结构体的参数指定了从一个坐标系的点转化成另外一个坐标系的规则。仿射变换是一种特殊类型的映射,保留在一个路径中的平行线,但不一定保留长度或角度。缩放,旋转,平移是最常用的操作支持的仿射变换,但也可能扭曲。我们通常不会直接创建一个仿射变换,我们只需要根据现有的参数,修改现有的仿射变换。

我们创建一个view,当给它的transform属性赋值的时候,就是我们设置仿射变换的值,我们具体来分析一下仿射变换的具体细节。

    UIView *view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
    view.backgroundColor = [UIColor cyanColor];
    //视图的仿射变换设定:旋转
    view.transform = CGAffineTransformMakeRotation(M_1_PI);
    [self.view addSubview:view];


仿射变换机制

仿射变换是通过下面的矩阵来完成的,一共有9个参数,我们通过这9个参数来进行仿射变换。但是矩阵的最后一列总是0,0,1三个固定的值,所以实际上创建一个变换的结构体只需要6个参数,也就是下面给出的a,b,c,d,tx,ty六个CGFloat类型的参数(通过结构体来描述的六个值)。

                                                                                                           


CGAffineTransform t = CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);

变化原理:源视图上的点p(x,y)变化成目标视图中p'(x',y')。对应关系为:

                                                                                                        

这样源视图上的每一点都这样变换成目标视图的点的过程,就叫做仿射变换。

平移变换:
那么依照上面的矩阵,我们如果想要达到平移的目的,只需要x' = x + tx,y' = y + ty(改变对应点的横纵坐标的位置即可)。那么这样算来,仿射变换的参数中,a = 1,b = 0, c = 0, d = 1。也就是说,我们确定了四个参数,那么我们可以根据自己的需求给定tx,ty,这样就完成了平移的设置,也就是说,平移的仿射变换参数只有tx,ty是不确定的,所以系统的平移只提供了两个参数的原因(内部帮我们补充了固定的参数)。

CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)
当然细心的朋友发现还有另外一个平移变换的构造:

CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
两者的区别当我们对一个视图进行平移操作的时候,前者每次都会从初始位置开始平移(操作前回到原来的位置),后者是从给定参数(通常是上一次的状态)的基础上继续平移。


缩放变换:
缩放的操作,本质上是拉长或缩短了原来的点与点之间的距离,那么也就是说我们只需要让x' = a * x,y' = d *y(将一个点的横坐标和纵坐标放大或者缩小若干倍)。根据平移的经验,那么这样算来,仿射变换的参数中,b = 0, c = 0,tx = 0,ty = 0。也就是说,我们确定了四个参数,那么我们可以根据自己的需求给定a,b,这样就完成了缩放的设置,系统称变换的系数为sx,sy。同样它有两种给定参数的方式:

CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
前者依然是在视图初始状态的基础上进行缩放(每次缩放前都先回到初始状态),后者是在前一次操作后的基础上进行缩放操作。


旋转变换:
在iOS中,视图的旋转是按照顺时针进行一个角度(假定为α)的改变,按照数学理解,我们要想让一个点通过旋转到另一个点(不熟悉的朋友复习一下向量的知识),那我们的变化过程应该是这样x' = x * cos α - y *sin α,y’ = x *sin α + y *cos α。所以旋转操作中,tx、ty等于0,a = cosα,b = sinα, c = sinα,d = cosα。虽然有四个参数,但是全部依赖于我们给定的角度,所以系统帮我们封装了起来(角度参数为angle),我们只需要设定一个角度就可以了。所以系统通过的构造旋转操作的参数是:

CGAffineTransformMakeRotation(CGFloat angle)
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
同样,前者是在初始化的基础上操作旋转(每次旋转先回到初始状态),而后者是在上一个参数(通常情况下是上一次的操作结果)的基础上旋转。


iOS中的2D仿射变换常用的就是以上三种,通常配合手势或者动画来操作。通常iOS中视图的transform支持的就是这三种变换,我们只需要按照自己的需要进行创建就可以,依照系统给定的参数,我们填入合适的值之后,系统会转化成2D仿射对应矩阵,当然如果不满意系统提供的仿射变换,可以自己定义仿射的实现。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

IOS开发UI篇--仿射变换(CGAffineTransform)使用小结

一、理论基础请参考CGAffineTransform简单分析二、效果演示三、实现代码3.1:位移变换-(void)positionAnimation{ _demoView.transform ...

【深入iOS开发】iOS仿射变换和3D变换

2D仿射变换 UIView的transform属性是一个CGAffineTransform类型,用于在二维空间做旋转,缩放和平移。CGAffineTransform是一个可以和二维空间向量(例如CGP...

Halcon学习之仿射变换3D1

1.产生一个3D的单位阵 //产生一个3D的单位阵(4*4的仿射变换矩阵,真实存储在内存中的时候,最后一行不进行存储,因为最后一行都是相同的数据) HHomMat3D hhommat3d...

Halcon学习之仿射变换3D3

7.转换一个3d仿射变换矩阵为pose//转换一个3d仿射变换矩阵为pose,pose代表一个3d刚性物体变换数据集,可以平移和旋转 //pose对象参数说明:参数1-参数3:代表x,y,z三...

Q96:PT(2):纹理的仿射变换(Textures And Transformations)

一方面,我们想要将R=3球面这套纹理添加到小半径的球面上;另一方面,我们希望在将这套纹理添加到小半径球面上时,能够对纹理进行相应的缩小,以便纹理在小半径球面上的效果和R=3球面上的效果一样。换句话说,...

iOS编程——CGAffineTransform相关函数

CGAffineTransform rotation = CGAffineTransformMakeRotation(M_PI_2);
[xxx setTransform:rotation];
CGA...

CGAffineTransform相关函数2

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrie...

学习动画——变换CGAffineTransform和CATransform3D

CGAffineTransform 仿射变形
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)