Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CGContextAddArc counterclockwise instead of clockwise

I'm having an issue when drawing an arc inside of my drawing function inside of a CALayer subclass. The implementation for that drawing function is as follows:

-(void)drawInContext:(CGContextRef)ctx
{
    CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
    CGFloat radius = MIN(center.x, center.y);

    CGContextBeginPath(ctx);

    CGContextAddArc(ctx, center.x, center.y, radius, DEG2RAD(0), DEG2RAD(90), YES);

    CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(ctx, 5);

    CGContextDrawPath(ctx, kCGPathStroke);
}

Nothing too groundbreaking here, but the weird thing is that it's drawing the arc counterclockwise even though I specified that it shoud be clockwise. Conversely, when I specify NO for the clockwise parameter, it draws the arc clockwise. I did some research into flipped coordinate systems and figured that might be what the issue here is, but I didn't want to just hardcode the opposite bool parameter of what I meant. Any suggestions on how to fix this?

Thanks!

like image 874
J Kagney Avatar asked Jun 07 '13 00:06

J Kagney


1 Answers

This is indeed due to the flipped coordinate system of UIKit vs. Quartz. From the docs for CGContext:

The clockwise parameter determines the direction in which the arc is created; the actual direction of the final path is dependent on the current transformation matrix of the graphics context. For example, on iOS, a UIView flips the Y-coordinate by scaling the Y values by -1. In a flipped coordinate system, specifying a clockwise arc results in a counterclockwise arc after the transformation is applied.

You can alleviate this in your code by using the transformation matrix to flip your context:

CGContextTranslateCTM(ctx, 0.0, self.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

You probably want to flip it back when you are finished with your drawing i.e.

CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx, 0.0, self.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

// Draw...

CGContextRestoreGState(ctx);
like image 160
Matt Bridges Avatar answered Nov 10 '22 21:11

Matt Bridges