Search code examples
iosdrawingquartz-2d

Perfect alignment of triangles with Quartz2D drawing


I want to draw two general triangles in 2D space in such way that they share one edge, using Quartz2D. I'm using this code for the drawing:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    Triangle *t1 = [triangles objectAtIndex:0];
    Triangle *t2 = [triangles objectAtIndex:1];

    [self fillTriangle:t1 inContext:context];
    [self fillTriangle:t2 inContext:context];
}

- (void) fillTriangle:(Triangle *)t inContext:(CGContextRef)ctx
{
    CGContextMoveToPoint(ctx, t.p1.p.x, t.p1.p.y);
    CGContextAddLineToPoint(ctx, t.p2.p.x, t.p2.p.y);
    CGContextAddLineToPoint(ctx, t.p3.p.x, t.p3.p.y);
    CGContextAddLineToPoint(ctx, t.p1.p.x, t.p1.p.y);

    CGContextSetFillColorWithColor(ctx, t.color.CGColor);
    CGContextFillPath(ctx);
}

where Triangle is a NSObject subclass holding three points and a color.

The problem is that even when they share two points, there's a "space" between them when I fill them by this code, as shown in the image:

Two triangles sharing one edge

Question: Anyone knows how to get rid of the space so there's a seamless transition from one triangle to another with no line or whatever between them? I'd like to keep using Quartz2D but I'm glad for any help. Thanks!

EDIT: There were answers showing that the problem is caused by sub-pixel anti-aliasing, and adding the line

CGContextSetAllowsAntialiasing(ctx, NO);

to the fillTriangle method solved that. But it's not the result I'd like to see - I don't like it being aliased, as shown in the second picture.

Two triangles aliased

Question updated: do you know, how to solve both of the problems, that is, keeping the image clean with no ugly aliasing but no space between the triangles?

EDIT2: So, as was pointed in an answer, I could add the line stroke code, remove the antialiasing flag and the stroke would fill the space. Here's a last image to show what happened:

enter image description here

Notice the lines overlapping outside of the box. I was wondering what the cause might have been, and it disappeared when I set the width to 0.5f (since retina, that translates to 1px and that's probably what the responder thought), and that really solved the whole thing. Thanks to all help!


Solution

  • the problem is that you are drawing using antialiasing. disable it for your context via

        CGContextSetShouldAntialias(context, NO);
    

    and everything should be fine.

    EDIT: in case of antialiasing is needed (your updated multicolor example), you could try to not only fill the triangles but also stroke their border in the same color with a line width of 1px:

        CGContextSetLineWidth(ctx, 0.5f);
        CGContextDrawPath(ctx, kCGPathFillStroke); 
    

    of course you should remove the CGContextSetShouldAntialias line in that case. It's a simple solution but may not be the best performance wise, since the path has to be stroked and filled.