计算机图形学实验报告Word文档格式.docx

上传人:b****5 文档编号:19666694 上传时间:2023-01-08 格式:DOCX 页数:34 大小:356.01KB
下载 相关 举报
计算机图形学实验报告Word文档格式.docx_第1页
第1页 / 共34页
计算机图形学实验报告Word文档格式.docx_第2页
第2页 / 共34页
计算机图形学实验报告Word文档格式.docx_第3页
第3页 / 共34页
计算机图形学实验报告Word文档格式.docx_第4页
第4页 / 共34页
计算机图形学实验报告Word文档格式.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

计算机图形学实验报告Word文档格式.docx

《计算机图形学实验报告Word文档格式.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验报告Word文档格式.docx(34页珍藏版)》请在冰豆网上搜索。

计算机图形学实验报告Word文档格式.docx

实验语言:

C语言

2.实验内容

此次实验目的采用了以下算法实现。

2.1.Bresenham画直线算法

根据直线的斜率确定选择X或者Y方向作为计长方向,在此方向上每次递增一个单位步长(或者一个像素单位),另一个方向上是否同时产生一个单位增量由一个计算量很小的判别式来判断。

(以斜率在0~1之间的直线段为例)

这种情况下,选择X方向为计长方向,即增量dx=1。

如下图所示,设Pi(xi,yi)是已选定的离直线最近的像素,现在要决定Pi+1是T还是S。

若d<

0.5,则S比较靠近直线,应选S;

若d>

=0.5,则应选T。

(m=△y/△x)

令e=d-0.5(初值为m-0.5),即有:

e<

0时,选Pi+1(xi+1,yi),更新e=e+m;

e>

=0时,选Pi+1(xi+1,yi+1),更新e=e+m-1。

2.2.Bresenham画圆算法

与Bresenham直线生成算法一样,其基本方法是从一个起点出发,利用判别式选择下一个显示点。

判别式的值通过简单计算获得,其符号用作判断。

(以位于第一象限的1/8圆弧为例)

此算法在每一步都选择一个离开理想圆周最近的点Pi(xi,yi),使其误差项

|D(Pi)|=|xi2+yi2-R2|在每一步都是极小值。

设Pi-1(xi-1,yi-1)已被选定为最靠近圆弧的点,下一步x=xi-1+1时,参见下图:

要决定T还是S更接近理想的圆弧,令

D(S)=(xi-1+1)2+yi-12-R2

D(T)=(xi-1+1)2+(yi-1-1)2-R2

显然,|D(S)|>

=|D(T)|时,应该取T点,反之则取S点。

即若令

di=|D(S)|-|D(T)|

则di>

=0,选择T点,否则选取S点。

结论:

d1=3-2R;

如果di<

0,选Pi(xi,yi-1),将yi=yi-1代入求di+1:

di+1=di+4xi+2=di+4xi-1+6

如果di>

=0,选Pi(xi,yi-1-1),将yi=yi-1-1代入求di+1:

di+1=di+4xi-4yi-1+6=di+4(xi-1-yi-1)+10

2.3.Bresenham画椭圆算法

与Bresenham直线和圆生成算法原理一样,但是椭圆的生成的过程中要分为上半部与下半部的情况讨论。

在生成椭圆上部区域时,以x轴为步进方向,如图所示:

x每步进一个单位,就需要在判断y保持不变还是也步进减1,bresenham算法定义判别式为:

di=d1-d2

0,则取P1为下一个点,否则,取P2为下一个点。

采用判别式di,使得判别式规约为全整数运算,算法效率得到了很大的提升。

根据椭圆方程,可以计算出d1和d2分别是:

d1=a2(yi2-y2)

d2=a2(y2-yi+12)

以(0,b)作为椭圆上部区域的起点,将其代入判别式di可以得到如下递推关系:

当di<

0时,di+1=di+2b2(2xi+3)

当di>

=0时,di+1=di+2b2(2xi+3)-4a2(yi-1)

d1=2b2–2a2b+a2

在生成椭圆下部区域时,以y轴为步进方向,如图所示:

y每步进减一个单位,就需要在判断x保持不变还是步进加一个单位,对于下部区域,计算出d1和d2分别是:

d1=b2(xi+12-x2)

d2=b2(x2-xi2)

以(xp,yp)作为椭圆下部区域的起点,将其代入判别式di可以得到如下递推关系:

当di<

0时,di+1=di-4a2(yi-1)+2a2

=0时,di+1=di+2b2(xi+1)-4a2(y-1)+2a2+b2

d1=b2(xp+1)2+b2xp2-2a2b2+2a2(yp-1)2

2.4.多边形阴影线填充算法

算法步骤如下:

a.对于MN条棱边,计算每一条棱边Li的两个端点分别按阴影线斜率k=tgα引线得到的截距,其中较小值放在B(1,i)中,较大值放在B(2,i)中。

b.求出Bmin=minB(1,i),Bmax=maxB(2,i),i=1,2,...,MN。

c.取第一条阴影线截距为b=Bmin+△b(△b=h/|cosα|)。

d.初始化存放阴影线与各棱边交点的数组D(2,MN);

判断当前阴影线与各棱边是否有交点,若存在则计算出交点坐标并存入D数组;

按X/Y坐标排列D数组中的交点并生成阴影线段;

取下一条阴影线b=b+△b,若b≠Bmax转d继续。

2.5.多边形扫描转换算法

a.非极值奇点的预处理。

(极值奇点算作2个交点;

非极值奇点算作1个交点)

b.建立边的分类表ET。

c.取扫描线初始值y为ET表中所列的最小y坐标值。

d.边的活化链表AEL初始化,使其为空。

e.重复下列操作,直至ET表和AEL表都变成空:

e1.把ET表中纵坐标为y的链取下,与AEL表合并,并保持AEL表中元素按x域值升序排列,x相同时,按△x域。

e2.对于当前扫描线y,从左到右,将AEL表中元素两两配对,按每对两个x域定义的区段填充所需要的像素值。

e3.将AEL表中满足ymax=y的元素删除;

e4.对于仍留在AEL表中的元素,求下一条扫描线与边的交点,即x域累加△x:

x=x+△x。

e5.取下一条扫描线作为当前扫描线:

y=y+1。

3.实验步骤

3.1.程序设计

函数库的声明部分如下:

#include<

stdio.h>

stdlib.h>

math.h>

windows.h>

#definePI3.1416

#defineDEF-10000

#defineMAX100

structlist{

intymax;

doublex;

doubledx;

structlist*next;

};

structhead{

intnum;

structlist*start;

structlist*end;

typedefstructlistL;

typedefstructheadH;

typedefL*LP;

voidDrawLine(HDChdc,intx1,inty1,intx2,inty2,COLORREFcolor);

voidDrawCircle(HDChdc,intxc,intyc,intr,COLORREFcolor);

voidDrawEllipse(HDChdc,intxc,intyc,inta,intb,COLORREFcolor);

voidDrawPolygon(HDChdc,intp[][MAX],intpoint_num,intin_num,COLORREFcolor);

voidPolygonShadow(HDChdc,intp[][MAX],intpoint_num,intin_num,doublea,inth,COLORREFcolor);

voidPolygonFill(HDChdc,intp[][MAX],intpoint_num,intin_num,COLORREFcolor);

voidPlotC(HDChdc,intx,inty,intxc,intyc,COLORREFcolor);

voidPlotE(HDChdc,intx,inty,intxc,intyc,COLORREFcolor);

intLineIntersection(doublek,intb,intx1,inty1,intx2,inty2);

voidSortPoint(intd[][MAX],intd_num);

voidPreProcessing(intp[][MAX],intpoint_num,intin_num);

intCreateET(intp[][MAX],intpoint_num,intin_num,intymin,HET[]);

LPInsertList(intx1,inty1,intx2,inty2,LPh,LP*t);

LPDeleteList(LPhead,LPcurrent,LP*tail);

LPSortAEL(LPhead);

各个函数与数据结构的定义见下文。

3.1.1.画线段

将2.1里提到的算法思想推广到所有象限,设计函数

voidDrawLine(HDChdc,intx1,inty1,intx2,inty2,COLORREFcolor)

其中参数意义如下:

HDChdc画图界面

intx1线段一端横坐标

inty1线段一端纵坐标

intx2线段一端横坐标

inty2线段一端横坐标

COLORREFcolor直线的颜色

该部分实现代码如下:

{

inti,interchange,s1,s2;

intx,y,dx,dy,dxy,d;

x=x1;

y=y1;

dx=abs(x2-x1);

dy=abs(y2-y1);

if(x2-x1>

0){

s1=1;

}

else{

s1=-1;

if(y2-y1>

s2=1;

s2=-1;

if(dy>

dx){

dxy=dx;

dx=dy;

dy=dxy;

interchange=1;

interchange=0;

d=2*dy-dx;

for(i=1;

i<

=dx;

i++){

SetPixel(hdc,x,y,color);

while(d>

=0){

if(interchange==1){

x=x+s1;

}

else{

y=y+s2;

d=d-2*dx;

}

if(interchange==1){

y=y+s2;

else{

x=x+s1;

d=d+2*dy;

}

3.1.2.画圆

将2.2中提到的算法思想根据圆的对称性推广到所有象限,其中函数

voidPlotC(HDChdc,intx,inty,intxc,intyc,COLORREFcolor)

是根据圆的对称性画8个点的辅助函数。

其参数意义如下:

intx当前扫描的点相对圆心的横坐标距离

inty当前扫描的点相对圆心的纵坐标距离

intxc圆心横坐标

intyc圆心纵坐标

COLORREFcolor圆的颜色

执行画圆的函数为

voidDrawCircle(HDChdc,intxc,intyc,intr,COLORREFcolor)

intr圆的半径

SetPixel(hdc,xc+x,yc+y,color);

SetPixel(hdc,xc+x,yc-y,color);

SetPixel(hdc,xc-x,yc+y,color);

SetPixel(hdc,xc-x,yc-y,color);

SetPixel(hdc,xc+y,yc+x,color);

SetPixel(hdc,xc+y,yc-x,color);

SetPixel(hdc,xc-y,yc+x,color);

SetPixel(hdc,xc-y,yc-x,color);

intx,y,d;

y=r;

d=3-2*r;

x=0;

while(x<

=y){

PlotC(hdc,x,y,xc,yc,color);

if(d<

d=d+4*x+6;

d=d+4*(x-y)+10;

y--;

x++;

3.1.3.画椭圆

将2.3中提到的算法思想根据椭圆的对称性推广到所有象限,其中函数

voidPlotE(HDChdc,intx,inty,intxc,intyc,COLORREFcolor)

是根据椭圆的对称性画4个点的辅助函数。

intx当前扫描的点相对椭圆心的横坐标距离

inty当前扫描的点相对椭圆心的纵坐标距离

intxc椭圆心横坐标

intyc椭圆心纵坐标

COLORREFcolor椭圆的颜色

执行画椭圆的函数为

voidDrawEllipse(HDChdc,intxc,intyc,inta,intb,COLORREFcolor)

inta椭圆的长半轴长

intb椭圆的短半轴长

intx,y,d,e;

y=b;

d=2*b*b-2*b*a*a+a*a;

PlotE(hdc,x,y,xc,yc,color);

e=(int)((double)(a*a)/sqrt((double)(a*a+b*b)));

=e){

d=d+2*b*b*(2*x+3);

d=d+2*b*b*(2*x+3)-4*a*a*(y-1);

PlotE(hdc,x,y,xc,yc,color);

d=b*b*(x*x+x)+a*a*(y*y-y)-a*a*b*b;

while(y>

y--;

x++;

d=d-2*a*a*y-a*a+2*b*b*x+2*b*b;

d=d-2*a*a*y-a*a;

3.1.4.多边形阴影线填充

程序设计基于2.4中的算法原理。

该算法首先要画出多边形,执行画多边形的函数为

voidDrawPolygon(HDChdc,intp[][MAX],intpoint_num,intin_num,COLORREFcolor)

该函数遍历了多边形的各个定点,通过调用画线段函数

来达到效果(画线段函数详见3.1.1)。

该画多边形函数的参数意义如下:

intp[][MAX]储存多边形各个定点的数组

intpoint_num多边形的总定点数

intin_num多边形的内部定点数

COLORREFcolor多边形的颜色

在执行多边形阴影填充的过程中需要求填充阴影线与多边形棱边的交点,使用到函数

intLineIntersection(doublek,intb,intx1,inty1,intx2,inty2)

该函数的参数意义如下:

doublek填充阴影线的斜率

intb填充阴影线的截距

intx1该棱边的一个定点的横坐标

inty1该棱边的一个定点的纵坐标

intx2该棱边另一个定点的横坐标

inty2该棱边另一个定点的纵坐标

返回值(类型int)交点的横坐标

该过程还需要对一条阴影线与多边形产生的多个交点按照X坐标升序进行排列,使用到函数

voidSortPoint(intd[][MAX],intd_num)

排序原理为简单的选择排序。

intd[][MAX]储存交点坐标的数组

intd_num交点个数

进行多边形阴影线填充的主体函数为

voidPolygonShadow(HDChdc,intp[][MAX],intpoint_num,intin_num,doublea,inth,COLORREFcolor)

doublea阴影线与水平线的夹角

inth阴影线之间的间隔

COLORREFcolor填充阴影线的颜色

inti;

for(i=0;

=point_num-1-in_num;

if(i==point_num-1-in_num){

DrawLine(hdc,p[0][i],p[1][i],p[0][0],p[1][0],color);

DrawLine(hdc,p[0][i],p[1][i],p[0][i+1],p[1][i+1],color);

for(i=point_num-in_num;

=point_num-1;

if(i==point_num-1){

DrawLine(hdc,p[0][i],p[1][i],p[0][point_num-in_num],p[1][point_num-in_num],color);

intb1,b2,min,max,x;

b1=y1-(int)(0.5+k*(double)x1);

b2=y2-(int)(0.5+k*(double)x2);

if(b1<

b2){

min=b1;

max=b2;

min=b2;

max=b1;

if(b>

=min&

&

b<

=max){

x=(x1*y2-y1*x2+b*(x2-x1))/((y2-y1)-(int)(0.5+k*(double)(x2-x1)));

returnx;

returnDEF;

inti,j,min,tempx,tempy;

=d_num-2;

min=i;

for(j=i+1;

j<

=d_num-1;

j++){

if(d[0][j]<

d[0][min]){

min=j;

tempx=d[0][i];

tempy=d[1][i];

d[0][i]=d[0][min];

d[1][i]=d[1][min];

d[0][min]=tempx;

d[1][min]=tempy;

DrawPolygon(hdc,p,point_num,in_num,color);

//按要求画出多边形

inti,db,b[MAX];

doublek;

k=tan(a);

db=(int)(0.5+(double)h/cos(a));

b[i]=(p[1][i]-p[1][0])-(int)(0.5+k*(double)(p[0][i]-p[0][0]));

//对于每个顶点作阴影线求截距

intbmax,bmin;

bmax=b[0];

bmin=b[0];

i++){//确认阴影线扫描范围

if(b[i]>

bmax){

bmax=b[i];

if(b[i]<

bmin){

bmin=b[i];

intbc

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 军事政治

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1