BRESENHAM'S LINE ALGORITHM


'Bresenham's line algorithm' is an algorithm that 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.
Through a minor expansion, the original algorithm for lines can also be used to draw circles. Also this can be done with simple arithmetic operations; quadratic or trigonometric expressions can be avoided or recursively dissolved into simpler steps.
The mentioned properties make it still an important algorithm, and it is used among others in plotters, in graphics chips of modern graphics cards, and in many graphics libraries. As it is so simple, it is not only implemented in the firmware of such devices, but is also ''cast into hardware'' of those graphics chips.
To be precise, the label "Bresenham" is today often used for a whole family of algorithms, which have actually been developed by others, later, yet in succession of Bresenham and with a similar basic approach. See deeper references below.

Contents
The algorithm
Generalisation
Optimisation
Different approach to the algorithm
Circle Variant
Drawing incomplete octants
Ellipses
History
Similar Algorithms
References
See also
External links

The algorithm


Illustration of the result of Bresenham's line algorithm.

The line is drawn between two points (''x''0, ''y''0) and (''x''1, ''y''1), where these pairs indicate column and row, respectively, increasing in the down and right directions (as is common in computer programming).
We will initially assume that our line goes down and to the right, and that the horizontal distance x_1-x_0 exceeds the vertical distance ''y''1-''y''0 (that is, the line has a slope less than 1 and greater than 0.) Our goal is, for each column ''x'' between x_0 and x_1, to identify the row ''y'' in that column which is closest to the line and plot a pixel at (x,y).
Now, how do we figure out which pixel is closest to the line for a given column? The general formula for the line between the two points is given by:
:y - y_0 = rac{y_1-y_0}{x_1-x_0} (x-x_0).
Since we know the column, ''x'', the pixel's row, ''y'', is given by rounding this quantity to the nearest integer:
: rac{y_1-y_0}{x_1-x_0} (x-x_0) + y_0.
However, explicitly calculating this value for each column, ''x'', is silly; we need only note that ''y'' starts at ''y''0, and each time we add 1 to ''x'', we add the fixed value (y_1-y_0)/(x_1-x_0), which we can precalculate, to the exact ''y''. Moreover, since this is the slope of the line, by assumption it is between 0 and 1; in other words, after rounding, in each column we either use the same ''y'' as in the previous column, or we add one to it.
We can decide which of these to do by keeping track of an ''error value'' which denotes the vertical distance between the current ''y'' value and the exact ''y'' value of the line for the current ''x''. Each time we increment ''x'', we increase the error by the slope value above. Each time the error surpasses 0.5, the line has become closer to the next ''y'' value, so we add 1 to ''y'', simultaneously decreasing the error by 1. The procedure looks like this, assuming plot(x,y) plots a point and abs returns absolute value:
Expressed in pseudo code, the naive implementation below uses comparatively expensive floating point arithmetic, but it can be easily tweaked (see optimization section) to use integer math:
'function' line(x0, x1, y0, y1)
''int'' deltax := x1 - x0
''int'' deltay := y1 - y0
''real'' error := 0
''real'' deltaerr := deltay / deltax // Assume deltax != 0 (line is not vertical)
''int'' y := y0
'for' x 'from' x0 'to' x1
plot(x,y)
error := error + deltaerr
'if' abs(error) ≥ 0.5 'then'
y := y + 1
error := error - 1.0

Generalisation


This first version only handles lines that descend to the right. We would of course like to be able to draw all lines. The first case is allowing us to draw lines that still slope downwards but head in the opposite direction. This is a simple matter of swapping the initial points if x0 > x1. Trickier is determining how to draw lines that go up. To do this, we check if ''y''0 ≥ ''y''1; if so, we step ''y'' by -1 instead of 1. Lastly, We still need to generalize the algorithm to drawing lines in ''all'' directions. Up until now we have only been able to draw lines with a slope less than one. To be able to draw lines with a steeper slope, we take advantage of the fact that a steep line can be reflected across the line ''y=x'' to obtain a line with a small slope. The effect is to switch the ''x'' and ''y'' variables throughout, including switching the parameters to ''plot''. The code looks like this:
'function' line(x0, x1, y0, y1)
''boolean'' steep := abs(y1 - y0) > abs(x1 - x0)
'if' steep 'then'
swap(x0, y0)
swap(x1, y1)
'if' x0 > x1 'then'
swap(x0, x1)
swap(y0, y1)
''int'' deltax := x1 - x0
''int'' deltay := abs(y1 - y0)
''real'' error := 0
''real'' deltaerr := deltay / deltax
''int'' ystep
''int'' y := y0
'if' y0 < y1 'then' ystep := 1 'else' ystep := -1
'for' x 'from' x0 'to' x1
'if' steep 'then' plot(y,x) 'else' plot(x,y)
error := error + deltaerr
'if' error ≥ 0.5 'then'
y := y + ystep
error := error - 1.0
The function now handles all lines and implements the complete Bresenham's algorithm.
A more standard C code for the algorithm is shown here:
void Bresenham(int x1, int y1, int x2, int y2)
{
int slope;
int dx, dy, incE, incNE, d, x, y;
// Reverse lines where x1 > x2
if (x1 > x2)
{
Bresenham(x2, y2, x1, y1);
return;
}
dx = x2 - x1;
dy = y2 - y1;
// Adjust y-increment for negatively sloped lines
if (dy < 0)
{
slope = -1;
dy = -dy;
}
else
{
slope = 1;
}
// Bresenham constants
incE = 2
★ dy;
incNE = 2
★ dy - 2
★ dx;
d = 2
★ dy - dx;
y = y1;
// Blit
for (x = x1; x <= x2; x++)
{
putpixel(x, y);
if (d <= 0)
{
d += incE;
}
else
{
d += incNE;
y += slope;
}
}
}

Optimisation


The problem with this approach is that computers operate relatively slowly on fractional numbers like error and deltaerr; moreover, errors can accumulate over many floating-point additions. Working with integers will be both faster and more accurate. The trick we use is to multiply all the fractional numbers above by deltax, which enables us to express them as integers. The only problem remaining is the constant 0.5—to deal with this, we change the initialization of the variable error. The new program looks like this:
'function' line(x0, x1, y0, y1)
''boolean'' steep := abs(y1 - y0) > abs(x1 - x0)
'if' steep 'then'
swap(x0, y0)
swap(x1, y1)
'if' x0 > x1 'then'
swap(x0, x1)
swap(y0, y1)
''int'' deltax := x1 - x0
''int'' deltay := abs(y1 - y0)
''int'' error := -deltax / 2
''int'' ystep
''int'' y := y0
'if' y0 < y1 'then' ystep := 1 'else' ystep := -1
'for' x 'from' x0 'to' x1
'if' steep 'then' plot(y,x) 'else' plot(x,y)
error := error + deltay
'if' error > 0 'then'
y := y + ystep
error := error - deltax

Different approach to the algorithm


Principle of the Bresenham line algorithm, the lower part showing the error term

A different approach to the Bresenham algorithm works more from the practical side. It was published by ''Pitteway'' [1] and confirmed by ''van Aken'' [2]. Again we first consider a line in the first octant, which means a slope between 0 and 1. Mathematically spoken, we want to draw a line from point (x1,y1) to (x2,y2). The intervals in the two directions are dx=x2-x1 and dy=y2-y1, and the slope is dy/dx. The line equation can be written as y=y1+(x-x1)
★ dy/dx. In this first octant, we have 0 So, when working pixel-wise along this line, we have one "fast" direction, the positive x direction, and a "slow" direction, the positive y direction, where fewer steps have to be done than in the fast one. So the algorithm simply goes like this: a) Always do a single pixel step in the fast direction. b) Every now and then also do a step in the slow direction.
Bresenham's trick is the introduction of an error term, which deals with the decision, when to do also this extra step in the slow direction. The line equation is transformed into 0=dx
★ (y-y1)-dy
★ (x-x1), and then the null on the left side is replaced by the error term. A step by 1 in the x direction (variable x) causes a decrement of the error term by one times dy. If the error term gets below zero due to this, it will be increased by one times dx through a step by 1 in the y direction (variable y). Because of dx>=dy, this will render the error term positive again in any case, at least brought back to zero.
You realize a cross-wise subtraction of dy from the error term for any x step and an addition of dx for any y step. This way, the division dy/dx for the slope is dissolved into a number of more elementary operations.
A critical issue is the initialisation of the error term. In this approach here, we simply consider a line with dy=1, so with only one single step in the y direction along the whole line. Of course for the best look of the line, we want this step to happen right in the middle of the line. This leads to initialising the error term to dx/2. (Rounding this term to integers in case of odd dx is no problem.)
This approach comes out a little different from the original, as it avoids the additional factor of 2 on both sides, which has to do with the initialisation.
To generalize this algorithm for all octants, you will again have to do role changes of x and y and consider the different signs of dx and dy.
A simple implementation of this approach is not very elegant, but demonstrates the principle of the algorithm fairly well.
REM Bresenham algorithm for a line in the first octant in Pseudo Basic
dx = xend-xstart
dy = yend-ystart
REM in first octant, we have 0 < dy <= dx
REM Initialisations
x = xstart
y = ystart
SETPIXEL x,y
error = dx/2
REM Pixel loop: always do a step in fast direction, every now and then also one in the slow direction
WHILE x < xend
REM Step in fast direction
x = x + 1
error = error-dy
IF error < 0 THEN
REM Step in slow direction
y = y + 1
error = error + dx
END IF
SETPIXEL x,y
WEND

Circle Variant


The approach for the ''Circle Variant'' shown here is also not originally from Bresenham, see again references to ''Pitteway'' and ''van Aken'' below. The algorithm starts accordingly with the circle equation x²+y²=r². Again we consider first only the first octant. Here you want to draw a curve which starts at point (r,0) and then proceeds to the top left, up to reaching the angle of 45°.
The "fast" direction here is the y direction. You always do a step in the positive y direction (upwards), and every now and then you also have to do a step in the "slow" direction, the negative x direction.
The frequent computations of squares in the circle equation, trigonometric expressions or square roots can again be avoided by dissolving everything into single steps and recursive computation of the quadratic terms from the preceding ones.
From the circle equation you get to the transformed equation 0=x²+y²-r² with r² to be computed only a single time during initialisation, x²=(xpreceding-1)²=xpreceding²-2
★ xpreceding+1 (according for y), where x² (or xpreceding²) is kept as an own variable. Additionally you need to add the mid point coordinates when setting a pixel. These frequent integer additions do not limit the performance much, as you spare those square (root) computations in the inner loop in turn. Again the zero in the transformed circle equation is replaced by the error term.
The initialization of the error term is derived from an offset of ½ pixel at the start. Until the intersection with the perpendicular line, this leads to an accumulated value of r in the error term, so that this value is used for initialisation.
The following implementation is shown here only for the first octant, and again the other octants need sign changes for x and/or y and the swapping of x and y. An easy expansion for full circles, as it is possible for graphics displays, but not for plotters, is added in the comments.
REM Bresenham Algorithm for one eighth of a circle in Pseudo-Basic
REM given: r, xmid, ymid
REM initialisations for the first octant
r2 = r
★ r : REM single multiplication
x = r
y = 0
error = r
SETPIXEL xmid + x, ymid + y
REM Pixel loop: always a step in fast direction, every now and then also in slow one
WHILE y <= x
REM step in fast direction (positive y direction)
dy = y
★ 2+1 : REM in Assembler implementation
★ 2 per Shift
y = y+1
error = error-dy
IF error<0 THEN
REM step in slow direction (here the negative x direction)
dx = 1-x
★ 2 : REM in Assembler implementation
★ 2 per Shift
x = x-1
error = error-dx
END IF
SETPIXEL xmid+x, ymid+y
REM If this deals with a screen and not a mechanical plotter,
REM you can cover simultaneously also the other octants:
REM SETPIXEL xmid-x, ymid+y
REM SETPIXEL xmid-x, ymid-y
REM SETPIXEL xmid+x, ymid-y
REM SETPIXEL xmid+y, ymid+x
REM SETPIXEL xmid-y, ymid+x
REM SETPIXEL xmid-y, ymid-x
REM SETPIXEL xmid+y, ymid-x
WEND
A possible implementation of the Bresenham Algorithm for a full circle in C. Here another variable for recursive computation of the quadratic terms is used, which corresponds with the term 2
★ n+1 above. It just has to be increased by 2 from one step to the next:
void rasterCircle(int x0, int y0, int radius)
{
int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2
★ radius;
int x = 0;
int y = radius;
setPixel(x0, y0 + radius);
setPixel(x0, y0 - radius);
setPixel(x0 + radius, y0);
setPixel(x0 - radius, y0);
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
setPixel(x0 + x, y0 + y);
setPixel(x0 - x, y0 + y);
setPixel(x0 + x, y0 - y);
setPixel(x0 - x, y0 - y);
setPixel(x0 + y, y0 + x);
setPixel(x0 - y, y0 + x);
setPixel(x0 + y, y0 - x);
setPixel(x0 - y, y0 - x);
}
}
Note: There is correlation between this algorithm and the sum of first N odd numbers. Which this one basically does.
Sum of N odd numbers, from 1 inclusive, is equal to the square of N ( N squared). See Square number.
So.
When we compare sum of N odd numbers to this algorithm we have.
ddF_y = -2
★ radius is connected to last member of of sum of N odd numbers.
This member has index equal to value of radius (integral).
Since odd number is 2
★ n + 1 there is 1 handled elsewhere
or it should be -2
★ radius - 1
ddF_x = 0 should be 1. Because difference between two consecutive odd numbers is 2.
If so f += ddF_y + 1 is f+= ddF_y. Saving one operation.
f = - radius + 1 Initial error equal to half of "bigger" step.
In case of saving one addition it should be either -radius or -radius + 2.
In any case there should be addition of 1 driven out of outer loop.
So.
f += ddF_y Adding odd numbers from Nth to 1st.
f += ddF_x Adding odd numbers from 1st to Nth. 1 is missing because it can be moved outside of loop.
Drawing incomplete octants

The implementations above always only draw complete octants or circles. If you want to draw only a certain arc from an angle α to an angle β, you have to implement it in a way to first calculate the x and y coordinates of these end points, where you inevitably have to resort to trigonometric or square root computations (see Methods of computing square roots). Then you run the Bresenham algorithm over the complete octant or circle and set the pixels only if they fall into the wanted interval. After finishing this arc, you can abort the algorithm prematurely.
Ellipses

By scaling the drawn x and y values (and horizontal or vertical line expansion, respectively) you can produce even ellipses parallel to the x or y axis. For this, you use the circle algorithm with the smaller ellipse axis as radius and add a value in the other direction, which again is computed through another Bresenham line algorithm increasing from the pole to the equator. As the ellipse has to be elongated into the longer axis direction, you don't set single pixels anymore, but have to draw lines (though simple ones, only horizontal or vertical) from the previous to the next point.
A general ellipse can be derived from such an axis-parallel one by application of a shearing operation on it. Again you use an additional Bresenham line algorithm to compute the offset increasing in one of the axis directions and to let it contribute to every drawn coordinate.

History


The algorithm was developed by Jack E. Bresenham in 1962 at IBM. In 2001 Bresenham wrote:
:"''I was working in the computation lab at IBM's San Jose development lab. A Calcomp plotter had been attached to an IBM 1401 via the 1407 typewriter console. [The algorithm] was in production use by summer 1962, possibly a month or so earlier. Programs in those days were freely exchanged among corporations so Calcomp (Jim Newland and Calvin Hefte) had copies. When I returned to Stanford in Fall 1962, I put a copy in the Stanford comp center library.''
:''A description of the line drawing routine was accepted for presentation at the 1963 ACM national convention in Denver, Colorado. It was a year in which no proceedings were published, only the agenda of speakers and topics in an issue of Communications of the ACM. A person from the IBM Systems Journal asked me after I made my presentation if they could publish the paper. I happily agreed, and they printed it in 1965.''"
Bresenham later modified his algorithm to produce circles.

Similar Algorithms


The principle of using an incremental error in place of division operations has other applications in graphics. It is possible to use this technique to calculate the U,V co-ordinates during raster scan of texture mapped polygons. The voxel heightmap software-rendering engines seen in some PC games also used principle.

References



"The Bresenham Line-Drawing Algorithm", by Colin Flanagan
Bresenham also published a Run-Slice (as opposed to the Run-Length) computational algorithm.
1. Pitteway, M.L.V., "Algorithm for Drawing Ellipses or Hyperbolae with a Digital Plotter", Computer J., 10(3) November 1967, pp 282-289
2. Van Aken, J.R., "An Efficient Ellipse Drawing Algorithm", CG&A, 4(9), September 1984, pp 24-35

See also



Patrick-Gilles Maillot's Thesis an extension of the Bresenham line drawing algorithm to perform 3D hidden lines removal; also published in MICAD '87 proceedings on CAD/CAM and Computer Graphics, page 591 - ISBN 2-86601-084-1.

Xiaolin Wu's line algorithm, a similarly fast method of drawing lines with antialiasing.

External links



Analyze Bresenham's line algorithm in an online Javascript IDE

''The Bresenham Line-Drawing Algorithm'' by Colin Flanagan

National Institute of Standards and Technology page on Bresenham's algorithm

Calcomp 563 Incremental Plotter Information

Bresenham's Original Paper

An implementation in Java at the Code Codex

This article provided by Wikipedia. To edit the contents of this article, click here for original source.

psst.. try this: add to faves