实验二:直线与画圆算法
实验目的: 理解光栅化,掌握几何数据如何经过一系列变换后转化为像素从而呈现在显示 设备上。
基本要求:
实现 DDA 和 Bresenham 画线算法
实现画圆算法
请勿直接调用 OpenGL 库中提供的绘制线段和圆的函数,需手动模拟如何通过绘 制像素来显示几何图形,效果可参考下图。(界面显示的是“虚拟的像素”)
可通过交互操作来确定线段的起点和终点。
实现:
1 #include<GL/glut.h> 2 #define EXIT_SUCCESS 0 3 #include<stdio.h> 4 #include<math.h> 5 // later Edition 6 int MODE = 0; // 模式代码:0-DAA算法,1-Bresenham算法,2-中点圆算法 7 bool mouseLeftDown; // 实时记录鼠标左键状态 8 bool mouseRightDown; // 实时记录鼠标左键状态 9 float mouseX, mouseY; // 实时记录鼠标位置,与下一次鼠标位置之间形成微分 10 11 int startX=0, startY=0, endX=0, endY=0; 12 int start[2] = { 0 }; 13 int end[2] = { 0 }; 14 float red=1.0,green=1.0, blue=0.0; 15 float PI = 3.415926535; 16 17 int arr[500][500]; 18 19 void init(void) 20 { 21 //glClearColor(0.0, 0.0, 0.0, 0.0);/* select clearing color */ // 设置背景颜色为黑色 22 //glMatrixMode(GL_MODELVIEW); 23 glClearColor(0.0, 0.0, 0.0, 0.0); /* white background */ 24 glColor3f(1.0, 0.0, 0.0); /* draw in red */ 25 26 /* set up viewing: */ 27 /* 500 x 500 window with origin lower left */ 28 29 glMatrixMode(GL_PROJECTION); 30 glLoadIdentity(); 31 gluOrtho2D(0.0, 500.0, 0.0, 500.0); 32 glMatrixMode(GL_MODELVIEW); 33 } 34 35 36 37 38 #define RED 1233 39 #define BLUE 1234 40 #define GREEN 1235 41 #define WHITE 12366 42 #define YELLOW 12367 43 #define DAA_LINE 12368 44 #define BRES_LINE 12369 45 #define CIRCLE 12370 46 void processMenuEvents(int option) { 47 //option,就是传递过来的value的值。 48 switch (option) { 49 case RED: 50 red = 1.0; 51 green = 0.0; 52 blue = 0.0; break; 53 case GREEN: 54 red = 0.0; 55 green = 1.0; 56 blue = 0.0; break; 57 case BLUE: 58 red = 0.0; 59 green = 0.0; 60 blue = 1.0; break; 61 case WHITE: 62 red = 1.0; 63 green = 1.0; 64 blue = 1.0; break; 65 case YELLOW: 66 red = 1.0; 67 green = 1.0; 68 blue = 0.0;break; 69 case DAA_LINE: 70 MODE = 0;break; 71 case BRES_LINE: 72 MODE = 1;break; 73 case CIRCLE: 74 MODE = 2;break; 75 } 76 } 77 void createGLUTMenus() { 78 79 int menu; 80 81 // 创建菜单并告诉GLUT,processMenuEvents处理菜单事件。 82 menu = glutCreateMenu(processMenuEvents); 83 84 //给菜单增加条目 85 glutAddMenuEntry("红色", RED); 86 glutAddMenuEntry("蓝色", BLUE); 87 glutAddMenuEntry("绿色", GREEN); 88 glutAddMenuEntry("白色", WHITE); 89 glutAddMenuEntry("黄色", YELLOW); 90 glutAddMenuEntry("DAA_LINE", DAA_LINE); 91 glutAddMenuEntry("BRES_LINE", BRES_LINE); 92 glutAddMenuEntry("CIRCLE_SCAN", CIRCLE); 93 94 // 把菜单和鼠标右键关联起来。 95 glutAttachMenu(GLUT_RIGHT_BUTTON); 96 } 97 98 void DAA_alogrithm(int x0, int y0, int x1, int y1) { 99 int x; 100 float dx, dy, y, k; 101 dx = x1 - x0,dy = y1 - y0; 102 k = dy / dx, y = y0; 103 glPointSize(5.0); 104 105 glBegin(GL_POINTS); 106 107 for (x = x0;x <= x1;x++) { 108 109 glVertex2d(x, int(y + 0.5)); 110 y = y + k; 111 } 112 glEnd(); 113 } 114 void y_DAA_alogrithm(int x0, int y0, int x1, int y1) { 115 int y; 116 float dx, dy, x, k; 117 dx = x1 - x0, dy = y1 - y0; 118 k = dx / dy, x = x0; 119 glPointSize(5.0); 120 121 glBegin(GL_POINTS); 122 123 for (y = y0;y <= y1;y++) { 124 125 glVertex2d(int(x + 0.5),y ); 126 x = x + k; 127 } 128 glEnd(); 129 } 130 void Bresenham(int x0, int y0, int x1, int y1) { 131 bool is_nagetive_k = false; 132 if ((y1 - y0) * (x1 - x0) < 0) { 133 y1 *= -1, y0 *= -1; 134 is_nagetive_k = true; 135 } 136 int x, y, dx, dy, e; 137 dx = x1 - x0, dy = y1 - y0,e=-dx; 138 x = x0;y = y0; 139 glPointSize(5.0); 140 141 glBegin(GL_POINTS); 142 for (int i = 0;i < dx;i++) { 143 if (!is_nagetive_k)glVertex2d(x, y);else { 144 glVertex2d(x, -y); 145 } 146 x++, e = e + 2 * dy; 147 if (e >= 0)y++, e = e - 2 * dx; 148 } 149 glEnd(); 150 } 151 void y_Bresenham(int x0, int y0, int x1, int y1) { 152 bool is_nagetive_k = false; 153 if ((y1 - y0) * (x1 - x0) < 0) { 154 y1 *= -1;y0 *= -1; 155 is_nagetive_k = true; 156 } 157 158 int x, y, dx, dy, e; 159 dx = x1 - x0, dy = y1 - y0, e = -dy; 160 x = x0;y = y0; 161 glPointSize(5.0); 162 163 glBegin(GL_POINTS); 164 for (int i = 0;i < dy;i++) { 165 if (!is_nagetive_k)glVertex2d(x, y);else { 166 glVertex2d(x, -y); 167 } 168 y++, e = e + 2 * dx; 169 if (e >= 0)x++, e = e - 2 * dy; 170 } 171 glEnd(); 172 } 173 void circlePoints(int x,int y) { 174 glPointSize(5.0); 175 glBegin(GL_POINTS); 176 glVertex2d(x,y);glVertex2d(y,x); 177 glVertex2d(-x,y);glVertex2d(-y,x); 178 glVertex2d(x,-y);glVertex2d(y,-x); 179 glVertex2d(-x,-y);glVertex2d(-y,-x); 180 glEnd(); 181 } 182 void mindCircle(int r) { 183 int x, y; 184 float d; 185 x = 0;y = r; d = 1.25 - r; 186 circlePoints(x, y); 187 while (x <= y) { 188 if (d < 0) { 189 d += 2 * x + 3; 190 } 191 else { 192 d += 2 * (x - y) + 5;y--; 193 } 194 x++; 195 circlePoints(x, y); 196 } 197 } 198 void display(void) 199 { 200 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 201 glColor3f(red, green, blue); 202 glLoadIdentity(); 203 204 205 206 207 if (MODE == 0) { 208 if (abs(startY - endY) > abs(startX - endX)) { 209 if (startY > endY) { 210 y_DAA_alogrithm(endX, endY,startX, startY); 211 } 212 else { 213 y_DAA_alogrithm(startX, startY, endX, endY); 214 } 215 } 216 else { 217 if (startX > endX) { 218 DAA_alogrithm(endX, endY, startX, startY); 219 } 220 else { 221 DAA_alogrithm(startX, startY, endX, endY); 222 } 223 } 224 } 225 else if (MODE == 1) { 226 227 if (startX > endX) { 228 if (abs(startY - endY) > abs(startX - endX))y_Bresenham(endX, endY, startX, startY); 229 else Bresenham(endX, endY, startX, startY); 230 } 231 else { 232 if(abs(startY - endY) > abs(startX - endX))y_Bresenham(startX, startY, endX, endY); 233 else Bresenham(startX, startY, endX, endY); 234 } 235 236 } 237 else if(MODE==2){ 238 glPushMatrix(); 239 glTranslated(startX, startY, 0); 240 mindCircle(int(pow((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY), 0.5))); 241 glTranslated(-endX, -endY, 0); 242 glPopMatrix(); 243 } 244 245 246 247 248 /* 249 glBegin(GL_LINES); 250 251 glVertex2d(startX, startY);glVertex2d(endX, endY); 252 253 glEnd(); 254 255 */ 256 /* 257 glPointSize(10.0); 258 for (int i = 0;i < 500;i++) { 259 glVertex2d(100, i); 260 glVertex2d(i, 100); 261 glVertex2d(i, i); 262 263 } 264 glEnd(); 265 */ 266 267 glutSwapBuffers(); 268 } 269 int saveStack = 0; 270 int firstSaveFlag = -1; 271 void keyboard(unsigned char key, int x, int y) 272 273 { 274 switch (key) { 275 case 'q':case 'Q': 276 exit(EXIT_SUCCESS); 277 break; 278 } 279 } 280 int ww, hh; 281 282 void mouse_process(int button, int state, int x, int y) 283 { 284 mouseX = x; 285 mouseY = y; 286 printf("(%d,%d)\n", x, y); 287 printf("(%d,%d)", startX,startY); 288 printf("(%d,%d)\n", endX,endY); 289 hh = glutGet(GLUT_WINDOW_HEIGHT); 290 if (button == GLUT_LEFT_BUTTON) 291 { 292 if (state == GLUT_DOWN) 293 { 294 if (!mouseLeftDown) { 295 startX = x;startY = hh-y; 296 } 297 298 mouseLeftDown = true; 299 } 300 else if (state == GLUT_UP) { 301 mouseLeftDown = false; 302 303 } 304 305 } 306 307 else if (button == GLUT_RIGHT_BUTTON) 308 { 309 if (state == GLUT_DOWN) 310 { 311 mouseRightDown = true; 312 } 313 else if (state == GLUT_UP) 314 mouseRightDown = false; 315 } 316 317 318 319 } 320 321 void mouse_process_active(int x, int y) 322 { 323 if (mouseLeftDown){ 324 endX = x;endY = hh - y; 325 glutPostRedisplay(); 326 } 327 if(mouseRightDown) 328 { 329 330 } 331 glutPostRedisplay(); 332 333 } 334 void mouse_process_passtive(int x, int y) {} 335 336 337 int main(int argc, char** argv) 338 { 339 glutInit(&argc, argv); 340 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 341 glutInitWindowSize(500, 500); 342 glutCreateWindow("19智能 右键开启菜单"); 343 344 init(); 345 346 glutDisplayFunc(display); 347 348 // later Edition 349 glutMouseFunc(mouse_process); 350 glutMotionFunc(mouse_process_active); 351 glutPassiveMotionFunc(mouse_process_passtive); 352 createGLUTMenus(); 353 glutKeyboardFunc(keyboard); 354 glutMainLoop(); 355 356 return 0; 357 }