I am currently rotating a UIImageView by touching, dragging, and releasing. I am rotating the object by the function:
-(void)rotateForTime:(CGFloat)time distance:(CGFloat)distance
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat:distance];
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.duration = time;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.timingFunction = [CAMediaTimingFunctionfunctionWithName:
kCAMediaTimingFunctionEaseOut];
rotationAnimation.delegate = self;
[bottle.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
Since after a rotation, the bounds of the rectangular image change, in order to tell if the user touches inside the image or not, I keep track of the corners of the image by rotating them the same distance I rotate the image and then use vector->edge intersection detection methods to check if the user touched in the bounds of the rectangle made by the corners. I use this function to rotate the corners:
-(void) rotateImageBounds:(CGFloat) angle
{
// Translate the center and the corners of the image to the origin and their respective positions.
corner1.x = corner1.x - bottle.center.x;
corner1.y = corner1.y - bottle.center.y;
corner2.x = corner2.x - bottle.center.x;
corner2.y = corner2.y - bottle.center.y;
corner3.x = corner3.x - bottle.center.x;
corner3.y = corner3.y - bottle.center.y;
corner4.x = corner4.x - bottle.center.x;
corner4.y = corner4.y - bottle.center.y;
// Rotates the point around the origin/center.
// x = x1cos(angle) - x1sin(angle)
// y = x1sin(angle) + y1cos(angle)
CGFloat tempX;
tempX = (corner1.x*cos(angle)) - (corner1.y*sin(angle));
corner1.y = (corner1.x*sin(angle)) + (corner1.y*cos(angle));
corner1.x = tempX;
tempX = (corner2.x*cos(angle)) - (corner2.y*sin(angle));
corner2.y = (corner2.x*sin(angle)) + (corner2.y*cos(angle));
corner2.x = tempX;
tempX = (corner3.x*cos(angle)) - (corner3.y*sin(angle));
corner3.y = (corner3.x*sin(angle)) + (corner3.y*cos(angle));
corner3.x = tempX;
tempX = (corner4.x*cos(angle)) - (corner4.y*sin(angle));
corner4.y = (corner4.x*sin(angle)) + (corner4.y*cos(angle));
corner4.x = tempX;
// Translates the points back to the original center of the image.
corner1.x = corner1.x + bottle.center.x;
corner1.y = corner1.y + bottle.center.y;
corner2.x = corner2.x + bottle.center.x;
corner2.y = corner2.y + bottle.center.y;
corner3.x = corner3.x + bottle.center.x;
corner3.y = corner3.y + bottle.center.y;
corner4.x = corner4.x + bottle.center.x;
corner4.y = corner4.y + bottle.center.y;
}
This works fine after the first rotation, the corners look like the are still at the corners of the image. However, after more rotations, the image and the corners no longer line up. As far as I know, the rotation method is accurate and the math for the corners is right. I've been trying to figure out this problem for days now. Any help would be greatly appreciated.
EDIT * Problem solved: I ended up letting the animation remove itself when it was done and just rotate the image into the right position when I was done (it was easier this way because I also need to rotate the image during mouse motion). For the rotation function: (angle is the angle that the mouse (or touch) was currently at, gotten using atan2(dy,dx) where dy is the height between the touch and center and dx is the width. Distance is the distance it needs to rotate.
-(void)rotateForTime:(CGFloat)time distance:(CGFloat)distance {
animating = TRUE;
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithFloat:angle];
rotationAnimation.toValue = [NSNumber numberWithFloat:distance + angle];
rotationAnimation.removedOnCompletion = YES;
rotationAnimation.fillMode = kCAFillModeForwards;
rotationAnimation.duration = time;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseOut];
rotationAnimation.delegate = self;
[bottle.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
And then at the end of the animation:
-(void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
animating = FALSE;
// Rotates the image to the last spot that the animation rotated to.
[bottle.layer setValue:[NSNumber numberWithFloat:angle + distance]
forKeyPath:@"transform.rotation.z"];
// Gives the corners of the image after rotation (Thanks to mustISignUp) check to make sure
// that the touch is within these bounds (I use a ray line intersection algorithm in another part of my code)
ptInLayerCoords1 = [[bottle.layer presentationLayer] convertPoint:corner1 toLayer:self.view.layer];
ptInLayerCoords2 = [[bottle.layer presentationLayer] convertPoint:corner2 toLayer:self.view.layer];
ptInLayerCoords3 = [[bottle.layer presentationLayer] convertPoint:corner3 toLayer:self.view.layer];
ptInLayerCoords4 = [[bottle.layer presentationLayer] convertPoint:corner4 toLayer:self.view.layer];
}