OPENGL—編碼裁剪(Cohen-Sutherland)法裁剪圖
阿新 • • 發佈:2019-01-02
//編碼裁剪(Cohen-Sutherland)法裁剪圖 #include"stdafx.h" #include<Gl/glut.h> #include <process.h> class wcPt2D { public: float x, y; }; const int winLeftBitCode = 0x1; const int winRightBitCode = 0x2; const int winBottomBitCode = 0x4; const int winTopBitCode = 0x8; GLubyte encode(wcPt2D pt, wcPt2D winMin, wcPt2D winMax) { //進行編碼 GLubyte code = 0x00; if (pt.x < winMin.x) //D0=1,否則為0 code = code | winLeftBitCode; if (pt.x > winMax.x) //D1=1,否則為0 code = code | winRightBitCode; if (pt.y < winMin.y) //D2=1,否則為0 code = code | winBottomBitCode; if (pt.y > winMax.y) //D3=1,否則為0 code = code | winTopBitCode; return (code); } inline int inside(int code) { //在內部,inside=1 return int(!code); } inline int reject(int code1, int code2) { //code1&code2不等於0,“簡棄”,reject=true return int(code1 & code2); } inline int accept(int code1, int code2) { //code1|code2等於0,“簡取”,accept=true return int(!(code1 | code2)); } void swapPts(wcPt2D *p1, wcPt2D *p2) { //交換座標值 wcPt2D tmp; tmp = *p1; *p1 = *p2; *p2 = tmp; } void swapCodes(GLubyte *c1, GLubyte *c2) { //交換編碼 GLubyte tmp; tmp = *c1; *c1 = *c2; *c2 = tmp; } void lineClip(wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2) //裁剪 { GLubyte code1, code2; int done = false, plotLine = false; float m; while (!done) //保證用新的P1P2重新進行計算 { code1 = encode(p1, winMin, winMax); //對p1、p2進行編碼,分別為code1、code2 code2 = encode(p2, winMin, winMax); if (accept(code1, code2)) //對直線P1P2“簡取”之 { done = true; plotLine = true; } else if (reject(code1, code2)) //對直線P1P2“簡棄”之 { done = true; } else //否則 { if (inside(code1)) //若P1在視窗內,則交換P1和P2的座標值和編碼 { swapPts(&p1, &p2); swapCodes(&code1, &code2); } //判斷P1在視窗外哪一側,然後求出兩者的交點,並用交點的值替代P1的座標值,以達到去掉P1S線段的目的 if (p2.x != p1.x) m = (p2.y - p1.y) / (p2.x - p1.x); if (code1 & winLeftBitCode) { p1.y += (winMin.x - p1.x) * m; p1.x = winMin.x; } else if (code1 & winRightBitCode) { p1.y += (winMax.x - p1.x) * m; p1.x = winMax.x; } else if (code1 & winBottomBitCode) { if (p2.x != p1.x) p1.x += (winMin.y - p1.y) / m; p1.y = winMin.y; } else if (code1 & winTopBitCode) { if (p2.x != p1.x) p1.x = (winMax.y - p1.y) / m; p1.y = winMax.y; } } } //重新繪製當前的直線段P1P2 if (plotLine) glBegin(GL_LINES); glColor3f(1, 0, 0); glVertex2f(p1.x, p1.y); glVertex2f(p2.x, p2.y); glEnd(); } void drawpolygon(double cd[]) { glBegin(GL_LINE_LOOP); //繪製直線 glLineWidth(10); for (int i = 0; i < 8; i = i + 2) { glVertex2f(cd[i], cd[i + 1]); } glEnd(); } void drawline(double cd[]) { glBegin(GL_LINES); //繪製點 glLineWidth(10); for (int i = 0; i < 8; i = i + 2) { glVertex2f(cd[i], cd[i + 1]); } glEnd(); } void myKeyBoard(unsigned char key, int x, int y) //處理按鍵資訊 { wcPt2D winMin = {200, 200}; wcPt2D winMax = {400, 400}; wcPt2D p1 = {100, 0}; wcPt2D p2 = {500, 500}; if (key == 13) //按下Enter鍵 lineClip(winMin, winMax, p1, p2); glFlush(); if (key == 27) //按下ESC鍵 exit(0); } void display(void) { double re[8] = {200, 200, 400, 200, 400, 400, 200, 400}; //按照比例輸出 double line[4] = {100,0 , 500, 500}; glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, 600, 600); glColor3f(0, 0, 0); //繪製 drawpolygon(re); drawline(line); glFlush(); } int main(int argc, char **argv) { //初始化 glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RED); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow("Cohen-Sutherland演算法"); glClearColor(1, 1, 1, 0.0); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, 600.0, 0.0, 600.0); glutKeyboardFunc(myKeyBoard); //鍵盤輸入控制 glutDisplayFunc(display); glutMainLoop(); return 0; }
執行結果: