算法是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 }