I’m struggling with rotating a triangle resulting from a UIRotationGestureRecognizer. If you could look over my approach and offer suggestions, I’d greatly appreciate it.
I ask the gesture recognizer object for the rotation, which the documentation says is returned in radians.
My strategy had been to think of each vertex as a point on a circle that exists between the center of the triangle and the vertex, and then use the radians of rotation to find the new point on that circumference. I’m not totally sure this is a valid approach, but I wanted to at least try it. Visually I’d know whether or not it was working.
Here’s the code I created in that attempt:
- (CGPoint)rotateVertex:(CGPoint)vertex byRadians:(float)radians
{
float deltaX = center.x - vertex.x;
float deltaY = center.y - vertex.y;
float currentAngle = atanf( deltaX / deltaY );
float newAngle = currentAngle + radians;
float newX = cosf(newAngle) + vertex.x;
float newY = sinf(newAngle) + vertex.y;
return CGPointMake(newX, newY);
}
When executed, there’s a slight rotation at the beginning, but then as I continue rotating my fingers the vertices just start getting farther away from the center point, indicating I’m confusing something here.
I looked at what the CGContextRotateCTM could do for me, but ultimately I need to know what the vertices are after the rotation, so just rotating the graphics context doesn’t appear to leave me with those changed coordinates.
I also tried the technique described here but that resulted in the triangle being flipped about the second vertex, which seems odd, but then that technique works with p and q being the x and y coordinates of the second vertex.
Thanks for taking a look!
Solved: Here is the corrected function. It assumes you have calculated the center of the triangle. I used the 1/3(x1 + x2 + x3), 1/3(y1 + y2 + y3) method described on the Wikipedia article on Centroids.
- (CGPoint)rotatePoint:(CGPoint)currentPoint byRadians:(float)radiansOfRotation
{
float deltaX = currentPoint.x - center.x;
float deltaY = currentPoint.y - center.y;
float radius = sqrtf(powf(deltaX, 2.0) + powf(deltaY, 2.0));
float currentAngle = atan2f( deltaY, deltaX );
float newAngle = currentAngle + radiansOfRotation;
float newRun = radius * cosf(newAngle);
float newX = center.x + newRun;
float newRise = radius * sinf(newAngle);
float newY = center.y + newRise;
return CGPointMake(newX, newY);
}
Of noteworthy relevance to why the first code listing did not work was that the arguments to atan2 were reversed. Also, the correct calculation of the delta values was reversed.
You’re forgetting to multiply by the radius of the circle. Also, since the Y axis points down in the UIKit coordinate system, you have to subtract instead of add the radians and negate the y coordinate at the end. And you need to use atan2 only gives output in the range -pi/2 to pi/2: