Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CGAffineTransform concatenating two matrices vs applying one to the other

In this example below, why the first matrix is equal to the third, not the second?

let t1 = CGAffineTransform(scaleX: 2, y: 2)
    .concatenating(CGAffineTransform(translationX: 50, y: 50))

let t2 = CGAffineTransform(scaleX: 2, y: 2).translatedBy(x: 50, y: 50)

let t3 = CGAffineTransform(translationX: 50, y: 50).scaledBy(x: 2, y: 2)
like image 305
Dannie P Avatar asked Oct 16 '22 21:10

Dannie P


1 Answers

To avoid confusion with names, I'm renaming your variables from tN to rN:

let r1 = CGAffineTransform(scaleX: 2, y: 2)
    .concatenating(CGAffineTransform(translationX: 50, y: 50))

let r2 = CGAffineTransform(scaleX: 2, y: 2).translatedBy(x: 50, y: 50)

let r3 = CGAffineTransform(translationX: 50, y: 50).scaledBy(x: 2, y: 2)

It really does seem backwards. And the documentation for the methods doesn't really make it clear for any of the math other than for the concatenating function.

As you can see in the documentation for concatenating:

A new affine transformation matrix. That is, t’ = t1*t2.

In your sample code for the r1 variable this is scale * translate.

That part seems clear enough.

As for the translatedBy and scaledBy functions you need to look at the Objective-C header file for the corresponding functions of CGAffineTransformTranslate and CGAffineTransformScale.

For CGAffineTransformTranslate you see the comment:

Translate t by (tx, ty) and return the result: t' = [ 1 0 0 1 tx ty ] * t

And for CGAffineTransformScale you see:

Scale t by (sx, sy) and return the result: t' = [ sx 0 0 sy 0 0 ] * t

This information tells us that let r = t.translatedBy(t2) is equivalent to t' = t2 * t. Of course the scaledBy and rotatedBy are similar.

This means that this line in your code:

let r3 = CGAffineTransform(translationX: 50, y: 50).scaledBy(x: 2, y: 2)

is the same as:

let r3 = CGAffineTransform(scaleX: 2, y: 2).concatenating(CGAffineTransform(translationX: 50, y: 50))

and not:

let r3 = CGAffineTransform(translationX: 50, y: 50).concatenating(CGAffineTransform(scaleX: 2, y: 2))

This is why in your sample code, r1 is equal to r3. Reading those 2nd two lines like English leads to the idea that the matrices are concatenated in the reverse order.

like image 115
rmaddy Avatar answered Oct 21 '22 01:10

rmaddy