Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
459 views
in Technique[技术] by (71.8m points)

core graphics - Calculate controlPoints while drawing in iOS

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...