实验报告文档.docx
- 文档编号:29062063
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:23
- 大小:149.46KB
实验报告文档.docx
《实验报告文档.docx》由会员分享,可在线阅读,更多相关《实验报告文档.docx(23页珍藏版)》请在冰豆网上搜索。
实验报告文档
中南民族大学
学生实验报告
院系:
计算机科学学院
专业:
软件工程
年级:
2011级
课程名称:
计算机图形学
组号:
37组
组员:
向杨辉、蒙德亮、王鸿儒
指导教师:
孙阳光
2013年11月22日
年级
2011级
学号
11065118
11065120
11065124
专业
软件工程
姓名
向杨辉
蒙德亮
王鸿儒
实验时间
10.30
实验地点
9-206
实验
名称
1直线的扫描转换
实验
类型
设计型
综合型
创新型
√
实
验
目
的
或
要
求
1.实验内容
用基本增量算法和Bresenham算法画直线
2.实验目的
1)理解在显示器上画图与在纸上画图的本质区别;
2)掌握直线的光栅扫描转换过程;
3)掌握不同算法绘制直线的思路和优缺点
3.实验要求
1)将像素网格表现出来,建立网格坐标系;
2)用橡皮筋的形式输入参数;
3)鼠标移动时,显示鼠标当前位置;
4)显示判别式的计算过程和下一点的选择策略;
5)记录生成点的坐标,建议用表的形式;
6)图形生成过程可以重复进行。
4.详细设计
算法原理(DDA)
根据直线方程y=kx+b,由两个直线的端点(x0,y)(x1y1)可求得斜率k。
可以将变量x设定初值为x0,y初值y0。
每次x步进1,同时使y步进k,可获得表示直线的所有近似的结果集。
该方法简单,但是每次循环都要做一次乘法、一次加法并调用一次对y的取整运算,因此效率比较低。
实
验
原
理
DDA算法画线(关键代码):
voidDDACreateLine(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)
{
//设置颜色
glColor3f(0.0f,0.0f,1.0f);
//对画线动画进行控制
if(num==1)
printf("DDA画线算法:
各点坐标\n");
elseif(num==0)
return;
//画线算法的实现
GLsizeidx,dy,epsl,k;
GLfloatx,y,xIncre,yIncre;
dx=x1-x0;
dy=y1-y0;
x=x0;
y=y0;
if(abs(dx)>abs(dy))epsl=abs(dx);
elseepsl=abs(dy);
xIncre=(float)dx/epsl;
yIncre=(float)dy/epsl;
for(k=0;k<=epsl;k++){
putpixel((int)(x+0.5),(int)(y+0.5));
if(k>=num-1){
printf("x=%f,y=%f,取整后x=%d,y=%d\n",x,y,(int)(x+0.5),(int)(y+0.5));
break;
}
x+=xIncre;
y+=yIncre;
if(x>=25||y>=25)break;
}
}
算法原理(Bresenham):
过各行各列象素中心构造一组虚拟网格线。
按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列象素中与此交点最近的象素。
该算法的巧妙之处在于采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列的所求象素。
Bresenham算法画线(关键代码):
voidLine(GLsizeix0,GLsizeiy0,GLsizeix1,GLsizeiy1,GLsizeinum)
{
glColor3f(1.0f,0.0f,0.0f);
if(num==1)
{
printf("中点Bresenham算法画直线:
各点坐标及判别式的值\n");
}
elseif(num==0)
return;
//中点Bresenham划线算法的实现
GLsizeidx,dy,d,UpIncre,DownIncre,x,y;
if(x0>x1){
x=x1;x1=x0;x0=x;
y=y1;y1=y0;y0=y;
}
x=x0;y=y0;
dx=x1-x0;dy=y1-y0;
d=dx-2*dy;
UpIncre=2*dx-2*dy;DownIncre=-2*dy;
while(x<=x1)
{
putpixel(x,y);
printf("x=%d,y=%d\n",x,y);
x++;
if(d<0)
{
y++;
d+=UpIncre;
}
else
d+=DownIncre;
}
}
实
验
结
果
分
析
以下为画直线的过程:
显示各点坐标值:
年级
2011级
学号
11065118
11065120
11065124
专业
软件工程
姓名
向杨辉
蒙德亮
王鸿儒
实验时间
11.6
实验地点
9-206
实验
名称
2圆弧的扫描转换
实验
类型
设计型
综合型
创新型
√
实
验
目
的
或
要
求
1.实验内容
用正负法和Bresenham算法画圆弧
2.实验目的
1)掌握圆及圆弧的光栅扫描转换过程;
2)掌握不同算法绘制圆弧的技巧和优缺点。
3.实验要求
1)将像素网格表现出来,建立网格坐标系;
2)用橡皮筋的形式输入参数;
3)鼠标移动时,显示鼠标当前位置;
4)显示判别式的计算过程和下一点的选择策略;
5)记录生成点的坐标,建议用表的形式;
6)图形生成过程可以重复进行。
4.详细设计
设要显示圆的圆心在原点(0,0),半径为R,初始点的坐标为(0,R),顺时针生成八分之一圆,令:
F(x,y)=x2+y2-R2
则圆的方程为:
F(x,y)=0
当点(x,y)在圆内时,则F(x,y)<0;
当点(x,y)在圆外时,则F(x,y)>0;
实
验
原
理
当点(x,y)在圆上时,则F(x,y)=0;
正负法:
利用平面曲线将平面划分成正负区域,对当前点产生的圆函数进行符号判别,利用负反馈调整以决定下一个点的产生来直接生成圆弧。
假设当前点为Pi(xi,yi),取下一个点Pi+1(xi+1,yi+1)的原则是:
1、当F(xi,yi)≤0时:
取xi+1=xi+1,yi+1=yi。
即向右走一步,从圆内走向圆外。
对应图(a)中的从Pi到Pi+1。
2、当F(xi,yi)>0时:
取xi+1=xi,yi+1=yi-1。
即向下走一步,从圆外走向圆内。
对应图(b)中的从Pi到Pi+1。
由于向圆内或向圆外走取决于F(xi,yi)的正负,因此称为正负法
给象素坐标(x,y)及F赋初始值后,进入循环画点;
画点后,根据F的符号进行F值的递推和下一个点的获取,直到x>y为止。
同前面介绍的一样,利用圆的八分对称性,循环一次,画八个点。
正负法画圆:
voidcircle(intx0,inty0,intr,intcolor){
intx=0,y=r,f=0;
while(x<=y){
putdot(x0,y0,x,y,color);
if(f<=0)
{
f=f+2*x+1;
x++;}
else
{
f=f-2*y+1;
y--;
}
}
}
Bresenham算法:
它的思想在于用误差量来衡量点选取的逼近程度。
其过程如下:
以平面二维图形的扫描转换为例,设要画的图形方程为F(x,y)=0,要画的区域为[x0,x](不妨设x方向是最大位移方向,即△x> △y),则F(x,y) 也是一个误差度量函数,我们拿离散的点值代入如果大于0则正向偏离,否则负向偏离,等于0的情况比较少,它表示的是不偏离即恰好与真实点重合。
既然x是最大位移方向,那每次对x自增1,相应的y可以选择不增或增1(或-1,具体问题具体分析),选择的方法就是d=F(x+1,y ± 0.5)的正负情况进行判断从而选择y的值。
实际情况中还要考虑到浮点数的计算问题,因为基本的图形扫描转换算法最好能够硬件实现,所以摆脱浮点数是最好的,常用的方法是对d进行递推,而不是直接由F(x,y)给出(直接给出速度会慢)
Bresenham算法画圆:
voidCircle(GLsizeix,GLsizeiy,GLsizeiR,GLsizeinum){
glColor3f(0.0f,0.0f,1.0f);
if(num==1)
printf("Bresenham算法画圆:
各点坐标及判别式的值\n");
intd,k=0,xa,ya;
xa=0;ya=R;d=1-R;
while(xa<=ya){
putpixel(xa+x,ya+y);
putpixel(ya+x,xa+y);
putpixel(-ya+x,xa+y);
putpixel(-xa+x,ya+y);
putpixel(-xa+x,-ya+y);
putpixel(-ya+x,-xa+y);
putpixel(ya+x,-xa+y);
putpixel(xa+x,-ya+y);
if(k>=num-1){
printf("x=%d,y=%d\n",xa+x,ya+y);
break;}
k++;
if(d<0)d+=2*xa+3;
else{
d+=2*(xa-ya)+5;
ya--;
}
xa++;
}
}
实
验
结
果
分
析
显示所作图形:
各点坐标显示:
年级
2011级
学号
11065118
11065120
11065124
专业
软件工程
姓名
向杨辉
蒙德亮
王鸿儒
实验时间
11.13
实验地点
9-206
实验
名称
3直线段的裁剪
实验
类型
设计型
综合型
创新型
√
实
验
目
的
或
要
求
1.实验内容
用Cohen-SutherLand算法和liang_barsky算法进行线段裁剪
2.实验目的
1)理解裁剪的相关概念
2)掌握直线段的一般裁剪过程;
3)理解并掌握Cohen-SutherLand算法的编码思想;
4)理解并掌握Liang_Barsky算法的参数化裁剪思想;
3.实验要求
1)将像素网格表现出来,建立网格坐标系;
2)用橡皮筋的形式输入剪裁线段和裁剪窗口;
3)鼠标移动时,显示鼠标当前位置;
4)对于线段裁剪,线段被窗口的四条边裁剪的过程要显示出来;
5)裁剪过程可以重复进行。
实
验
原
理
4.详细设计
Cohen-Sutherland算法
首先对线段的两个端点按所在的区域进行分区编码,根据编码可以迅速地判明全部在窗口内的线段和全部在某边界外侧的线段。
只有不属于这两种情况的线段,才需要求出线段与窗口边界的交点,求出交点后,舍去窗外部分。
对剩余部分,把它作为新的线段看待,又从头开始考虑。
两遍循环之后,就能确定该线段是部分截留下来,还是全部舍弃。
1、分区编码
延长裁剪边框将二维平面分成九个区域,每个区域各用一个四位二进制代码标识。
各区代
码值如图中所示。
2、判别
根据C1和C2的具体值,可以有三种情况:
(1)C1=C2=0,表明两端点全在窗口内,因而整个线段也在窗内,应予保留。
(2)C1&C2≠0(两端点代码按位作逻辑乘不为0),即C1和C2至少有某一位同时为1,表明两端点必定处于某一边界的同一外侧,因而整个线段全在窗外,应予舍弃。
(3)不属于上面两种情况,均需要求交点。
3、求交点
假设算法按照:
左、右、下、上边界的顺序进行求交处理,对每一个边界求完交点,并相关处理后,算法转向第2步,重新判断,如果需要接着进入下一边界的处理。
为了规范算法,令线段的端点P1为外端点,如果不是这样,就需要P1和P2交换端点。
当条件(C1&0001≠0)成立时,表示端点P1位于窗口左边界外侧,按照前面介绍的求交公式,进行对左边界的求交运算。
依次类推,对位于右、下、上边界外侧的判别,应将条件式中的0001分别改为0010、0100、1000即可。
求出交点P后,用P1=P来舍去线段的窗外部分,并对P1重新编码得到C1,接下来算法转回第2步继续对其它边界进行判别。
Cohen-Sutherland裁剪算法:
voidClip(floatx0,floaty0,floatx1,floaty1,Rect*rect,CDC*pDC){
boolaccept,done;
accept=FALSE;
done=FALSE;
OutCodecode0,code1;
OutCode*outCode;
floatx,y;
CompOutCode(x0,y0,rect,&code0);
CompOutCode(x1,y1,rect,&code1);
do{
if(code0.all==0&&code1.all==0){
accept=TRUE;
done=TRUE;
}elseif((code0.all&code1.all)!
=0){
done=TRUE;
}else{
if(code0.all!
=0){
outCode=&code0;
}else{
outCode=&code1;
}
if(outCode->left){
y=y0+(y1-y0)*(rect->xmin-x0)/(x1-x0);
x=(float)rect->xmin;
}elseif(outCode->top){
x=x0+(x1-x0)*(rect->ymax-y0)/(y1-y0);
y=(float)rect->ymax;
}elseif(outCode->right){
y=y0+(y1-y0)*(rect->xmax-x0)/(x1-x0);
x=(float)rect->xmax;
}elseif(outCode->bottom){
x=x0+(x1-x0)*(rect->ymin-y0)/(y1-y0);
y=(float)rect->ymin;
}
if(outCode->all==code0.all){
x0=x;
y0=y;
CompOutCode(x0,y0,rect,&code0);}
else{
x1=x;
y1=y;
CompOutCode(x1,y1,rect,&code1);}
}
}while(!
done);
if(accept){
DrawLine((int)x0,(int)y0,(int)x1,(int)y1,pDC,1);
}
}
梁友栋-Barsky裁剪算法:
一条两端点为P1(x1,y1)、P2(x2,y2)的线段可以用参数方程形式表示:
x=x1+u•(x2-x1)=x1+u•Δx
y=y1+u•(y2-y1)=y1+u•Δy 0≤u≤1
式中,Δx=x2-x1,Δy=y2-y1,参数u在0~1之间取值,P(x,y)代表了该线段上的一个点,其值由参数u确定,由公式可知,当u=0时,该点为P1(x1,y1),当u=1时,该点为P2(x2,y2)。
梁友栋-Barsky算法只能应用于矩形窗口的情形。
通常梁友栋-Barsky算法比Cohen-Sutherland算法效率更高,因为需要计算的交点数目减少了。
更新参数u1、u2仅仅需要一次除法;线段与窗口边界的交点仅计算一次,就计算出u1、u2最后的值。
相比之下,即使一条线段完全落在裁剪窗口之外,Cohen-Sutherland算法也要对它反复求交点,而且每次求交计算都需要做乘除法
liang-Barskey裁剪:
voidCTestView:
:
LBClip(double*x1,double*y1,double*x2,double*y2)//裁剪函数
{
doubletmax,tmin,dx,dy;
dx=*x2-*x1;dy=*y2-*y1;tmax=0.0,tmin=1.0;
//窗口边界的左、右、下、上顺序裁剪直线
if(LBClipTest(-dx,*x1-wxl,&tmax,&tmin))//n=1,左边界u1=-△x,v1=x1-wxl
{
if(LBClipTest(dx,wxr-*x1,&tmax,&tmin))//n=2,右边界u2=△x,v2=wxr-x1
{
if(LBClipTest(-dy,*y1-wyb,&tmax,&tmin))//n=3,下边界u3=-△y,v3=y1-wyb
{
if(LBClipTest(dy,wyt-*y1,&tmax,&tmin))//n=4,上边界u4=△y,v4=wyt-y1
{
if(tmin<1.0)//判断直线的终点
{
*x2=*x1+tmin*dx;//重新计算直线端点
*y2=*y1+tmin*dy;//x=x1+t(x2-x1)格式
}
if(tmax>0.0)//判断直线的起点
{
*x1+=tmax*dx;
*y1+=tmax*dy;
}
}
}
}
}
}
实
验
结
果
分
析
程序运行截图如下:
将限定区域外的直线剪裁后:
年级
2011级
学号
11065118
11065120
11065124
专业
软件工程
姓名
向阳辉
蒙德亮
王鸿儒
实验时间
11.20
实验地点
9-206
实验
名称
4多边形的裁剪
实验
类型
设计型
综合型
创新型
√
实
验
目
的
或
要
求
1.实验内容
用Sutherland-Hodgman算法进行多边形裁剪
2.实验目的
1)理解多边形裁剪与直线段裁剪的区别;
2)掌握多边形的裁剪过程;
3)理解并掌握Sutherland-Hodgman算法的裁剪思想
3.实验要求
1)将像素网格表现出来,建立网格坐标系;
2)用橡皮筋的形式输入剪裁多边形和裁剪窗口;
3)鼠标移动时,显示鼠标当前位置;
4)多边形被窗口的四条边裁剪的过程以及多边形顶点增删的过程要显示出来;
5)裁剪过程可以重复进行。
实
验
原
理
4.详细设计
Sutherland-Hodgeman多边形裁剪算法思想:
每次用窗口的一条边界(包括延长线)对要裁剪的多边形进行裁剪,裁剪时,顺序地测试多边形各顶点,保留边界内侧的顶点,删除外侧的顶点,同时,适时地插入新的顶点:
即交点和窗口顶点,从而得到一个新的多边形顶点序列。
然后以此新的顶点序列作为输入,相对第二条窗边界线进行裁剪,又得到一个更新的多边形顶点序列。
依次下去,相对于第三条、第四条边界线进行裁剪,最后输出的多边形顶点序列即为所求的裁剪好了的多边形。
新的多边形顶点序列产生规则:
在用窗口一条边界及其延长线裁剪一个多边形时,该边界线把平面分成两个部分:
一部分称为边界内侧;另一部分称为边界外侧。
依序考虑多边形的各条边。
假设当前处理的多边形的边为SP(箭头表示顺序关系,S为前一点,P为当前点),边SP与裁剪线的位置关系只有下面四种情况:
1、S在外侧,P在内侧。
则交点Q、当前点P保存到新多边形中。
2、S、P均在内侧,则当前点P保存到新多边形中。
3、S在内侧,P在外侧。
则交点Q保存到新多边形中。
4、S、P均在外侧。
则没有点被保存到新多边形中。
Sutherland-Hodgeman多边形裁剪实现:
voidCTestView:
:
Cohen()//Cohen-Sutherland算法
{
BOOLChange;
doublex,y;
RC0=EnCode(Pointx[0],Pointy[0]);
RC1=EnCode(Pointx[1],Pointy[1]);
while(TRUE)
{
Change=FALSE;
if(0==(RC0|RC1))
{//简取之
return;
}
elseif(0!
=(RC0&RC1))
{//简弃之
return;
}
else
{
if(0==RC0)//如果P0点在窗口内,交换P0和P1,保证p0点在窗口外
{
//交换点的坐标值
doubleTPointx,TPointy;
TPointx=Pointx[0];TPointy=Pointy[0];
Pointx[0]=Pointx[1];Pointy[0]=Pointy[1];
Pointx[1]=TPointx;Pointy[1]=TPointy;
//交换点的编码值
unsignedintTRC;
TRC=RC0;RC0=RC1;RC1=TRC;
}
//按左、右、下、上的顺序裁剪
if(RC0&LEFT)//P0点位于窗口的左侧
{
x=wxl;//求交点y
y=Pointy[0]+(Pointy[1]-Pointy[0])*(x-Pointx[0])/(Pointx[1]-Pointx[0]);
Pointx[0]=x;Pointy[0]=y;
Change=TRUE;
RC0=EnCode(Pointx[0],Pointy[0]);RC1=EnCode(Pointx[1],Pointy[1]);
}
if(RC0&RIGHT)//P0点位于窗口的右侧{
x=wxr;//求交点y
Cha
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 报告 文档