12

I want to rotate a CGPoint on the screen depending on the angle and the rotation is anchored on another point. Was wondering what is the most efficient way of doing this?

Frank
  • 3,073
  • 5
  • 40
  • 67

6 Answers6

24

You can also use that:

rotatedPoint = CGPointApplyAffineTransform(initialPoint, CGAffineTransformMakeRotation(angle));

EDIT: to perform rotation around custom point you must do like Adam described in his answer. Using CGAffineTransform it must look something like:

CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(customCenter.x, customCenter.y);
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(angle);

CGAffineTransform customRotation = CGAffineTransformConcat(CGAffineTransformConcat( CGAffineTransformInvert(translateTransform), rotationTransform), translateTransform);

rotatedPoint = CGPointApplyAffineTransform(initialPoint, customRotation);
rounak
  • 9,217
  • 3
  • 42
  • 59
Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • just made a few changes on that code, CGAffineTransformMakeTransation is CGAffineTransformMakeTranslation, minor typo. and for angle, it has to be radian but other than that this works thx! – Frank Oct 21 '09 at 15:18
13

Use a 2D rotation matrix. If you want to rotate a point counterclockwise about the origin by an angle of angle, then you would do this:

CGPoint RotatePointAboutOrigin(CGPoint point, float angle)
{
    float s = sinf(angle);
    float c = cosf(angle);
    return CGPointMake(c * point.x - s * point.y, s * point.x + c * point.y);
}

If you want to rotate about a point other than the origin, you'll have to first subtract the center of rotation from your point, rotate it using the above, and then add back in the center of rotation (this is called conjugation in matrix theory).

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
3

Swift 5

extension CGPoint {
    func rotate(around center: CGPoint, angle: CGFloat) -> CGPoint {
        let translate = CGAffineTransform(translationX: -center.x, y: -center.y)
        let transform = translate.concatenating(CGAffineTransform(rotationAngle: angle))
        let rotated = applying(transform)
        return rotated.applying(CGAffineTransform(translationX: center.x, y: center.y))
    }
}
Thompsonmachine
  • 137
  • 1
  • 6
1

Use a CGAffineTransform.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
1

You can also let Core Animation do it for you. Take a look at Apple's docs on layer geometry and transforms in the Core Animation Programming Guide

All you have to do is set the anchorPoint of the layer and then you can apply the transform with something like this:

CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation 
                     animationWithKeyPath:@"transform.rotation.z"];

[rotationAnimation setFromValue:DegreesToNumber(0)];
[rotationAnimation setToValue:DegreesToNumber(360)];

DegreesToNumber converts degrees to radians and returns an NSNumber representation.

I'm not sure what you're attempting to do exactly, but often Core Animation is a great choice for visualizations.

Matt Long
  • 24,438
  • 4
  • 73
  • 99
0

Using Vladimir’s answer, below is the Swift 3 answer:

    let initialPoint = CGPoint(x: 100, y: 100) // the point you want to rotate
    let translateTransform = CGAffineTransform(translationX: initialPoint.x, y: initialPoint.y)
    let rotationTransform = CGAffineTransform(rotationAngle: angle)
    let customRotation = (rotationTransform.concatenating(translateTransform.inverted())).concatenating(translateTransform)
    rotatedPoint = initialPoint.applying(customRotation)
Community
  • 1
  • 1
Enrique
  • 1,586
  • 17
  • 14