Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find Frame Coordinates After UIView Transform is Applied (CGAffineTransform)

I rotate my view with CGAffineTransform

[view setTransform:newTransform]; 

The frame values remain the same after transform is applied but how do I find "rotated" or transformed values of this frame?


(source: informit.com)

I want the exact coordinates of rotated frame edges, that is a, b, c, d points.

like image 636
Vad Avatar asked Oct 22 '13 16:10

Vad


1 Answers

One thing to keep in mind is that the transform changes the coordinate system, so you will need to be able to convert between the parent 'view' and the child (transformed) view. Also, transforms preserve the center of the transformed object but not any of the other coordinates. So you need to calculate things in terms of the center. And there are several helpers you will need. (I got most of the following approach from Erica Sadun's book Core iOS Developer's Cookbook).

I usually add these as a category on UIView.

In order to transform the child's coordinates to those of the parent you need something like:

// helper to get pre transform frame -(CGRect)originalFrame {    CGAffineTransform currentTransform = self.transform;    self.transform = CGAffineTransformIdentity;    CGRect originalFrame = self.frame;    self.transform = currentTransform;     return originalFrame; }  // helper to get point offset from center -(CGPoint)centerOffset:(CGPoint)thePoint {     return CGPointMake(thePoint.x - self.center.x, thePoint.y - self.center.y); } // helper to get point back relative to center -(CGPoint)pointRelativeToCenter:(CGPoint)thePoint {   return CGPointMake(thePoint.x + self.center.x, thePoint.y + self.center.y); } // helper to get point relative to transformed coords -(CGPoint)newPointInView:(CGPoint)thePoint {     // get offset from center     CGPoint offset = [self centerOffset:thePoint];     // get transformed point     CGPoint transformedPoint = CGPointApplyAffineTransform(offset, self.transform);     // make relative to center     return [self pointRelativeToCenter:transformedPoint]; }  // now get your corners -(CGPoint)newTopLeft {     CGRect frame = [self originalFrame];     return [self newPointInView:frame.origin]; } -(CGPoint)newTopRight {     CGRect frame = [self originalFrame];     CGPoint point = frame.origin;     point.x += frame.size.width;     return [self newPointInView:point]; } -(CGPoint)newBottomLeft {     CGRect frame = [self originalFrame];     CGPoint point = frame.origin;     point.y += frame.size.height;     return [self newPointInView:point]; } -(CGPoint)newBottomRight {     CGRect frame = [self originalFrame];     CGPoint point = frame.origin;     point.x += frame.size.width;     point.y += frame.size.height;     return [self newPointInView:point]; } 

Swift 4

extension UIView {     /// Helper to get pre transform frame     var originalFrame: CGRect {         let currentTransform = transform         transform = .identity         let originalFrame = frame         transform = currentTransform         return originalFrame     }      /// Helper to get point offset from center     func centerOffset(_ point: CGPoint) -> CGPoint {         return CGPoint(x: point.x - center.x, y: point.y - center.y)     }      /// Helper to get point back relative to center     func pointRelativeToCenter(_ point: CGPoint) -> CGPoint {         return CGPoint(x: point.x + center.x, y: point.y + center.y)     }      /// Helper to get point relative to transformed coords     func newPointInView(_ point: CGPoint) -> CGPoint {         // get offset from center         let offset = centerOffset(point)         // get transformed point         let transformedPoint = offset.applying(transform)         // make relative to center         return pointRelativeToCenter(transformedPoint)     }      var newTopLeft: CGPoint {         return newPointInView(originalFrame.origin)     }      var newTopRight: CGPoint {         var point = originalFrame.origin         point.x += originalFrame.width         return newPointInView(point)     }      var newBottomLeft: CGPoint {         var point = originalFrame.origin         point.y += originalFrame.height         return newPointInView(point)     }      var newBottomRight: CGPoint {         var point = originalFrame.origin         point.x += originalFrame.width         point.y += originalFrame.height         return newPointInView(point)     } } 
like image 74
Bladebunny Avatar answered Sep 20 '22 21:09

Bladebunny