CGAffineTransform和CATransform3D原理

####简述
CGAffineTransform是用来做View层2D的形变的,UIView有个属性transform的类型就是CGAffineTransform
CATransform3D是用来做layer层3D的形变的,CALayer也有个属性transform的类型就是CATransform3D

那么CGAffineTransform和CATransform3D的原理是什么呢?

###先来看CGAffineTransform
查看源码发现这是个结构体

1
2
3
4
struct CGAffineTransform {
CGFloat a, b, c, d;
CGFloat tx, ty;
};

我们先来看下平移的方法CGAffineTransformMakeTranslation(CGFloat tx,
CGFloat ty)的原理是什么呢?

1
2
3
4
5
/* Return a transform which translates by `(tx, ty)':
t' = [ 1 0 0 1 tx ty ] */

CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx,
CGFloat ty) CG_AVAILABLE_STARTING(10.0, 2.0);
1
2
3
4
提示:
为了把二维图形的变化统一在一个坐标系里,这里用到了齐次坐标的概
念,即把一个二维图形用一个三维矩阵表示,其中第三列总是(0,0,1),
用来作为坐标系的标准。所以所有的变化都由前两列完成。

那么,CGAffineTransform结构体中的参数用矩阵来表示,如下:

|a b 0|

|c d 0|

|tx ty 1|

运算的原理:设原坐标为(X,Y,1),通过矩阵运算如下:

1
2
3
|a    b    0|
[X,Y,1] |c d 0| = [aX + cY + tx bX + dY + ty 1]
|tx ty 1|

矩阵运算后的坐标[aX + cY + tx bX + dY + ty 1]

我们将 t’ = [ 1 0 0 1 tx ty ]代入公式[aX + cY + tx bX + dY + ty 1]中

1
[aX + cY + tx   bX + dY + ty  1] = [X + tx , Y + ty, 1]

我们发现X坐标向左移动了tx,Y坐标向下移动了ty,这就是方法CGAffineTransformMakeTranslation(CGFloat tx,
CGFloat ty)的原理

同样的道理,CGAffineTransform的所有方法的原理都是通过这种矩阵的运算,来实现坐标的变换的

###再来看看 CATransform3D
CATransform3D也是结构体,这里也是引入齐次坐标的概念,将三维图形的变化用四维矩阵来表示。

1
2
3
4
5
6
7
struct CATransform3D
{
CGFloat m11, m12, m13, m14;
CGFloat m21, m22, m23, m24;
CGFloat m31, m32, m33, m34;
CGFloat m41, m42, m43, m44;
};

设原坐标为(X,Y,Z,1),通过矩阵运算的到

1
2
3
4
5
6
7
[m11, m12, m13, m14]

[m21, m22, m23, m24]

[X,Y,Z,1] [m31, m32, m33, m34] = [m11X+ m21Y + m31Z + m41,m12X+m22Y+m32Z+m42,m13X+m23Y+m33Z+m43,m14+m24+m34+m44];

[m41, m42, m43, m44]

我们还是来看平移的方法CATransform3DMakeTranslation (CGFloat tx,
CGFloat ty, CGFloat tz)

1
2
3
4
/* Returns a transform that translates by '(tx, ty, tz)':
* t' = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]. */
CATransform3D CATransform3DMakeTranslation (CGFloat tx,
CGFloat ty, CGFloat tz)

把t’ = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]代入公式 [m11X+ m21Y + m31Z + m41,m12X+m22Y+m32Z+m42,m13X+m23Y+m33Z+m43,m14+m24+m34+m44];

(X,Y,Z,1) = (X + tx,Y+ty,Z+tz,1)即X、Y、Z坐标的平移
CATransform3D其他方法的原理是类似的就不啰嗦了

####最后再附上CGAffineTransform和CATransform3D相互转化的API

1
2
3
4
5
6
7
/* Return a transform with the same effect as affine transform 'm'. */
CATransform3D CATransform3DMakeAffineTransform (CGAffineTransform m)

/* Returns the affine transform represented by 't'. If 't' can not be
* represented exactly by an affine transform the returned value is
* undefined. */
CGAffineTransform CATransform3DGetAffineTransform (CATransform3D t)

以上,懂了原理之后是不是感觉其实很简单的呢