Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One step affine transform for rotation around a point?

How can I make a Core Graphics affine transform for rotation around a point x,y of angle a, using only a single call to CGAffineTransformMake() plus math.h trig functions such as sin(), cos(), etc., and no other CG calls.

Other answers here seem to be about using multiple stacked transforms or multi-step transforms to move, rotate and move, using multiple Core Graphics calls. Those answers do not meet my specific requirements.

like image 1000
hotpaw2 Avatar asked Nov 26 '11 02:11

hotpaw2


People also ask

How many points are needed for affine transformation?

To define a unique affine 2D transformation, we need 3 points in the original position, and 3 points in the corresponding new position, .

How do you do affine transformation?

Affine transformations on the 2D plane can be performed by linear transformations in three dimensions. Translation is done by shearing along over the z axis, and rotation is performed around the z axis.

Does a circle always remain a circle after an affine transformation?

Only the position and orientation of the object will change. Affine transformations are generalizations of Euclidean transformations. Under affine transformations, lines transforms to lines; but, circles become ellipses. Length and angle are not preserved.


2 Answers

A rotation of angle a around the point (x,y) corresponds to the affine transformation:

CGAffineTransform transform = CGAffineTransformMake(cos(a),sin(a),-sin(a),cos(a),x-x*cos(a)+y*sin(a),y-x*sin(a)-y*cos(a)); 

You may need to plug in -a instead of a depending on whether you want the rotation to be clockwise or counterclockwise. Also, you may need to plug in -y instead of y depending on whether or not your coordinate system is upside down.

Also, you can accomplish precisely the same thing in three lines of code using:

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y); transform = CGAffineTransformRotate(transform, a); transform = CGAffineTransformTranslate(transform,-x,-y); 

If you were applying this to a view, you could also simply use a rotation transform via CGAffineTransformMakeRotation(a), provided you set the view's layer's anchorPoint property to reflect the point you want to rotate around. However, is sounds like you aren't interested in applying this to a view.

Finally, if you are applying this to a non-Euclidean 2D space, you may not want an affine transformation at all. Affine transformations are isometries of Euclidean space, meaning that they preserve the standard Euclidean distance, as well as angles. If your space is not Euclidean, then the transformation you want may not actually be affine, or if it is affine, the matrix for the rotation might not be as simple as what I wrote above with sin and cos. For instance, if you were in a hyperbolic space, you might need to use the hyperbolic trig functions sinh and cosh, along with different + and - signs in the formula.

P.S. I also wanted to remind anyone reading this far that "affine" is pronounced with a short "a" as in "ask", not a long "a" as in "able". I have even heard Apple employees mispronouncing it in their WWDC talks.

like image 62
landweber Avatar answered Sep 29 '22 13:09

landweber


for Swift 4

print(x, y) // where x,y is the point to rotate around let degrees = 45.0 let transform = CGAffineTransform(translationX: x, y: y)     .rotated(by: degrees * .pi / 180)     .translatedBy(x: -x, y: -y) 
like image 34
Ming Chu Avatar answered Sep 29 '22 13:09

Ming Chu