计算机图形学(3.1)——编码裁剪算法实现

这是一次计算机图形学实验的报告

1. 实验目的

了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。

2. 实验内容

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

2) 利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。

3) 调试、编译、修改程序。

4) 尝试实现梁友栋裁剪算法。

3. 实验原理

编码裁剪算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图A.4所示的空间划分和编码方案。

计算机图形学(3.1)——编码裁剪算法实现_第1张图片

A.4 裁剪编码

裁剪一条线段时,先求出两端点所在的区号code1和code2,若code1 = 0且code2 = 0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之;若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上方、下方、左方或右方。这种情况下,对线段的处理是弃之。如果上述两种条件都不成立,则按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理。

3. 实验代码

(1)示例程序:

// CG_4_编码裁剪算法.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include 

#include 

#include 

 

#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

code=code|4;

if(y>rect.ymax)

code=code|8;

if(x>rect.xmax)

code=code|2;

if(x

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;

}

 

示例程序运行结果:

第一种情况:线段穿过裁剪窗口

x0=450,y0=0,x1=0,y1=450;    //设置线段的两个端点坐标
计算机图形学(3.1)——编码裁剪算法实现_第2张图片

“c”裁剪:

计算机图形学(3.1)——编码裁剪算法实现_第3张图片 

第二种情况:线段的两个端点,一个在裁剪窗口中,另一个在裁剪窗口外

x0=200,y0=0,x1=200,y1=200;   //设置线段的两个端点坐标

计算机图形学(3.1)——编码裁剪算法实现_第4张图片
“c”裁剪:
计算机图形学(3.1)——编码裁剪算法实现_第5张图片

你可能感兴趣的:(计算机图形学(3.1)——编码裁剪算法实现)