CGAffineTransform 连接两个矩阵与将一个矩阵应用于另一个矩阵

CGAffineTransform concatenating two matrices vs applying one to the other

在下面的例子中,为什么第一个矩阵等于第三个而不是第二个?

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)

为了避免与名称混淆,我将您的变量从 tN 重命名为 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)

确实看起来倒退了。除了 concatenating 函数之外,这些方法的文档并没有真正说明任何数学。

如您在 concatenating 的文档中所见:

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

r1 变量的示例代码中,这是 scale * translate

这部分看起来很清楚。

至于translatedByscaledBy函数需要查看Objective-C头文件中CGAffineTransformTranslateCGAffineTransformScale对应的函数。

对于 CGAffineTransformTranslate 你看到评论:

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

对于 CGAffineTransformScale 你会看到:

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

这个信息告诉我们 let r = t.translatedBy(t2) 等同于 t' = t2 * t。当然 scaledByrotatedBy 是相似的。

这意味着您代码中的这一行:

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

等同于:

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

而不是:

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

这就是为什么在您的示例代码中,r1 等于 r3。像英语一样阅读第二两行会导致矩阵以相反顺序连接的想法。