Original: 3D image engine from zero: (2) It is not easy to draw a 2D line
1. Mathematical analysis
1) The problem of drawing straight line
I thought it would be easy to draw a straight line, take a straight line formula, traverse X for Y to draw out is not finished, but it is not true. Take the 2D line as an example, because the 3D line is just introducing a z-coordinate. The key question: The straight line we learned in mathematics is based on the real field, and on the computer screen, the line is based on a positive integer field, and you can imagine a situation where, at a certain point in the line, x=1,y=0.01, how do you draw on the screen? A straight line is contrasted with a real field, and a straight line based on a positive integer field:
Why is the line in the positive integer field discontinuous, remember the definition of slope: slope m = DY/DX = (y1-y0)/(x1-x0)
This means that when the x-coordinate increases by 1, the y-coordinate increases by M. This is the root cause of the situation.
2) Bresenham algorithm
The algorithm was invented by Bresenham in 1965, what exactly did it do? The idea is simply to move one pixel per x and consider how y should move. Why should we pay attention to the Bresenham algorithm, we found that this algorithm actually only do the addition and subtraction, is very suitable for computer operations, the speed of this algorithm is quite fast.
The algorithm divides the straight line into two kinds: one is the slope <1 line, namely the near X axis. The other is the slope >1 line, that is, the near Y axis.
We take the near x-axis line as an example,
The core of the Bresenham algorithm is how to determine the movement of Y when X is added to 1. Apparently, the dy<dx of the near x-axis line. So an intuitive idea is to save an error-accumulating variable that, when X plus 1, adds a dy to the error variable. When the cumulative error is less than or equal to DX, y does not move, when the accumulated error is greater than DX, y plus 1, while the cumulative error minus a DX. In this way, the algorithm will keep minimizing the error between the grating line and the actual line.
2. Function implementation
Here is an example of implementation of the above algorithm, but only the near x-axis and from the top left to the bottom of the picture, you can clearly see the implementation of the logic. The common drawing line has been implemented in the source code and can be downloaded for download.
int dx = X1-x0;int dy = y1-y0;int error = 0;if (dx > Dy)//near X axis {for (int x = x0, y = y0; x<= x1; ++x) {Drawpixel ( x, y, color); error + = dy; Cumulative error if (Error > DX) {error = Dx;++y;}}}
The complete code for all cases is as follows, with some optimizations in the calculation of errors, with the starting value centered rather than 0 of the write dead.
int _cppyin_3dlib::D rawline (int x0, int y0, int x1, int y1, DWORD color) {int x, y, dx, dy, dx2, Dy2, Xstep, Ystep, error, index;x = X0;y = Y0;DX = X1-x0;dy = y1-y0;if (dx >= 0)//draw from left to right {Xstep = 1;//x Step positive 1}else//draw from right to left {xstep =-1;//x Step Input negative 1DX =-DX; Take absolute}if (dy >= 0)//draw from top {ystep = 1;//y step positive 1}else//from bottom to top {ystep =-1;//y step negative 1dy =-dy;//Take absolute value}dx2 = DX << 1; 2 * dxdy2 = dy << 1; 2 * dyif (dx > Dy)//near x-axis straight line {error = dy2-dx;for (index = 0; index <= DX; ++index) {drawpixel (x, y, color); if (err or >= 0) {error-= dx2;y + = Ystep;} Error + = dy2;x + = Xstep;}} else//near y-axis line {error = dx2-dy;for (index = 0; index <= dy; ++index) {drawpixel (x, y, color); if (Error >= 0) {Error-= Dy2;x + = Xstep;} Error + = Dx2;y + = Ystep;}} return 1;}
3. Source code Download
This example uses this function to draw a line of 500 random colors in a window per frame, as follows:
Project source code download:>> Click to go to download page <<
4. Supplemental Updates
There are some algorithms for drawing straight lines that are faster, such as:
Run-slicing
Symmetric Double Step
Quadruple Step
If there is time I will realize, if the reader has been implemented, please leave a message to share, thank you.
"Reprint" from zero to achieve 3D Image engine: (2) Draw 2D Straight line is not simple