iPhone multi-touch scale and rotate, how to prevent scale?

Posted by russhill on Stack Overflow See other posts from Stack Overflow or by russhill
Published on 2010-06-15T12:28:31Z Indexed on 2010/06/15 12:32 UTC
Read the original article Hit count: 234

Filed under:
|
|

I have existing code for tracking multi-touch positions and then 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 rotation 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 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, whereas the above code is spot on for scale and rotate actions.

Any help appreciated!

© Stack Overflow or respective owner

Related posts about iphone

Related posts about rotation