All hail tea pot
This post serves as my first introduction into the “blogosphere” as well, hopefully, the first of many write-ups about computing and technology in general. So with that out of the way lets get on with it.
Today I will be discussing the Scan Line Polygon Fill (SLPF) algorithm, and then showing my implementation of the algorithm in C++. The purpose of the SLPF algorithm is to fill (color) the interior pixels of a polygon given only the vertices of the figure.
The basic idea is to collect all of the edges (except horizontal edges) that compose the polygon, fill in the figure scan line by scan line using the edges as starting and stopping points.
To successfully fill in a polygon three main components will be used: Edge Buckets, an Edge Table and an Active List. These components will contain an edge’s information, hold all of the edges that compose the figure and maintain the current edges being used to fill in the polygon, respectively.
The edge bucket is a structure that holds information about the polygon’s edges. The edge bucket looks different pending on the implementation of the algorithm, in my case it looks like this:
Edge Bucket representation
Here is a breakdown of what each member represent in an edge bucket:
The ET is a list that contains all of the edges that make up the figure.
Important ET notes:
The AL contains the edges that are being processed/used to fill the polygon. Every edge in the AL has a pairing buddy edge, because when filling a scan line, pixels are filled starting from one edge until the buddy edge is encountered.
Important AL notes:
Now that we have the main components covered, lets go over the SLPF algorithm in more detailed steps.
~General assumptions~
Here are the steps:
1. Create ET1. Process the vertices list in pairs, start with [numOfVertices-1] and [0].2. For each vertex pair, create an edge bucket2. Sort ET by yMin3. Process the ET1. Start on the scan line equal to theyMin of the first edge in the ET2. While the ET contains edges1. Check if any edges in the AL need to be removes (when yMax == current scan line)1. If an edge is removed from the AL, remove the associated the Edge Bucket from the Edge Table.2. If any edges have a yMin == current scan line, add them to the AL3. Sort the edges in AL by X4. Fill in the scan line between pairs of edges in AL5. Increment current scan line6. Increment all the X's in the AL edges based on their slope1. If the edge's slope is vertical, the bucket's x member is NOT incremented.
(Why doesn’t Medium support nested lists??)
Final Important Notes:
Something is not right here…
To maintain only integers in the Edge Bucket, the slope is not actually calculated but is instead maintained as three distinct members: sign, dX, dY.
No x increment == pixelated image?
Now that the details are covered, here is the implementation of the SLPF in C++.
Due to a request from my professor the C++ implementation of the code has been taken down and replaced with pseudo code (There is a strong concern that students will copy the code for projects). If you are interested in my C++ implementation feel free to message me for it.
Main Program (Pseudo code)
/*Creates edge buckets from the given edges
[@param](http://twitter.com/param "Twitter profile for @param") n Number of vertices
[@param](http://twitter.com/param "Twitter profile for @param") x\[\] array of x points
[@param](http://twitter.com/param "Twitter profile for @param") y\[\] array of y points
[@return](http://twitter.com/return "Twitter profile for @return") List of edge buckets
*/createEdges(n, x[], y[]) {instantiate a new edge table
loop through x[] & y[] pairs {if the edge's slope is NOT undefined (verticle) {create bucket with edgeadd bucket to edge table}}}
/*Given the edge table of the polygon, fill the polygons
[@param](http://twitter.com/param "Twitter profile for @param") edgeTable The polygon's edge table representation
*/processEdgeTable (edgeTable) {while (edge table is NOT empty) {
// Remove edges from the active list if y == ymaxif (active list is NOT empty) {for (iterate through all buckets in the active list) {if (current bucket's ymax == current scanline) {remove bucket from active listremove bucket from edge table}}}
// Add edge from edge table to active list if y == yminfor (iterate through the bucket in the edge table) {if (bucket's ymin == scanline) {add bucket to active list}}
// Sort active list by x position and slopesortTheActiveList();
// Fill the polygon pixelfor (iterate through the active list) {for (from vertex1.x to vertex2.x of the bucket) {setPixelColor()}}
// Increment X variables of buckets based on the slopefor (all buckets in the active list) {if (bucketsdX != 0) {bucket's sum += bucket's dX
while (bucket's sum >= bucket's dY) {
increment or decrement bucket's X depending on sign of bucket's slope
edge's sum -= dY
}
}
}
}
}
///// Draw a filled polygon in the Canvas C.//// The polygon has n distinct vertices. The coordinates of the vertices// making up the polygon are stored in the x and y arrays. The ith// vertex will have coordinate (x[i],y[i]).//// @param n - number of vertices// @param x - x coordinates// @param y - y coordinates///drawPolygon(n, x[], y[]) {// Create edge tablefinalEdgeTable = createEdges()
// Sort edges by minYsort(finalEdgeTable)
processEdgeTable(finalEdgeTable)}
Header file with structs
/*Bucket struct to hold edge information*/struct Bucket {int yMax;int yMin;int x;int sign;int dX;int dY;double sum;};
/*Vertex struct to hold x and y values*/struct Vertex {int x;int y;};
That all it takes to implement the SLPF algorithm! I hope this post is constructive and that you enjoyed reading through it. If there are any mistakes and you want to leave comment, feel free to do so or send me a message.
Cheers!