I’m assisting someone with user interface code to visualise a mathematical image analysis.
During this process we’ll be segmenting part of a 2D shape into triangles, and filling some of these triangles in on the UI.
We’re looking for a fill algorithm which guarantees that if two triangles share an edge (specifically, if any two vertices of the triangles are identical), then regardless of drawing order and aliasing there will be not be blank, undrawn pixels on the line between the two. (It’s alright if some pixels are drawn twice.) The result should look OK under arbitrary scaling. Some triangles may be extremely thin slivers in places, down to 1 pixel wide.
Ideally it should also be a reasonably efficient fill algorithm!
Anti-aliasing will not be used in triangle rendering, as the final image needs to be 1-bit depth.
The context is an image-recognition application, so all vertex coordinates will be accurate to one pixel.
Given the requirements, it looks like there’s a simple solution.
First, rasterize the triangle edges. You can use the Bresenham’s line drawing algorithm for that (as in the code below) or anything that works. Then fill in the area in-between. This will work with arbitrarily thin triangles.
To make sure there are no gaps irrespective of the order in which triangles are drawn and irrespective of the order of the vertices supplied to the triangle-drawing code you want to rasterize shared edges in the same way in the triangles sharing an edge. Same way means the same pixels every time.
To guarantee that every time you get the same pixels from the same pairs of vertex coordinates you basically want to establish a fixed order, that is, establish a rule that would always choose the same one vertex out of the two given irrespective of the order in which they are given.
One simple way to enforce this order is to treat your line (triangle edge) as a 2-d vector and flip its direction if it points in the direction of negative y’s or is parallel to the x axis and points in the direction of negative x’s. Time for some ASCII art! 🙂
See, here line segment, say, 1 and line segment 5 are really the same kind of thing, the only difference is the direction from the endpoint at the origin to the other endpoint. So we reduce these cases in half by turning segments 4 through 7 into segments 0 through 3 and get rid of the direction ambiguity. IOW, we choose to go in the direction of increasing y’s OR, if y’s are the same on the edge, in the direction of increasing x’s.
Here’s how you could do it in code:
Sample output:
Legend:
Beware that even though there will be no unfilled gaps (pixels), the triangle whose pixels (on the shared edge) get overwritten (because of the other triangle drawn on top of it) may show up as disjoint or awkwardly shaped if it’s too thin. Example: