iPhone multi-touch move, scale and rotate, how to prevent scale?
I have existing code for tracking multi-touch positions and then moving, rotating and scaling the item - in this case an image - appropriately.
The code works really well and in itself is perfect, however for this particular task, I need the movement and rota开发者_JS百科tion ONLY. I have spent time trying to work out what is going on in this routine, but maths is not my strong point so wanted to see if anyone could assist?
- (CGAffineTransform)incrementalTransformWithTouches:(NSSet *)touches
{
NSArray *sortedTouches = [[touches allObjects] sortedArrayUsingSelector:@selector(compareAddress:)];
NSInteger numTouches = [sortedTouches count];
// No touches
if (numTouches == 0) {
return CGAffineTransformIdentity;
}
// Single touch
if (numTouches == 1) {
UITouch *touch = [sortedTouches objectAtIndex:0];
CGPoint beginPoint = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch);
CGPoint currentPoint = [touch locationInView:self.superview];
return CGAffineTransformMakeTranslation(currentPoint.x - beginPoint.x, currentPoint.y - beginPoint.y);
}
// If two or more touches, go with the first two (sorted by address)
UITouch *touch1 = [sortedTouches objectAtIndex:0];
UITouch *touch2 = [sortedTouches objectAtIndex:1];
CGPoint beginPoint1 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch1);
CGPoint currentPoint1 = [touch1 locationInView:self.superview];
CGPoint beginPoint2 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch2);
CGPoint currentPoint2 = [touch2 locationInView:self.superview];
double layerX = self.center.x;
double layerY = self.center.y;
double x1 = beginPoint1.x - layerX;
double y1 = beginPoint1.y - layerY;
double x2 = beginPoint2.x - layerX;
double y2 = beginPoint2.y - layerY;
double x3 = currentPoint1.x - layerX;
double y3 = currentPoint1.y - layerY;
double x4 = currentPoint2.x - layerX;
double y4 = currentPoint2.y - layerY;
// Solve the system:
// [a b t1, -b a t2, 0 0 1] * [x1, y1, 1] = [x3, y3, 1]
// [a b t1, -b a t2, 0 0 1] * [x2, y2, 1] = [x4, y4, 1]
double D = (y1-y2)*(y1-y2) + (x1-x2)*(x1-x2);
if (D < 0.1) {
return CGAffineTransformMakeTranslation(x3-x1, y3-y1);
}
double a = (y1-y2)*(y3-y4) + (x1-x2)*(x3-x4);
double b = (y1-y2)*(x3-x4) - (x1-x2)*(y3-y4);
double tx = (y1*x2 - x1*y2)*(y4-y3) - (x1*x2 + y1*y2)*(x3+x4) + x3*(y2*y2 + x2*x2) + x4*(y1*y1 + x1*x1);
double ty = (x1*x2 + y1*y2)*(-y4-y3) + (y1*x2 - x1*y2)*(x3-x4) + y3*(y2*y2 + x2*x2) + y4*(y1*y1 + x1*x1);
return CGAffineTransformMake(a/D, -b/D, b/D, a/D, tx/D, ty/D);
}
I have tried to read up on the way matrix's work, but cannot figure it out entirely. More likely to be the issue is the calculations, which as I mention is not my strong point.
What I need from this routine is a transform that performs my movement and rotation but ignores scale - so the distance between the 2 finger touch points is ignored and scale is not affected.
I have looked at other routines on the internet to handle multi-touch rotation but all the ones I tried had issues in some way or other (smoothness, jumping when lifting fingers etc), whereas the above code is spot on for move, scale and rotate actions.
Any help appreciated!
Do something like this:
CGAffineTransform transform = self.view.transform;
float scale = sqrt(transform.a*transform.a + transform.c*transform.c);
self.view.transform = CGAffineTransformScale(transform, 1/scale, 1/scale);
At the end of your touchesMoved:withEvent: and updateOriginalTransformForTouches methods. Basically, you calculate the current scale value, then multiply your transformation matrix with the reversed scale value.
精彩评论