Search code examples
objective-cioscgpointcgpathtouchesmoved

How can I store the path of finger movement in objective c?


I want to store the path of finger movement on iPhone screen. As of now I am just reading touches and adding CGPoints to NSMutableArray. when I try to print the all cgpoint in that array some how it is missing intermediate points. Is there a better way to this ? Can we store entire path directly ?

Here is the code that I am using

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
 {

fingerSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
[self.myPoints addObject:[NSValue valueWithCGPoint:lastPoint]];
  }


 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
   {
fingerSwiped = YES;

UITouch *touch = [touches anyObject];   
CGPoint currentPoint = [touch locationInView:self.view];



UIGraphicsBeginImageContext(self.view.frame.size);
[slateImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), lineWidth);
//CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(),0,0,0, 1.0);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.drawcolor.CGColor);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
slateImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
[myPoints addObject:[NSValue valueWithCGPoint:lastPoint]];   
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

if(!fingerSwiped) 
{
    UIGraphicsBeginImageContext(self.view.frame.size);
    [slateImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), lineWidth);
    //CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(),0,0,0, 1.0);
    CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.drawcolor.CGColor);
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    CGContextFlush(UIGraphicsGetCurrentContext());
    slateImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [myPoints addObject:[NSValue valueWithCGPoint:lastPoint]];
}
}

Solution

  • You are recording every point that iOS is willing to give you.

    iOS only reports touch-moved events every 16.67 milliseconds (60 times per second). There is no way (as far as I know) to get updated touch locations faster than that.

    You say you are getting straight lines when you plot the touch points. This is happening because the user is moving his finger so fast that the touch moves a significant amount in 16.67 milliseconds. The touch is moving so far between updates that when you connect the points, it doesn't look like a smooth curve. Unfortunately, there is (as I said) no way to get updates faster than 60 times per second.

    The only way to deal with this is to use spline interpolation to connect the reported points. Spline interpolation is a complicated subject. You can find lots of information about it using Google.

    You can see an example of this in the Adobe Ideas app on an iPad. If you draw a big spiral fast and watch carefully, you can see that the line becomes smoother when you lift your finger. I believe it's doing some incremental smoothing as you draw the spiral, and when you lift your finger, it goes back and computes a better interpolation of the entire line.