You can use the scanline approach. A rectangle is a closed convex polygon, so it is enough to save the leftmost and rightmost pixel for each horizontal scan line. (Both the top and bottom scan lines, too.)
The Breshenem algorithm tries to draw a thin, visually pleasing line without adjacent cells in a smaller size. We need an algorithm that visits every cell through which the edges of the polygon pass. The basic idea is to find the starting cell (x, y) for each edge, and then adjust x whenever the edge crosses the vertical border and adjust y when it crosses the horizontal border.
We can represent the intersections using the normalized coordinate s , which moves along the edge and is equal to 0.0 in the first node n1 and 1.0 in the second node n2 .
var x = Math.floor(n1.x / cellsize); var y = Math.floor(n1.y / cellsize); var s = 0;
Vertical intrusions can be represented as equidistant stages with dsx from the initial sx .
var dx = n2.x - n1.x; var sx = 10; // default value > 1.0 // first intersection if (dx < 0) sx = (cellsize * x - n1.x) / dx; if (dx > 0) sx = (cellsize * (x + 1) - n1.x) / dx; var dsx = (dx != 0) ? grid / Math.abs(dx) : 0;
Similarly for horizontal intersections. A default value greater than 1.0 captures cases of horizontal and vertical lines. Add the first point to the scan line data:
add(scan, x, y);
Then we can visit the next neighboring cell by looking at the next intersection with the smallest s .
while (sx <= 1 || sy <= 1) { if (sx < sy) { sx += dsx; if (dx > 0) x++; else x--; } else { sy += dsy; if (dy > 0) y++; else y--; } add(scan, x, y); }
Do this for all four edges and with the same scan line data. Then fill in all the cells:
for (var y in scan) { var x = scan[y].min; var xend = scan[y].max + 1; while (x < xend) {
(I just looked at the links provided by MBo. It seems that the approach presented in this article is essentially the same as mine. If so, please excuse the unnecessary answer, but after that I decided it.)