4

I'd like to draw circle with hole (like donut) on mapview. my code is here.

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CG    ContextRef)context {

WPCircleOverlay * circleOverlay = self.overlay;

CGPoint centerPoint = [self pointForMapPoint:MKMapPointForCoordinate(circleOverlay.coordinate)];

CGFloat innerRadius = MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) * circleOverlay.innerRadius;
CGFloat outerRadius = MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) * circleOverlay.outerRadius;
CGMutablePathRef path = CGPathCreateMutable();

//CGPathMoveToPoint(path, ...);
CGPathAddArc(path, NULL, centerPoint.x, centerPoint.y, outerRadius, 0, 2 * M_PI, true);
CGPathCloseSubpath(path);

// Add the inner arc to the path (later used to substract the inner area)
CGPathAddArc(path, NULL, centerPoint.x, centerPoint.y, innerRadius, 0, 2 * M_PI, true);
CGPathCloseSubpath(path);

// Add the path to the context
CGContextAddPath(context, path);

CGContextSetFillColorWithColor(context, self.fillColor.CGColor);
CGContextEOFillPath(context);

CGPathRelease(path);

It works well in simulator, but on device it doesn't.

On device, outer circle is filled with color, and inner circle wasn't clipped. How can I modify my code to work well on device?

Paul
  • 759
  • 2
  • 7
  • 20
  • Might want to add screen shots to show difference. – matt Feb 20 '14 at 03:29
  • I fixed it. Maybe CGPathAddArc and CGContextEOFillPath could not use simultaneously. (I updated my code.) – Paul Feb 20 '14 at 09:31
  • A better way to show this might be to answer your own question. That is perfectly legal (ask a question, answer it yourself) and a good use of the stack overflow format. – matt Feb 20 '14 at 15:50

1 Answers1

2

I fixed it by using CGContextAddEllipseInRect method instead of CGContextAddArc.

WPCircleOverlay * circleOverlay = self.overlay;

CGRect rectForMapRect = [self rectForMapRect:mapRect];
CGPoint centerPoint = [self pointForMapPoint:MKMapPointForCoordinate(circleOverlay.coordinate)];

CGFloat innerRadius = MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) * circleOverlay.innerRadius;
CGFloat outerRadius = MKMapPointsPerMeterAtLatitude(circleOverlay.coordinate.latitude) * circleOverlay.outerRadius;

CGRect innerRect = CGRectMake(centerPoint.x - innerRadius, centerPoint.y - innerRadius, innerRadius * 2.0, innerRadius * 2.0);
CGRect outerRect = CGRectMake(centerPoint.x - outerRadius, centerPoint.y - outerRadius, outerRadius * 2.0, outerRadius * 2.0);

if (CGRectIntersectsRect(rectForMapRect, outerRect)) {

    CGContextAddRect(context, rectForMapRect);

    CGContextSaveGState(context);
    CGContextClip(context);

    CGContextAddEllipseInRect(context, outerRect);
    CGContextAddEllipseInRect(context, innerRect);

    CGContextSaveGState(context);
    CGContextEOClip(context);

    UIColor * color = [self.fillColor copy];
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, outerRect);

    CGContextRestoreGState(context);
    CGContextRestoreGState(context);

    UIGraphicsPopContext();
}
Paul
  • 759
  • 2
  • 7
  • 20
  • Upvoted your question, for being interesting and clearly presented, and your answer, because you solved your own problem. – matt Feb 20 '14 at 16:18