如何正确组合 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 不会产生相同的结果,因为相加时矩阵顺序无关紧要他们在一起?
缩放矩阵和平移矩阵的乘法和加法结果相同,纯属巧合
一般情况下,scaledBy
和translatedBy
不是相加的意思,它们是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 中顺序颠倒,因此产生不同的结果。
应缩放和变换图像。
根据变换矩阵的组成方式,我得到不同的结果:
// 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 不会产生相同的结果,因为相加时矩阵顺序无关紧要他们在一起?
缩放矩阵和平移矩阵的乘法和加法结果相同,纯属巧合
一般情况下,scaledBy
和translatedBy
不是相加的意思,它们是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 ] * tCGAffineTransformScale
: t' = [ sx 0 0 sy 0 0 ] * tCGAffineTransformRotate
: t' = [ cos(角度) sin(角度) -sin(角度) cos(角度) 0 0 ] * tCGAffineTransformConcat
: t' = t1 * t2
这意味着当您使用 CGAffineTransformConcat
时,t1
必须是您正在应用的转换,而 t2
必须是您正在转换的矩阵。换句话说,scale.translatedBy
等价于 concat(translation, scale)
,而不是 concat(scale, translation)
。当使用 concatenate
作为方法时,这会使操作向后看,因为它的数学定义。
除了@zneak 所说的,矩阵运算的顺序很重要,因为矩阵乘法(串联)是不可交换的。即一般情况下A * B ≠ B * A。
由于在 C 中顺序颠倒,因此产生不同的结果。