CG实验4裁剪.docx
- 文档编号:9667261
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:13
- 大小:25KB
CG实验4裁剪.docx
《CG实验4裁剪.docx》由会员分享,可在线阅读,更多相关《CG实验4裁剪.docx(13页珍藏版)》请在冰豆网上搜索。
CG实验4裁剪
实验四裁剪
1.实验目的:
了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。
2.实验内容:
(1) 理解直线裁剪的原理(Cohen-Surtherland算法、梁友栋算法)
(2) 利用VC+OpenGL实现直线的编码裁剪算法,在屏幕上用一个封闭矩形裁剪任意一条直线。
(3) 调试、编译、修改程序。
3.实验原理:
编码裁剪算法的主要思想是:
对于每条线段,分为三种情况处理。
(1)若线段完全在窗口之内,则显示该线段,称为“取”;
(2)若线段明显在窗口之外,则丢弃该线段,称为“弃”;(3)若线段既不满足“取”的条件,也不满足“舍”的条件,则把线段分割为两段。
其中一段完全在窗口之外,可弃之;对另一段则重复上述处理。
算法中,为了快速判断一条直线段与矩形窗口的位置关系,采用了如图所示的空间划分和编码方案。
延长窗口的四条边界,把未经裁剪的图形区域分为九个区,每个区有一个四位二进制的编码,从左到右各位依次表示上、下、右、左。
例如,区号0101,左起第二位1表示该区在窗口的下方;右起第一位的1表示该区在窗口的左方。
整个区号表示该区在窗口的左下方。
裁剪一条线段时,先求出两端点所在的区号code1和code2,若code1=0且code2=0,则说明线段的两个端点均在窗口内,那么整条线段必在窗口内,应取之;若code1和code2经按位与运算的结果不为0,则说明两个端点同在窗口的上方、下方、左方或右方。
这种情况下,对线段的处理是弃之。
如果上述两种条件都不成立,则按第三种情况处理。
求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段完全在窗口外,可弃之,对另一段则重复上述处理。
4.实验代码:
#include
#include
#include
voidLineGL(intx0,int y0,intx1,inty1)
{
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f); glVertex2f(x0,y0);
glColor3f(0.0f,1.0f,0.0f); glVertex2f(x1,y1);
glEnd();
}
structoutcode
{
unsignedall;
unsignedleft,right,top,bottom;
};
structRectangle
{
floatxmin,xmax,ymin,ymax;
};
Rectangle rect;
intx0,y0,x1,y1;
GLbooleanbClip=false;
voidcompoutcode(floatx,floaty,Rectanglerect,outcode*outcode)
{
outcode->all=0;
outcode->top=outcode->bottom=0;
if(y>(float)rect.ymax)
{
outcode->top=1;
outcode->all+=1;
}
elseif(y<(float)rect.ymin)
{
outcode->bottom=1;
outcode->all+=1;
}
outcode->right=outcode->left=0;
if(x>(float)rect.xmax)
{
outcode->right=1;
outcode->all+=1;
}
elseif(x<(float)rect.xmin)
{
outcode->left=1;
outcode->all+=1;
}
}
intcohensutherlandlineclip(Rectangle rect,int&x0,int&y0,int&x1,int&y1)
{
intaccept,done;
outcodeoutcode0,outcode1;
outcode*outcodeout;
floatx,y;
accept=0;
done=0;
compoutcode(x0,y0,rect,&outcode0);
compoutcode(x1,y1,rect,&outcode1);
do{
if(outcode0.all==0&&outcode1.all==0)
{
accept=1;
done=1;
}
elseif(outcode0.all&outcode1.all!
=0)
done=1;
else
{
if(outcode0.all!
=0)
outcodeout=&outcode0;
else
outcodeout=&outcode1;
if(outcodeout->left)
{
y=y0+(y1-y0)*(rect.xmin-x0)/(x1-x0);
x=(float)rect.xmin;
}
elseif(outcodeout->top)
{
x=x0+(x1-x0)*(rect.ymax-y0)/(y1-y0);
y=(float)rect.ymax;
}
elseif(outcodeout->right)
{
y=y0+(y1-y0)*(rect.xmax-x0)/(x1-x0);
x=(float)rect.xmax;
}
elseif(outcodeout->bottom)
{
x=x0+(x1-x0)*(rect.ymin-y0)/(y1-y0);
y=(float)rect.ymin;
}
if(outcodeout->all==outcode0.all)
{
x0=x;y0=y;compoutcode(x0,y0,rect,&outcode0);
}
else
{
x1=x;y1=y;
compoutcode(x1,y1,rect,&outcode1);
}
}
}while(!
done);
if(accept)
LineGL(x0,y0,x1,y1);
returnaccept;
}
voidmyDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f);
glRectf(rect.xmin,rect.ymin,rect.xmax,rect.ymax);
if(!
bClip)
LineGL(x0,y0,x1,y1);
else
cohensutherlandlineclip(rect,x0,y0,x1,y1);
glFlush();
}
voidInit()
{
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("Presskey'c'toClip!
\nPresskey'r'toRestore!
\n");
}
voidReshape(intw,inth)
{
glViewport(0,0,(GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);
}
voidkeyboard(unsignedcharkey,intx,inty)
{
switch(key)
{
case'c':
bClip=true;
glutPostRedisplay();//重画
break;
case'r':
bClip=false;
Init();
glutPostRedisplay();//
break;
case'x':
exit(0);
break;
default:
break;
}
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,480);
glutCreateWindow("HelloWorld!
");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return0;
}
5.实验思考题
请分别给出直线的三种不同位置情况,测试实验代码是否存在问题,有的话请调试改正。
可能的话,可以尝试实现梁友栋裁剪算法。
#include
#include
#include
voidLineGL(intx0,inty0,intx1,inty1)
{
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);glVertex2f(x0,y0);
glColor3f(0.0f,1.0f,0.0f);glVertex2f(x1,y1);
glEnd();
}
structoutcode
{
unsignedall;
unsignedleft,right,top,bottom;
};
structRectangle
{
floatxmin,xmax,ymin,ymax;
};
structRectanglerect;
intx0,y0,x1,y1;
intbClip=0;
voidcompoutcode(floatx,floaty,structRectanglerect,structoutcode*outcode)
{
outcode->all=0;
outcode->top=outcode->bottom=0;
if(y>(float)rect.ymax)
{
outcode->top=1;
outcode->all+=1;
}
elseif(y<(float)rect.ymin)
{
outcode->bottom=1;
outcode->all+=1;
}
outcode->right=outcode->left=0;
if(x>(float)rect.xmax)
{
outcode->right=1;
outcode->all+=1;
}
elseif(x<(float)rect.xmin)
{
outcode->left=1;
outcode->all+=1;
}
}
intcohensutherlandlineclip(structRectanglerect,intx0,inty0,intx1,inty1)
{
intaccept,done;
structoutcodeoutcode0,outcode1;
structoutcode*outcodeout;
floatx,y;
accept=0;
done=0;
compoutcode(x0,y0,rect,&outcode0);
compoutcode(x1,y1,rect,&outcode1);
do{
if(outcode0.all==0&&outcode1.all==0)
{
accept=1;
done=1;
}
elseif(outcode0.all&outcode1.all!
=0)
done=1;
else
{
if(outcode0.all!
=0)
outcodeout=&outcode0;
else
outcodeout=&outcode1;
if(outcodeout->left)
{
y=y0+(y1-y0)*(rect.xmin-x0)/(x1-x0);
x=(float)rect.xmin;
}
elseif(outcodeout->top)
{
x=x0+(x1-x0)*(rect.ymax-y0)/(y1-y0);
y=(float)rect.ymax;
}
elseif(outcodeout->right)
{
y=y0+(y1-y0)*(rect.xmax-x0)/(x1-x0);
x=(float)rect.xmax;
}
elseif(outcodeout->bottom)
{
x=x0+(x1-x0)*(rect.ymin-y0)/(y1-y0);
y=(float)rect.ymin;
}
if(outcodeout->all==outcode0.all)
{
x0=x;y0=y;compoutcode(x0,y0,rect,&outcode0);
}
else
{
x1=x;y1=y;
compoutcode(x1,y1,rect,&outcode1);
}
}
}while(!
done);
if(accept)
LineGL(x0,y0,x1,y1);
returnaccept;
}
voidmyDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f);
glRectf(rect.xmin,rect.ymin,rect.xmax,rect.ymax);
if(!
bClip)
LineGL(x0,y0,x1,y1);
else
cohensutherlandlineclip(rect,x0,y0,x1,y1);
glFlush();
}
voidInit()
{
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("Presskey'c'toClip!
\nPresskey'r'toRestore!
\n");
}
voidReshape(intw,inth)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);
}
voidkeyboard(unsignedcharkey,intx,inty)
{
switch(key)
{
case'c':
bClip=1;
glutPostRedisplay();//重画
break;
case'r':
bClip=0;
Init();
glutPostRedisplay();//
break;
case'x':
exit(0);
break;
default:
break;
}
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,480);
glutCreateWindow("HelloWorld!
");
Init();
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return0;
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- CG 实验 裁剪