图形学实验四线段裁剪算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QQQZSJ/article/details/83590226

实验四  线段裁剪算法

实验类型:设计型   实验学时:2实验要求:必修

一、实验目的

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

二、实验内容

1 理解直线裁剪的原理(编码裁剪算法、梁友栋算法)

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

3 交互实现直线段的裁剪。

三、实验原理

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

 

图3   直线裁剪分区编码图

基础:

 

升级1

 

 

 

 

 

按 c 裁剪,并且按 r 要恢复到原形状

 

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

四、实验示范代码(略)

五、实验步骤

1 在Windows xp/win7操作环境下,启动VC;

2 建立W32 Console Application 的应用工程;

3 建立源程序编辑环境,进行编辑源程序。

4 调试运行程序,完成实验。

六、实验结果处理

演示结果并保存相关文件。

七、实验注意事项

注意编程环境的配置,即在Windows环境下,OpenGL扩展库相关文件的配置,把头文件“GL.H”、库文件“OPENGL32.LIB”和动态链接库“OPENGL32.DLL”配置到相应的目录下。

八、预习与思考题

预习:阅读课本相关内容,仔细阅读示范代码。

思考题:如何实现横平竖直线段的裁剪。

九、实验报告要求

1、实验报告中应包括相关操作步骤和程序代码和运行效果截图。

2.书写实验报告时要结构合理,层次分明,在分析描述的时候,需要注意语言的流畅。

 基础代码:


#include<stdio.h>
#include<stdlib.h>
#include<GL/glut.h>


#define LEFT_EDGE 1
#define RIGHT_EDGE 2
#define BOTTOM_EDGE 4
#define TOP_EDGE 8


int x0,y0,x1,y1;

void LineGL(int x0,int y0,int x1,int y1)
{
	glBegin(GL_LINES);
	glColor3f(1.0,0.0,0.0); glVertex2f(x0,y0);
	glColor3f(0.0,1.0,0.0); glVertex2f(x1,y1);	
	glEnd();
}

struct Rectangle
{
	float xmin,xmax,ymin,ymax;
};

Rectangle rect;



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;
	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.0,0.0,0.0);
		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!\n");
		printf("Press 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;
}

#include<stdio.h>
#include<stdlib.h>
#include<GL/glut.h>


#define LEFT_EDGE 1
#define RIGHT_EDGE 2
#define BOTTOM_EDGE 4
#define TOP_EDGE 8


int x0,y0,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5;

void LineGL(int x0,int y0,int x1,int y1)
{
	glBegin(GL_LINES);
	glVertex2f(x0,y0);
	glVertex2f(x1,y1);	
	glEnd();
}

struct Rectangle
{
	float xmin,xmax,ymin,ymax;
};

Rectangle rect;



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;
	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.0,0.0,0.0);
		glBegin(GL_LINE_LOOP);
		glVertex2f(rect.xmin,rect.ymax);
		glVertex2f(rect.xmax,rect.ymax);
		glVertex2f(rect.xmax,rect.ymin);
		glVertex2f(rect.xmin,rect.ymin);
		glEnd();

		glColor3f(0.0,1.0,0.0);LineGL(x0,y0,x1,y1);
		glColor3f(1.0,0.0,1.0);LineGL(x2,y2,x3,y3);
		glColor3f(1.0,1.0,1.0);LineGL(x4,y4,x5,y5);
	
		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,x2=0,y2=200,x3=450,y3=200,x4=200,y4=400,x5=200,y5=10;
		printf("Press key 'c' to Clip!\n");
		printf("Press 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);
			cohensutherlandlineclip(rect, x2,y2,x3,y3);
			cohensutherlandlineclip(rect, x4,y4,x5,y5);
			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;
}

结果即为实验要求!

不在展示。 

猜你喜欢

转载自blog.csdn.net/QQQZSJ/article/details/83590226