CGAffineTransform2D仿射变换原理

A和B两个矩阵相乘,就要A的列数等于B的行数才有相乘的意义,相乘结果是一个矩阵C,C的行数和A的行数相等,C的列数和B的列数相等C的每个元素值为A对应的行与B对应的列的元素乘积的和:

CGAffineTransform 的结构如下

struct CGAffineTransform

{
  CGFloat a, b, c, d;
  CGFloat tx, ty;
};

typedef struct CGAffineTransform CGAffineTransform;

为了把二维图形的变换统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准。

CGAffineTransform表示的是这样一个矩阵

  

因为最后一列总是是(0,0,1),所以有用的信息就是前面两列。

运算原理:假设原坐标设为(X,Y,1),变换后的坐标为(xx,yy,1),那么原坐标、坐标变换以及变换后的坐标对应矩阵的关系应该是:

                        |a    b    0|

 [X,Y,  1]   x   |c    d    0|  = [xx,yy,1];

                        |tx    ty  1|

根据矩阵计算方法,左边矩阵相乘的实际结果是:[aX + cY + tx , bX + dY + ty , 1];所以对比出来原坐标 X 经过CGAffineTransform变换之后等于 aX + cY + tx,原坐标Y经过CGAffineTransform变换之后等于 bX + dY + ty。我们对比一下可知:

第一种:设a=d=1, b=c=0.  

[aX + cY + tx, bX + dY + ty,  1] = [X  + tx,  Y + ty,  1];即X  + tx = xx;Y + ty = yy;

可见,这个时候,坐标是按照向量(tx,ty)进行平移,其实这也就是函数

CGAffineTransform CGAffineMakeTranslation(CGFloat tx,CGFloat ty)的计算原理。

第二种:设b=c=tx=ty=0.  

[aX + cY + tx, bX + dY + ty,  1] = [aX dY,  1];aX = xx;dY, = yy;

可见,这个时候,坐标X按照a进行缩放,Y按照d进行缩放,a,d就是X,Y的比例系数,其实这也就是函数

CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)的计算原理。a对应于sx,d对应于sy。

第三种:设tx=ty=0,a=cos?,b=sin?,c=-sin?,d=cos?。

[aX + cY + tx , bX + dY + ty,  1] = [Xcos? - Ysin?,   Xsin? + Ycos?,  1] ;即Xcos? - Ysin?xx; Xsin? + Ycos? = yy;

可见,这个时候,?就是旋转的角度,逆时针为正,顺时针为负。其实这也就是函数

CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)的计算原理。angle即?的弧度表示。


常量  CGAffineTransformIdentity

const CGAffineTransformCGAffineTransformIdentity;

 这个就是没有变换的最初的样子。


创建一个仿射矩阵,用一下几个方法创建的仿射矩阵,多次作用于一个对象,效果不会累加,即每次只会以原始位置进行放射变换。

  • CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty) 直接赋值来创建
  • CGAffineTransformMakeTranslation(CGFloat tx,CGFloat ty)  设置偏移
  • CGAffineTransformMakeRotation(CGFloat angle) 设置角度来生成矩阵
  • CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)  通过设置缩放系数生成矩阵

改变已经存在的放射矩阵,即会在上一次的放射矩阵的基础上累加

  • CGAffineTransformTranslate(CGAffineTransform t,CGFloat tx, CGFloat ty)  原始的放射矩阵基础上加上偏移,生成新的放射矩阵
  • CGAffineTransformScale(CGAffineTransform t,CGFloat sx, CGFloat sy)原始的放射矩阵基础上加上缩放,生成新的放射矩阵
  • CGAffineTransformRotate(CGAffineTransform t,CGFloat angle)原始的放射矩阵基础上加上旋转,生成新的放射矩阵
  • CGAffineTransformInvert (CGAffineTransform t)原始的放射矩阵进行反向得到新的放射矩阵,比如(x,y)通过矩阵t得到了(x’,y’)那么通过这个函数生成的t’作用与(x’,y’)就能得到原始的(x,y)
  • CGAffineTransformConcat(CGAffineTransform t1,CGAffineTransform t2) 通过两个已经存在的放射矩阵生成一个新的矩阵t‘ = t1 * t2

应用仿射矩阵

  • CGPointApplyAffineTransform 得到新的点
  • CGSizeApplyAffineTransform  得到新的size
  • CGRectApplyAffineTransform  得到新的rect

评测矩阵

  • CGAffineTransformIsIdentity  是否是CGAffineTransformIsIdentity
  • CGAffineTransformEqualToTransform 看两个矩阵是否相等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值