AffineTransform(仿射变换)
一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移)。 我们能够用仿射变换来表示:
- 旋转 (线性变换)
- 平移 (向量加)
- 缩放操作 (线性变换)
我们通常使用 2 x 3 矩阵来表示仿射变换(以下需要一些线性代数的知识)。
用矩阵 A 和 B 对二维向量 X 做变换,那上式也可表示为
单位矩阵,主对角线为 1,其他都为 0 的矩阵
CGAffineTransform 官方定义
struct CGAffineTransform {
CGFloat a, b, c, d;
CGFloat tx, ty;
};
虽然结构体中只有 a
,b
,c
,d
,tx
,ty
6 个参数,但其实还有 3 个固定的参数[0,0,1] 来组成 3x3 的矩阵。
PS:anchorPoint 定义了应用变换的坐标系的原点。
仿射变换表示为一个 3x3 的矩阵如下:
对于一个 CGPoint
(x, y), 经过以上仿射变换后为(x’, y’),可表示为
即公式(1):
identity 矩阵
/* The identity transform: [ 1 0 0 1 0 0 ]. */
CG_EXTERN const CGAffineTransform CGAffineTransformIdentity
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
identity 矩阵可以表示为 代入公式(1),的得到 整理后得到
identity 仿射矩阵计算后的坐标也就是坐标自己本身。
CGAffineTransformMakeTranslation 方法
/* 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(__MAC_10_0, __IPHONE_2_0);
CGAffineTransformMakeTranslation
是一个进行平移的方法,根据注释得到的矩阵为
代入公式(1),的得到
整理后得到
CGAffineTransformMakeTranslation
也就是所对原来坐标进行一个平移的操作,在 x 轴方向上移动 tx,在 y 轴方向上移动 ty。
CGAffineTransformMakeScale 方法
/* Return a transform which scales by `(sx, sy)':
t' = [ sx 0 0 sy 0 0 ] */
CG_EXTERN CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
CGAffineTransformMakeScale
是一个进行缩放的方法,根据注释得到的矩阵为
代入公式(1),的得到
整理后得到
CGAffineTransformMakeScale
方法在x轴上缩放 sx,在 y 轴上缩放 sx
CGAffineTransformMakeRotation 方法
/* Return a transform which rotates by `angle' radians:
t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] */
CG_EXTERN CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
CGAffineTransformMakeRotation
是一个进行旋转的方法,根据注释得到的矩阵为
1、证明 x’ 和 y’ 构成圆方程
代入公式(1),的得到 整理后得到 两边都平方,得到 两式左右都相加得到
化简后得到
直接就是圆的方程,这只是证明 x’ 与 y’ 在变换后任然在与 x 和 y 在以 (0,0) 为圆心的圆上。
2、真正的推导过程
根据上图用三角函数表示公式(1)
CGAffineTransformMakeRotation
方法用来计算出原来点 (x,y) 旋转 α° 之后的 (x’,y’),即将原来的旋转 α°。也就是将 view 或者 layer 以 anchorPoint 为中心点旋转 α°
##胡乱吐槽 数学真的是很奇妙的东西,矩阵虽然不明白这是如何抽象出来的,但是觉得很厉害的样子。Google 了一些资料,还是云里雾里的,只能感叹其中的精妙了。
以下摘自理解矩阵
这样的一类问题,经常让使用线性代数已经很多年的人都感到为难。就好像大人面对小孩子的刨根问底,最后总会迫不得已地说“就这样吧,到此为止”一样,面对这样的问题,很多老手们最后也只能用:“就是这么规定的,你接受并且记住就好”来搪塞。然而,这样的问题如果不能获得回答,线性代数对于我们来说就是一个粗暴的、不讲道理的、莫名其妙的规则集合,我们会感到,自己并不是在学习一门学问,而是被不由分说地“抛到”一个强制的世界中,只是在考试的皮鞭挥舞之下被迫赶路,全然无法领略其中的美妙、和谐与统一。直到多年以后,我们已经发觉这门学问如此的有用,却仍然会非常迷惑:怎么这么凑巧?
我认为,这是我们的线性代数教学中直觉性丧失的后果。上述这些涉及到“如何能”、“怎么会”的问题,仅仅通过纯粹的数学证明来回答,是不能令提问者满意的。比如,如果你通过一般的证明方法论证了矩阵分块运算确实可行,那么这并不能够让提问者的疑惑得到解决。他们真正的困惑是:矩阵分块运算为什么竟然是可行的?究竟只是凑巧,还是说这是由矩阵这种对象的某种本质所必然决定的?如果是后者,那么矩阵的这些本质是什么?只要对上述那些问题稍加考虑,我们就会发现,所有这些问题都不是单纯依靠数学证明所能够解决的。像我们的教科书那样,凡事用数学证明,最后培养出来的学生,只能熟练地使用工具,却欠缺真正意义上的理解。
自从 1930 年代法国布尔巴基学派兴起以来,数学的公理化、系统性描述已经获得巨大的成功,这使得我们接受的数学教育在严谨性上大大提高。然而数学公理化的一个备受争议的副作用,就是一般数学教育中直觉性的丧失。数学家们似乎认为直觉性与抽象性是矛盾的,因此毫不犹豫地牺牲掉前者。然而包括我本人在内的很多人都对此表示怀疑,我们不认为直觉性与抽象性一定相互矛盾,特别是在数学教育中和数学教材中,帮助学生建立直觉,有助于它们理解那些抽象的概念,进而理解数学的本质。反之,如果一味注重形式上的严格性,学生就好像被迫进行钻火圈表演的小白鼠一样,变成枯燥的规则的奴隶。。
-以上-