Opengl implements line scanning algorithm and area filling algorithm, and opengl Algorithm
Overview
1. Use the line scanning algorithm to draw a line segment. A straight line consists of discrete points.
2. Use the area Filling Algorithm to draw a polygon area. The area consists of discrete points.
Development Environment VS2012 + OpenGL
Development Platform: Intel core i5, Intel HD Graphics Family
Design Concept
I. Line Scanning Algorithm
1. Numerical differentiation (DDA)
Known through the terminal P0 (x0, y0), P1 (x1, y1) line segment L: y = kx + B, it is easy to know that the straight line slope is: k = (y1-y0) /(x1-x0), (assuming x1 =x0 ).
We assume that | k | ≤ 1, so that k is increased for each increase of x, and the increment of y cannot be greater than 1 for each increase of x. If | k |> 1, x and y should be exchanged. Since k is a floating point number, we need to round y to the int type in the algorithm and round it to the nearest position.
The x and y values of the DDA Algorithm in each iteration are obtained by adding an incremental value to the value in the previous step. Therefore, it is an incremental algorithm. However, this method is intuitive but inefficient, because each step requires a floating-point multiplication and a rounding operation.
2. midpoint Line Drawing Method
The slope of the line is 0 ~ 1. If the current pixel is set to (x, y), the next pixel is p1 (x + 1, y) or p2 (x + 1, y + 1). If the point M (px + 1, y + 0.5) of p1 and p2 is called, Q is the intersection of the ideal line and the x + 1 vertical line, when Q is below M, p1 is the next pixel; otherwise p2 is the next pixel.
3. Bresenham Algorithm
Creates a set of virtual gridlines through the pixel center of each row column. Calculate the intersection of a straight line and each vertical grid line in the order from the start point to the end point, and then determine the nearest pixel of the column pixel. The clever use of this algorithm is incremental computing, so that for each column, you only need to check the symbol of an error item to determine the pixel for this column.
Set the linear equation to yi + 1 = yi + k (xi + 1-xi) + k. Assume that the column coordinate pixel has been determined as xi, and its row coordinate is yi. Then the column coordinate of the next pixel is xi + 1, while the row coordinate is yi or 1 is yi + 1. Whether to add 1 depends on the value of error item d. The initial value of the error item d is d0 = 0. For each increase of 1 in the x coordinate, the value of d increments the slope value k of the straight line, that is, d = d + k. Once d is greater than or equal to 1, it is subtracted from 1 to ensure that d is between 0 and 1. When d is greater than or equal to 0.5, the intersection of the straight line and the vertical line x = xi + 1 is closest to the upper right pixel (xi + 1, yi + 1) of the current pixel (xi, yi ); when d is less than 0.5, it is closer to the right pixel (xi + 1, yi ). For convenient calculation, e = d-0.5, e initial value is-0.5, incremental is k. When e is greater than or equal to 0, the upper-right pixels (xi + 1, yi + 1) of the current pixel (xi, yi) are obtained. When e is less than 0, the values (xi, yi) are obtained) right pixel (xi + 1, yi ).
2. Area Filling Algorithm
1. Recursive Algorithms
Starting from the specified seed point, search for each direction and process each pixel one by one until a boundary is met. Various Seed Filling algorithms only differ in the color and boundary processing methods.
2. Scanning line algorithm
The basic process of the scanning line Seed Filling Algorithm is as follows: when the seed point (x, y) is given, first, fill in the scanning line of the seed point in the left and right directions, respectively, a section in the given area, and write down the range of this section [xLeft, xRight], then, determine the upper and lower scanning lines that are connected to the CIDR block, and save them in sequence. Repeat this process until the filling ends.
The scanning line Seed Filling Algorithm can be implemented in the following four steps:
(1) Initialize an empty stack to store the seed points and import the seed points (x, y) into the stack;
(2) judge whether the stack is empty. If the stack is empty, end the algorithm. Otherwise, the top element of the stack is taken out as the seed point (x, y) of the current scanning line, and y is the current scanning line;
(3) starting from the seed point (x, y), fill in the left and right directions along the current scanning line until the boundary. The coordinates of the left and right endpoints of the CIDR blocks are xLeft and xRight respectively;
(4) Check the pixels of the y-1 and y + 1 scanning lines adjacent to the current scanning line in the range [xLeft, xRight], and search for the lines from xLeft to xRight, if there are non-boundary and unfilled pixels, find the rightmost of these adjacent pixels and press them into the stack as the seed points, and then return step (2;
Iii. Algorithm Implementation
Summary and learning insights
When I learned the line scanning algorithm, I couldn't draw it at first. Later I found this glBegin (GL_POINTS). If I miss a second, I can only draw one point without a second. The details are very important.
When learning the area filling algorithm, the basic idea is to start from a point and constantly explore the surrounding area. If it is in this area, the color will be filled, and if it encounters a boundary, it will stop. The scanning line algorithm is also used. First, draw a straight line at a certain point and fill in the color of the line segment in the area.
We are like the selected 1.1. everything around us is unknown black. Only by constantly exploring can we know where the border is, or maybe there is no border, maybe there is another bigger New World on the boundary. I think too much.
Main source code scanning Algorithms
void k1() //0<k<1 { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0,0.0,0.0); glBegin(GL_POINTS); GLint x1=0,y1=0,x2=400,y2=200; GLint x=x1,y=y1; GLint dx=x2-x1,dy=y2-y1,dT=2*(dy-dx),dS=2*dy; GLint d=2*dy-dx; glVertex2i(x,y); while(x<x2) { x++; if(d<0) d=d+dS; else { y++; d=d+dT; } glVertex2i(x,y); } glEnd(); glFlush(); }
Area Filling
# Include "gl/glut. h "# include" windows. h "const int POINTNUM = 7; // polygon points. /****** defines the struct for the active edge table AET and the new edge table NET ********************** * ***********/typedef struct XET {float x; float dx, ymax; XET * next;} AET, NET; ***************************** * ***********************/struct point {float x; float y;} polypoint [POINTNUM] = {550,150,550,400,250,250,100,350,100,100,120, 50, 30}; // polygon vertex void PolyScan () {/****** calculate the y coordinate of the highest point (scanning ends here) **************************************** /int MaxY = 0; int I; for (I = 0; I <POINTNUM; I ++) if (polypoint [I]. y> MaxY) MaxY = polypoint [I]. y; ***************************** * ****************************/AET * pAET = new AET; pAET-> next = NULL; ****************************** * ****************************/NET * pNET [1024]; for (I = 0; I <= MaxY; I ++) {pNET [I] = new NET; pNET [I]-> next = NULL;} glClear (GL_COLOR_BUFFER_BIT ); // The Value assignment window is displayed. glColor3f (0.0, 0.0, 0.0); // set the color of the line to Red glBegin (GL_POINTS ); **************************** * ***************************/for (I = 0; I <= MaxY; I ++) {for (int j = 0; j <POINTNUM; j ++) if (polypoint [j]. y = I) {// a point is a line segment formed by a point above it, and the point following it also forms a line segment if (polypoint [(J-1 + POINTNUM) % POINTNUM]. y> polypoint [j]. y) {NET * p = new NET; p-> x = polypoint [j]. x; p-> ymax = polypoint [(J-1 + POINTNUM) % POINTNUM]. y; p-> dx = (polypoint [(J-1 + POINTNUM) % POINTNUM]. x-polypoint [j]. x)/(polypoint [(J-1 + POINTNUM) % POINTNUM]. y-polypoint [j]. y); p-> next = pNET [I]-> next; pNET [I]-> next = p;} if (polypoint [(j + 1 + POINTNUM) % POINTNUM]. y> polypoint [j]. y) {NET * p = new NET; p-> x = polypoint [j]. x; p-> ymax = polypoint [(j + 1 + POINTNUM) % POINTNUM]. y; p-> dx = (polypoint [(j + 1 + POINTNUM) % POINTNUM]. x-polypoint [j]. x)/(polypoint [(j + 1 + POINTNUM) % POINTNUM]. y-polypoint [j]. y); p-> next = pNET [I]-> next; pNET [I]-> next = p ;}}} ************************** * **************************/for (I = 0; I <= MaxY; I ++) {// calculate the new intersection x and update AET NET * p = pAET-> next; while (p) {p-> x = p-> x + p-> dx; p = p-> next ;} // After the update, the new AET is sorted ******************************** **************************** // sort the broken table, no longer open space AET * tq = pAET; p = pAET-> next; tq-> next = NULL; while (p) {while (tq-> next & p-> x> = tq-> next-> x) tq = tq-> next; NET * s = p-> next; p-> next = tq-> next; tq-> next = p; p = s; tq = pAET;} // (Improved Algorithm) delete the node ************************************* from the AET table ***************************** * **********/AET * q = pAET; p = q-> next; while (p) {if (p-> ymax = I) {q-> next = p-> next; delete p; p = q-> next;} else {q = q-> next; p = q-> next ;}// Add a new vertex in NET to AET, sort by X value with the insert method ******************************** **/p = pNET [I]-> next; q = pAET; while (p) {while (q-> next & p-> x> = q-> next-> x) q = q-> next; NET * s = p-> next; p-> next = q-> next; q-> next = p; p = s; q = pAET ;} ****************************** * *******************************/p = pAET-> next; while (p & p-> next) {for (float j = p-> x; j <= p-> next-> x; j ++) glVertex2i (static_cast <int> (j), I); p = p-> next; // consider the endpoint} glEnd (); glFlush ();} void init (void) {glClearColor (1.0, 1.0, 1.0, 0.0); // set the background color of the window to white glMatrixMode (GL_PROJECTION); gluOrtho2D (0.0, 600.0, 0.0, 450.0);} void main (int argc, char * argv) {gluinit (& argc, & argv); // I initialize GLUT. gluinitdisplaymode (glu_single | glu_rgb); // sets the display mode: A single cache and uses the RGB model gluinitwindowposition (50,100); // sets the top and left positions of the window. gluinitwindowsize (400,300 ); // set the window height and width ); // The graphic definition is passed to the window. glumainloop (); // display all images and wait}