计算机图形学实验报告.docx
- 文档编号:28881371
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:17
- 大小:56.08KB
计算机图形学实验报告.docx
《计算机图形学实验报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验报告.docx(17页珍藏版)》请在冰豆网上搜索。
计算机图形学实验报告
实验成绩:
《计算机图形学》实验报告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(); } 实验地点 专业软件实验室 指导教师 李丽亚
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)