CGAffineTransform:如何计算乘法 CGAffineTransform?

Posted

技术标签:

【中文标题】CGAffineTransform:如何计算乘法 CGAffineTransform?【英文标题】:CGAffineTransform: How to calculate multiply CGAffineTransform? 【发布时间】:2016-02-16 10:12:55 【问题描述】:

我需要将视图从原点 (250, 250) 转换为原点 (352, 315),并将宽度/高度从 (100.0, 100.0) 更改为 (68, 68)。 我知道我可以将几个 CGAffineTransform 函数组合在一起,例如缩放、旋转、平移。 但我不知道如何计算这些转换的顺序,以及它们的确切参数。 我尝试了几次,但无法将视图移动到正确的位置。

有人可以帮忙吗?

【问题讨论】:

【参考方案1】:

在这些矩阵转换中,对幕后发生的事情有一点了解总是很好的。

Apple 文档有一个关于转换的 great documentation,所以让我们使用它。


一个平移矩阵看起来像:

|  1   0   0  |
|  0   1   0  |
|  tx  ty  1  |

(tx, ty) 是您的翻译向量。


缩放矩阵看起来像:

|  sx  0   0  |
|  0   sy  0  |
|  0   0   1  |

其中sxsy是X和Y轴的比例因子。


您想使用CGAffineTransformConcat 连接这些矩阵,但根据its doc:

请注意,矩阵运算不是可交换的—— 连接矩阵很重要。也就是相乘的结果 矩阵 t1 乘以矩阵 t2 不一定等于 将矩阵 t2 与矩阵 t1 相乘。

您必须在缩放之前平移视图,否则您的平移向量将根据sxsy 系数进行缩放。

让我们轻松展示一下:

let scaleMatrix = CGAffineTransformMakeScale(0.68, 0.68)
let translateMatrix = CGAffineTransformMakeTranslation(102, 65)

let translateThenScaleMatrix = CGAffineTransformConcat(scaleMatrix, translateMatrix)
NSLog("translateThenScaleMatrix : \(translateThenScaleMatrix)")
// outputs : CGAffineTransform(a: 0.68, b: 0.0, c: 0.0, d: 0.68, tx: 102.0, ty: 65.0)
// the translation is the same

let scaleThenTranslateMatrix = CGAffineTransformConcat(translateMatrix, scaleMatrix)
NSLog("scaleThenTranslateMatrix : \(scaleThenTranslateMatrix)")
// outputs : CGAffineTransform(a: 0.68, b: 0.0, c: 0.0, d: 0.68, tx: 69.36, ty: 44.2)
// the translation has been scaled too

让我们用数学方法证明它。请注意,当您执行操作 A 然后执行操作 B 时,通过执行 matB*matA 计算相关矩阵,第一个操作在右侧。由于矩阵的乘法不可交换,所以它很重要。

// Translate then  scaling :
|  sx  0   0  |   |  1   0   0  |   |    sx   0    0 |
|  0   sy  0  | . |  0   1   0  | = |    0    sy   0 |
|  0   0   1  |   |  tx  ty  1  |   |    tx   ty   1 |
// The resulting matrix has the same value for translation

// Scaling then translation :
|  1   0   0  |   |  sx  0   0  |   |    sx     0      0 |
|  0   1   0  | . |  0   sy  0  | = |    0      sy     0 |
|  tx  ty  1  |   |  0   0   1  |   |  sx.tx   sy.ty   1 |
// The translation values are affected by scaling coefficient

【讨论】:

非常感谢,现在我的问题转向 4 矩阵(身份、平移、缩放、旋转)计算。 见这里:developer.apple.com/library/mac/documentation/GraphicsImaging/… 这不是完全错误的吗?如果你去 Xcode 中 CGAffineTransformConcat(A,B) 的定义,它说得到的变换矩阵正好是 T=A*B。所以首先应用 A,然后应用 B,因为 p_new = p * T = (p * A)*B - 其中 p 是一个点。尝试通过应用 CGaffinetransformconcat(rotateMatrix, translateMatrix) 来旋转然后平移。对象将在其坐标系中旋转,然后在其坐标系中进行平移。 顺便说一句,我并不是说你解释的最终结果是错误的 - 错误是对内部如何完成的解释,甚至很多书都有问题。 当你在一个点上使用变换矩阵时,变换矩阵是左操作数,所以实际上你有pNew = T * p = A * B * p,因此第一个变换应用于p是 B。【参考方案2】:
struct CGAffineTransform 
  CGFloat a, b, c, d;
  CGFloat tx, ty;
;

你可以通过这个struct获取参数。而且transforms总是override,也就是说不会叠加,注意这一点。

【讨论】:

以上是关于CGAffineTransform:如何计算乘法 CGAffineTransform?的主要内容,如果未能解决你的问题,请参考以下文章

CGAffineTransform 放射变换解析 即矩阵变换

旋转超级视图后计算 CGAffineTransform 矩阵

有没有办法计算将视图从帧 A 转换到帧 B 所需的 CGAffineTransform?

iphone sdk CGAffineTransform 获取对象的旋转角度

我如何使用 CGAffineTransform 进行正确的拖放

如何理解CGAffineTransform