OpenGL画线画圆画多边形

算法是midpoint drawing algorithm,谁想的我也不知道...

画线:按l,用鼠标点两个点;

画圆:按o,用鼠标点一个圆心拉成一个圆;

画多边形:按p,就跟画线差不多,最后右键闭合;

清屏:按c;

重画:按c后按r,redraw,需要用链表保存每个图形;

ps:在vs下运行.

  1 又修改了一下
  2 // Computer Graphics: Lab1
  3 #include <iostream>
  4 #include <stdlib.h>
  5 #include <cmath>
  6 #include <gl/glut.h>
  7 
  8 using namespace std;
  9 int height, width;
 10 static int xOrg = 0, yOrg = 0;
 11 // Max number of lines for drawing: 100
 12 const int max_line=100;
 13 // Max number of polygons for drawing: 20
 14 const int max_polygon=20;
 15 // Max number of circles for drawing: 20
 16 const int max_circle=20;
 17 
 18 
 19 struct line_structure
 20 {
 21     int x0,x1,y0,y1;
 22 };
 23 struct line_data
 24 {
 25     int x,y;
 26     line_data* next;
 27 };
 28 struct center_data
 29 {
 30     int c_x, c_y;
 31 };
 32 
 33 struct poly_point
 34 {
 35     int x;
 36     int y;
 37 }pp[max_line];
 38 
 39 line_structure line[max_line];
 40 line_data line_start[max_line];
 41 line_data polygon_start[max_polygon];
 42 line_data circle_start[max_circle];
 43 center_data center[max_circle];
 44 //line_data* lcp;
 45 line_data* temp;
 46 
 47 int points[3];
 48 
 49 int key_line=1;
 50 
 51 int num_lines=0; //这个全局变量好像有点问题,不知道为什么值会变
 52 int num_polygon=0;
 53 int num_circle=0;
 54 int count_num_line=0;
 55 
 56 bool connected=false;
 57 bool first_point=true;
 58 int count_line_points=0;
 59 int count_poly_point=0;
 60 
 61 void drawDot(int x, int y, float r, float g, float b);
 62 void Mymouse_Dot(int button, int state, int x, int y);
 63 void Myhouse_Line(int button, int state, int x, int y);
 64 void Mymouse_Polygon(int button, int state, int x, int y);
 65 void Mymouse_Circle(int button, int state, int x, int y);
 66 void drawLine1(int x0, int x1, int y0, int y1, bool xy_interchange);
 67 void drawLine2(int x0, int x1, int y0, int y1, bool xy_interchange);
 68 void drawLine3(int x0, int x1, int y0, int y1, bool xy_interchange);
 69 void drawLine4(int x0, int x1, int y0, int y1, bool xy_interchange);
 70 void drawCircle(int radius, int center_x, int center_y);
 71 void CirclePoints(int x, int y, int center_x, int center_y);
 72 void redraw();
 73 void myKeyboard(unsigned char key, int x, int y);
 74 void clear();
 75 void displayFunc(void);
 76 void DrawLines_4(int x1, int y1, int x2, int y2);
 77 
 78 void DrawLines_4(int x1, int y1, int x2, int y2) //判断画哪一种线
 79 {
 80     if(x1 >= x2)
 81     {
 82         if(y1 >= y2)
 83         {
 84             swap(x1, x2);
 85             swap(y1, y2);
 86             if((y2-y1) >= (x2-x1))            
 87                 drawLine2(x1, y1, x2, y2, 1);    
 88             else
 89                 drawLine1(x1, y1, x2, y2, 1);
 90         }
 91         else
 92         {
 93             if((y2-y1) >= (x1-x2))
 94                 drawLine3(x1, y1, x2, y2, 1);
 95             else
 96                 drawLine4(x2, y2, x1, y1, 1);
 97         }                
 98     }
 99     else
100     {
101         if(y2 >= y1)
102         {
103             if((y2-y1) <= (x2-x1))
104                 drawLine1(x1, y1, x2, y2, 1);
105             else
106                 drawLine2(x1, y1, x2, y2, 1);
107         }
108         else
109         {
110             if((y1-y2) <= (x2-x1))
111                 drawLine4(x1, y1, x2, y2, 1);
112             else
113                 drawLine3(x2, y2, x1, y1, 1);
114         }
115     }
116     
117     glFlush();
118 }
119 
120 // Draw 8 points
121 void CirclePoints(int x, int y, int center_x, int center_y)
122 {
123     drawDot(x+center_x, y+center_y, 10.0, 0.0, 0.0);
124     drawDot(x+center_x, -y+center_y, 10.0, 0.0, 0.0);
125     drawDot(-x+center_x, y+center_y, 10.0, 0.0, 0.0); 
126     drawDot(-x+center_x, -y+center_y, 10.0, 0.0, 0.0); 
127     drawDot(y+center_x, x+center_y, 10.0, 0.0, 0.0); 
128     drawDot(y+center_x, -x+center_y, 10.0, 0.0, 0.0); 
129     drawDot(-y+center_x, x+center_y, 10.0, 0.0, 0.0); 
130     drawDot(-y+center_x, -x+center_y, 10.0, 0.0, 0.0); 
131 }
132 
133 // Draw a circle
134 void drawCircle(int radius, int center_x, int center_y)
135 {
136     cout << "Drawing Circle!!!" << endl;
137     int x = 0; //初始值必须为0
138     int y = radius;
139     
140     center_data center_point; //储存圆心
141     center_point.c_x = xOrg;
142     center_point.c_y = yOrg;
143     center[num_circle] = center_point;
144     
145     circle_start[num_circle].x = x; //储存起点
146     circle_start[num_circle].y = y;
147     circle_start[num_circle].next = NULL;
148     line_data *tmp = &circle_start[num_circle];
149     num_circle++;
150 
151     int d = 1 - radius;
152     int IncE = 3;
153     int IncSE = -2 * radius + 5;
154     while(x < y)
155     {
156         if(d < 0)
157         {
158             d += IncE;
159             x++;
160             IncE += 2;
161             IncSE += 2;
162         }
163         else
164         {
165             d += IncSE;
166             x++;
167             y--;
168             IncE += 2;
169             IncSE += 4;
170         }
171         CirclePoints(x, y, center_x, center_y);
172         
173         line_data *add = new line_data;
174         add->x = x;
175         add->y = y;
176         add->next = NULL;
177         tmp->next = add;
178         tmp = add;
179     }
180 }
181 
182 // Mouse control for circle drawing
183 void Mymouse_Circle(int button, int state, int x, int y)                                 //Circle
184 {
185     if(num_circle > max_circle)
186         return ;
187     int radius = 0;
188     if (state == GLUT_DOWN) {
189         cout << "	button is down" << endl;
190         if (button == GLUT_LEFT_BUTTON)
191         {
192             drawDot(x, y, 0.0, 10.0, 0.0); 
193             glFlush();        
194         }
195         xOrg = x;
196         yOrg = y;
197         
198     }
199     else if (state == GLUT_UP) {
200         cout << "	button is up" << endl;
201         if (button == GLUT_LEFT_BUTTON)
202         {
203             drawDot(x, y, 0.0, 10.0, 0.0); 
204             glFlush();    
205             radius = (int)sqrt((xOrg-x)*(xOrg-x) + (yOrg-y)*(yOrg-y));
206             drawCircle(radius, xOrg, yOrg);
207             glFlush(); //必须要加
208         }
209     }
210     cout << "		 Previous location: (" << xOrg << " , " << yOrg << ")" << endl;
211     cout << "		 New location: (" << x << " , " << y << ")" << endl;
212 
213     /*
214     cout << "x_down: " << xOrg << endl;
215     cout << "y_down: " << yOrg << endl;
216     cout << "x_up: " << x_up << endl;
217     cout << "y_up: " << y_up << endl;
218     cout << "radius: " << radius << endl;
219     */
220 }
221 
222 // Clear screen
223 void clear()
224 {
225     glClearColor(0.0,0.0,0.0,0.0);
226     glClear(GL_COLOR_BUFFER_BIT);
227     glFlush();
228 }
229 
230 // Mouse control for polygon drawing
231 void Mymouse_Polygon(int button, int state, int x, int y)                             //Polygon
232 {
233     cout << count_poly_point << endl;
234     if(num_polygon > max_polygon)
235         return ;
236     if (state == GLUT_DOWN) {
237         cout << "	button is down" << endl;
238         if (button == GLUT_LEFT_BUTTON)
239         {
240             drawDot(x, y, 0.0, 10.0, 0.0); 
241             glFlush();
242             if(count_poly_point < 1)
243             {
244                 polygon_start[num_polygon].x = x;
245                 polygon_start[num_polygon].y = y;
246                 polygon_start[num_polygon].next = NULL;
247             
248                 temp = &polygon_start[num_polygon];
249 
250                 poly_point p;
251                 p.x = x;
252                 p.y = height - y; //转换坐标
253                 pp[count_poly_point] = p;
254             }
255             else
256             {    
257                 int x1 = pp[count_poly_point-1].x;
258                 int y1 = pp[count_poly_point-1].y;
259                 int x2 = x;
260                 int y2 = height - y;
261                 pp[count_poly_point].x = x2;
262                 pp[count_poly_point].y = y2;
263                 
264 
265                 DrawLines_4(x1, y1, x2, y2);
266             }
267             count_poly_point++;
268         }
269         
270         
271         if (button == GLUT_RIGHT_BUTTON)
272         {
273             int x1 = pp[0].x;
274             int y1 = pp[0].y;
275             int x2 = pp[count_poly_point-1].x;
276             int y2 = pp[count_poly_point-1].y;
277             DrawLines_4(x1, y1, x2, y2);
278             num_polygon++;
279             count_poly_point = 0;
280         }
281     }
282 }
283 
284 // Redraw all objects stored 
285 void redraw()                                                                               //Redraw
286 {
287     int i;
288     line_data* rd_line;
289     line_data* rd_polygon;
290     line_data* rd_circle;
291 
292     for (i=0;i<count_num_line;i++)
293     {
294         rd_line=&line_start[i];
295         drawDot(rd_line->x,rd_line->y,0,1,0);
296         do
297         {
298             rd_line=rd_line->next;
299             drawDot(rd_line->x,rd_line->y,0,1,0);
300         } while (rd_line->next!=NULL);
301     }
302     
303     for (i=0;i<num_polygon;i++)
304     {
305         rd_polygon=&polygon_start[i];
306         drawDot(rd_polygon->x,rd_polygon->y,0,1,0);
307         do
308         {
309             rd_polygon=rd_polygon->next;
310             drawDot(rd_polygon->x,rd_polygon->y,0,1,0);
311         } while (rd_polygon->next!=NULL);
312     }
313     
314     for (i=0;i<num_circle;i++)
315     {
316         rd_circle=&circle_start[i];
317         CirclePoints(rd_circle->x,rd_circle->y,center[i].c_x,center[i].c_y);        
318         do
319         {
320             rd_circle=rd_circle->next;
321             CirclePoints(rd_circle->x,rd_circle->y,center[i].c_x,center[i].c_y);
322         } while (rd_circle->next!=NULL);
323     }
324     glFlush();
325 }
326 
327 // draw a dot at location with integer coordinates (x,y), and with color (r,g,b)
328 void drawDot(int x, int y, float r, float g, float b) 
329 {
330     glBegin(GL_POINTS);
331   
332     // set the color of dot
333     glColor3f(r, g, b);
334   
335     // invert height because the opengl origin is at top-left instead of bottom-left
336     glVertex2i(x , height - y);
337   
338     glEnd();
339 }
340 
341 // Mouse callback function
342 void Mymouse_Dot(int button, int state, int x, int y)                                            //Dot
343 {
344     if (state == GLUT_DOWN) {
345         cout << "	button is down" << endl;
346         if (button == GLUT_LEFT_BUTTON) {
347             drawDot(x, y, 0.0, 10.0, 0.0);
348             glFlush();
349         }
350         else if (button == GLUT_MIDDLE_BUTTON) {
351             drawDot(x, y, 0.0, 1.0, 0.0);
352             glFlush();
353         }
354         else if (button == GLUT_RIGHT_BUTTON) {
355             drawDot(x, y, 0.0, 0.0, 1.0);
356             glFlush();
357         }
358         xOrg = x;
359         yOrg = y;
360     }
361     else if (state == GLUT_UP) {
362         cout << "	button is up" << endl;
363         if (button == GLUT_LEFT_BUTTON) {    
364             drawDot(x, y, 0.0, 10.0, 0.0);
365             glFlush();
366         }
367         else if (button == GLUT_MIDDLE_BUTTON) {
368             drawDot(x, y, 0.0, 0.5, 0.0);
369             glFlush();
370         }
371         else if (button == GLUT_RIGHT_BUTTON) {
372             drawDot(x, y, 0.0, 0.0, 0.5);
373             glFlush();
374         }
375     }
376     cout << "		 Previous location: (" << xOrg << " , " << yOrg << ")" << endl;
377     cout << "		 New location: (" << x << " , " << y << ")" << endl;
378 }
379 
380 
381 
382 // Mouse control for line drawing 
383 void Mymouse_Line(int button, int state, int x, int y)                                    //Line
384 {
385     if(count_num_line > max_line)
386         return ;
387     if (state == GLUT_DOWN) {
388         cout << "	button is down" << endl;
389         if (button == GLUT_LEFT_BUTTON)
390         {
391             drawDot(x, y, 0.0, 10.0, 0.0); 
392             glFlush();        
393         }
394         xOrg = x;
395         yOrg = height - y; //转换坐标
396         
397         if(count_line_points < 4)
398         {
399             points[count_line_points++] = xOrg;
400             points[count_line_points++] = yOrg;
401         }
402         if(count_line_points == 4)
403         {
404             count_line_points = 0;
405             int x1 = points[0];
406             int y1 = points[1];
407             int x2 = points[2];
408             int y2 = points[3];
409             
410             line_start[count_num_line].x = x;
411             line_start[count_num_line].y = y;
412             line_start[count_num_line].next = NULL;
413             temp = &line_start[count_num_line];
414 
415             DrawLines_4(x1, y1, x2, y2);
416 
417             count_num_line++;
418 
419             glFlush();
420         }
421         
422     }
423     cout << "		 Previous location: (" << xOrg << " , " << yOrg << ")" << endl;
424     cout << "		 New location: (" << x << " , " << y << ")" << endl;
425 }
426 
427 // Draw line for dx>0 and dy>0
428 void drawLine1(int x1, int y1, int x2, int y2, bool xy_interchange) //0-45度
429 {
430     cout << "Drawing Line1!" << endl;
431     int x = x1;
432     int y = y1;    
433 
434     int a = y2 - y1;
435     int b = x1 - x2;
436     int d = 2 * a + b;
437     int IncE = 2 * a;
438     int IncNE = 2 * (a + b);
439 
440     while(x <= x2)
441     {
442         if(d <= 0)
443         {
444             x++;
445             d += IncE;
446         }
447         else
448         {
449             x++;
450             y++;
451             d += IncNE;
452         }
453         drawDot(x, height-y, 0.0, 10.0, 0.0);
454         
455         line_data *add = new line_data;
456         add->x = x;
457         add->y = height-y;
458         add->next = NULL;
459         temp->next = add;
460         temp = add;
461     }
462 }
463 
464 // Draw line for dx>0 and dy<0
465 void drawLine2(int x1, int y1, int x2, int y2, bool xy_interchange) //45-90度
466 {
467     cout << "Drawing Line2!" << endl;
468     //转换为0-45度的情况
469     swap(x2, y2);
470     swap(x1, y1);
471 
472     int x = x1;
473     int y = y1;
474     
475     int a = y2 - y1;
476     int b = x1 - x2;
477     int d = 2 * a + b;
478     int IncE = 2 * a;
479     int IncNE = 2 * (a + b);
480 
481     while(x <= x2)
482     {
483         if(d <= 0)
484         {
485             x++;
486             d += IncE;
487         }
488         else
489         {
490             x++;
491             y++;
492             d += IncNE;
493         }
494         drawDot(y, height-x, 0.0, 10.0, 0.0);
495 
496         line_data *add = new line_data;
497         add->x = y;
498         add->y = height-x;
499         add->next = NULL;
500         temp->next = add;
501         temp = add;    
502     }    
503 }
504 
505 // Draw line for dx<0 and dy>0
506 void drawLine3(int x1, int y1, int x2, int y2, bool xy_interchange) //90-135度
507 {
508     cout << "Drawing Line3!" << endl;
509     swap(x2, y2);
510     swap(x1, y1);
511     y1 = -y1;
512     y2 = -y2;
513     int x = x1;
514     int y = y1;
515 
516     int a = y2 - y1;
517     int b = x1 - x2;
518     int d = 2 * a + b;
519     int IncE = 2 * a;
520     int IncNE = 2 * (a + b);
521 
522     while(x <= x2)
523     {
524         if(d <= 0)
525         {
526             x++;
527             d += IncE;
528         }
529         else
530         {
531             x++;
532             y++;
533             d += IncNE;
534         }
535         drawDot(-y, height-x, 0.0, 10.0, 0.0);
536 
537         line_data *add = new line_data;
538         add->x = -y;
539         add->y = height-x;
540         add->next = NULL;
541         temp->next = add;
542         temp = add;
543     }
544 }
545 
546 // Draw line for dx<0 and dy>0
547 void drawLine4(int x1, int y1, int x2, int y2, bool xy_interchange) //135-180度
548 {
549     cout << "Drawing Line4!" << endl;
550     y1 = -y1;
551     y2 = -y2;
552     int x = x1;
553     int y = y1;
554     
555     int a = y2 - y1;
556     int b = x1 - x2;
557     int d = 2 * a + b;
558     int IncE = 2 * a;
559     int IncNE = 2 * (a + b);
560 
561     while(x <= x2)
562     {
563         if(d <= 0)
564         {
565             x++;
566             d += IncE;
567         }
568         else
569         {
570             x++;
571             y++;
572             d += IncNE;
573         }
574         drawDot(x, height+y, 0.0, 10.0, 0.0);
575 
576         line_data *add = new line_data;
577         add->x = x;
578         add->y = height+y;
579         add->next = NULL;
580         temp->next = add;
581         temp = add;
582     }
583 }
584 
585 // Keyboard callback function
586 void myKeyboard(unsigned char key, int x, int y) 
587 {
588     switch(key) {
589     // Draw dots with 'd' or 'D'
590     case 'd':
591     case 'D':
592         cout << "press key: " << 'd' << endl;
593           glutMouseFunc(Mymouse_Dot);
594           break;
595     // Draw lines with 'l' or 'L'
596     case 'l':
597     case 'L':
598         cout << "press key: " << 'l' << endl;
599         glutMouseFunc(Mymouse_Line);
600         break;
601     // Draw polygons with 'p' or 'P'
602     case 'p':
603     case 'P':
604         cout << "press key: " << 'p' << endl;
605         glutMouseFunc(Mymouse_Polygon);
606         break;
607     // Draw circle with 'c' or 'C'
608     case 'o':
609     case 'O':
610         cout << "press key: " << 'o' << endl;
611         glutMouseFunc(Mymouse_Circle);
612         break;
613     // Redraw all with 'r' or 'R'
614     case 'r':
615     case 'R':
616         cout << "press key: " << 'r' << endl;
617         redraw();
618         break;
619     // Clear screen with 'c' or 'C'
620     case 'c':
621     case 'C':
622         cout << "press key: " << 'c' << endl;
623         clear();
624         break;
625     // Quit with 'q' or 'Q'
626     case 'q':
627     case 'Q':
628         cout << "press key: " << 'q' << endl;
629         exit(0);
630         break;
631     }
632 }
633 
634 // Display function
635 void displayFunc(void){
636     // clear the entire window to the background color
637     glClear(GL_COLOR_BUFFER_BIT); 
638     glClearColor(0.0, 0.0, 0.0, 0.0); 
639 
640     // draw the contents!!! Iterate your object's data structure!
641 
642     // flush the queue to actually paint the dots on the opengl window
643     glFlush();
644 }
645 
646 // Main
647 void main(int ac, char** av) {
648 
649     cout << "Hello Glut!" << endl;
650     
651     int winSizeX, winSizeY;
652   
653     if(ac == 3) {
654     winSizeX = atoi(av[1]);
655     winSizeY = atoi(av[2]);
656     }
657     else { // default window size
658     winSizeX = 800;
659     winSizeY = 600;
660     }
661 
662     width  = winSizeX;
663     height = winSizeY;
664 
665     // initialize OpenGL utility toolkit (glut)
666     glutInit(&ac, av);
667 
668     // single disply and RGB color mapping
669     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set display mode
670     glutInitWindowSize(winSizeX, winSizeY);      // set window size
671     glutInitWindowPosition(400, 100);                // set window position on screen
672     glutCreateWindow("Lab1 Window");       // set window title
673   
674     // set up the mouse and keyboard callback functions
675     glutKeyboardFunc(myKeyboard); // register the keyboard action function
676 
677     // displayFunc is called whenever there is a need to redisplay the window,
678     // e.g., when the window is exposed from under another window or when the window is de-iconified
679     glutDisplayFunc(displayFunc); // register the redraw function
680 
681     // set background color
682     glClearColor(0.0, 0.0, 0.0, 0.0);     // set the background to black
683     glClear(GL_COLOR_BUFFER_BIT); // clear the buffer
684 
685     // misc setup
686     glMatrixMode(GL_PROJECTION);  // setup coordinate system
687     glLoadIdentity();
688     gluOrtho2D(0, winSizeX, 0, winSizeY);
689     glShadeModel(GL_FLAT);
690     glFlush();
691     glutMainLoop();
692 }
原文地址:https://www.cnblogs.com/dominjune/p/4374860.html