本博客计算机图形学系列文章索引:
参考教材:《计算机图形学》 机械工业出版社 ,徐文鹏主编
实验内容:利用Cohen-Sutherland编码裁剪算法,用矩形框裁剪直线。
实验代码如下(已调试过):
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glut32.lib" )
#define LEFT_EDGE 1
#define RIGHT_EDGE 2
#define BOTTOM_EDGE 4
#define TOP_EDGE 8
static int times=1;
//画从(x0,y0)到(x1,y1)的直线
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();
}
//矩形的结构体
typedef struct Rectangle
{
float xmin;
float xmax;
float ymin;
float ymax;
} Rectan;
Rectan rect;
int x0,y0,x1,y1;
//求出坐标点的Cohen-Sutherland编码
int CompCode(int x,int y,Rectan 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(Rectan rect,int& x0,int& y0,int& x1,int& y1)
{
int accept=0,done=0;
float x,y;
int code0,code1,codeout;
int x00 = x0,y00 = y0,x11 = x1,y11 = y1;
code0= CompCode(x0,y0,rect);
code1= CompCode(x1,y1,rect);
//直线全部在矩形框内部,应保留
if (!(code0 | code1))
{
accept=1;
done=1;
}
//直线和矩形不相交,并且划直线的两点在矩形同侧(上、下、右。左),应去掉。
if( code0 & code1 )
{
done=1;
}
while(!done)
{
//直线和矩形有交点,只保留矩形内部的
if (!(code0 | code1))
{
accept=1;
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=y0+(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);
}
//直线和矩形不相交,但是划直线的两点在矩形不同侧,这时应去掉。
if((times<=3) && (code0 & code1))
{
x0=x1;
y0=y1;
done=1;
accept=1;
}
}
}
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=0;
y0=650;
x1=650;
y1=0;
}
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);
}
//按键盘上字母c裁剪,字母r恢复原状,字母x退出。
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("裁剪");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
实验结果(修改不同的(x0,y0)和(x1,y1)可得到):