代码之家  ›  专栏  ›  技术社区  ›  Manuel

如何正确组合cg仿射变换矩阵?

  •  1
  • Manuel  · 技术社区  · 6 年前

    // 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不产生相同的结果,因为当将它们相加时,矩阵顺序应该无关紧要?

    2 回复  |  直到 6 年前
        1
  •  2
  •   zneak    6 年前

    比例矩阵和平移矩阵的乘法和加法结果相同,这是一种巧合。

    scaledBy translatedBy 不是说加法,它们是连接两个变换的缩写,这是矩阵乘法。矩阵乘法只对对角矩阵(在对角线上只有非零值的矩阵)是可交换的,所以 S * T 一般来说和 T * S

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

    • CGAffineTransformTranslate
    • CGAffineTransformScale :t'=[sx 0 0 sy 0 0]*t
    • CGAffineTransformRotate :t'=[cos(angle)sin(angle)-sin(angle)cos(angle)0]*t
    • CGAffineTransformConcat :t'=t1*t2

    这意味着当你使用 , t1 一定是你正在申请的转变 t2 一定是你正在转换的矩阵。换句话说, scale.translatedBy 相当于 concat(translation, scale) concat(scale, translation) . 使用时 concatenate

        2
  •  0
  •   user1118321    6 年前

    除了@zneak所说的之外,矩阵运算的顺序也很重要,因为矩阵乘法(级联)是不可交换的。一般来说是A*B*A。

    因为顺序在C中是颠倒的,所以产生了不同的结果。