如何正确组合 CGAffineTransform 矩阵?

How to correctly combine CGAffineTransform matrices?

应缩放和变换图像。

根据变换矩阵的组成方式,我得到不同的结果:

// A) This produces the desired result, scales the image and translates the image independently from each other
let transform = CGAffineTransform(translationX: translation.x, y: translation.y).scaledBy(x: scale.width, y: scale.height)

// B) This also produces the desired result
let scaleTransform = CGAffineTransform(scaleX: scale.width, y: scale.height)
let translateTransform = CGAffineTransform(translationX: translation.x, y: translation.y)
let transform = scaleTransform.concatenating(translateTransform)

// C) This does not produce the desired result, it also scales the translation, so a 10x scale results in a 10x translation
let transform = CGAffineTransform(scaleX: scale.width, y: scale.height).translatedBy(x: translation.x, y: translation.y)

// Transform image
image = image.transformed(by: transform)

如果 .concatenating 表示相乘而 .scaledBy.translatedBy 表示相加两个矩阵,为什么 A 和 C 不会产生相同的结果,因为相加时矩阵顺序无关紧要他们在一起?

缩放矩阵和平移矩阵的乘法和加法结果相同,纯属巧合

一般情况下,scaledBytranslatedBy不是相加的意思,它们是shorthand用于连接两个变换,也就是矩阵乘法。矩阵乘法仅对对角矩阵(对角线上只有非零值的矩阵)是可交换的,因此 S * T 通常与 T * S.

不同

查找 $(xcrun --show-sdk-path)/System/Library/Frameworks/CoreGraphics.framework/Headers/CGAffineTransform.h 每个函数的作用:

  • CGAffineTransformTranslate: t' = [ 1 0 0 1 tx ty ] * t
  • CGAffineTransformScale: t' = [ sx 0 0 sy 0 0 ] * t
  • CGAffineTransformRotate: t' = [ cos(角度) sin(角度) -sin(角度) cos(角度) 0 0 ] * t
  • CGAffineTransformConcat: t' = t1 * t2

这意味着当您使用 CGAffineTransformConcat 时,t1 必须是您正在应用的转换,而 t2 必须是您正在转换的矩阵。换句话说,scale.translatedBy 等价于 concat(translation, scale),而不是 concat(scale, translation)。当使用 concatenate 作为方法时,这会使操作向后看,因为它的数学定义。

除了@zneak 所说的,矩阵运算的顺序很重要,因为矩阵乘法(串联)是不可交换的。即一般情况下A * B ≠ B * A。

由于在 C 中顺序颠倒,因此产生不同的结果。