1

I'm rotating some views in my code and it seems that some of them get weird fractions, e.g., 10.0 becomes 10.000000000000002.

You can see it for yourself with this snippet:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)];

for (NSUInteger i = 0; i < 100; i++) {
    view.transform = CGAffineTransformRotate(view.transform, ((90.0) / 180.0 * M_PI));
    NSLog(@"%@", NSStringFromCGRect(view.frame));
}

Any help is greatly appreciated!

Rick van der Linde
  • 2,581
  • 1
  • 20
  • 22

2 Answers2

1

If the floating point inaccuracies are causing problems, one possible workaround for exactly 90 degrees is to specify the matrix by hand:

// rotate by 90˚
view.transform = CGTransformConcat(view.transform,
                                   CGAffineTransformMake(0, 1, -1, 0, 0, 0));

These magic numbers come from the equation of a rotation matrix:

⎛ cos α      sin α       0 ⎞
⎜-sin α      cos α       0 ⎟
⎝     0          0       1 ⎠

And then the left 6 parameters become the parameters to CGAffineTransformMake

when α = 90˚, we get (0, 1, -1, 0, 0, 0)

cobbal
  • 69,903
  • 20
  • 143
  • 156
  • That seems to work, but how do you know what you need to use for a, b, c, d, tx and ty? Because it's not always 90 degrees in the project itself. – Rick van der Linde Nov 18 '13 at 21:35
  • @RickvanderLinde Updated with explanation – cobbal Nov 18 '13 at 21:41
  • Ok I did some further testing, but this seems the only thing that is actually 'fixing' it. Now I just gotta do some reading about the rotation matrix, never used it before... Thank you! – Rick van der Linde Nov 19 '13 at 07:03
0

If you're looking to normalize these values, you can use CGRectIntegral. From the docs (this may change the rectangle)

A rectangle with the smallest integer values for its origin and size that contains the source rectangle. That is, given a rectangle with fractional origin or size values, CGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers, such that the result contains the original rectangle.

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)];

for (NSUInteger i = 0; i < 100; i++) {
    view.transform = CGAffineTransformRotate(view.transform, M_PI_2);
    NSLog(@"%@", NSStringFromCGRect(CGRectIntegral(view.frame)));
}
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281