0

I currently have the following code to try and allow the user to draw a dotted path and make a custom shape. Once they have made this shape, I wanted it to automatically be filled with colour. That isn't happening.

At the moment I am getting this error for the code below:

<Error>: CGContextClosePath: no current point.

Here's the code I'm using:

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

UITouch *touch = [touches anyObject];

CGPoint previous = [touch previousLocationInView:self];
CGPoint current = [touch locationInView:self];

#define SQR(x) ((x)*(x))
//Check for a minimal distance to avoid silly data
if ((SQR(current.x - self.previousPoint2.x) + SQR(current.y - self.previousPoint2.y)) > SQR(10))
{

    float dashPhase = 5.0;
    float dashLengths[] = {10, 10};
    CGContextSetLineDash(context,
                         dashPhase, dashLengths, 2);

    CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
    CGContextFillPath(context);

    CGContextSetLineWidth(context, 2);
    CGFloat gray[4] = {0.5f, 0.5f, 0.5f, 1.0f};
    CGContextSetStrokeColor(context, gray);

    self.brushSize = 5;
    self.brushColor = [UIColor lightGrayColor];

    self.previousPoint2 = self.previousPoint1;
    self.previousPoint1 = previous;
    self.currentPoint = current;

    // calculate mid point
    self.mid1 = [self pointBetween:self.previousPoint1 andPoint:self.previousPoint2];
    self.mid2 = [self pointBetween:self.currentPoint andPoint:self.previousPoint1];

    if(self.paths.count == 0)
    {

    UIBezierPath* newPath = [UIBezierPath bezierPath];

    CGContextBeginPath(context);

    [newPath moveToPoint:self.mid1];
    [newPath addLineToPoint:self.mid2];
    [self.paths addObject:newPath];

    CGContextClosePath(context);

    }

    else

    {

        UIBezierPath* lastPath = [self.paths lastObject];

        CGContextBeginPath(context);

        [lastPath addLineToPoint:self.mid2];
        [self.paths replaceObjectAtIndex:[self.paths indexOfObject:[self.paths lastObject]] withObject:lastPath];

        CGContextClosePath(context);

    }

    //Save
    [self.pathColors addObject:self.brushColor];

    self.needsToRedraw = YES;
  [self setNeedsDisplayInRect:[self dirtyRect]];
  //[self setNeedsDisplay];
}

}

Why is this happening and why is the inside of the path not being filled with colour?

James Anderson
  • 556
  • 3
  • 16
  • 41
  • I'm not much of an expert on custom drawing, but if I remember correctly, the drawing should (or even must?) happen in the drawRect: method. Perhaps thats the problem here? – Tobi Oct 23 '12 at 07:12
  • but the user needs to determine where the lines are drawn, not the app :) so I'd have to use touchesMoved wouldn't I? – James Anderson Oct 23 '12 at 07:13
  • No, you could save the points the user touched to a property or an ivar and use that in the drawRect: method to actually draw to path. – Tobi Oct 23 '12 at 07:16
  • Are there any examples of doing this online? – James Anderson Oct 23 '12 at 07:22
  • Probably, but I dont know where ;) But you can use basically the same code your using now. Just move the code from touchesMoved to drawRect. Then in touchesMoved you save the current(Point) to an Array. An in the drawRect method you iterate through the array "unpacking" the points in there. – Tobi Oct 23 '12 at 07:34

1 Answers1

2

Your code has a few issues:

  • You should be doing your drawing in your view's drawRect: method, not the touch handler.
  • You never set the variable context with a value for the current context. Do that with the UIGraphicsGetCurrentContext() method. Again, within your drawRect: method.
  • You go through the trouble of creating a UIBezierPath object, but you never use it. Do that by calling CGContextAddPath( context, newPath.CGPath ), changing the variable name as needed in the two places you appear to the using a UIBezierPath.
  • Keep the call to setNeedsDisplayInRect: in your touch handler method. That tells the system to do the work to update your view using the drawing that your (yet to be implemented) drawRect: method draws.
kamprath
  • 2,220
  • 1
  • 23
  • 28
  • Thanks! Now I've managed to get the custom shape to have a colour fill - see this: http://pixelbit.in/KL83, but how can I get the CGRect of the custom shape? Is there any simple way? :-) – James Anderson Oct 23 '12 at 10:47
  • See this questions for ifo on how to find the bounding box of your path: http://stackoverflow.com/questions/2587751/an-algorithm-to-find-bounding-box-of-closed-bezier-curves – kamprath Oct 23 '12 at 20:12