计算机图形学上机指导_第1页
计算机图形学上机指导_第2页
计算机图形学上机指导_第3页
计算机图形学上机指导_第4页
计算机图形学上机指导_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算机图形学上机实验指导书机电工程系 丁有和编班级:学号:姓名电气与自动化工程学院2009年10月目 录上机实验说明2实验1 直线3实验2 矩形、多边形和圆16实验3 曲线21实验4 对象拾取和对象颜色修改31实验5 删除和移动40上机实验说明1. 不同与其他课程的实验,本课程的实验是将各次分实验的内容组合成一个简单的cad软件系统。故每次实验后,需要自行保存实验中所写的代码,且一旦实验1创建的项目名定下来之后,以后实验的项目名就难以更改,切记切记!2. 每次实验后,请及时完成本实验书中的思考与问答。由于这些题目都是涉及到本次实验中的内容,因此做完每次实验后方可回答,并做好每次实验的预习工作。

2、若是文字思考与问答题,则将回答的文字内容写在项目中的readme.txt中;若是程序题,则将添加或修改的过程和代码一并写在readme.txt,注意要注明是哪个实验的回答。3. 实验完成后,要将项目工作文件夹中的debug子文件夹删除,同时删除扩展名为*.aps和*.opt(各一个)文件,然后将整个项目工作文件夹用winrar或其它压缩工具软件压缩成一个文件,文件名就是项目工作文件夹名。这样,就可以提交了!4. 本课程实验的开发平台是visual c+ 6.0,若有疑问请email:dingyouhe或致电实验1 直线实验内容(1) 构造图元存取模型和交互框架。(2)

3、 用bresenham算法绘制直线,并实现直线段的动态定位过程。实验准备和说明(1) 阅读教材中关于直线的生成算法内容。(2) 准备本次上机所需要的程序。(3) 创建工作文件夹“学号”。实验步骤1 创建工作文件夹以自己的学号(全称,如21060501)创建一个工作文件夹。2 启动visual c+ 6.03 创建并运行一个单文档应用程序ex_cgyxzz(1) 选择“文件”“新建”菜单,在弹出的“新建”对话框中选择“工程”标签,这时显示出一系列的应用程序项目类型;选择mfc appwizard(exe)的项目类型;单击按钮将项目工作文件夹位置定位在“学号”;在工程框中输入项目名ex_cgyxz

4、z(注意:项目名中,y表示年号的最后一个数字,如2008用8表示,x表示班号的最后一位数字,如210605用5表示,zz表示学号的后两位数。例如21060501学生2008年做此实验时应创建的项目名称应为ex_cg8501)。如图1.1所示的步骤。图1.1 创建的步骤次序注意:作为示例参考,本项目程序名指定为ex_cg8。(2) 单击确定按钮,在出现的step 1对话框中,选择“单个文档”类型,然后单击完成按钮。随后出现“工程信息”对话框,单击确定按钮,回到了visual c+主开发环境。(3) 单击编译工具条上的生成工具按钮“”或直接按快捷键f7或打开“编译”菜单,选取“编译ex_hello

5、.exe”命令,系统开始对ex_hello进行编译、连接,同时在输出窗口中显示出编译的内容,当出现表示ex_cg8.exe可执行文件已经正确无误地生成了。(4) 单击编译工具条上的运行工具按钮“”或直接按快捷键ctrl+f5或在“编译”菜单中选取“执行ex_cg8.exe”,就可以运行刚刚生成的ex_cg8.exe了。注:以后凡是说“编译和运行”,就是指上述(3)、(4)这两步操作。4 添加图元存取模型基本思路:a, 在创建的项目中进行基本图元的绘制,需要将其数据保存下来,保存的最简单方法就是将图元绘制命令及其参数构成一个字符串,命令和各参数之间用逗号隔开。这样,若将这些字符串保存在字符串集合

6、类型(cstringarray,mfc库的集合类,相当于数组)变量中,就可以读取并解析集合中的图元,然后根据定义图元的不同命令词决定图元的绘制。b, 为了能通过文件来保存和读取,因而还需对字符串集合进行文档序列化,并设置其文件的扩展名。具体步骤如下:(1) 将项目工作区切换到classview页面,展开ex_cg8所有的类节点。(2) 双击,将在右边的文档窗口中自动打开ccgdemodoc.h文档,添加下列cstringarray类型成员m_strdataarray,用来存取图元绘制命令及其参数:class cex_cg8doc : public cdocumentpublic:cstring

7、arraym_strdataarray;protected: / create from serialization onlycex_cg8doc();declare_dyncreate(cex_cg8doc)注:凡是带有底纹的代码都是自己要添加的代码。(3) 在左边项目工作区的classview页面中,展开cex_cg8doc类的所有成员节点,双击节点,将自动定位到ex_cg8doc.cpp文档中成员函数serialize实现代码处,添加图元字符串集合数据的序列化代码:void cex_cg8doc:serialize(carchive& ar)if (ar.isstoring()/ tod

8、o: add storing code herefor (int i=0; iloadstandardcursor( idc_cross ) );return true;/return cview:onsetcursor(pwnd, nhittest, message);(8) 编译运行后,当鼠标移动到客户区内,鼠标是否变成了十字形。6 添加绘制直线函数(1) 将项目工作区切换到classview页面,展开ex_cg8所有的类节点。(2) 右击节点,从弹出的快捷菜单中选择add member function菜单命令,弹出添加成员函数对话框。(3) 在对话框中,输入drawbline(cdc

9、*pdc, point pt1, point pt2, colorref color)成员函数的类型(void)和声明。如图1.4所示。图1.4 添加成员函数(4) 单击确定按钮,将在文档窗口中自动定位函数drawbline的实现位置,输入下列代码(该函数用bresenham算法绘制直线,color是直线的颜色):void cex_cg8view:drawbline(cdc *pdc, point pt1, point pt2, colorref color)int x1 = pt1.x, y1 = pt1.y;int x2 = pt2.x, y2 = pt2.y;int dx, dy, x,

10、 y, p, const1, const2, inc, tmp;dx = x2 - x1; dy = y2 - y1;if (dx*dy = 0)inc = 1;elseinc = -1;if (abs(dx)abs(dy) if (dxsetpixelv( x, y, color );while (xx2) x+;if (psetpixelv( x, y, color ); else if (dysetpixelv( x, y, color );while (yy2) y+;if (psetpixelv( x, y, color );需要说明的是:代码中,setpixelv是cdc类的一个成

11、员函数,用来在指定的位置显示一个色素。colorref是颜色的一个参考类型,其颜色的值的指定常使用宏rgb来进行。(5) 编译,看看有没有错误?若有,则比对上述代码,直到编译通过为止。7 测试直线函数的功能(1) 将项目工作区切换到resourceview页面,展开所有的节点。(2) 双击资源“menu”项中的idr_mainframe,则菜单编辑器窗口出现在主界面的右边,相应的ex_cg8项目的菜单资源被显示出来。如图1.5所示。菜单的空位置图1.5 菜单编辑器(3) 在菜单的空位置上双击鼠标左键,则出现它的属性对话框,如图1.6所示。在该对话框中用户可以定义菜单的文本内容和资源id号。虽然

12、,id号的定义是随意的,但最好按易记的规则来确定的。图1.6 菜单项属性对话框需要注意的是: 当菜单项的属性中选中了“弹出(pop_up)”时,对话框中id、分隔符(separator)和提示 (prompt)项无效。 增加新的菜单项后,用户可以用鼠标将菜单项拖到其他位置,而当菜单项位置改变时,其属性并没改变。 标题框输入的“绘图(&d)”中的“&”字符表示后面的字符是该菜单项的助记符。助记符与alt构成一个组合键,当按住“alt”键不放,再敲击该字母时,对应的菜单项就会被选中。(4) 双击“绘图”菜单下的空位置,弹出“菜单项属性”对话框,在该对话框中,输入id号为id_draw_line,标

13、题内容为“直线段(&l)”。然后关闭该对话框。(5) 将“绘图”菜单项拖放到“查看”和“帮助”菜单项之间,如图1.7所示。图1.7 “绘图”菜单拖放的位置(6) 按ctrl+w快捷键打开mfc classwizard对话框。在class name组合框中,将类名选定为cex_cg8view。此时,object ids和messages列表内容会相应的改变。(7) 在object ids列表框中选定id_draw_line,而在messages列表中选定command消息。双击messages列表中的command消息或单击add function按钮,都会在cex_cg8view类中添加该菜单

14、id_draw_line消息的映射函数ondrawline,同时在member funcions列表中显示这一消息映射函数和被映射的消息,结果如图1.8所示。图1.8 映射菜单项的命令消息(8) 单击edit code按钮,mfc classwizard对话框退出,并自动定位到文档窗口中的cex_cg8view类的ondrawline函数处,为其添加下列测试代码:void cex_cg8view:ondrawline() / todo: add your command handler code herecpointpt1( 30, 10 );cpointpt2( 100, 18 );cpoi

15、ntpt3( 90, 90 );cpointpt4( 10, 70 );cdc *pdc= getdc();colorref color = rgb( 0,0,0 );drawbline( pdc, pt1, pt2, color );drawbline( pdc, pt2, pt3, color );drawbline( pdc, pt3, pt4, color );drawbline( pdc, pt4, pt1, color );需要说明的是:cpoint是mfc常用的点类,用于描述平面中的一个点坐标(x, y)。getdc是cwnd(窗口类)的一个成员函数,用于返回当前窗口的设备指针。

16、rgb是用于构成colorref颜色类型数据的宏,其参数是用于r(红)、g(绿)、b(蓝)三个颜色元的值(0255)。(9) 编译并运行,选择“绘图”“直线段”菜单,结果如图1.9所示。图1.9 运行的结果8 实现交互在程序中,动态定位实际上可以分为三个步骤:启动、动态和终止。启动时,可设置动态定位标志为true;而进入动态过程后,一种是通过多线程方式来获取动态终止的条件,但这种方法比较繁琐,另一种方法是根据单击鼠标的次数来作为动态的终止条件。但动态过程的图形须用程序来指定其形状,并通过xor绘图方式来进行。具体步骤如下:(1) 双击节点,将自动打开该的头文件ex_cg8view.h,在该类中

17、添加下列声明代码:class cex_cg8view : public cviewpublic:cstringm_strcurcommand;/ 当前命令cstringm_strprevcommand;/ 前一个命令boolm_benterrubber;/ 是否进入橡皮条过程boolm_berfirst;/ 进入橡皮条过程后,是否首次绘制橡皮条,er表示enterrubbercpointm_pterprev;/ 进入橡皮条的前一个位置点cpointm_ptcurrent;/ 当前位置点intm_ncmdptnum;/ 该绘制命令所需要的点数,当为负数时,表示无穷个intm_nerptnum;/

18、 进入橡皮条前所需要的点的个数intm_ncurptnum;/ 当前实际点的个数colorref m_crcurcolor;/ 当前绘制图形颜色protected: / create from serialization onlycex_cg8view();declare_dyncreate(cex_cg8view)思路:m_strcurcommand用来决定命令的类型以及橡皮条形状,这样当绘图命令开始时,m_ncurptnum的初值为0,每在客户区单击鼠标时,m_ncurptnum自动加1,当m_ncurptnum大于等于m_nerptnum值时,m_benterrubber置为true,此

19、时移动鼠标,将需要代码绘制橡皮条形状,当左击鼠标的次数超过m_ncmdptnum时,橡皮条过程结束,绘制实际所构造的图形。(2) 右击节点,从弹出的快捷菜单中选择add member function菜单命令,弹出添加成员函数对话框。在对话框中,输入resetdrawdata(void)成员函数的类型(void)和声明。单击确定按钮,将在文档窗口中自动定位函数resetdrawdata的实现位置,输入下列初始化代码:void cex_cg8view:resetdrawdata()m_strcurcommand= ;m_strprevcommand= ;m_benterrubber= false

20、;m_berfirst= true;m_pterprev= cpoint( 0, 0 );m_ncmdptnum= 0;m_nerptnum= 0;m_ncurptnum= 0;(3) 按上一步,为cex_cg8view添加成员函数void drawrubber( cpoint point ),添加下列代码:void cex_cg8view:drawrubber(cpoint point)cdc *pdc = getdc();pdc-setrop2( r2_xorpen );colorref color = rgb( 196, 96, 96 );if ( m_strcurcommand.lef

21、t(4) = line )drawbline( pdc, m_pterprev, point, color );(4) 在项目工作区的classview页面中,展开cex_cg8view下的所有节点,双击节点,将自动定位到cex_cg8view:cex_cg8view构造函数处,添加下列初始化代码:cex_cg8view:cex_cg8view()/ todo: add construction code herem_crcurcolor = rgb( 0, 0, 0 );(5) 类似的,定位到cex_cg8view:ondrawline函数,修改成下列代码:void cex_cg8view:

22、ondrawline() / todo: add your command handler code hereresetdrawdata();m_strcurcommand= line;m_ncmdptnum= 2;m_nerptnum= 1;(6) 定位到cex_cg8view:onlbuttondown函数处,添加下列代码:void cex_cg8view:onlbuttondown(uint nflags, cpoint point) / todo: add your message handler code here and/or call defaultif ( m_strcurco

23、mmand != )m_ncurptnum+;if ( m_ncurptnum = m_nerptnum )m_pterprev= point;m_benterrubber= true;if ( m_ncurptnum = m_ncmdptnum ) & (m_ncmdptnum0)resetdrawdata();cview:onlbuttondown(nflags, point);(7) 定位到cex_cg8view: onmousemove函数处,添加下列代码:void cex_cg8view:onmousemove(uint nflags, cpoint point) / todo: a

24、dd your message handler code here and/or call defaultif (m_benterrubber) if ( m_berfirst )m_berfirst= false;m_ptcurrent= point;drawrubber( m_ptcurrent ); elsedrawrubber( m_ptcurrent );m_ptcurrent= point;drawrubber( m_ptcurrent );cview:onmousemove(nflags, point);(8) 定位到cex_cg8view: onrbuttondown函数处,添

25、加下列代码:void cex_cg8view:onrbuttondown(uint nflags, cpoint point) / todo: add your message handler code here and/or call defaultdrawrubber( m_ptcurrent );resetdrawdata();cview:onrbuttondown(nflags, point);(9) 编译并运行,选择“绘图”“直线段”菜单,然后在客户区任意单击一次鼠标,移动鼠标,看看有什么现象出现?(10) 定位到cex_cg8view: onsetcursor函数处,修改成下列代码

26、:bool cex_cg8view:onsetcursor(cwnd* pwnd, uint nhittest, uint message) / todo: add your message handler code here and/or call defaultif ( m_strcurcommand != )setcursor( afxgetapp()-loadstandardcursor( idc_cross ) );return true;else return cview:onsetcursor(pwnd, nhittest, message);9 绘制和更新说明:当程序运行后,改

27、变窗口的大小时,客户区已绘制的图线会消失。这是因为cex_cg8view视图类所控制的客户区的自动更新是由ondraw这个虚函数来完成的。因而,需要在该函数添加所有图元的绘制代码。其次,绘制时,图元的相关的参数又是如何保存的呢?下面的步骤就是用来解决这些问题。(1) 右击节点,从弹出的快捷菜单中选择add member function菜单命令,弹出添加成员函数对话框。在对话框中,输入drawcommand(cdc *pdc, cstring strcmd)成员函数的类型(void)和声明。单击确定按钮,将在文档窗口中自动定位函数drawcommand的实现位置,输入下列初始化代码:void

28、cex_cg8view:drawcommand(cdc *pdc, cstring str)cstring strline = str;strline.trimleft();strline.trimright();if ( strline.isempty() ) return;/ 解析出命令字和数据,它们之间的分隔符是逗号cstring strcmd;longnbuffer 256 ;/* 设置最大的数据个数为256个 */intnnum;/* 实际个数 */int nindex = strline.find(,);if (nindex 0 ) strcmd = strline.left( n

29、index );else return;nnum = 0;while ( nindex 0 ) & ( nnum 0 )nbuffer nnum = atol(strline.left( nindex );elsenbuffer nnum = atol( strline );nnum+;/ 绘制命令strcmd.trimleft();strcmd.trimright();if ( strcmd = line ) & (nnum=4)/ 绘制直线段cpoint pt1( nbuffer0, nbuffer1 );cpoint pt2( nbuffer2, nbuffer3 );drawbline

30、( pdc, pt1, pt2, m_crcurcolor );/ 以后还要添加代码(2) 将项目工作区切换到classview页面,定位到cex_cg8view:onlbuttondown函数处,修改下列代码:void cex_cg8view:onlbuttondown(uint nflags, cpoint point) / todo: add your message handler code here and/or call defaultif ( m_strcurcommand != )cstring str;str.format(%s,%ld,%ld, m_strcurcomman

31、d, point.x, point.y );m_strcurcommand= str;m_ncurptnum+;if ( m_ncurptnum = m_nerptnum )m_pterprev= point;m_benterrubber= true;if ( m_ncurptnum = m_ncmdptnum ) & (m_ncmdptnum0)drawrubber( m_ptcurrent );drawcommand( getdc(), m_strcurcommand );cex_cg8doc* pdoc = getdocument();pdoc-m_strdataarray.add( m

32、_strcurcommand );resetdrawdata();cview:onlbuttondown(nflags, point);(3) 定位到cex_cg8view:ondraw函数处,添加下列代码:void cex_cg8view:ondraw(cdc* pdc)cex_cg8doc* pdoc = getdocument();assert_valid(pdoc);/ todo: add draw code for native data herefor (int i=0; im_strdataarray.getsize(); i+)cstringstrline = pdoc-m_s

33、trdataarray.getat(i);drawcommand( pdc, strline );(4) 这样整个框架就基本构建好了,但还有一个细节,即每次单击鼠标时,最好能有一个标记点显示出来。故为类cex_cg8view添加成员函数void drawtag ( cpoint pt),该函数的代码如下:cex_cg8view:drawtag(cpoint pt)cdc *pdc = getdc();colorref color = rgb( 96, 96, 96 );drawbline( pdc, cpoint( pt.x - 4, pt.y ), cpoint( pt.x + 4, pt.

34、y ), color );drawbline( pdc, cpoint( pt.x, pt.y - 4 ), cpoint( pt.x, pt.y + 4 ), color );(5) 定位到cex_cg8view:onlbuttondown函数处,添加下列代码:void cex_cg8view:onlbuttondown(uint nflags, cpoint point) if ( m_strcurcommand != )cstring str;str.format(%s,%ld,%ld, m_strcurcommand, point.x, point.y );m_strcurcomman

35、d= str;drawtag( point );m_ncurptnum+;if ( m_ncurptnum = m_nerptnum )(6) 编译运行并测试。思考与问答(1) 说说向一个类中添加成员函数的方法和过程。(2) 将drawbline中的bresenham算法代码改成dda算法代码。实验2 矩形、多边形和圆实验内容在实验1的基础上,添加下列功能:(1) 实现矩形的动态定位过程及其命令的存取。(2) 实现一般多边形的动态定位过程及其命令的存取。(3) 实现圆的动态定位过程及其命令的存取。实验准备和说明(1) 在上一个实验中,直线的动态定位的结束判断是通过判断指定的命令点个数是否满足要

36、求。但对于多边形而言,由于并不能预先知道点的个数,因此上述方法并不适用,为此需要单击鼠标右键,来使动态定位的过程结束。(2) 本次实验是在上一次实验的基础上进行的,请构思本次上机所需要的程序。实验步骤1 启动visual c+ 6.02 打开上一次实验项目ex_cg8(1) 选择“文件(file)”“打开工作空间”命令,弹出如图2.1所示的对话框。图2.1 “打开工作区”对话框(2) 定位到上一次实验项目的保存时的文件夹ex_cg8,双击或选中ex_cg8.dsw,然后单击打开按钮。3 添加矩形的动态定位(1) 打开菜单资源,在“绘图”菜单下再添加一个菜单项“矩形(&r)”,id号设为id_d

37、raw_rect。(命令字为“rect”)(2) 用mfc classwizard为该菜单项在cex_cg8view类中映射其command消息,并添加下列代码:void cex_cg8view: ondrawrect() resetdrawdata();m_strcurcommand= rect;m_ncmdptnum= 2;m_nerptnum= 1;(3) 定位到cex_cg8view:drawrubber函数处,添加下列代码:void cex_cg8view:drawrubber(cpoint point)if ( m_strcurcommand.left(4) = line )dra

38、wbline( pdc, m_pterprev, point, color );else if ( m_strcurcommand.left(4) = rect )drawbline( pdc, m_pterprev, cpoint(point.x, m_pterprev.y), color );drawbline( pdc, cpoint( point.x, m_pterprev.y), point, color );drawbline( pdc, m_pterprev, cpoint(m_pterprev.x, point.y), color );drawbline( pdc, cpoin

39、t( m_pterprev.x, point.y), point, color ); (4) 定位到cex_cg8view:drawcommand函数处,添加下列代码:void cex_cg8view:drawcommand(cdc *pdc, cstring str)/ 以后还要添加代码if ( strcmd = rect ) & (nnum=4)/ 绘制矩形cpoint pt1( nbuffer0, nbuffer1 );cpoint pt2( nbuffer2, nbuffer3 );drawbline( pdc, pt1, cpoint(pt2.x, pt1.y), m_crcurco

40、lor );drawbline( pdc, cpoint( pt2.x, pt1.y), pt2, m_crcurcolor );drawbline( pdc, pt1, cpoint(pt1.x, pt2.y), m_crcurcolor );drawbline( pdc, cpoint( pt1.x, pt2.y), pt2, m_crcurcolor );(5) 编译运行并测试。4 添加多边形的动态定位(1) 打开菜单资源,在“绘图”菜单下再添加一个菜单项“多边形(&p)”,id号设为id_draw_poly。(命令字为“poly”)(2) 用mfc classwizard为该菜单项在c

41、ex_cg8view类中映射其command消息,并添加下列代码:void cex_cg8view:ondrawpoly() resetdrawdata();m_strcurcommand= poly;m_ncmdptnum= -1;/* 点个数未知 */m_nerptnum= 1;(3) 定位到cex_cg8view:drawrubber函数处,添加下列代码:void cex_cg8view:drawrubber(cpoint point)else if ( m_strcurcommand.left(4) = rect ) else if ( m_strcurcommand.left(4)

42、= poly )drawbline( pdc, m_pterprev, point, color );(4) 定位到cex_cg8view:drawcommand函数处,添加下列代码:void cex_cg8view:drawcommand(cdc *pdc, cstring str)if ( strcmd = rect ) & (nnum=4)/ 绘制矩形 if ( strcmd = poly ) & (nnum=4)/ 绘制矩形cpoint pt1( nbuffer0, nbuffer1 );cpoint temp;for ( int i=1; i= 6 )/ 不小于3个点,可以构成一个多

43、边形,绘制最后的封闭线drawbline( pdc, temp, cpoint(nbuffer0, nbuffer1), m_crcurcolor );(5) 定位到cex_cg8view:onrbuttondown函数处,添加下列代码:void cex_cg8view:onrbuttondown(uint nflags, cpoint point) drawrubber( m_ptcurrent );if ( m_strcurcommand != ) & ( m_ncmdptnum = m_nerptnum + 1)drawcommand( getdc(), m_strcurcommand );cex_cg8doc* pdoc = getdocument();pdoc-m_strdataar

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论