實驗4 編碼裁剪算法


 

1.實驗目的:

了解二維圖形裁剪的原理(點的裁剪、直線的裁剪、多邊形的裁剪),利用VC+OpenGL實現直線的裁剪算法。

2.實驗內容:

(1) 理解直線裁剪的原理(Cohen-Surtherland算法、梁友棟算法)

(2) 利用VC+OpenGL實現直線的編碼裁剪算法,在屏幕上用一個封閉矩形裁剪任意一條直線。

(3) 調試、編譯、修改程序。

(4) 嘗試實現梁友棟裁剪算法。

3.實驗原理:

編碼裁剪算法中,為了快速判斷一條直線段與矩形窗口的位置關系,采用了如圖A.4所示的空間划分和編碼方案。

clip_image002

圖A.4 裁剪編碼

裁剪一條線段時,先求出兩端點所在的區號code1和code2,若code1 = 0且code2 = 0,則說明線段的兩個端點均在窗口內,那么整條線段必在窗口內,應取之;若code1和code2經按位與運算的結果不為0,則說明兩個端點同在窗口的上方、下方、左方或右方。這種情況下,對線段的處理是棄之。如果上述兩種條件都不成立,則按第三種情況處理。求出線段與窗口某邊的交點,在交點處把線段一分為二,其中必有一段完全在窗口外,可棄之,對另一段則重復上述處理。

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

void LineGL(int x0,int y0,int x1,int y1)

{

glBegin (GL_LINES);

glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (x0,y0);

glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (x1,y1);

glEnd ();

}

struct Rectangle

{

float xmin,xmax,ymin,ymax;

};

Rectangle rect;

int x0,y0,x1,y1;

int CompCode(int x,int y,Rectangle rect)

{

int code=0x00;

if(y<rect.ymin)

code=code|4;

if(y>rect.ymax)

code=code|8;

if(x>rect.xmax)

code=code|2;

if(x<rect.xmin)

code=code|1;

return code;

}

int cohensutherlandlineclip(Rectangle rect, int &x0,int & y0,int &x1,int &y1)

{

int accept,done;

float x,y;

accept=0;

done=0;

int code0,code1, codeout;

code0 = CompCode(x0,y0,rect);

code1 = CompCode(x1,y1,rect);

do{

if(!(code0 | code1))

{

accept=1;

done=1;

}

else if(code0 & code1)

done=1;

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);

if(accept)

LineGL(x0,y0,x1,y1);

return accept;

}

void myDisplay()

{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f (1.0f, 0.0f, 0.0f);

glRectf(rect.xmin,rect.ymin,rect.xmax,rect.ymax);

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 = 450,y0 = 0, x1 = 0, y1 = 450;

printf("Press key 'c' to Clip!\nPress key 'r' to Restore!\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':

cohensutherlandlineclip(rect, x0,y0,x1,y1);

glutPostRedisplay();

break;

case 'r':

Init();

glutPostRedisplay();

break;

case 'x':

exit(0);

break;

default:

break;

}

}

int main(int argc, char *argv[])

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

glutInitWindowPosition(100, 100);

glutInitWindowSize(640, 480);

glutCreateWindow("Hello World!");

Init();

glutDisplayFunc(myDisplay);

glutReshapeFunc(Reshape);

glutKeyboardFunc(keyboard);

glutMainLoop();

return 0;

}

  附上本實驗的VC++工程代碼(VC++2008)

5.實驗提高

請分別給出直線的三種不同位置情況,測試實驗代碼是否存在問題,有的話請調試改正。可能的話,可以嘗試實現梁友棟裁剪算法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM