luckylefty01

Jun 29, 2008, 08:56 PM

This is the current code I'm using to do your typical iPhone rotate/scale with two fingers on a view. I did it using your fairly typical pythagorean theorem and trig combination.

What I'm wondering is if there's a better/cleaner/more efficient mathematically way to do it?

This is an example of how it could be used in program:

view.transform = CGAffineTransformWithTouches(view.transform, firstTouch, secondTouch);

[UIView commitAnimations];

The code:

CGFloat distanceBetweenPoints(CGPoint firstPoint, CGPoint secondPoint) {

CGFloat distance;

//Square difference in x

CGFloat xDifferenceSquared = pow(firstPoint.x - secondPoint.x, 2);

// NSLog(@"xDifferenceSquared: %f", xDifferenceSquared);

// Square difference in y

CGFloat yDifferenceSquared = pow(firstPoint.y - secondPoint.y, 2);

// NSLog(@"yDifferenceSquared: %f", yDifferenceSquared);

// Add and take Square root

distance = sqrt(xDifferenceSquared + yDifferenceSquared);

// NSLog(@"Distance: %f", distance);

return distance;

}

CGPoint vectorBetweenPoints(CGPoint firstPoint, CGPoint secondPoint) {

// NSLog(@"Point One: %f, %f", firstPoint.x, firstPoint.y);

// NSLog(@"Point Two: %f, %f", secondPoint.x, secondPoint.y);

CGFloat xDifference = firstPoint.x - secondPoint.x;

CGFloat yDifference = firstPoint.y - secondPoint.y;

CGPoint result = CGPointMake(xDifference, yDifference);

return result;

}

CGAffineTransform CGAffineTransformWithTouches(CGAffineTransform oldTransform,

UITouch *firstTouch,

UITouch *secondTouch) {

CGPoint firstTouchLocation = [firstTouch locationInView:nil];

CGPoint firstTouchPreviousLocaion = [firstTouch previousLocationInView:nil];

CGPoint secondTouchLocation = [secondTouch locationInView:nil];

CGPoint secondTouchPreviousLocaion = [secondTouch previousLocationInView:nil];

CGAffineTransform newTransform;

// Calculate new scale and rotation

// Get distance between points

CGFloat currentDistance = distanceBetweenPoints(firstTouchLocation,

secondTouchLocation);

CGFloat previousDistance = distanceBetweenPoints(firstTouchPreviousLocaion,

secondTouchPreviousLocaion);

// Figure new scale

CGFloat distanceRatio = currentDistance / previousDistance;

// NSLog(@"DifferenceRatio: %f, %f", distanceRatio.x, distanceRatio.y);

// Combine with current transform

newTransform = CGAffineTransformScale(oldTransform, distanceRatio, distanceRatio);

// Now figure new rotation

// Get previous angle

CGPoint previousDifference = vectorBetweenPoints(firstTouchPreviousLocaion, secondTouchPreviousLocaion);

CGFloat xDifferencePrevious = previousDifference.x;

// Use acos to get angle to avoid issue with the denominator being 0

CGFloat previousRotation = acos(xDifferencePrevious / previousDistance); // adjacent over hypotenuse

if (previousDifference.y < 0) {

// account for acos of angles in quadrants III and IV

previousRotation *= -1;

}

// NSLog(@"previousRotation: %f", previousRotation);

// Get current angle

CGPoint currentDifference = vectorBetweenPoints(firstTouchLocation, secondTouchLocation);

CGFloat xDifferenceCurrent = currentDifference.x;

// Use acos to get angle to avoid issue with the denominator being 0

CGFloat currentRotation = acos(xDifferenceCurrent / currentDistance); // adjacent over hypotenuse

if (currentDifference.y < 0) {

// account for acos of angles in quadrants III and IV

currentRotation *= -1;

}

// NSLog(@"currentRotation: %f", currentRotation);

CGFloat newAngle = currentRotation - previousRotation;

// Combine with current transform

newTransform = CGAffineTransformRotate(newTransform, newAngle);

// Return result

return newTransform;

}

What I'm wondering is if there's a better/cleaner/more efficient mathematically way to do it?

This is an example of how it could be used in program:

view.transform = CGAffineTransformWithTouches(view.transform, firstTouch, secondTouch);

[UIView commitAnimations];

The code:

CGFloat distanceBetweenPoints(CGPoint firstPoint, CGPoint secondPoint) {

CGFloat distance;

//Square difference in x

CGFloat xDifferenceSquared = pow(firstPoint.x - secondPoint.x, 2);

// NSLog(@"xDifferenceSquared: %f", xDifferenceSquared);

// Square difference in y

CGFloat yDifferenceSquared = pow(firstPoint.y - secondPoint.y, 2);

// NSLog(@"yDifferenceSquared: %f", yDifferenceSquared);

// Add and take Square root

distance = sqrt(xDifferenceSquared + yDifferenceSquared);

// NSLog(@"Distance: %f", distance);

return distance;

}

CGPoint vectorBetweenPoints(CGPoint firstPoint, CGPoint secondPoint) {

// NSLog(@"Point One: %f, %f", firstPoint.x, firstPoint.y);

// NSLog(@"Point Two: %f, %f", secondPoint.x, secondPoint.y);

CGFloat xDifference = firstPoint.x - secondPoint.x;

CGFloat yDifference = firstPoint.y - secondPoint.y;

CGPoint result = CGPointMake(xDifference, yDifference);

return result;

}

CGAffineTransform CGAffineTransformWithTouches(CGAffineTransform oldTransform,

UITouch *firstTouch,

UITouch *secondTouch) {

CGPoint firstTouchLocation = [firstTouch locationInView:nil];

CGPoint firstTouchPreviousLocaion = [firstTouch previousLocationInView:nil];

CGPoint secondTouchLocation = [secondTouch locationInView:nil];

CGPoint secondTouchPreviousLocaion = [secondTouch previousLocationInView:nil];

CGAffineTransform newTransform;

// Calculate new scale and rotation

// Get distance between points

CGFloat currentDistance = distanceBetweenPoints(firstTouchLocation,

secondTouchLocation);

CGFloat previousDistance = distanceBetweenPoints(firstTouchPreviousLocaion,

secondTouchPreviousLocaion);

// Figure new scale

CGFloat distanceRatio = currentDistance / previousDistance;

// NSLog(@"DifferenceRatio: %f, %f", distanceRatio.x, distanceRatio.y);

// Combine with current transform

newTransform = CGAffineTransformScale(oldTransform, distanceRatio, distanceRatio);

// Now figure new rotation

// Get previous angle

CGPoint previousDifference = vectorBetweenPoints(firstTouchPreviousLocaion, secondTouchPreviousLocaion);

CGFloat xDifferencePrevious = previousDifference.x;

// Use acos to get angle to avoid issue with the denominator being 0

CGFloat previousRotation = acos(xDifferencePrevious / previousDistance); // adjacent over hypotenuse

if (previousDifference.y < 0) {

// account for acos of angles in quadrants III and IV

previousRotation *= -1;

}

// NSLog(@"previousRotation: %f", previousRotation);

// Get current angle

CGPoint currentDifference = vectorBetweenPoints(firstTouchLocation, secondTouchLocation);

CGFloat xDifferenceCurrent = currentDifference.x;

// Use acos to get angle to avoid issue with the denominator being 0

CGFloat currentRotation = acos(xDifferenceCurrent / currentDistance); // adjacent over hypotenuse

if (currentDifference.y < 0) {

// account for acos of angles in quadrants III and IV

currentRotation *= -1;

}

// NSLog(@"currentRotation: %f", currentRotation);

CGFloat newAngle = currentRotation - previousRotation;

// Combine with current transform

newTransform = CGAffineTransformRotate(newTransform, newAngle);

// Return result

return newTransform;

}