Как правильно комбинировать матрицы CGAffineTransform? - PullRequest
0 голосов
/ 25 сентября 2018

Изображение должно быть масштабировано и преобразовано.

В зависимости от того, как составлена ​​матрица преобразования, я получаю разные результаты:

// 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 ]

0 голосов
/ 25 сентября 2018

В дополнение к тому, что сказал @zneak, порядок матричных операций имеет значение, поскольку умножение матриц (конкатенация) не является коммутативным.То есть A * B ≠ B * A в целом.

Поскольку порядок в C обратный, он дает другой результат.

0 голосов
/ 25 сентября 2018

Это совпадение, что умножение и сложение матрицы масштабирования и матрицы перевода имеют одинаковый результат.

В общем случае scaledBy и translatedBy не означают сложение,они являются сокращением для объединения двух преобразований, что является умножением матрицы.Умножение матриц является коммутативным только для диагональных матриц (матриц, которые имеют ненулевые значения в диагональной линии), поэтому 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 00] * t
  • CGAffineTransformRotate: t '= [cos (угол) sin (угол) -in (угол) cos (угол) 0 0] * t
  • CGAffineTransformConcat:t '= t1 * t2

Это означает, что когда вы используете CGAffineTransformConcat, t1 должно быть преобразованием, которое вы применяете, и t2 должно быть матрицей, которую вы преобразовываете,Другими словами, scale.translatedBy эквивалентно concat(translation, scale), а не concat(scale, translation).При использовании concatenate в качестве метода это заставляет операцию смотреть назад из-за ее математического определения.

...