문제

How to eliminate the boundary between triangles?

black triangles with white boundaries

I'm implementing export-to-pdf in my triangle drawing app. The image above shows what the pdf output looks like. There are white boundaries everywhere, less than 1 pixel wide.

The triangles can have any color.


I draw each triangle, like this:

CGContextBeginPath(context);
CGContextMoveToPoint(context, x0, y0);
CGContextAddLineToPoint(context, x1, y1);
CGContextAddLineToPoint(context, x2, y2);
CGContextClosePath(context);
CGContextFillPath(context);

It's important that black and white triangles have the same sizes.


Approaches

Approach 1 - Stroke

Draw a 1 pixel thick stroke around all triangles.

Approach 2 - Extrude

Extrude all triangles by 2 pixels so the triangles overlaps.

Approach 3 - Combine

Combine touching triangles into a single polygon.

Approach 4 - PDF overlap settings

Perhaps PDF has settings for eliminating boundaries. Dunno.

Approach 5 - Post processing

Create a filter that detects boundary pixels and eliminates them. This will not work for me, it needs to be saved to a PDF. Shader code is not supported in PDF on iOS, AFAIK.

Approach X - A smarter way

Is there a better way of snapping triangles together?

도움이 되었습니까?

해결책 3

Approach 3 - Combine

I'm using GPC – General Polygon Clipper library and it almost works as desired.

I run a UNION operation one triangle at a time. Until all triangles have been UNION'ed into the result.

Below is output from GPC. No white edges can be seen.

Output when using GPC.


I also tried using Angus Johnson's Clipper library, but was unable to built polygons by UNIONing one triangle at a time. It only removed a few of the white edges between triangles. Although Clipper seems more powerful than GPC.

Below is output from Clipper, it shows white edges. Output when using Clipper, has white edges

다른 팁

Are your coordinates (x0, y0, x1, y1, etc.) at integer point values? It's common for people to make that mistake because they're used to setting views' frames to be on whole point boundaries. CoreGraphics draws with one point lines drawn centered on the coordinates you provide. I suspect that you can eliminate your artifacts by adjusting your coordinates by 0.5 points in all cases:

CGContextBeginPath(context);
CGContextMoveToPoint(context, x0 + 0.5, y0 + 0.5);
CGContextAddLineToPoint(context, x1 + 0.5, y1 + 0.5);
CGContextAddLineToPoint(context, x2 + 0.5, y2 + 0.5);
CGContextClosePath(context);
CGContextFillPath(context);

Edit: Actually I don't think this is going to work. Here's another suggestion:

I'm leaving my previous comments because I think what I said about the CoreGraphics coordinates is true, but I tried some experiments with the setup you described and shifting everything over didn't eliminate those border artifacts. However adding this line did:

CGContextSetAllowsAntialiasing(context, false);

(I don't know why CGContextSetAllowsAntialiasing is declared to take a stdbool style bool, but it is, that's why I used false instead of NO here, not that it makes a difference.)

Cheap/Easy solution is to draw each triangle twice. This will reduce anti-aliasing but boost the coverage along the edges. Rendering as a single path should work too if it's all the same color.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top