收藏 分销(赏)

计算机图形学课程设计实习报告.doc

上传人:w****g 文档编号:9874934 上传时间:2025-04-11 格式:DOC 页数:42 大小:2.28MB 下载积分:12 金币
下载 相关 举报
计算机图形学课程设计实习报告.doc_第1页
第1页 / 共42页
计算机图形学课程设计实习报告.doc_第2页
第2页 / 共42页


点击查看更多>>
资源描述
计算机图形学课程设计实习报告 42 2020年4月19日 文档仅供参考,不当之处,请联系改正。 实验零  Visual C++ 绘图系统 地点: 土木楼B401机房 时间: 星期三下午 节次: 第三大节 一、 实验目的: 1. 了解Visual C++ 绘图的基本概念 2. 了解Visual C++ 绘图环境 3. 掌握用Visual C++ 设计绘图项目的基本步骤 4. 掌握用Visual C++ 绘图的基本命令 二、 实验内容: 实验内容1:创立绘图应用程序主框架 实验内容2:应用程序编译运行 实验内容3:设置菜单项并生成消息响应函数 实验内容4:SetPixel绘图 三、 实验步骤: 实验内容1:创立绘图应用程序主框架 步骤: 1.创立一个工作目录D:\MyProject 2.启动 Visual Studio 3.单击“文件”->“新建”->“项目”,项目类型对话框中选择“其它语言”->“VC++” ->“MFC”,模版选择“MFC应用程序”。在工作目录D:\MyProject 下创立一个新应用项目: Sample,如下图所示。 4.单击“确定”按钮。 5.单击“下一步”按钮。 6.在“应用程序类型中”,选择“单文档”类型。 7.单击“完成”,创立了一项空的工程-绘图应用程序主框架。 实验内容2:应用程序编译运行 运行版本有两类:Debug、Release, 生成Debug解决方案步骤如下: 1.生成解决方案 点击“生成-〉生成解决方案”, 生成了Debug版的可运行程序。 2.调试运行程序 点击菜单“调试——〉开始执行(不调试)”, 执行Debug版的可运行程序。 结果如下: 生成Release解决方案步骤如下: 1.生成解决方案 点击“生成-〉批生成”。 2.勾选“Release”,单击“生成”,生成能够独立于Visual C++ 外运行的.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.进入代码编辑器 在void Csample0View::OnLineDda()中的 // TODO: 在此添加命令处理程序代码处输入的自己代码: AfxMessageBox("Hello World",MB_OK,NULL); 7.修改项目字符集属性 选择“项目”菜单->属性->,弹出“属性”对话框,选择“配置属性 ->常规->字符集”,改为“未设置”。 8.运行结果 重新生成解决方案,运行结果如下。 实验内容4:SetPixel绘图 在void Csample0View::OnLineDda()中的 // TODO: 在此添加命令处理程序代码处输入的代码: // TODO: Add your command handler code here CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); int x,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=new CClientDC(this);//定义一个指针类型的CClientDC对象,客户区设备上下文用于客//户区的输出,与特定窗口关联 CPen pen;//定义一个画笔对象 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算法程序 添加函数:void DDALine(int Xa, int Ya, int Xb, int Yb) //DDA算法 void CSampleView::DDALine(int Xa, int Ya, int Xb, int Yb) { CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); float delta_x,delta_y;int x,y; int dx,dy,steps,k; dx=Xb-Xa; dy=Yb-Ya; if(abs(dx)>abs(dy)) steps=abs(dx); else steps=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算法程序的设计画直线 void CSampleView::OnDdaLine() { DDALine(100,100,300,300); } 实验内容2:设计中点Bresenham算法程序 添加函数:void LineBresenhams(int Xa,int Ya,int Xb,int Yb) //Bresenhams算法程序的设计画直线的实现 void CSampleView::LineBresenhams(int Xa,int Ya,int Xb,int Yb) { CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); int dx=abs(Xa-Xb); int dy=abs(Ya-Yb); int p=2*dy-dx; int twody=2*dy; int twodydx = 2*(dy-dx); int x,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<xend) { x++; if(p<0) p+=twody; else { y++; p+=twodydx; } pdc->SetPixelV(x,y,RGB(255,0,0));; } }添加事件响应函数: void CSampleView::OnBresenhamline() { // TODO: 在此添加命令处理程序代码 LineBresenhams(100,200,300,300); } 实验内容3:改进的Bresenham算法 添加函数:void ImproveBresenhams(int Xa, int Ya, int Xb, int Yb) //Bresenham算法改进算法的实现 void CSampleView::ImproveBresenhams(int Xa, int Ya, int Xb, int Yb) { CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); int dx,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算法 void CSampleView::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类中添加函数bool CircleLine(x1,y1,r) 实现代码: bool CSampleView::CircleLine(int x1, int y1, int r) { CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); int x,y,d; x = 0; y = r; d = 3 - 2 * r; while(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)); 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)); } return true; } 步骤3;添加画圆菜单响应函数: void CSampleView::OnCircle() { // TODO: 在此添加命令处理程序代码 CircleLine(200,200,100); } 步骤四:调试运行。 实验内容2:Bresenham法生成椭圆 步骤1:添加菜单“实验二”,子菜单如下:椭圆:ID_Ellipse 步骤2:在SampleView类中添加函数void Ellipse(int x1,int y1,int a, int b) 实现代码: // 画椭圆的函数 void CSampleView::Ellipse(int x1,int y1,int a, int b) { CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_DOT,1,RGB(255,0,0)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); float d1,d2; int x,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)<a*a*(y-0.5)) { 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;添加画圆菜单响应函数: void CSampleView::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:初始化函数,画出图形平移前的状态。实现在 void CSampleView::OnDraw(CDC* pDC) { CSampleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); //初始化画出图形平移旋转前的状态 static double x1[]={0.0,10.0,100.0,110.0,0.0}; static double y1[]={0.0,50.0,50.0,0.0,0.0}; static double x2[5]; static double y2[5]; int i; double r; 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(int x=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类里添加旋转函数void Rotate();// 旋转 ⑵再依次添加辅助函数及变量 public: int scx(double xj); int scy(double yj); public: double affinex(double x,double y,double d); double affiney(double x,double y,double d); public: void parallel(double dx,double dy); public: double f[3][3]; //成员变量 double xmax; double ymax; void rotate(double theta); ⑶在SampleView.cpp中依次实现她们,函数如下: //平移函数 void CSampleView::Pan() { // TODO: Add your command handler code here static double x1[]={0.0,10.0,100.0,110.0,0.0}; static double y1[]={0.0,50.0,50.0,-10.0,0.0}; static double x2[5]; static double y2[5]; int i; double x; CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_SOLID,1,RGB(0,0xff,0x1f)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); 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(x=-300;x<=200;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])); } } pdc->DeleteDC(); } int CSampleView::scx(double xj) { int x; x=(int)(xj+xmax/2); return(x); } int CSampleView:: scy(double yj) { int y; y=(int)ymax-(int)(yj+(ymax/2)); return(y); } void CSampleView:: parallel(double dx,double dy) { f[0][0]=1.0;f[0][1]=0.0;f[0][2]=0.0; f[1][0]=0.0;f[1][1]=1.0;f[1][2]=0.0; f[2][0]=dx;f[2][1]=dy;f[2][2]=1.0; } double CSampleView::affinex(double x,double y,double d) { double xx; xx=x*f[0][0]+y*f[1][0]+d*f[2][0]; return(xx); } double CSampleView::affiney(double x,double y,double d) { double yy; yy=x*f[0][1]+y*f[1][1]+d*f[2][1]; return(yy); } ⑷添加事件响应函数调用平移函数 void CSampleView::OnPan() { // TODO: 在此添加命令处理程序代码 Pan(); } 平移完成。 2、旋转 步骤一:在平移完成的基础上添加旋转函数void Rotate()和辅助函数void rotate(); 实现函数如下: void CSampleView::rotate(double theta) { double th; th=theta/180*3.1415927; f[0][0]=cos(th);f[0][1]=sin(th);f[0][2]=0.0; f[1][0]=-sin(th);f[1][1]=cos(th);f[1][2]=0.0; f[2][0]=0.0;f[2][1]=0.0;f[2][2]=1.0; } 实现代码如下: //旋转函数 void CSampleView::Rotate() { static double x1[]={0.0,10.0,100.0,110.0,0.0}; static double y1[]={0.0,50.0,50.0,0.0,0.0}; static double x2[5]; static double y2[5]; int i; double r; CClientDC *pdc=new CClientDC(this); CPen pen; pen.CreatePen(PS_SOLID,1,RGB(0,0xff,0x1f)); CPen *oldpen=(CPen*)pdc->SelectObject(&pen); 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(r=0;r<360;r=r+10){ rotate(r); 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])); } } pdc->DeleteDC(); } 添加事件响应函数调用旋转函数: void CSampleView::Onrotate() { // TODO: 在此添加命令处理程序代码 Rotate(); } 旋转完成。 四、实验结果: 1.程序 实验步骤中已包含完整的程序代码。 2.图形 程序打开时如图: 平移N次后: 旋转n次后: 五、 其它的实验内容: 其它内容:用工具栏按钮实现平移和旋转。 六、 实验中发现的问题及你解决的方法: 发现的问题:老师给的参考程序上有些函数没有定义,需自己编。 解决方法:自己在网上找图形学的资料,找到该函数后在程序中自己定义。
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 应用文书 > 报告/总结

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服