从CGAffineTransform中获取缩放转换

时间:2010-04-22 11:31:42

标签: objective-c math cgaffinetransform

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

矩阵不是我的力量,所以如果有人提示我如何从CGAffineTransform中获得仅缩放,我会非常感激。

顺便说一句。我尝试在CGSize上应用CGAffineTransform然后获得高度x宽度以查看它缩放了多少,但是高度x宽度具有奇怪的值(取决于在CGAffineTransform中找到的旋转,所以... hm不起作用)< / p>

7 个答案:

答案 0 :(得分:45)

假设转换是一个缩放后跟一个旋转(可能在那里有一个平移但没有倾斜),水平比例因子是sqrt(a^2+c^2),垂直比例因子是sqrt(b^2+d^2),并且水平比例因子与垂直比例因子的比率应为a/d = -c/b,其中abcd为六个成员中的四个CGAffineTransform的{​​{1}},txty仅代表翻译,不影响比例因素。)

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

答案 1 :(得分:29)

- (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);
}

答案 2 :(得分:8)

这是一个老问题,但我还是会在有人需要时添加更多信息。

对我来说,获得规模,转换轮换和复制它的好答案和示例代码来自文章:

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

答案 3 :(得分:5)

我不熟悉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)

由于仿射变换是通过线性变换的简单技巧实现的,并且由于线性变换不是可交换的,因此您需要了解在实际处理如何拉出单个变换之前如何排序变换。

答案 4 :(得分:4)

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

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 
}

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

答案 5 :(得分:0)

让我提出不同的解决方案。我首先沿相反方向旋转仿射变换,然后从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);
}

答案 6 :(得分:0)

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。