讲一下我对二维图形变换的理解。
图形变换的代码(CGContextScaleCTM, CGContextRotateCTM, CGContextTranslateCTM等),只作用于图形,对坐标系没有影响,CGContext的坐标系的原点一直在左下角。(参见我的另一篇文章)
问题1:为什么图形变换的代码在绘制图形代码的前边
答:调用图形变换的代码只操作CGContext中保存的矩阵,除此之外,什么都不做。CGContext在初始时保存一个单位矩阵,当调用图形变换代码的时候,会将代码指定的图形变换作用于这个单位矩阵。调用绘制图形代码的时候,api内部会使用CGContext中保存的矩阵与图形数据进行计算,并将计算后的数据提交到CGContext的二维数组中,然后系统会将二维数组中的数据映射到屏幕。如果图形变换的代码在绘制代码的后边,此时只是操作了CGContext中的矩阵,对图形数据没有任何影响(在当前绘制周期内无作用,对下一个(调用setNeedsDisplay刷新)绘制周期有作用)
问题2:什么是图形变换矩阵,它的作用是什么?
答:图形变换的本质或者说目的是将构成图形的所有点,全部变换到对应的另一个位置。基础变换包括缩放变换,旋转变换和平移变换,使用基础变换的组合能够实现绝大多数复杂的变换。假设(x,y)是构成图形(初始图形,没有经过任何变换)的一个点,下边讨论下变换的实现过程
缩放变换:
缩放变换(x,y)经过缩放后位置变成了(Sx*x, Sy*y) = (x', y')
旋转变换:参考https://blog.csdn.net/csxiaoshui/article/details/65446125
旋转变换(x,y)变成了(cosθ*x - sinθ*y, sinθ*x + cosθ*y) = (x', y')
平移变换:
平移变换(x,y)经过平移变换变成了(x+tx, y+ty)
我们看到,缩放和旋转变换使用的是2行2列的矩阵,而平移变换使用的是3行3列的矩阵,所以为了变换的一致性,基础变换统一使用3行3列
的变换矩阵,当图形的所有点都与变换矩阵计算后,就得到了我们想要的结果
问题3:为什么图形变换真实的变换顺序与代码写的顺序是相反的?
示例如上,假设绘制的矩形的任一点(x,y)的矩阵
表示为G,平移的矩阵表示为T,旋转的矩阵表示为R,那么上边示例代码中的变换可以表示为T1RT2G。
根据矩阵乘法分配律表达式可以变成T1(R(T2G)),所以第一个和图形矩阵进行计算的,是离G最近的T2。
结合上边说的图形变换的代码必须在绘制图形代码的前边和矩阵乘法的分配律,我们可以得出,变换执行的顺序和代码的顺序是
相反的。
图形变换可以使用基本变换拼接计算,这样代码更容易理解。也可以直接生成最终的变换矩阵,这样效率更高,如使用CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)可以直接生成3行3列的变换矩阵,通过
配置a,b,c,d,tx,ty,能够直接得到最终的变换矩阵,但是这个需要更专业的知识。同学们可以根据自己需要选择合适的方法。
网友评论