北京工商大学.docx
- 文档编号:30748464
- 上传时间:2023-08-20
- 格式:DOCX
- 页数:14
- 大小:26.72KB
北京工商大学.docx
《北京工商大学.docx》由会员分享,可在线阅读,更多相关《北京工商大学.docx(14页珍藏版)》请在冰豆网上搜索。
北京工商大学
北京工商大学
计算机图形学实验报告
试验名称计算机图形学实验共10页
成绩实验日期2005年5月日
班级微机024班组别交报告日期2005年6月15日
学号0214020415姓名欧阳锦林
同组学生教师审批签字
图形学实验报告
——微机024班15号欧阳锦林
一、实验目的:
通过本实验,使自己了解计算机图形学的有关原理、算法及系统,掌握基本图形显示程序设计方法,及二维和三维图形变换程序设计方法,为进一步学习计算机辅助设计方面的技术知识打下基础。
二、实验内容和要求:
1、实验内容
1直线和圆的生成,设定屏幕图形工作方式,彩色象素的读写,直线和圆的扫描转换。
2多边形的裁剪和填充
3图形变换:
二维变换、及投影、透视变换
2、上机实验要求
上机实验是巩固课堂内容。
增强感性认识。
实验后要求学生认真编写实验报告,作为学生平时成绩的依据。
三、实验报告:
1、实验环境:
VStudio6.0的VC6.0,MFC
2、实现功能:
a)直线和圆的生成,直线和圆的扫描转换。
并且实现了用鼠标点击取点的交互功能。
b)多边形的裁剪和填充,实现了点扫描与直线扫描多边形。
c)直线剪裁,并可以自动判断与某条或某些条直线可剪裁,剪裁结果是一条线段生成两到三条线段,并可在文档中保存。
d)图形变换:
二维变换:
平移、旋转、缩放功能,其中平移已实现了鼠标点击取点的交互功能。
e)提供了用户对对象的选择,再在在被选择的对象上进行相应操作。
f)实现了文档存储与打开。
3、文件格式:
1、Graph1.txt文件格式是:
第一行表示有3种类形的图元数据,在本程序中为3,分别为直线,圆,多边形,第二行为第一个数据为类型,1表示为直线容器,第二个数据3表示此直线容器(用双链表实现)中有3条直线。
下面3行的格式相同,分别是颜色,起点、终点的x、y坐标。
第六行中3表示类型3是多边形,2表示多边形个数。
再下面就是各个多边形的信息的,0表示不用填充,15550是颜色值,3表示3边形。
下面三行是三个顶点的x、y坐标。
11-16行信息同理。
17行2表示类型2为圆,1表示1个,18行各个数据分别表示,是否填充、颜色、圆心x、y坐标、半径。
2、可以直接用记事等不带格式的文本编辑器按文件格式进行手工修改,注意:
一定要按格式,否则将不能生成你想要的图元。
4、所用数据结构:
1、GraphObject:
本程序得用一个数据结构把所有的图元装入了,并可以根据不同的类型,做不同的动作,类的定义如下:
//GraphObject是用来存放各种图形对象的,根据type的不同,
//object做不同的类型转换.
classGraphObject
{
private:
void*object;
inttype;
public:
GraphObject();
GraphObject(void*Object,intType);
virtual~GraphObject();
//根据type的不同,做不同的动作。
boolaction(CDC*pCDC);
//根据type的不同,保存不同为格式。
boolsave(ofstream&out);
};
再用CList
容器把所有的对象都装入进去了。
当然,后来为了方便,再加了三个容器,这个容器的作用就不大了,可它却体现了大自然的面向对象的基本原理,值得关注。
2、Matrix:
#definePI3.1415926
//3*3矩阵类:
classMatrix
{
public:
Matrix();
Matrix(constMatrix&mat);
Matrix(inttx,intty);
Matrix(floattx,floatty);
virtual~Matrix();
floatarray[3][3];
voidSetIdentity();//设置对角为1,其余为0
Matrix&operator*(constMatrix&mat);//矩阵乘法.
Matrix&operator+(constMatrix&mat);//矩阵加法
//将点通过矩阵转换为另一个点.
POINT&pointTrans(POINT&point);
};
3、MidLine:
#definePrecision5//此为选择对象的精确度
//线段类:
classMidLine
{
public:
MidLine();
MidLine(intx0,inty0,intx1,inty1);
MidLine(POINTPoint0,POINTPoint1);
virtual~MidLine();
voidMidPointLine(CDC*pCDC);
voidsetColor(COLORREFColor);
boolSelectIt(POINTpoint);
//二维复合变换
voidmove(POINTpoint);
voidrotate(floata,CPointrefpt);
voidscale(floatsx,floatsy,CPointrefpt);
boolselect;
POINTpoint0,point1;
COLORREFcolor;
private:
voidMidPointLine0(intx0,inty0,intx1,inty1,intcolor,intindex,CDC*pCDC);
};
4、MidCircle:
#definePI3.1415926
//3*3矩阵类:
classMatrix
{
public:
Matrix();
Matrix(constMatrix&mat);
Matrix(inttx,intty);
Matrix(floattx,floatty);
virtual~Matrix();
floatarray[3][3];
voidSetIdentity();//设置对角为1,其余为0
Matrix&operator*(constMatrix&mat);//矩阵乘法.
Matrix&operator+(constMatrix&mat);//矩阵加法
//将点通过矩阵转换为另一个点.
POINT&pointTrans(POINT&point);
};
5、Polygon:
#include
#include
#include
#definePrecision5//此为选择对象的精确度
//扫描线算法中的“边”数据结构表示
structEdge{
inty;//边的上端点的y坐标
floatx;//AEL中当前扫描线与边的交点(或ET中边的下端点的x坐标)
floatdeltax;//边的斜率的倒数
//定义边类型的大小比较关系(用于排序)
friendbooloperator<(constEdge&,constEdge&);
};
//结点为边的链表的数据类型
typedefstd:
:
list
//Et表数据类型
typedefstd:
:
map
//多边形类:
classpolygon
{
public:
//多边形数据结构表示
intcount;//多边形顶点数
POINT*pPointArray;//多边形顶点数组
COLORREFcolor;
boolFill;//是否填充
boolselect;//是否为当前选择对象
boolSelectIt(POINTpoint);//判断当前点是否选中多边形
EtTypeet;
EgListael;
//四个构造函数
polygon();
polygon(intCount,POINT*pPoint);
polygon&operator=(constpolygon&py);
virtual~polygon();
//下面四个函数为扫描填充多边形
inttoInt(floata,inttype);
voidinit();
voiddrawLine(intxLeft,intxRight,inty,CDC*pDC);
voidLineScan(CDC*pDC);
voidsetColor(COLORREFColor);
//画多边形,根据Fill是否填充.
voiddrawPoly(CDC*pCDC);
//二维复合变换
voidmove(POINTpoint);
voidrotate(floata,CPointrefpt);
voidscale(floatsx,floatsy,CPointrefpt);
private:
polygon(constpolygon&py);
};
5、调试经验:
我在调试这个程序的时候遇到了一些“低级”错误,也理解了关于C++的一些高级主题,为方便大家的交流,也方便自已以后的学习,我将这此经验都用注释写在相应的地方了。
试举几例:
(1)、polygon&polygon:
:
operator=(constpolygon&py){
//注意下面两行代码,是必须的,
//一定要释放对象以前指向的内存区。
//详细情况请看polygon:
:
polygon(constpolygon&py)的注释
if(pPointArray!
=NULL)
delete[]pPointArray;
count=py.count;
pPointArray=newPOINT[count];
color=15550;
Fill=py.Fill;
select=py.select;
for(inti=0;i pPointArray[i]=py.pPointArray[i]; return*this; } polygon: : polygon(constpolygon&py) { //if(pPointArray! =NULL) //delete[]pPointArray; //! ! ! ! //当用polygonp(py)时,p.pPointArray不会自动设为空! ! //此时用delete将会产生寻常! ! ! //然而: 又如何保证在赋值前释放以前的空间呢! ! ? ? //解答: test类: test.h,注意: 如果写成: testc=a则会调用其拷贝构造函数 //只有写成testc;c=a;才会调用operator= //基于此,可把拷贝构造函数设为私有,才可保证生成对象时一定会调用默认 //构造函数! //但是,如果这样,则在使用这个类时会遇上很多"阻碍",那就是你要避免系统 //"自动"调用你的拷贝构造函数,比如当你的函数形参是对象而不是引用时, //因此,这时你最好检查你的函数,使其用引用做为形参,如果不想因函数改变 //形参,则设为引用即可. //也许,C++在扩充C时加入了一个引用这种奇怪的数值引用方式. count=py.count; pPointArray=newPOINT[count]; color=15550; Fill=py.Fill; select=py.select; for(inti=0;i pPointArray[i]=py.pPointArray[i]; } polygon: : polygon(intCount,POINT*pPoint) { //由于用此种构造函数时,不会设置pPoint为NULL, //故不用下面两行代码 //否则可能删除未初始化指针,产生异常。 //if(pPointArray! =NULL) //delete[]pPointArray; …… (2)、//画多边形,根据Fill选择是否填充. voidpolygon: : drawPoly(CDC*pCDC) { for(inti=0;i { MidLineline(pPointArray[i],pPointArray[i+1]); line.setColor(color); line.MidPointLine(pCDC); } MidLineline(pPointArray[count-1],pPointArray[0]); line.setColor(color); line.MidPointLine(pCDC); if(Fill) { LineScan(pCDC); //下面是用点填充算法实现填充! //由于递归算法太过消耗资源,故将其注释掉 //改成线扫描 /*intx=0,y=0; for(i=0;i //! ! 一个count-1用了我1个半小时 //还是上厕所的时候突然想到,for语句控制错误! ! //可见编程最是要头脑清醒! ! ………… (3)、POSITIONpos=polygonList.GetHeadPosition(); //注意! ! : (CList ! 6、程序特点: (1)、由于本程序是为了实现图形学的各种算法,因此,哪怕是画直线这样的事也都没有调用MFC提供的函数来实现,全部都是自己编写的。 (2)、结构较严谨,在编写的过程中,我注意到了类的结构严谨,文档类视图类的分工合作明确。 但还是很遗留了很多冗繁的地方,因为有的一开始就没有注意,到后来也就没有改了。 (3)、保存了调试信息,我在编写代码是时候喜欢由接口到实现,由简单到复杂的顺序编写,最后我保存了那些有价值的调试代码做为注释,以便以后学习与修改。 (4)、纠正并完善了某些书上的算法: 我用的图形参考书是: 《计算机图形学》倪明田、吴良芝编著,北京大学出版社,但其中很多算法没有用 (1)、//此算法在这里有问题,可能是因为我们所用的坐标系 //原点在左上角而不是程序假设的左下角. /*P0(x0,y0)P1(x1,y1)为待裁剪线段*/ /*rect为裁剪窗口*/ boolCGraphView: : CohenSutherlandLineClip(floatx0,floaty0,floatx1,floaty1,CutRect *rect,POINT&point0,POINT&point1) (2)、boolCGraphView: : CohenSutherlandLineClip(floatx0,floaty0,floatx1,floaty1,CutRect *rect,POINT&point0,POINT&point1)函数中: //注意,书上此行代码有问题! ! //原句是: x=x0+(x1-x0)*((float)rect->ymin-x0)/(y1-y0); //书111面 (3)、在直线的中点算法中,voidMidLine: : MidPointLine0(intx0,inty0,intx1,inty1,intcolor,intindex,CDC*pCDC) { ………… d+=incrE; x++;//注意: 书本47面的的程序少了这行代码,应该加上. …… (4)、直线的中点算法书上只是实现1/8的区域,要以任意点画直线,需要自己做一些转化。 7、待扩充内容: 本程序还有很多地方值得改进,由于时间不够,先做到这里,但现在因为我采用了各种类来定义不同的图元,因此,要扩充是很容易的。 需要扩充的地方有: 图元变换的交互式实现(包括鼠标的变形)、图形类型的添加,如,椭圆,圆弧等,还有就是调色板对颜色的控制。 四、实验总结: 1、实验收获与体会: 比较起这个学期的其他课程来说,我这个图形实验上用的时间是最多的,当然收获也是最大的,做完实验后,不免清点一下: a、对C++语言的进一步应用与理解,最大的收获便是引用,我以前一直对引用总是一知半解,知其然不知其所以然,现在明白了,在C++这种语言中,为什么要在C语言的基础上加入引用呢? 我觉得是基于以下几个方面的原因: 1、高效: 如果用对象做为函数的形参,不仅要支付构造函数析构函数的执行代价,当遇上大对象时更是空间的极大浪费,还有就是对象做为形参是不能改变函数体外的数据的;如果用指针,效率问题可以得到问题,却要承担更大的风险,如空指针、野指针引发的内存泄漏或异常;还有不能有效防止函数体内不影响函数体个的数据,引用用const修饰保证常量性,用声明时初始化来保证非空。 2、安全: 主要与指针相比,原因在1中说明。 3、可以避免在某些情况禁止拷贝构造函数。 关于拷贝构造函数的具体介绍见调试经验中的详细说明。 b、对MFC的学习。 利用这次实验的机会,我在以前C++语言的基础上学习了windows环境下的编程,先是API,后来就是MFC了,可以在这次实验后,我已可以基本了解windows以及MFC的编程机制了。 C、对图形理论的更深入的理解。 毕竟,从理论到实践还有那么一段距离,可是当你跨过去之后,也是对理论学习的一种补充与提高。 更重要的是,就像郝老师说的: 编程到了一定程度上时又要求理论知识的良好掌握。 是的,两者相辅相成,缺一不可。 D、最后,要感谢我的图形老师郝建强老师,他不仅在理论上帮助了我,更从编程方面给了我许多有益的启发。 参考书: 1、《计算机图形学》倪明田、吴良芝编著,北京大学出版社 2、《MFCwindows程序设计》(第2版)JeffProsise清华大学出版社 3、《windows图形编程》FengYuan机械工业出版社 4、《C++编程思想》Bruck著侯捷译机械工业出版社
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北京 工商大学
![提示](https://static.bdocx.com/images/bang_tan.gif)