计算机图形学课程设计实习报告.docx
《计算机图形学课程设计实习报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学课程设计实习报告.docx(34页珍藏版)》请在冰豆网上搜索。
计算机图形学课程设计实习报告
计算机图形学课程设计实习报告
实验零 VisualC++绘图系统
地点:
土木楼B401机房时间:
星期三下午节次:
第三大节
一、实验目的:
1.了解VisualC++绘图的基本概念
2.了解VisualC++绘图环境
3.掌握用VisualC++设计绘图项目的基本步骤
4.掌握用VisualC++绘图的基本命令
二、实验内容:
实验内容1:
创立绘图应用程序主框架
实验内容2:
应用程序编译运行
实验内容3:
设置菜单项并生成消息响应函数
实验内容4:
SetPixel绘图
三、实验步骤:
实验内容1:
创立绘图应用程序主框架
步骤:
1.创立一个工作目录D:
\MyProject
2.启动VisualStudio
3.单击“文件”->“新建”->“项目”,项目类型对话框中选择“其它语言”->“VC++”->“MFC”,模版选择“MFC应用程序”。
在工作目录D:
\MyProject下创立一个新应用项目:
Sample,如下图所示。
4.单击“确定”按钮。
5.单击“下一步”按钮。
6.在“应用程序类型中”,选择“单文档”类型。
7.单击“完成”,创立了一项空的工程-绘图应用程序主框架。
实验内容2:
应用程序编译运行
运行版本有两类:
Debug、Release,生成Debug解决方案步骤如下:
1.生成解决方案
点击“生成-〉生成解决方案”,生成了Debug版的可运行程序。
2.调试运行程序
点击菜单“调试——〉开始执行(不调试)”,执行Debug版的可运行程序。
结果如下:
生成Release解决方案步骤如下:
1.生成解决方案
点击“生成-〉批生成”。
2.勾选“Release”,单击“生成”,生成能够独立于VisualC++外运行的.exe程序。
3.查看目录,sample.exe是Release版,单击即能够运行。
运行结果:
实验内容3:
设置菜单项并生成消息响应函数
1.弹出菜单设计器
单击“解决方案管理器”窗口中的资源文件Sample.rc,弹出资源视图,
2.插入一项菜单
双击“资源视图”中的“Menu”展开文件夹,双击“IDR_MAINFRAME”,弹出菜单设计器。
右健单击菜单设计器的“帮助”,选择“新插入”,插入一项菜单。
在新插入的菜单项的“Caption”中输入“绘图”。
3.输入ID
输入“打开”菜单项,输入“直线”菜单项,在“直线”菜单项下输入“DDA”菜单,“DDA”菜单的ID为ID_LINE_DDA。
ID
Caption
功能
ID_LINE_DDA
DDA
用DDA发绘制直线
4.调出类视图窗口
单击菜单“视图-〉类视图”,
在“解决方案管理器”窗口中出现“类视图”窗口。
4.生成菜单消息响应函数
在类视图窗口,单击Csample0View类,单击事件按钮,
5.选择ID_LINE_DDA的COMMAND,添加OnLineDDA事件。
6.进入代码编辑器
在voidCsample0View:
:
OnLineDda()中的//TODO:
在此添加命令处理程序代码处输入的自己代码:
AfxMessageBox("HelloWorld",MB_OK,NULL);
7.修改项目字符集属性
选择“项目”菜单->属性->,弹出“属性”对话框,选择“配置属性->常规->字符集”,改为“未设置”。
8.运行结果
重新生成解决方案,运行结果如下。
实验内容4:
SetPixel绘图
在voidCsample0View:
:
OnLineDda()中的//TODO:
在此添加命令处理程序代码处输入的代码:
//TODO:
Addyourcommandhandlercodehere
CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
intx,y;
y=100;
for(x=100;x<=300;x+=3){
y++;
pdc->SetPixelV(x,y,RGB(255,0,0));
}
pdc->DeleteDC();
}
运行结果如下。
四、实验结果:
实验内容1:
创立绘图应用程序主框架结果
实验内容2:
应用程序编译运行结果
实验内容3:
设置菜单项并生成消息响应函数
实验内容4:
SetPixel绘图
五、回答如下问题:
解释以下每条命令的含义
CClientDC*pdc=newCClientDC(this);//定义一个指针类型的CClientDC对象,客户区设备上下文用于客//户区的输出,与特定窗口关联
CPenpen;//定义一个画笔对象
pen.CreatePen(PS_DOT,1,RGB(255,0,0));//赋予pen对象以风格
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);//
pdc->SetPixelV(x,y,RGB(255,0,0));//画出像素坐标为(x,y),风格为红色的一点
六、其它的实验内容:
答:
工具条按钮的添加
七、实验中发现的问题及你解决的方法:
答:
发现的问题:
调试过程中出现如下错误
解决的方法:
重新生成解决方案,如还出现则多生成几次。
实验一直线的生成算法
地点:
土木楼B401机房时间:
星期三下午节次:
第三大节
一、实验目的:
1.理解DDA算法
2.理解中点Bresenham算法
3.理解改进的Bresenham算法
4.了解DDA和Bresenham算法的区别,以及生成图形的差异原因
二、实验内容:
实验内容1:
设计DDA算法程序
实验内容2:
设计中点Bresenham算法程序
实验内容3:
改进的Bresenham算法
三、实验步骤:
实验内容1:
设计DDA算法程序
添加函数:
voidDDALine(intXa,intYa,intXb,intYb)
//DDA算法
voidCSampleView:
:
DDALine(intXa,intYa,intXb,intYb)
{
CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
floatdelta_x,delta_y;intx,y;
intdx,dy,steps,k;
dx=Xb-Xa;
dy=Yb-Ya;
if(abs(dx)>abs(dy))
steps=abs(dx);
elsesteps=abs(dy);
delta_x=(float)dx/(float)steps;
delta_y=(float)dy/(float)steps;
x=Xa;
y=Ya;
pdc->SetPixelV(x,y,RGB(255,0,0));
for(k=1;k<=steps;k++)
{
x+=(int)delta_x;
y+=(int)delta_y;
pdc->SetPixelV(x,y,RGB(255,0,0));
}
pdc->DeleteDC();
}
添加事件响应函数:
//消息响应函数DDA算法程序的设计画直线
voidCSampleView:
:
OnDdaLine()
{
DDALine(100,100,300,300);
}
实验内容2:
设计中点Bresenham算法程序
添加函数:
voidLineBresenhams(intXa,intYa,intXb,intYb)
//Bresenhams算法程序的设计画直线的实现
voidCSampleView:
:
LineBresenhams(intXa,intYa,intXb,intYb)
{CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
intdx=abs(Xa-Xb);
intdy=abs(Ya-Yb);
intp=2*dy-dx;
inttwody=2*dy;
inttwodydx=2*(dy-dx);
intx,y,xend;
if(Xa>Xb)
{x=Xb;y=Yb;
xend=Xa;
}
else
{
x=Xa;y=Ya;
xend=Xb;
}
pdc->SetPixelV(x,y,RGB(255,0,0));;
while(x{x++;
if(p<0)
p+=twody;
else
{
y++;
p+=twodydx;}
pdc->SetPixelV(x,y,RGB(255,0,0));;
}
}添加事件响应函数:
voidCSampleView:
:
OnBresenhamline()
{
//TODO:
在此添加命令处理程序代码
LineBresenhams(100,200,300,300);
}
实验内容3:
改进的Bresenham算法
添加函数:
voidImproveBresenhams(intXa,intYa,intXb,intYb)
//Bresenham算法改进算法的实现
voidCSampleView:
:
ImproveBresenhams(intXa,intYa,intXb,intYb)
{CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
intdx,dy,e,x,y;
dx=Xb-Xa;
dy=Yb-Ya;
e=-dx;
x=Xa;
y=Ya;
while(x<=Xb){
pdc->SetPixelV(x,y,RGB(255,0,0));;
x++;
e+=2*dy;
if(e>0){
y++;
e-=2*dx;
}
}
}
添加事件响应函数:
//菜单响应函数生成直线ImproveBresenhams算法
voidCSampleView:
:
OnImprove()
{
//TODO:
在此添加命令处理程序代码
ImproveBresenhams(200,100,300,300);
}
四、实验结果:
实验内容1:
设计DDA算法程序
实验内容2:
设计中点Bresenham算法程序
实验内容3:
改进的Bresenham算法
五、回答如下问题:
DDA算法的缺点是什么?
答:
DDA算法的缺点是:
它的y和斜率k必须用浮点数表示,而且每一步都必须对y进行舍入取整,这不利于用硬件实现。
六、其它的实验内容:
答:
添加工具栏按钮DDA,Bresenham,Bresenham改进画直线
在SampleView.cpp中添加代码:
ON_COMMAND(ID_BUTTONDDALine,OnDda)
ON_COMMAND(ID_BUTTONBresenham,OnBresenham)
ON_COMMAND(ID_BUTTONImprovedBresenham,OnImprovedbresenham)
调试点击工具栏按钮查看效果。
七、实验中发现的问题及你解决的方法:
发现的问题:
在生成Release文件时出现错误,但调试时没有错误。
解决的方法:
查了资料,现在还没有解决。
实验二:
圆和椭圆的生成算法
地点:
B401机房时间:
星期四节次:
第一大节
一、实验目的:
1、了解Bresenham法生成圆和椭圆方法
2、掌握Bresenham生成圆和椭圆算法的基本思想、推导和算法
二、实验内容:
实验内容1:
Bresenham法生成圆
实验内容2:
Bresenham法生成椭圆
三、实验步骤:
实验内容1:
Bresenham法生成圆
步骤1:
添加菜单“实验二”,子菜单如下:
圆ID_Circle
步骤2:
在SampleView类中添加函数boolCircleLine(x1,y1,r)
实现代码:
boolCSampleView:
:
CircleLine(intx1,inty1,intr)
{
CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
intx,y,d;
x=0;y=r;d=3-2*r;
while(xpdc->SetPixelV(x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(y+x1,x+y1,RGB(255,0,0));
pdc->SetPixelV(-y+x1,x+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(-y+x1,-x+y1,RGB(255,0,0));
pdc->SetPixelV(y+x1,-x+y1,RGB(255,0,0));
pdc->SetPixelV(x+x1,-y+y1,RGB(255,0,0));
if(d<0)d+=4*x+6;
else{
d+=4*(x-y)+10;
y--;
}
x++;
}
if(x==y){
pdc->SetPixelV(x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(y+x1,x+y1,RGB(255,0,0));
pdc->SetPixelV(-y+x1,x+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(-y+x1,-x+y1,RGB(255,0,0));
pdc->SetPixelV(y+x1,-x+y1,RGB(255,0,0));
pdc->SetPixelV(x+x1,-y+y1,RGB(255,0,0));
}
returntrue;
}
步骤3;添加画圆菜单响应函数:
voidCSampleView:
:
OnCircle()
{
//TODO:
在此添加命令处理程序代码
CircleLine(200,200,100);
}
步骤四:
调试运行。
实验内容2:
Bresenham法生成椭圆
步骤1:
添加菜单“实验二”,子菜单如下:
椭圆:
ID_Ellipse
步骤2:
在SampleView类中添加函数voidEllipse(intx1,inty1,inta,intb)
实现代码:
//画椭圆的函数
voidCSampleView:
:
Ellipse(intx1,inty1,inta,intb)
{
CClientDC*pdc=newCClientDC(this);
CPenpen;
pen.CreatePen(PS_DOT,1,RGB(255,0,0));
CPen*oldpen=(CPen*)pdc->SelectObject(&pen);
floatd1,d2;
intx,y;
x=0;
y=b;
d1=b*b+a*a*(-b+0.25);
pdc->SetPixelV(x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,y+y1,RGB(255,0,0));
while(b*b*(x+1){
if(d1<=0)
{
d1+=b*b*(2*x+3);
x++;
}
else
{
d1+=b*b*(2*x+3)+a*a*(-2*y+2);
x++;
y--;
pdc->SetPixelV(x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,y+y1,RGB(255,0,0));
}
}
d2=b*b*(x+0.5)*(x+0.5)+a*a*(y-1)*(y-1)-a*a*b*b;
while(y>0)
{
if(d2<=0)
{
d2+=b*b*(2*x+2)+a*a*(-2*y+3);
x++;
y--;
}
else
{
d2+a*a*(-2*y+3);
y--;
}
pdc->SetPixelV(x+x1,y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(x+x1,-y+y1,RGB(255,0,0));
pdc->SetPixelV(-x+x1,y+y1,RGB(255,0,0));
}
}
步骤3;添加画圆菜单响应函数:
voidCSampleView:
:
OnEllipse()
{
//TODO:
在此添加命令处理程序代码
Ellipse(100,100,20,10);
}
步骤四:
调试运行。
四、实验结果:
1.程序:
程序在实验步骤中已有
2.图形:
五、回答如下问题:
1、屏幕上显示圆的几部分?
为什么?
答:
8部分,因为我们采用的画圆方法是八分法画圆,在屏幕上画出的是圆的8部分。
2、屏幕上显示椭圆的几部分?
为什么?
答:
8部分,因为我们在画圆的时候在第一象限内画出的有两部分:
上半部分和下半部分;因此在四个象限内画出的是8部分。
六、其它的实验内容:
答:
用动态画圆和椭圆的的方法来画圆:
七、实验中发现的问题及你解决的方法:
答:
发现的问题:
在调用函数的时候用传参的方法传递CClientDC*pdc不能运行;
解决方法:
舍弃传参,每次画图形时重新声明CClientDC指针对象。
实验三:
二维图形的基本几何变换
地点:
B401机房时间:
星期四节次:
第四大节
一、实验目的:
1、掌握二维图形基本的几何变换原理及变换矩阵
2、掌握矩阵运算的程序设计
二、实验内容:
1、平移
2、旋转
三、实验步骤:
1、平移
步骤1:
初始化函数,画出图形平移前的状态。
实现在
voidCSampleView:
:
OnDraw(CDC*pDC)
{CSampleDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//初始化画出图形平移旋转前的状态
staticdoublex1[]={0.0,10.0,100.0,110.0,0.0};
staticdoubley1[]={0.0,50.0,50.0,0.0,0.0};
staticdoublex2[5];
staticdoubley2[5];
inti;
doubler;
pDC->MoveTo(scx(0),scy(-ymax/2));
pDC->LineTo(scx(0),scy(ymax/2));
pDC->MoveTo(scx(-xmax/2),scy(0.0));
pDC->LineTo(scx(xmax/2),scy(0.0));
for(intx=0;x<=1;x=x+20)
{
parallel(x,x/2);
for(i=0;i<=4;i++){
x2[i]=affinex(x1[i],y1[i],1.0);
y2[i]=affiney(x1[i],y1[i],1.0);
}
for(i=0;i<=3;i++){
pDC->MoveTo(scx(x2[i]),scy(y2[i]));
pDC->LineTo(scx(x2[i+1]),scy(y2[i+1]));
}
}
}
步骤2:
⑴旋转函数的添加,在CSampleView类里添加旋转函数voidRotate();//旋转
⑵再依次添加辅助函数及变量
public:
intscx(doublexj);
intscy(doubleyj);
public:
doubleaffinex(doublex,doubley,doubled);
doubleaffiney(doublex,doubley,doubled);
public:
voidparallel(doubledx,doubledy);
public:
doublef[3][3];
//成员变量
doublexmax;
doubleymax;
voidrotate(doubletheta);
⑶在SampleView.cpp中依次实现她们,函数如下:
//平移函数
voidCSampleView:
:
Pan()
{
//TODO:
Addyourcommandhandlercodehere
staticdoublex1[]={0.0,1