计算机图形学实验报告.docx

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

计算机图形学实验报告.docx

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

计算机图形学实验报告.docx

计算机图形学实验报告

实验成绩:

《计算机图形学》实验报告2

 

班级:

1420551

专业:

网络工程

学号:

姓名

 

《计算机图形学》课程实验报告

(二)

班级

1420551

实验日期

2016.11.7

姓名

学号

实验名称

多边形有效边表填充算法

1.有效边表和桶表的数据结构

2.颜色对话框的调用方法

3.动态链表的排序方法

 

 

1.调用颜色对话框读取填充色

2.根据实例多边形顶点坐标值,计算扫描线的最大值与最小值

3.用多边形覆盖的扫描线动态建立桶节点

4.循环访问多边形的所有顶点

5.对每个同节点连接的边表,根据x|ymin值的大小进行排序

6.循环访问每个桶结点,将桶内每个节点的边表合并成有效边表,并循环访问有效边表

7.从有效边表中取出扫描线上相邻两节点进行配对

8.循环下一桶节点,按照Xi+1=X+k(k=1/k)修改有效边表,同时合并桶内的新边表,形成新的有效边表

9.当同节点不为空转(6),负责删除桶表和边表的头结点,算法结束

定义类

1.定义有效边表类CART

2.定义桶类CBucket

3.定义填充类CFill

4.修改CTestview类

实验结果:

填充前的界面

调色板界面

填充后的界面

 

 

1.CAET类:

classCAET

{public:

CAET();

virtual~CAET();

public:

doublex;//当前扫描线与有效边交点的x坐标

intyMax;//边的最大y值

doublek;//斜率的倒数(x的增量)

CPi2ps;//边的起点

CPi2pe;//边的终点

CAET*pNext;};

2.CBucket:

classCBucket

{

public:

CBucket();

virtual~CBucket();

public:

intScanLine;//扫描线

CAET*pET;//桶上的边表指针

CBucket*pNext;

};

3.CFill:

classCFill

{

public:

CFill();

virtual~CFill();

voidSetPoint(CPi2*p,int);//初始化

voidCreateBucket();//创建桶

voidCreateEdge();//边表

voidAddET(CAET*);//合并ET表

voidETOrder();//ET表排序

voidGouraud(CDC*);//填充多边形

voidClearMemory();//清理内存

voidDeleteAETChain(CAET*pAET);//删除边表

protected:

intPNum;//顶点个数

CPi2*P;//顶点坐标动态数组

CAET*pHeadE,*pCurrentE,*pEdge;//有效边表结点指针

CBucket*pHeadB,*pCurrentB;//桶表结点指针

};

CFill:

:

CFill()

{

PNum=0;

P=NULL;

pEdge=NULL;

pHeadB=NULL;

pHeadE=NULL;

}

CFill:

:

~CFill()

{if(P!

=NULL)

{delete[]P;

P=NULL;}

ClearMemory();}

voidCFill:

:

SetPoint(CPi2*p,intm)

{

P=newCPi2[m];//创建一维动态数组

for(inti=0;i

{P[i]=p[i];}

PNum=m;

}

voidCFill:

:

CreateBucket()//创建桶表

{

intyMin,yMax;

yMin=yMax=P[0].y;

for(inti=0;i

{

if(P[i].y

{

yMin=P[i].y;//扫描线的最小值

}

if(P[i].y>yMax)

{

yMax=P[i].y;//扫描线的最大值

}

}

for(inty=yMin;y<=yMax;y++)

{

if(yMin==y)//如果是扫描线的最小值

{pHeadB=newCBucket;//建立桶的头结点

pCurrentB=pHeadB;//pCurrentB为CBucket当前结点指针

pCurrentB->ScanLine=yMin;

pCurrentB->pET=NULL;//没有链接边表

pCurrentB->pNext=NULL;

}

else//其他扫描线

{pCurrentB->pNext=newCBucket;//建立桶的其他结点

pCurrentB=pCurrentB->pNext;

pCurrentB->ScanLine=y;

pCurrentB->pET=NULL;

pCurrentB->pNext=NULL;}}}

voidCFill:

:

CreateEdge()//创建边表

{

for(inti=0;i

{pCurrentB=pHeadB;

intj=(i+1)%PNum;//边的另一个顶点,P[i]和P[j]点对构成边

if(P[i].y

{

pEdge=newCAET;

pEdge->x=P[i].x;//计算ET表的值

pEdge->yMax=P[j].y;

pEdge->k=(P[j].x-P[i].x)/(P[j].y-P[i].y);//代表1/k

pEdge->ps=P[i];//绑定顶点和颜色

pEdge->pe=P[j];

pEdge->pNext=NULL;

while(pCurrentB->ScanLine!

=P[i].y)//在桶内寻找当前边的yMin

{

pCurrentB=pCurrentB->pNext;//移到yMin所在的桶结点

}

}

if(P[j].y

{

pEdge=newCAET;

pEdge->x=P[j].x;

pEdge->yMax=P[i].y;

pEdge->k=(P[i].x-P[j].x)/(P[i].y-P[j].y);

pEdge->ps=P[i];

pEdge->pe=P[j];

pEdge->pNext=NULL;

while(pCurrentB->ScanLine!

=P[j].y)

{

pCurrentB=pCurrentB->pNext;

}

}

if(P[i].y!

=P[j].y)

{

pCurrentE=pCurrentB->pET;

if(pCurrentE==NULL)

{

pCurrentE=pEdge;

pCurrentB->pET=pCurrentE;

}

else

{

while(pCurrentE->pNext!

=NULL)

{

pCurrentE=pCurrentE->pNext;

}

pCurrentE->pNext=pEdge;

}

}

}

}

voidCFill:

:

Gouraud(CDC*pDC)//填充多边形

{

CAET*pT1=NULL,*pT2=NULL;

pHeadE=NULL;

for(pCurrentB=pHeadB;pCurrentB!

=NULL;pCurrentB=pCurrentB->pNext)

{

for(pCurrentE=pCurrentB->pET;pCurrentE!

=NULL;pCurrentE=pCurrentE->pNext)

{

pEdge=newCAET;

pEdge->x=pCurrentE->x;

pEdge->yMax=pCurrentE->yMax;

pEdge->k=pCurrentE->k;

pEdge->ps=pCurrentE->ps;

pEdge->pe=pCurrentE->pe;

pEdge->pNext=NULL;

AddET(pEdge);

}

ETOrder();

pT1=pHeadE;

if(pT1==NULL)

return;

while(pCurrentB->ScanLine>=pT1->yMax)//下闭上开

{

CAET*pAETTEmp=pT1;

pT1=pT1->pNext;

deletepAETTEmp;

pHeadE=pT1;

if(pHeadE==NULL)

return;

}

if(pT1->pNext!

=NULL)

{

pT2=pT1;

pT1=pT2->pNext;

}

while(pT1!

=NULL)

{

if(pCurrentB->ScanLine>=pT1->yMax)//下闭上开

{

CAET*pAETTemp=pT1;

pT2->pNext=pT1->pNext;

pT1=pT2->pNext;

deletepAETTemp;

}

else

{

pT2=pT1;

pT1=pT2->pNext;

}

}

BOOLbInFlag=FALSE;//区间内外测试标志,初始值为假表示区间外部

doublexb,xe;//扫描线与有效边相交区间的起点和终点坐标

for(pT1=pHeadE;pT1!

=NULL;pT1=pT1->pNext)

{

if(FALSE==bInFlag)

{

xb=pT1->x;

bInFlag=TRUE;

}

else

{

xe=pT1->x;

for(doublex=xb;x

{

pDC->SetPixelV(Round(x),pCurrentB->ScanLine,RGB(pT1->ps.c.red*255,pT1->ps.c.green*255,pT1->ps.c.blue*255));

}

bInFlag=FALSE;

}

}

for(pT1=pHeadE;pT1!

=NULL;pT1=pT1->pNext)//边的连续性

{

pT1->x=pT1->x+pT1->k;

}

}

}

voidCFill:

:

AddET(CAET*pNewEdge)//合并ET表

{

CAET*pCE=pHeadE;

if(pCE==NULL)

{

pHeadE=pNewEdge;

pCE=pHeadE;

}

else

{

while(pCE->pNext!

=NULL)

{

pCE=pCE->pNext;

}

pCE->pNext=pNewEdge;

}

}

voidCFill:

:

ETOrder()//边表的冒泡排序算法

{

CAET*pT1,*pT2;

intCount=1;

pT1=pHeadE;

if(pT1==NULL)

{

return;

}

if(pT1->pNext==NULL)//如果该ET表没有再连ET表

{

return;//桶结点只有一条边,不需要排序

}

while(pT1->pNext!

=NULL)//统计边结点的个数

{

Count++;

pT1=pT1->pNext;

}

for(inti=0;i

{

CAET**pPre=&pHeadE;

pT1=pHeadE;

for(intj=0;j

{

pT2=pT1->pNext;

if((pT1->x>pT2->x)||((pT1->x==pT2->x)&&(pT1->k>pT2->k)))

{

pT1->pNext=pT2->pNext;

pT2->pNext=pT1;

*pPre=pT2;

pPre=&(pT2->pNext);//调整位置为下次遍历准备

}

else

{

pPre=&(pT1->pNext);

pT1=pT1->pNext;

}

}

}

}

voidCFill:

:

ClearMemory()//安全删除所有桶与桶上连接的边

{

DeleteAETChain(pHeadE);

CBucket*pBucket=pHeadB;

while(pBucket!

=NULL)//针对每一个桶

{

CBucket*pBucketTemp=pBucket->pNext;

DeleteAETChain(pBucket->pET);

deletepBucket;

pBucket=pBucketTemp;

}

pHeadB=NULL;

pHeadE=NULL;

}

voidCFill:

:

DeleteAETChain(CAET*pAET)

{while(pAET!

=NULL)

{CAET*pAETTemp=pAET->pNext;

deletepAET;

pAET=pAETTemp;}}

4.修改CTestview类

1).定义了ReadPoint()函数

voidCTestView:

:

ReadPoint()//点表

{

P[0].x=50;P[0].y=100;

P[1].x=-150;P[1].y=300;

P[2].x=-250;P[2].y=50;

P[3].x=-150;P[3].y=-250;

P[4].x=0;P[4].y=-50;

P[5].x=100;P[5].y=-250;

P[6].x=300;P[6].y=150;

}

2)绘制图形函数DrawGraph()

voidCTestView:

:

DrawGraph()//绘制图形

{

CRectrect;//定义客户区

GetClientRect(&rect);//获得客户区的大小

CDC*pDC=GetDC();//定义设备上下文指针

pDC->SetMapMode(MM_ANISOTROPIC);//自定义坐标系

pDC->SetWindowExt(rect.Width(),rect.Height());//设置窗口比例

pDC->SetViewportExt(rect.Width(),-rect.Height());//设置视区比例,且x轴水平向右,y轴垂直向上

pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2);//设置客户区中心为坐标系原点

rect.OffsetRect(-rect.Width()/2,-rect.Height()/2);//矩形与客户区重合

if(!

bFill)

DrawPolygon(pDC);//绘制多边形

else

FillPolygon(pDC);//填充多边形

ReleaseDC(pDC);//释放DC

}

3)绘制多边形边界函数DrawPolygon()

voidCTestView:

:

DrawPolygon(CDC*pDC)//绘制多边形边界

{

CLine*line=newCLine;

CP2t;

for(inti=0;i<7;i++)//绘制多边形

{if(i==0)

{line->MoveTo(pDC,P[i]);

t=P[i];}

else

{line->LineTo(pDC,P[i]);}}

line->LineTo(pDC,t);//闭合多边形

deleteline;}

4)填充多边形函数FillPolygon()

voidCTestView:

:

FillPolygon(CDC*pDC)//填充多边形

{for(inti=0;i<7;i++)//转储顶点坐标,y坐标取为整数

{P1[i].x=P[i].x;

P1[i].y=Round(P[i].y);

P1[i].c=CRGB(bRed/255.0,bGreen/255.0,bBlue/255.0);}

CFill*fill=newCFill;//动态分配内存

fill->SetPoint(P1,7);//初始化Fill对象

fill->CreateBucket();//建立桶表

fill->CreateEdge();//建立边表

fill->Gouraud(pDC);//填充多边形

deletefill;//撤销内存

}

5)菜单函数

voidCTestView:

:

OnDrawpic()

{

//TODO:

Addyourcommandhandlercodehere

COLORREFGetClr=RGB(0,0,0);//调色板颜色

CColorDialogccd(GetClr,CC_SOLIDCOLOR);

if(IDOK==ccd.DoModal())//调用颜色对话框选取填充色

GetClr=ccd.GetColor();

else

return;

bRed=GetRValue(GetClr);//获取红色分量

bGreen=GetGValue(GetClr);//获取绿色分量

bBlue=GetBValue(GetClr);//获取蓝色分量

bFill=TRUE;

Invalidate();

}

实验地点

专业软件实验室

指导教师

李丽亚

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

当前位置:首页 > 求职职场 > 笔试

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

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