问题
I am working on a drawing app, where user can draw/write with his finger or stylus. For this I have referred code from https://github.com/yusenhan/Smooth-Line-View
, in my application.
The problem which I am facing is that, the writing sometimes when you write very closely is not very smooth.
So I think, I am making some mistake in getting the control point.
Below is my code
//Find the midpoint
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
#pragma mark Gesture handle
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
//LocationInView returns the current location of the reciever in coordinate system of the given View.
m_previousPoint1 = [touch locationInView:self];
m_previousPoint2 = [touch locationInView:self];
m_currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//AnyObject:- Returns one of the objects in the set, or nil if the set contains no objects.
UITouch *touch = [touches anyObject];
m_previousPoint2 = m_previousPoint1;
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
if(m_drawStep != ERASE)
{
m_drawStep = DRAW;
m_drawing = TRUE;
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);//creates a graphics context suitable for use as an image(size of the image,opquae,scale, if scale = 0.0, means platform will take care of scaling)
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
m_curImage = UIGraphicsGetImageFromCurrentImageContext();// to turn the context into a UIImage
UIGraphicsEndImageContext();
}
- (void)drawRect:(CGRect)rect
{
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
[m_curImage drawAtPoint:CGPointMake(0, 0)];
CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw)
[self.layer renderInContext:context];
//Simply keep referring to this context in below functions with proper arguments.
CGContextMoveToPoint(context, mid1.x, mid1.y);//Position the current point
CGContextAddQuadCurveToPoint(context, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextSetShouldAntialias(context, YES);
CGContextSetAllowsAntialiasing(context, YES);
CGContextSetAlpha(context, self.lineAlpha);
CGContextSetFlatness(context, 0.6);
CGContextStrokePath(context);//paints(fills) the line along the current path.
}
According to me, the points which I am passing in the CGContextAddQuadCurveToPoint
can be tweaked, but how to tweak that, I am not getting. I read docs to find control points for Bezier Curve
, but I am not understanding.
So friends, please help me out understanding where I am going wrong.
回答1:
The problem you're having is that when the user drags his finger slowly, the control points you get are too far apart, so you get large line segments rather than the small pixel changes that would give you a smooth-looking curve.
Calcualting Bezier control points from an existing curve is really hard, since the control points are not on the line.
Better to use Catmull-Rom curves. There is an excellent "Recipe" in Erica Sadun's OUTSTANDING book "The Advanced iOS 6 Developer's Cookbook" that includes working code on Catmull-Rom spline based smoothing. Catmull-Rom splines use control points that are on the curve.
I highly recommend buying that book. The sample code for Recipe 4.3 will do exactly what you want.
来源:https://stackoverflow.com/questions/20881721/calculate-controlpoints-while-drawing-in-ios