对仿射变换中的混合变换的理解

最近看《iOS-Core-Animation-Advanced-Techniques》。在仿射变换中的混合变换里,提到了以下几个函数:

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

在看前面的仿射变换的时候,我知道了经过仿射变换,点的位置是经过以下矩阵的计算来得到的。


对仿射变换中的混合变换的理解_第1张图片



那以下几个函数是经过怎样的矩阵变换来计算变换后点的位置呢?

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

在苹果的官方文档上面我查到了以下资料:

对仿射变换中的混合变换的理解_第2张图片

这样看来,混合变换的几个函数,就是它们两个仿射变换矩阵想乘的结果用来做变换。

为了验证这个假设,我写了段简单的代码。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSLog(@"initial frame: %@", NSStringFromCGRect(self.outerView.frame));
    NSLog(@"initial bounds: %@", NSStringFromCGRect(self.outerView.bounds));
    NSLog(@"initial center: %@", NSStringFromCGPoint(self.outerView.center));
    NSLog(@"initial anchorPoint: %@", NSStringFromCGPoint(self.outerView.layer.anchorPoint));
    
    //消除anchorPoint对计算结果的影响
    CGRect frame = self.outerView.frame;
    self.outerView.layer.anchorPoint = CGPointMake(0, 0);
    self.outerView.frame = frame;
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    transform = CGAffineTransformScale(transform, 0.5, 0.5);
    transform = CGAffineTransformTranslate(transform, 270, 0);
    self.outerView.layer.affineTransform = transform;
    NSLog(@"after frame: %@", NSStringFromCGRect(self.outerView.frame));
    NSLog(@"after bounds: %@", NSStringFromCGRect(self.outerView.bounds));
    NSLog(@"after center: %@", NSStringFromCGPoint(self.outerView.center));
    NSLog(@"after anchorPoint: %@", NSStringFromCGPoint(self.outerView.layer.anchorPoint));
}

运行结果如下:

2015-06-15 23:13:44.334 CoreAnimationDemo[16716:750105] initial frame: {{0, 0}, {100, 100}}
2015-06-15 23:13:44.335 CoreAnimationDemo[16716:750105] initial bounds: {{0, 0}, {100, 100}}
2015-06-15 23:13:44.335 CoreAnimationDemo[16716:750105] initial center: {50, 50}
2015-06-15 23:13:44.335 CoreAnimationDemo[16716:750105] initial anchorPoint: {0.5, 0.5}
2015-06-15 23:13:44.336 CoreAnimationDemo[16716:750105] after frame: {{135, 0}, {50, 50}}
2015-06-15 23:13:44.336 CoreAnimationDemo[16716:750105] after bounds: {{0, 0}, {100, 100}}
2015-06-15 23:13:44.336 CoreAnimationDemo[16716:750105] after center: {0, 0}
2015-06-15 23:13:44.337 CoreAnimationDemo[16716:750105] after anchorPoint: {0, 0}

这段代码的作用是先缩小一半,然后右移270点。

缩小一半的矩阵为A:

对仿射变换中的混合变换的理解_第3张图片
A

右移270点的矩阵为B:

对仿射变换中的混合变换的理解_第4张图片
B

那么transform = CGAffineTransformTranslate(transform, 270, 0);到底是A*B还是B*A呢?

我们用点(0,0)来试验一下,当A*B时,我们计算出转换后的坐标为(270,0);当B*A时,计算出转换后的坐标为(135,0)。我们看下我们代码的运行结果,可以看出正确的结果是(135,0)。即应该是B*A。

由此,我们得出结论,以下函数都是新的矩阵*先前的矩阵t来进行混合变换的。

CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)

你可能感兴趣的:(对仿射变换中的混合变换的理解)