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

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

有人可以帮忙吗?

【问题讨论】:

    标签: ios 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 矩阵(身份、平移、缩放、旋转)计算。
    • 这不是完全错误的吗?如果你去 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,也就是说不会叠加,注意这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-24
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多