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 |
其中sx
和sy
是X和Y轴的比例因子。
您想使用CGAffineTransformConcat
连接这些矩阵,但根据its doc:
请注意,矩阵运算不是可交换的—— 连接矩阵很重要。也就是相乘的结果 矩阵 t1 乘以矩阵 t2 不一定等于 将矩阵 t2 与矩阵 t1 相乘。
您必须在缩放之前平移视图,否则您的平移向量将根据sx
和sy
系数进行缩放。
让我们轻松展示一下:
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 获取对象的旋转角度