The Beauty of Bresenham's Algorithm
free.pages.at
free.pages.at
"The Bresenham line algorithm is an algorithm which determines which points in an n-dimensional raster should be plotted in order to form a close approximation to a straight line between two given points. It is commonly used to draw lines on a computer screen, as it uses only integer addition, subtraction and bit shifting, all of which are very cheap operations in standard computer architectures. It is one of the earliest algorithms developed in the field of computer graphics. A minor extension to the original algorithm also deals with drawing circles."
There are 4 checks per loop in that version. The faster impl recognizes that in 1 direction or the other one coordinate will always increment or decrement by 1 while the other coordinate will or will not increment on each iteration.
That will remove 2 of the 4 checks. The loop just becomes N where N is max(abs(dx), abs(dy))
I don't know if that's still considered Bresenham's or not.
int sign(int v) {
return v > 0 ? 1 : ((v < 0) ? -1 : 0);
}
int abs(int x) {
return x > 0 ? x : -x;
}
int max(int a, b) {
return a > b ? a : b;
}
void drawLine(int x1, int y1, int x2, int y2) {
int deltaX = x2 - x1;
int deltaRow = abs(deltaX);
int rowInc = sign(deltaX);
int deltaY = y2 - y1;
int deltaCol = abs(deltaY);
int colInc = sign(deltaY);
int rowAccum = 0;
int colAccum = 0;
int rowCursor = x1;
int colCursor = y1;
int counter = max(deltaCol, deltaRow);
int endPnt = counter;
if (counter == deltaCol) {
rowAccum = endPnt / 2;
for (; counter > 0; --counter) {
rowAccum += deltaRow;
if (rowAccum >= endPnt) {
rowAccum -= endPnt;
rowCursor += rowInc;
}
colCursor += colInc;
setPixel(rowCursor, colCursor);
}
} else {
colAccum = endPnt / 2;
for (; counter > 0; --counter) {
colAccum += deltaCol;
if (colAccum > endPnt) {
colAccum -= endPnt;
colCursor += colInc;
}
rowCursor += rowInc;
setPixel(rowCursor, colCursor);
}
}
}
This is an optimized version of an algorithm I found in the Atari 400/800 Technical Reference Manual page 218.Basically, you model your map using a grid, after firing a sensor such as a LIDAR or sonar and finding something blocks its cone of sight you use Bresenham's to see what cells in your map the new reading provides information about. (i.e. something bouncing 2 meters from where your robot is not only tells you about a block at 2 meters but also about no block in that trajectory, all those cells you now suppose are free and the one you suppose is not are the result of Bressenham's Algorithm)
This is done because a LIDAR/sonar/whatever scanning range sensor returns the angle and range to a reflective object. In most cases, there's an implicit additional piece of information - namely that there's nothing in between the sensor and the object, since the EM radiation was able to get there and back. Bresenham's algorithm is used to tell you the grid cells in which you can assume free space.
it's very funny how this sort of stuff comes back at opportune times to magically solve really hard problems for you with a single pass. Sort of like having Knuth on your bookshelf.
#define ever (;;)
for ever {...}
;-)http://stackoverflow.com/questions/885908/while-1-vs-for-is-...
for (;;);
is the same as
{ while (true) { ; ; } }
I originally asked this question cos it's used this way in first C program in the link. Bit of a tangent though :P
And to add oil to the fire, here are some even 'better' ways to do this:
do {
...
} while(1);
At least that fits the common macro pattern "do{...}while(0)" (http://stackoverflow.com/questions/257418/do-while-0-what-is...).Of course, all of these are inferior to:
considered:
...
goto considered; for {
...
}I prefer "for(;;)" because it is explicitly defined as an infinite loop, but "while(1)" needs an implicit cast of "1" to "true", and even then there's an implicit test for "true".
The good thing is modern compilers can evaluate a loop and if the break condition is constant it can just do an infinite loop without checking.
http://pubs.opengroup.org/onlinepubs/007904975/basedefs/stdb...
Edit: Of course I'm talking about C here. Also, I prefer for(;;) because it's an easy to recognize idiom that means "infinite loop."
I just did a quick check and gcc -S produces the same ASM output for both of them, which doesn't include any comparisons whatsoever, just a jmp. So both of them are really compiled to an actual infinite loop.
[0] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf (See 6.8.5.3)
http://msdn.microsoft.com/en-us/library/6t66728h%28v=vs.80%2...
http://stackoverflow.com/questions/3490823/why-msvc-generate...
His discrete line equation is relatively beautiful (it is easily extractible from Bresenham's algorithm however): 0 ≤ ax − by < ω
just:
{ x++ and y+=slope } or { y++ and x+= 1./slope }
Then slopes are always rational in line drawing algorithms.