计算机图形学上机实验09.docx
《计算机图形学上机实验09.docx》由会员分享,可在线阅读,更多相关《计算机图形学上机实验09.docx(13页珍藏版)》请在冰点文库上搜索。
计算机图形学上机实验09
计算机图形学上机实验(09)
计算机图形学上机实验
齐金山
淮阴师范学院(江苏)
计算机科学与技术学院
计算机图形学上机说明
《计算机图形学》是计算机科学与技术专业本科的一门专业课程,课程的上机实践性环节是学生学习的重点和难点。
通过本实验,使学生掌握计算机图形学的基本原理、方法和相关的软硬件知识,掌握计算机图形学编程的基本方法,为学生进一步学习图形学及其他相关学科打下坚实的基础。
要求掌握计算机图形学的基本原理、算法与应用;学会用相关算法编程显示基本图形。
本次共有4次上机实验,涉及到计算机基本图形的生成算法、扫描填充算法、裁剪算法、几何变换和曲线等内容。
学生平时也可以去了解三维图形建模技术(曲面、体模型)、OpenGL、光照 消隐、三维技术(模型显示、光照、雾化、交互)等知识。
4次上机实验成果要求提交源代码?
!
实验一基本2D图形生成
一、实验目的
1.掌握基于MFC图形编程框架的搭建。
2.掌握直线和圆等图形扫描转换的原理及常用算法。
二、实验内容
基本2D图形生成:
1.直线生成算法
2.多边形生成算法
3.圆生成算法
4.MFC图形编程框架
三、实验步骤
实验二基本2D图形填充算法和坐标变换
一、实验目的
1.掌握扫描线多边形填充算法、种子填充算法等的基本原理和计算机实现填充功能。
2.掌握在齐次坐标系中进行二维基本线性变换(平移、比例、旋转、错切)的原理、性质、表示方法及应用。
二、实验内容
多边形填充算法、种子填充算法
二维基本线性变换(平移、比例、旋转、错切等)
三、实验步骤
1、创建应用程序框架,本例以单文档框架为例。
2、编辑菜单资源
在工作区的【ResourceView】标签中,单击Menu项左边的“+”,然后双击其子项IDR_MAINFRAME,并根据下图和下图添加编辑菜单资源。
菜单标题
菜单项标题
标识符ID
区域填充
种子填充算法
ID_FLOODFILL
边界填充算法
ID_BOUNDARY
扫描线多边形填充算法
ID_SCANLINEFILL
3、添加菜单项消息处理函数
利用ClassWizard(建立类向导)为应用程序添加与菜单项相关的消息处理函数,ClassName栏中选择CmyView,根据下表建立如下的消息映射函数,ClassWizard会自动生成有关的函数声明。
菜单项ID
消息
消息处理函数
ID_FLOODFILL
COMMAND
OnFloodfill
ID_BOUNDARY
COMMAND
OnBoundary
ID_SCANLINEFILL
COMMAND
OnScanlinefill
4、添加程序代码
Ø在OnDraw()函数中添加如下蓝色字体部分代码。
voidCMyView:
:
OnDraw(CDC*pDC)
{
CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
pDC->TextOut(20,20,"双击鼠标左键,出现需填充的多边形,点击相关功能菜单实现区域填充");
pDC->TextOut(20,50,"进行种子填充,需用鼠标右键,单击多边形内一点,作为开始填充的种子点");
}
Ø添加鼠标消息处理函数:
利用ClassWizard(建立类向导)为应用程序添加与鼠标相关的消息处理函数,ClassName栏中选择CmyView,根据下表建立如下的鼠标消息映射函数,ClassWizard会自动生成有关的函数声明。
ObjectIDs
消息
消息处理函数
CmyView
WM_LBUTTONDBLCLK
OnLButtonDblClk
WM_RBUTTONDOWN
OnRButtonDown
分别给鼠标消息映射函数添加如下代码:
voidCMyView:
:
OnLButtonDblClk(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
RedrawWindow();
CDC*pDC=GetDC();
CPennewpen(PS_SOLID,1,RGB(255,0,0));
CPen*old=pDC->SelectObject(&newpen);
pDC->Rectangle(100,100,200,200);
pDC->SelectObject(old);
ReleaseDC(pDC);
CView:
:
OnLButtonDblClk(nFlags,point);
}
voidCMyView:
:
OnRButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
a_point=point;//a_point为点类对象,表示种子点,定义为CmyView类的数据成员。
CView:
:
OnRButtonDown(nFlags,point);
}
Ø给CmyView类添加各种填充的函数成员:
voidboundary_fill_4(CDC*pDC,intx,inty,COLORREFboundary_Color,COLORREFnew_Color);
voidFlood_Fill_4(CDC*pDC,intx,inty,COLORREFold_Color,COLORREFnew_Color);
voidscanLineFill4(CDC*pDC,intxseed,intyseed,COLORREFoldColor,COLORREFfillColor);
voidCMyView:
:
boundary_fill_4(CDC*pDC,intx,inty,COLORREFboundary_Color,COLORREFnew_Color)
{
COLORREFcent=pDC->GetPixel(CPoint(x,y));
staticDWORDdwCount=0;
if(cent!
=boundary_Color&¢!
=new_Color)
{
pDC->SetPixel(CPoint(x,y),new_Color);
boundary_fill_4(pDC,x,y+1,boundary_Color,new_Color);
boundary_fill_4(pDC,x,y-1,boundary_Color,new_Color);
boundary_fill_4(pDC,x-1,y,boundary_Color,new_Color);
boundary_fill_4(pDC,x+1,y,boundary_Color,new_Color);
boundary_fill_4(pDC,x-1,y+1,boundary_Color,new_Color);
boundary_fill_4(pDC,x+1,y-1,boundary_Color,new_Color);
boundary_fill_4(pDC,x+1,y+1,boundary_Color,new_Color);
boundary_fill_4(pDC,x-1,y-1,boundary_Color,new_Color);
dwCount++;
}
}
voidCMyView:
:
Flood_Fill_4(CDC*pDC,intx,inty,COLORREFold_Color,COLORREFnew_Color)
{
COLORREFcent=pDC->GetPixel(CPoint(x,y));
staticDWORDdwCount=0;
if(cent==old_Color&¢!
=new_Color)
{
pDC->SetPixel(CPoint(x,y),new_Color);
Flood_Fill_4(pDC,x,y+1,old_Color,new_Color);
Flood_Fill_4(pDC,x,y-1,old_Color,new_Color);
Flood_Fill_4(pDC,x-1,y,old_Color,new_Color);
Flood_Fill_4(pDC,x+1,y,old_Color,new_Color);
Flood_Fill_4(pDC,x-1,y+1,old_Color,new_Color);
Flood_Fill_4(pDC,x+1,y+1,old_Color,new_Color);
Flood_Fill_4(pDC,x-1,y-1,old_Color,new_Color);
Flood_Fill_4(pDC,x+1,y-1,old_Color,new_Color);
dwCount++;
}
}
voidCMyView:
:
scanLineFill4(CDC*pDC,intxseed,intyseed,COLORREFoldColor,COLORREFfillColor)
{
intx,y,xtemp,xleft,xright;
intspanfill;
SeqStackstack;
stack.Push(xseed);
stack.Push(yseed);
while(!
stack.StackEmpty())
{
y=stack.Peek();
stack.Pop();
x=stack.Peek();
stack.Pop();
pDC->SetPixel(x,y,fillColor);
for(xtemp=x+1;pDC->GetPixel(xtemp,y)==oldColor;xtemp++)
pDC->SetPixel(xtemp,y,fillColor);
xright=xtemp-1;
for(xtemp=x-1;pDC->GetPixel(xtemp,y)==oldColor;xtemp--)
pDC->SetPixel(xtemp,y,fillColor);
xleft=xtemp+1;
xtemp=xleft;y=y+1;
while(xtemp<=xright)
{
spanfill=0;
COLORREFcr=pDC->GetPixel(xtemp,y);
while(cr!
=oldColor&&cr!
=fillColor&&xtemp<=xright)
{
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
while(cr==oldColor&&cr!
=fillColor&&xtemp<=xright)
{
spanfill=1;
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
if(spanfill==1)
{
stack.Push(xtemp-1);
stack.Push(y);
}
cr=pDC->GetPixel(xtemp,y);
if(cr!
=oldColor&&cr!
=fillColor&&xtemp<=xright)
{
xtemp++;
continue;
}
while(cr==oldColor||cr==fillColor&&xtemp<=xright)
{
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
xtemp=xleft;y=y-2;
while(xtemp<=xright)
{spanfill=0;
COLORREFcr=pDC->GetPixel(xtemp,y);
while(cr!
=oldColor&&cr!
=fillColor&&xtemp<=xright)
{
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
while(cr==oldColor&&cr!
=fillColor&&xtemp<=xright)
{
spanfill=1;
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
if(spanfill==1)
{
stack.Push(xtemp-1);
stack.Push(y);
}
cr=pDC->GetPixel(xtemp,y);
if(cr!
=oldColor&&cr!
=fillColor&&xtemp<=xright)
{
xtemp++;
continue;
}
while(cr==oldColor||cr==fillColor&&xtemp<=xright)
{
xtemp++;
cr=pDC->GetPixel(xtemp,y);
}
}
}
}
}
Ø分别给菜单消息映射函数添加如下代码:
voidCMyView:
:
OnFloodfill()
{
//TODO:
Addyourcommandhandlercodehere
CDC*pDC=GetDC();
intnew_Color=RGB(0,255,0);
intold_Color=pDC->GetPixel(a_point);
intx=a_point.x,y=a_point.y;
Flood_Fill_4(pDC,x,y,old_Color,new_Color);
ReleaseDC(pDC);
}
voidCMyView:
:
OnBoundary()
{
//TODO:
Addyourcommandhandlercodehere
CDC*pDC=GetDC();
intnew_Color=RGB(0,0,255);
intboundary_Color=pDC->GetPixel(100,100);
intx=a_point.x,y=a_point.y;
boundary_fill_4(pDC,x,y,boundary_Color,new_Color);
ReleaseDC(pDC);
}
voidCMyView:
:
OnScanlinefill()
{
//TODO:
Addyourcommandhandlercodehere
CDC*pDC=GetDC();
intfill_Color=RGB(0,0,255);
intold_Color=pDC->GetPixel(150,150);
intx=a_point.x,y=a_point.y;
scanLineFill4(pDC,x,y,old_Color,fill_Color);
ReleaseDC(pDC);
}
注:
扫描线多边形填充算法中要使用的栈代码如下():
typedefintDatatype;
classSeqStack
{
private:
Datatypedata[100];
//抽象类型Datatype的数组
inttop;//栈顶位置指示器
public:
SeqStack(void)//构造函数
{top=0;};
~SeqStack(void)//析构函数
{};
voidSeqStack:
:
Push(Datatypeitem);//把元素item入栈
DatatypePop(void);//出栈数据元素并返回
DatatypePeek(void);//读栈顶数据元素并返回
intStackEmpty(void)//堆栈空返回1;否则返回0
{return(top==0);};
intGetSize(void)//读栈元素个数top
{returntop;};
voidClearStack(void)//清空堆栈使之为初始化状态
{top=0;}
};
voidSeqStack:
:
Push(Datatypeitem){
if(top==100){
//cout<<"堆栈已满!
"<exit(0);
}
data[top]=item;
top++;
}
DatatypeSeqStack:
:
Pop()
{
if(top==0)
{
//cout<<"堆栈已空!
"<exit(0);
}
top--;//top先减1
returndata[top];//然后取top位置上的元素返回
}
DatatypeSeqStack:
:
Peek(void)
{
if(top==0)
{
//cout<<"堆栈空!
"<exit(0);
}
returndata[top-1];//top指在栈顶的下一个位置,取top-1上的元素返回
}
实验三裁剪算法
一、实验目的
掌握Cohen-Sutherland、Liang-Barsky等直线段裁剪算法以及多边形裁剪算法的基本原理
二、实验内容
1.直线裁剪算法
2.多边形裁剪算法
实验四基本3D图形生成以及变换、曲线和曲面生成
一、实验目的
1.知道曲线、曲面的常用表示方法,以及用参数法表示曲线、曲面的优点。
2.掌握基本3D图形生成以及变换。
3.掌握Bezier曲线的生成方法和性质。
4.了解一种完全过型值点的分段插值算法。
二、实验内容
3D图形生成以及各种变换、Bezier曲线曲面的生成方法。
三、实验步骤