线段的编码裁减

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

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

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

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

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

#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
float ymin=100; 
int ymax=300;
int xmin=100; 
int xmax=300;
struct Linea{
	int x0;
	int y0;
	int x1;
	int y1;
};              
Linea l1={l1.x0=450,l1.y0=0,l1.x1=0,l1.y1=450};
Linea l2={l2.x0=450,l2.y0=200,l2.x1=0,l2.y1=200};    
Linea l3={l3.x0=200,l3.y0=0,l3.x1=200,l3.y1=450};
void LineGL(Linea &li){
	glBegin(GL_LINES);		
	glVertex2f(li.x0,li.y0);
    glVertex2f(li.x1,li.y1);
	if((li.x0+li.x1)/2==225&&(li.y0+li.y1)/2==225)
		glColor3f(1.0f,0.0f,1.0f);
	else
		glColor3f(1.0f,1.0f,0.0f);
	glEnd();
}//决定整个图元的颜色
int CompCode(int x,int y){   
	int code=0x00;	//此处是二进制
	if(y<ymin)     code=code|4;                   
	if(y>ymax)     code=code|8;
	if(x>xmax)     code=code|2;                   
	if(x<xmin)     code=code|1;     
	return code;
}
int cohensutherlandlineclip(Linea &li){ 
	int accept=0,done=0; 
	float x=0,y=0; 
	int total=0,flag=0;//total与flag是标志
	int code0,code1,codeout;   
	code0=CompCode(li.x0,li.y0);   //printf("code0=%d\n",code0);
	code1=CompCode(li.x1,li.y1);   //printf("code1=%d\n",code1);
	do{
		if(!(code0|code1))		//code0&code1=0000B,线段完全在窗口内部,全部显示
		{      
			accept=1;       
			done=1;    
		}
		else if(code0 & code1){      
			done=1;     
			flag=1;  
		}			
		else{   
			if(code0!=0)    
				codeout=code0;
			else      
				codeout=code1;
		if(codeout&LEFT_EDGE){
			y=li.y0+(li.y1-li.y0)*(xmin-li.x0)/(li.x1-li.x0);      
			x=(float)xmin;   
		}
		else if(codeout&RIGHT_EDGE){	
			y=li.y0+(li.y1-li.y0)*(xmax-li.x0)/(li.x1-li.x0); 
			x=(float)xmax;
		}
		else if(codeout&BOTTOM_EDGE){ 
			x=li.x0+(li.x1-li.x0)*(ymin-li.y0)/(li.y1-li.y0);    
			y=(float)ymin;
		}
		else if(codeout&TOP_EDGE){
			x=li.x0+(li.x1-li.x0)*(ymax-li.y0)/(li.y1-li.y0);    
			y=(float)ymax;
		}
		if(codeout==code0){
			li.x0=x;	
			li.y0=y;   
			code0=CompCode(li.x0,li.y0);
		}
		else{ 
			li.x1=x;	
			li.y1=y;        
			code1=CompCode(li.x1,li.y1);
		}     
		total++;   
		if(total>3){
			done=1;	
			flag=1;
		}
	}	
}
	while(!done);
	if(accept)		//线段位于窗口内或者线段剪裁过accept=1;
	{
		LineGL(li);
	}	
	else{
		li.x0=0;
		li.y0=0;
		li.x1=0;
		li.y1=0;  
		LineGL(li); 
	}	
	return accept; 
	}
void myDisplay(){
	glClear(GL_COLOR_BUFFER_BIT);  
	glColor3f(0.0f,1.0f,1.0f);   
	glBegin(GL_LINE_LOOP);
	glVertex2f(100,100);  
	glVertex2f(300,100);   
	glVertex2f(300,300);  
	glVertex2f(100,300);   
	glEnd();
	LineGL(l1); 
	LineGL(l2);   
	LineGL(l3);  
	glFlush();
}
void Init(){ 
	glClearColor(0.0,0.0,0.0,0.0);
	glShadeModel(GL_FLAT);
	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(l1);    
	cohensutherlandlineclip(l2);
	cohensutherlandlineclip(l3);   
	glutPostRedisplay();    
	break;
case 'r':
	l1.x0=450;l1.y0=0;l1.x1=0;l1.y1=450; 
	l2.x0=450;l2.y0=200;l2.x1=0;l2.y1=200;
	l3.x0=200;l3.y0=0;l3.x1=200;l3.y1=450; 
	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("编码裁剪"); 
	Init();
	glutDisplayFunc(myDisplay);   
    glutReshapeFunc(Reshape);
	glutKeyboardFunc(&keyboard);
	glutMainLoop();  
    return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_34195441/article/details/79122287