Reputation: 327
I'm trying to use Bresenham's Line Drawing Algorithm to draw a line on a 20x20 grid of tiles.
So basically, when the variable deltaerror (from the wiki) is greater than 1 (when the change in y is greater than the change in x), the y value becomes almost double what it should be. Hopefully, I explain it better in the comments of the code. I also think I found the source of the error, which I'll also explain in the comments.
This is the code I made, mostly copied from the pseudocode in the wiki.
public static void drawLine(Tile t1, Tile t2) {
int dx = t2.x_index - t1.x_index;
int dy = t2.y_index - t1.y_index;
double error = 0;
double d_error = Math.abs((double) dy / dx); // dx =/= 0, therefore no vertical lines
// when d_error is greater than 1, the bug occurs
int y = t1.y_index;
if (d_error <= 1) { // if related acute angle is < 45 degrees
if (dx < 0) { // line drawn towards left side of screen
for (int x=t1.x_index; x>=t2.x_index; x--) {
Board.tiles[x][y].setColour(Color.red);
error += d_error;
while (error >= 0.5) {
Board.tiles[x][y].setColour(Color.red);
y += dy > 0 ? +1 : -1;// this is where I think the error occurs. In the
// wiki for the algorithm, this should be some
// function sign(T) which "decides whether t is
// positive or negative". I wasn't really sure
// what this meant, so I just assumed it returned
// -1 if it was negative and +1 if it was positive.
// Also it's the only place where y is edited
// that seems to be where the error is occurring.
error -= 1.0;
}
}
} else if (dx > 0) { // line drawn towards right side of screen
for (int x=t1.x_index; x<=t2.x_index; x++) {
Board.tiles[x][y].setColour(Color.red);
error += d_error;
while (error >= 0.5) {
Board.tiles[x][y].setColour(Color.red);
y += dy > 0 ? +1 : -1;
error -= 1.0;
}
}
}
// update: switched x and y values when d_error is greater than 1.
} else { // if related acute angle is > 45 degrees
dx = t2.y_index - t1.y_index; // switch x and y values
dy = t2.x_index - t1.x_index;
d_error = Math.abs((double) dy / dx); // recalculate d_error
y = t1.x_index;
if (dx < 0) { // line drawn towards left side of screen
for (int x=t1.y_index; x>=t2.y_index; x--) {
Board.tiles[x][y].setColour(Color.red);
error += d_error;
while (error >= 0.5) {
Board.tiles[x][y].setColour(Color.red);
y += dy > 0 ? +1 : -1;
error -= 1.0;
}
}
} else if (dx > 0) { // line drawn towards right side of screen
for (int x=t1.y_index; x<=t2.y_index; x++) {
Board.tiles[x][y].setColour(Color.red);
error += d_error;
while (error >= 0.5) {
Board.tiles[x][y].setColour(Color.red);
y += dy > 0 ? +1 : -1;
error -= 1.0;
}
}
}
}
}
Thanks for your help!
EDIT: Switched x and y values when d_error is greater than 1. The line disappears when the slope is above 1 and below -1.
Upvotes: 0
Views: 1265
Reputation: 1211
To quote from a quick google-result:
http://www.math.ubc.ca/~cass/courses/m308-02b/projects/puhalovic/#alldirections
"With slopes greater than 1 or less than -1, we must take the previous implementation and swap all x and y values to "move" the calculations back into the "First Octant"."
IOW: The textbook implementation of the bresenham only works for lines with (in your terms) d_error<=1
. You'll have to implement the swapping mentioned in the link above.
Upvotes: 1