【问题标题】:Get just the scaling transformation out of CGAffineTransform从 CGAffineTransform 中获取缩放转换
【发布时间】:2010-04-22 11:31:41
【问题描述】:

我发现了一个关于仅获取旋转的类似问题,但据我了解,缩放和旋转在变换矩阵中的工作方式不同。

矩阵不是我的强项,所以如果有人能提示我如何仅从 CGAffineTransform 中进行缩放,我将不胜感激。

顺便说一句。我尝试在 CGSize 上应用 CGAffineTransform,然后获取高度 x 宽度以查看它的缩放程度,但高度 x 宽度有奇怪的值(取决于在 CGAffineTransform 中找到的旋转,所以......嗯,这不起作用)

【问题讨论】:

    标签: objective-c math cgaffinetransform


    【解决方案1】:

    假设变换是缩放后旋转(可能有平移,但没有倾斜),水平比例因子为sqrt(a^2+c^2),垂直比例因子为sqrt(b^2+d^2),水平比例垂直比例因子的比例因子应为a/d = -c/b,其中abcdCGAffineTransform 的六个成员中的四个,每个the documentation (txty只代表平移,不影响比例因子)。

    |  a  b 0 |
    |  c  d 0 |
    | tx ty 1 |
    

    【讨论】:

    • 第一个答案得到分数。两者都投赞成票。感谢您对此有所了解
    • 虽然注意这样提取出来的比例总是正的(负的比例可以用来翻转物体)。
    【解决方案2】:
    - (CGFloat)xscale {
        CGAffineTransform t = self.transform;
        return sqrt(t.a * t.a + t.c * t.c);
    }
    
    - (CGFloat)yscale {
        CGAffineTransform t = self.transform;
        return sqrt(t.b * t.b + t.d * t.d);
    }
    

    【讨论】:

    • 多么甜蜜的回答。太好了,我现在患有糖尿病。
    【解决方案3】:

    这是一个老问题,但我仍然会添加更多信息以防有人需要。

    对我来说,获取比例、变换旋转和复制它的好答案和示例代码来自文章:

    http://www.informit.com/articles/article.aspx?p=1951182

    【讨论】:

      【解决方案4】:

      我不熟悉 CGAffineTransform 或 Objective-C(你用数学标签抓住了我)。通常,您需要单独退出转换。例如,如果仿射变换 A 只进行缩放、旋转和平移(下面的方法中缩放和旋转的顺序并不重要,但平移肯定是最后的):

      平移:将 A 应用于向量 (0,0) 将返回结果 (tx, ty),其中 tx 和 ty 分别是 X 和 Y 方向的平移。

      X 中的缩放 将 A 应用于向量 (1, 0) 并得到 (sx0 + tx, sx1 + ty)。 X 的缩放比例为 sqrt(sx0^2 + sx1^2)

      Y 中的缩放: 将 A 应用于向量 (0, 1) 并得到 (sy0 + tx, sy1 + ty)。 Y 的缩放比例为 sqrt(sy0^2 + sy1^2)

      由于仿射变换是通过线性变换的简单技巧实现的,并且由于线性变换不是可交换的,因此您需要了解变换的顺序,然后才能真正了解如何提取单个变换。

      【讨论】:

        【解决方案5】:

        这是一个古老的(Swift 之前的)问题,因此对于基于搜索 CGAffineTransform 到达这里的 Swift 人来说,这里是基于其他答案的 Swift 3 便利扩展:

        extension CGAffineTransform {
            var xScale: CGFloat { return sqrt(self.a * self.a + self.c * self.c) }
            var yScale: CGFloat { return sqrt(self.b * self.b + self.d * self.d) }
            var rotation: CGFloat { return CGFloat(atan2(Double(self.b), Double(self.a))) }
            // .tx and .ty are already available in the transform 
        }
        

        [编辑:根据评论更新旋转以使用双打。谢谢!]

        【讨论】:

        • 不错!谢谢你。请注意,CGFloat 在大多数平台上都是 Double。这意味着将其转换为浮点数可能会导致不准确,尤其是在使用 GPS 坐标或其他具有许多小数的值时。
        【解决方案6】:

        Swift 4 扩展(感谢 Robin Macharg 的回答)

        extension CGAffineTransform
        {
            var xScale: CGFloat { return sqrt(a * a + c * c) }
            var yScale: CGFloat { return sqrt(b * b + d * d) }
            var rotation: CGFloat { return CGFloat(atan2(Double(b), Double(a))) }
            var xOffset: CGFloat { return tx }
            var yOffset: CGFloat { return ty }
        }
        

        请注意,CGFloat 在大多数平台上等于 Double,因此转换需要为 Double。

        【讨论】:

          【解决方案7】:

          让我提出不同的解决方案。我首先沿相反方向旋转仿射变换,然后从 t.a 和 t.d 读取比例:

          - (CGPoint)scaleFromTransform {
              CGAffineTransform t = self.transform;
              CGFloat angle = atan2(t.b, t.a);
              // calculate rotation transform (by -angle)
              CGAffineTransform r = CGAffineTransformMakeRotation(-angle);
              // calculate main transform without rotation
              CGAffineTransform t0 = CGAffineTransformConcat(t, r);
              CGFloat xScale = t0.a;
              CGFloat yScale = t0.d;
              return CGPointMake(xScale, yScale);
          }
          

          【讨论】:

            猜你喜欢
            • 2014-09-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-22
            • 2018-01-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多