實驗3 直線裁剪演算法
阿新 • • 發佈:2018-12-30
1.實驗目的:
- 理解直線裁剪的基本原理;
- 驗證直線的編碼裁剪演算法,參考網路資料實現樑友棟-Barsky裁剪演算法;
- 瞭解與掌握OpenGL滑鼠操作。
2.實驗內容:
本次實驗主要結合滑鼠畫執行緒序來驗證編碼裁剪演算法和實現樑友棟-Barsky裁剪演算法,具體步驟如下:
(1) 閱讀學習所給的編碼裁剪示範程式碼,瞭解程式使用方法,並結合三種不同型別直線對其進行裁剪測試,將測試結果存為圖1-3,儲存至word實驗文件中(30分鐘);
(2) 為示範程式碼增加樑友棟-Barsky裁剪演算法,並通過鍵盤按鍵“L”來控制,即按鍵盤“L”鍵時,用樑友棟-Barsky演算法裁剪程式視窗內的直線。同樣測試三種不同型別的直線,將測試結果存為圖4-6,,儲存至word實驗文件中(60分鐘);
(3) 整理圖1-6,並增加程式程式碼合併到一個word文件,將其命名為“序號-姓名-Prj2.doc”,電子版提交至雨課堂,A4列印稿下一次課前或實驗課前提交。
3.實驗原理:
示範程式碼中編碼裁剪演算法原理參見教材裁剪內容,有關滑鼠操作知識請參考OpenGL程式設計 基礎篇(四)與滑鼠的互動。
4.實驗程式碼:
#include <GL/glut.h> #include <stdio.h> #include <stdlib.h> #define LEFT_EDGE 1 #define RIGHT_EDGE 2 #define BOTTOM_EDGE 4 #define TOP_EDGE 8 struct Rectangle { float xmin, xmax, ymin, ymax; }; Rectangle rect; int x0, y0, x1, y1; bool bDrawLine = true; int width = 640, height = 480; void LineGL(int x0, int y0, int x1, int y1) { glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(x0, y0); glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(x1, y1); glEnd(); } //求p點的編碼 int CompCode(int x, int y, Rectangle rect) { int code = 0x00; if (y < rect.ymin) code = code | 4;//即為1000 if (y > rect.ymax) code = code | 8;//即為0100 if (x > rect.xmax) code = code | 2; if (x < rect.xmin) code = code | 1; return code; } bool cohensutherlandlineclip(Rectangle rect, int &x0, int & y0, int &x1, int &y1) { bool accept, done; float x, y; accept = false; done = false; int code0, code1, codeout; code0 = CompCode(x0, y0, rect); code1 = CompCode(x1, y1, rect); do { if (!(code0 | code1)) { accept = true; done = true; } else if (code0 & code1) done = true; else { if (code0 != 0) codeout = code0; else codeout = code1; if (codeout&LEFT_EDGE) { y = y0 + (y1 - y0)*(rect.xmin - x0) / (x1 - x0); x = (float)rect.xmin; } else if (codeout&RIGHT_EDGE) { y = y0 + (y1 - y0)*(rect.xmax - x0) / (x1 - x0); x = (float)rect.xmax; } else if (codeout&BOTTOM_EDGE) { x = x0 + (x1 - x0)*(rect.ymin - y0) / (y1 - y0); y = (float)rect.ymin; } else if (codeout&TOP_EDGE) { x = x0 + (x1 - x0)*(rect.ymax - y0) / (y1 - y0); y = (float)rect.ymax; } if (codeout == code0) { x0 = x; y0 = y; code0 = CompCode(x0, y0, rect); } else { x1 = x; y1 = y; code1 = CompCode(x1, y1, rect); } } } while (!done); return accept; } void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 1.0f, 0.0f); glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); if (bDrawLine) LineGL(x0, y0, x1, y1); glFlush(); } void Init() { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); rect.xmin = 100; //視窗的大小 rect.xmax = 300; rect.ymin = 100; rect.ymax = 300; x0 = 300, y0 = 50, x1 = 0, y1 = 450;//裁剪前的直線端點 printf("Press key 'c' to Clip!\n"); printf("Please Click left button of mouse to input the points of Line!!\n"); } void Reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'c': bDrawLine = cohensutherlandlineclip(rect, x0, y0, x1, y1); glutPostRedisplay();//重畫 break; case 'x': exit(0); break; default: break; } } void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { if(bDrawLine) { x0 = x; y0 = height - y; bDrawLine = false; glutPostRedisplay();// } else { x1 = x; y1 = height - y; bDrawLine = true; glutPostRedisplay();// } } break; default: break; } } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(width, height); glutCreateWindow("Hello World!"); Init(); glutDisplayFunc(myDisplay); glutReshapeFunc(Reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMainLoop(); return 0; }
5.實驗思考
實驗示範程式碼的第162行:
y0 = height - y;
請解釋這行程式碼的含義和作用。