Line rasterisation: Cover all pixels, regardless of line gradient?
Without loss of generality, assume x2 >= x1, then
int x = floor(x1);
int y = floor(y1);
double slope = (x2 - x1) / (y2 - y1);
if (y2 >= y1) {
while (y < y2) {
int r = floor(slope * (y - y1) + x1);
do {
usepixel(x, y);
++x;
} while (x < r);
usepixel(x, y);
++y;
}
}
else {
while (y > y2) {
int r = floor(slope * (y - y1) + x1);
do {
usepixel(x, y);
++x;
} while (x < r);
usepixel(x, y);
--y;
}
}
The floor calls can probably be written just as a cast-to-integer.
There is an interesting article available in GPU Gems, maybe it can help you: Chapter 22. Fast Prefiltered Lines
I had exactly the same problem as you and found an very simple solution. Usually, Bresenham has two consecutive if's to determine whether it should increase the coordinate for the two dimensions:
public void drawLine(int x0, int y0, int x1, int y1, char ch) {
int dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2; // error value e_xy
for (;;) {
put(x0, y0, ch);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
// horizontal step?
if (e2 > dy) {
err += dy;
x0 += sx;
}
// vertical step?
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
Now all you have to do is to insert an else
before the second if
:
public void drawLineNoDiagonalSteps(int x0, int y0, int x1, int y1, char ch) {
int dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2;
for (;;) {
put(x0, y0, ch);
if (x0 == x1 && y0 == y1) break;
e2 = 2 * err;
// EITHER horizontal OR vertical step (but not both!)
if (e2 > dy) {
err += dy;
x0 += sx;
} else if (e2 < dx) { // <--- this "else" makes the difference
err += dx;
y0 += sy;
}
}
}
Now the algorithm doesn't change both coordinates at once anymore. I haven't thoroughly tested this but it seems to work pretty well.
This thread old, but I thought it'd be worth putting this on the Internet:
// This prints the pixels from (x, y), increasing by dx and dy.
// Based on the DDA algorithm (uses floating point calculations).
void pixelsAfter(int x, int y, int dx, int dy)
{
// Do not count pixels |dx|==|dy| diagonals twice:
int steps = Math.abs(dx) == Math.abs(dy)
? Math.abs(dx) : Math.abs(dx) + Math.abs(dy);
double xPos = x;
double yPos = y;
double incX = (dx + 0.0d) / steps;
double incY = (dy + 0.0d) / steps;
System.out.println(String.format("The pixels after (%d,%d) are:", x, y));
for(int k = 0; k < steps; k++)
{
xPos += incX;
yPos += incY;
System.out.println(String.format("A pixel (%d) after is (%d, %d)",
k + 1, (int)Math.floor(xPos), (int)Math.floor(yPos)));
}
}