iPhone smooth sketch drawing algorithm iPhone smooth sketch drawing algorithm ios ios

iPhone smooth sketch drawing algorithm


CGPoint midPoint(CGPoint p1, CGPoint p2){    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);}-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    UITouch *touch = [touches anyObject];    previousPoint1 = [touch previousLocationInView:self];    previousPoint2 = [touch previousLocationInView:self];    currentPoint = [touch locationInView:self];}-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{    UITouch *touch = [touches anyObject];    previousPoint2 = previousPoint1;    previousPoint1 = [touch previousLocationInView:self];    currentPoint = [touch locationInView:self];    // calculate mid point    CGPoint mid1 = midPoint(previousPoint1, previousPoint2);     CGPoint mid2 = midPoint(currentPoint, previousPoint1);    UIGraphicsBeginImageContext(self.imageView.frame.size);    CGContextRef context = UIGraphicsGetCurrentContext();    [self.imageView.image drawInRect:CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height)];    CGContextMoveToPoint(context, mid1.x, mid1.y);    // Use QuadCurve is the key    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);     CGContextSetLineCap(context, kCGLineCapRound);    CGContextSetLineWidth(context, 2.0);    CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);    CGContextStrokePath(context);    self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();}


The easiest way to smooth a curve like this is to use a Bezier curve instead of straight line segments. For the math behind this, see this article (pointed to in this answer), which describes how to calculate the curves required to smooth a curve that passes through multiple points.

I believe that the Core Plot framework now has the ability to smooth the curves of plots, so you could look at the code used there to implement this kind of smoothing.

There's no magic to any of this, as these smoothing routines are fast and relatively easy to implement.


I really love the topic. Thanks for all the implementations, espesially Krzysztof Zabłocki and Yu-Sen Han.I have modified the version of Yu-Sen Han in order to change line thickness depending on the speed of panning (in fact the distance between last touches). Also I've implemented dot drawing (for touchBegan and touchEnded locations being close to each other)Here is the result:enter image description here

To define the line thickness I've chosen such a function of distance:

(Don't ask me why... I just though it suits well, but I'm sure you can find a better one)

enter image description here

CGFloat dist = distance(previousPoint1, currentPoint);CGFloat newWidth = 4*(atan(-dist/15+1) + M_PI/2)+2;

One more hint. To be sure the thickness is changing smoothly, I've bounded it depending on the thickness of the previous segment and a custom coef:

self.lineWidth = MAX(MIN(newWidth,lastWidth*WIDTH_RANGE_COEF),lastWidth/WIDTH_RANGE_COEF);