计算机图形学学习体会

时间:2019-05-12 06:51:46下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《计算机图形学学习体会》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《计算机图形学学习体会》。

第一篇:计算机图形学学习体会

计算题图形学课程学习体会

计算机图形学是研究用计算机生成、处理和显示图形的一门学科。他的重要性体现在人们越来越强烈的需要和谐的人机交互环境,UI已经成为软件的重要组成部分,以图形的方式表示抽象的概念和数据已经成为信息领域的发张趋势。这门课我们通过自学和同学间互相上课,了解和掌握了计算机图形学的概念、方法和基本的算法。

学习的过程中,感触比较深的是,常常被那些算法所困扰,算法很难理解,解释的枯燥而且难学。原因首先是计算机图形学这门学科本身特点就是综合性很强,涉及的内容和应用广泛,学科交叉复杂。综合了计算机科学、数学、物理学等其他相关学科的知识。而且学科发展日新月异,新的应用领域不断拓展,相关学科相互渗透。其次是与计算机图形学课程中的算法特点有关。很多的算法是为了追求高效率,精益求精,构思独特、实现精巧,算法本身就很难看懂和理解。第三方面就是这门课程是一门理论性和实践性兼顾的综合性课程,实践性很强,不实践就显得空洞,枯燥乏味。

这门课学习的目的是让我们掌握计算机图形学的相关概念、原理和知识,算法的难学难理解,是我们学习的主要障碍。课程实践中,教员让我们自学,互相授课,增强时间体会。在自学和自作可见互相授课过程中,要求要注重基础,强调基本

这些动画,对增强原理、算法的理解性具有很大的作用。

以上是本人在计算机图形课学习过程中的体会,字数不多,确是心得,不足之处还请曹老师指正。

第二篇:《计算机图形学》实验报告

吉林大学

计算机科学与技术学院

《计算机图形学》实验报告

班级: 211923班

学号: 21190928

姓名: 林星宇

2021-2022学年第1学期

实验项目1

边标志算法的实现

实验性质

□演示性实验 验证性实验

□操作性实验 综合性实验

实验地点

计算机楼B212

机器编号

一、实现的功能

编写应用程序,采用鼠标输入顶点的方法确定待填充多边形(多边形最后一点双击);实现边标志算法完成对该多边形的填充,要求 完成使用自己学号的后四位数字对多边形内部进行填充。

二、采用的图形学算法及实现

(算法的实现函数是什么(函数名,参数,返回值,函数功能等)以及采用了哪些数据结构(数组,链表等))

要求使用边标志算法的原理和实 现方法,所以使用了EdgeMarkFill函数,即边标志算法:

void CMFCDrawTestView::EdgeMarkFill(CDC* pDC, CArray* plist, COLORREF color)

pDC为设备环境变量指针,plist为多边形点表,color为传入的RGB()值。

int zima[16][32]为学号后4位二维数组。

X1,x2,y1,y2分别为多边形上的最小最小大,y值

三、采用的交互方式及实现

(采用了哪些交互方式来完成绘制,这些交互方式应用到了哪些系统消息,是如何实现的)

边填充的实现:编写应用程序,采用鼠标输入顶点的方法确定待填充多边形(多边形最后一点双击);实现边标志算法完成对该多边形的填充,要求 完成使用自己学号的后四位数字对多边形内部进行填充。

易知,在画完多边形后,即双击左键(OnLButtonUp)后,使用EdgeMarkFill函数。

Type=2时,在OnLButtonUp中,调用EdgeMarkFill(pDC,&(obj->points), RGB(r, 0, 0));

四、实验结果

(程序的运行结果)

应用程序运行后,标志算法完成对该多边形的填充的图形结果如下:

”“

五、遇到的问题及解决办法

问题1:(在实现过程中遇到了什么样的问题,及采用了何种解决办法)

在获取下x1,x2,y1,y2时,因为Dos界面x、y大小颠倒的原因,获取时出现了问题。

首先,通过for(int i = 1;i < plist->GetSize();i++){

CPoint p = plist->GetAt(i);

if(x1 > p.x)x1 = p.x;

if(x2 < p.x)x2 = p.x;

if(y1 > p.y)y1 = p.y;

if(y2 < p.y)y2 = p.y;

}

获取x1,x2,y1,y2.在遍历多边形过程中:

int count = plist->GetSize();

for(int i = 0;i < count;i++){

CPoint p1 = plist->GetAt(i);

CPoint p2 = plist->GetAt((i + 1)% count);

if(p1.y == p2.y)

continue;

if(p1.y > p2.y)

{

CPoint p;p = p1;p1 = p2;p2 = p;

}

xs = p1.x;

dxs =(p2.x-p1.x)/(double)(p2.y-p1.y);

//dys = abs(p2.y-p1.y)/(p2.y-p1.y);

for(ys = p1.y;ys!= p2.y;ys += 1)

{

Ixs = int(xs + 0.5);

MARK[ys][Ixs] =!MARK[ys][Ixs];

xs = xs + dxs;

}

黄线处即为处理x1,x2,y1,y2的大小。

问题2:通过数组zima[][]来确定多边形区域填充学号后4位时,zima[y ][x ]未%其字长,即zima[y % 16][x % 32]。后改为:

for(y = y1;y <= y2;y++)

{

bool inside = false;

for(x = x1;x <= x2;x++)

{

if(MARK[y][x])

inside =!inside;

if(inside)

{

if(zima[y % 16][x % 32])

pDC->SetPixel(x, y, RGB(255, 0, 0));

}

}

}

实验项目2

立方体的比例、平移、旋转变换及投影显示

实验性质

□演示性实验 验证性实验

□操作性实验 综合性实验

实验地点

计算机楼B212

机器编号

一、实现的功能

建立立方体的数据模型;编写应用程序,利用菜单和键盘结合的方式完成对立方体的移动、比例和旋转变换,并显示透视或斜二测投影结果。要求应用程序具有如下功能:

1、通过菜单选择的方式,选择对三维空间中的立方体作斜二测投 影或透视投影;

2、通过键盘按键或鼠标移动的方式,完成对三维空间中的立方体 进行平移变换(上下左右前后),比例变换(放大或缩小)以及 旋转变换(绕 x,y,z 轴),并同时显示变换后的投影结果

3、创建对话框,通过对话框设置透视投影时候的投影中心,以及旋转变换时候的旋转轴(可以设置成分别绕 x 轴,y 轴,z 轴进 行旋转)

二、采用的图形学算法及实现

(算法的实现函数是什么(函数名,参数,返回值,函数功能等)以及采用了哪些数据结构(数组,链表等))

题目要求实现立方体的移动、比例和旋转变换,并显示透视或斜二测投影结果。

对要求1:在菜单选TY项中选择斜二测投影(斜二=1)或透视投影(透视=1)。然后在OnDraw中调用Draw_Cubic(CDC* pDC)画出立方体。

对要求2:在OnKeyDown中调用函数,即在键盘上按“S”使立方体变小,“B”使立方体变大,“←”“→”“↑”“↓”使立方体左右上下移动。

对要求3:在菜单XYZ中选择旋转的x,y,z轴,即x=1或y=1或z=1,然后在OnKeyDown中调用函数,即按键盘上的“T”或“P”.

三、采用的交互方式及实现

(采用了哪些交互方式来完成绘制,这些交互方式应用到了哪些系统消息,是如何实现的)

由题目要求1,易知需要一个函数Draw_Cubic(CDC* pDC)画出立方体的斜二测投影或透视投影并且建立一个菜单栏TY(投影)。即在菜单选TY项中选择斜二测投影(斜二=1)或透视投影(透视=1)。然后在OnDraw中调用Draw_Cubic(CDC* pDC)画出立方体。

由题目要求2:易知直接在OnKeyDown函数上添加使立方体变大变小,前后左右平移的功能。即即在键盘上按“S”使立方体变小,“B”使立方体变大,“←”“→”“↑”“↓”使立方体左右上下移动。

由题目要求3:建立一个菜单XYZ决定旋转的轴。

四、实验结果

(程序的运行结果)

斜二测投影:

”“

斜二测投影平移到左上角:

”“

斜二测投影平移到右下角:

”“

斜二测投影变大:

”“

斜二测投影变小:

”“

斜二测投影变为透视投影:

”“

斜二测投影绕z轴旋转:

”“

”“

”“

五、遇到的问题及解决办法

(在实现过程中遇到了什么样的问题,及采用了何种解决办法)

问题1:一开始建立立方体时,没有建立边表,导致投影困难。

后来建立了点表和对应的边表。

问题2:一开始Draw_Cubic中x1, y1,z1, x2, y2,z2定义为了int型。

实验项目3

用矩形窗口对多边形进行裁剪

实验性质

□演示性实验 验证性实验

□操作性实验 综合性实验

实验地点

计算机楼B212

机器编号

一、实现的功能

编写应用程序实现多边形裁剪。要求首先采用鼠标确定裁剪区域(矩形区域),然 后用鼠标输入待裁剪的多边形(可分别使用鼠标左键和右键来确定裁剪区域和待裁剪 的多边形)。多边形绘制完毕后进行裁剪,以不同颜色显示被裁剪对象位于窗口内(此 部分应保证多边形的完整性)及外部的部分。

二、采用的图形学算法及实现

(算法的实现函数是什么(函数名,参数,返回值,函数功能等)以及采用了哪些数据结构(数组,链表等))

因为要编写应用程序实现多边形裁剪。要求首先采用鼠标确定裁剪区域(矩形区域),然 后用鼠标输入待裁剪的多边形(可分别使用鼠标左键和右键来确定裁剪区域和待裁剪 的多边形)。所以要使用多边形裁剪算法,即Cut_Top(),Cut_Bottom(),Cut_Left(),Cut_Right()四个函数。

Cut()函数为用绿色显示被裁剪对象位于窗口内部分。

存在int type的变量;

当type=1时,在OnLButtonUp中画出矩形框。

当type=2时,画出多边形,在左键双击后,在OnLButtonDblClk中调用如下函数:Cut_Top();Cut_Right();Cut_Bottom();Cut_Left();Cut();

裁剪多边形在,并标出在矩形内部的部分。

三、采用的交互方式及实现

(采用了哪些交互方式来完成绘制,这些交互方式应用到了哪些系统消息,是如何实现的)

编写应用程序实现多边形裁剪。要求首先采用鼠标确定裁剪区域(矩形区域),然 后用鼠标输入待裁剪的多边形(可分别使用鼠标左键和右键来确定裁剪区域和待裁剪 的多边形)。多边形绘制完毕后进行裁剪,以不同颜色显示被裁剪对象位于窗口内(此 部分应保证多边形的完整性)及外部的部分。

根据以上绘制方法,可知需要处理WM_OnLButtonDblClk(左键双击)及WM_LButtonUp(左键抬起)消息,为了绘制橡皮线,还需处理调用WM_MouseMove(鼠标移动)消息。

因为可以用鼠标画出矩形和多边形,所以这么规定,当type=1时画矩形,即:

DDALine(pDC,lx,by,lx,ty,RGB(r, g, b));

DDALine(pDC, lx, by, rx, by, RGB(r, g, b));

DDALine(pDC, rx, by, rx, ty, RGB(r, g, b));

DDALine(pDC, lx, ty, rx, ty, RGB(r, g, b));

当type=2时画多边形,而后裁剪,即:

for(int i = 0;i < pointList.GetSize();i++)

{

p1 = pointList.GetAt(i);

p2 = pointList.GetAt((i+1)% count);

DDALine(pDC, p1.x, p1.y, p2.x, p2.y, RGB(0,255,0));

}

四、实验结果

(程序的运行结果)

裁剪结果如下图所示,黑色为裁剪窗口,红色为多边形被裁剪的部分,绿色为多边形裁剪后的部分:

”“

五、遇到的问题及解决办法

(在实现过程中遇到了什么样的问题,及采用了何种解决办法)

问题1:我在裁剪使一开始对多边形做上下左右裁剪时,这四个步骤是分别对原图形裁剪,而不是对图形接连进行裁剪。后来在裁剪函数上先除去之前图形,然后把已裁剪多边形重新构建。如下:

pointList.RemoveAll();

for(int i = 0;i < m;i++)

pointList.Add(CP[i]);

问题2:在多边形被矩形裁剪的部分显现不同颜色花费了挺多时间,后来我直接让裁剪的部分颜色被覆盖就可以了。如下:

for(int i = 0;i < pointList.GetSize();i++)

{

p1 = pointList.GetAt(i);

p2 = pointList.GetAt((i+1)% count);

DDALine(pDC, p1.x, p1.y, p2.x, p2.y, RGB(0,255,0));

}

第三篇:计算机图形学学习心得

《计算机图形学》学习报告

 东西方建筑中的理性

尽管东方“木构”的暂时性文化和西方“石砌”的永久性文化氛围造成了建筑形式风格的差异,但是它们都兼有理性和感性美。从柱式的英文“order”一词,到中国古建筑等级制的基数开间,无不透露着匠人的理性思考;从古埃及绘画中为了将人的特征最大限度表现而作的头部侧面身体正面的绘画,到文艺复兴达芬奇创造的透视画法,一步步将人们引向更为理性的世界。

西方古典主义者强调构图中的主从关系,突出轴线、讲求配称;倡导理性,主张建筑的真实,反对表现感情和情绪。随之而来的比例、节奏、韵律、秩序美,是建筑区别于雕塑和绘画两大艺术的特点。

维特鲁威提出的建筑三原则:坚固、适用、美观,时时刻刻提醒着我们建筑是要被建造起来的,它是我们的“避难所”,需要理性的结构、缜密的分析和思考。时代在进步,建筑理论从勒杜克的结构理性主义发展到现在的解构主义,再也不是建筑形式适应结构的时代了,而是两者互为促进。

我们对建筑的理解不再是像路易斯康那样再去问砖想做什么,等待它做拱卷的回答。我们向大自然学习,卡拉特拉瓦创造了许多带有理性美的仿生建筑。当我们想进一步拓宽我们的思维时,我们还能向谁求助?计算机图形学为我们打开了理性思考的一扇窗。

 计算机图形学对理性建筑的贡献

半个多世纪以来,计算机技术得到了飞速的发展。它的进步不仅仅使世界变得更平,信息交流更便捷,在此平台上开发的各种绘图软件更是将建筑师从传统的手工渲染画图中解放出来,也解放了结构师的工作量。用了30年的时间,计算机的速度从K(103)到T(1012),而从T到Z(1021),我们只用了10年时间。发展的速度是越来越快,我们设计方法和速度都得到了革新。这是这样一个数字化信息化的时代,才有弗兰克盖里建筑的夸张和扎哈哈迪德设计的新奇。

原来我们随手绘出的自由曲线,现在计算机都能帮我们算出是否有建造的可能,以及建筑性能也能在建造前得到分析。在创意上,计算机也能将我们模糊的概念无限发展,给它一个规则,它可能还你一个超乎想象的造型,在理性规则中生成感性而自由的建筑。

知其然,还应知其所以然,看着电视机的变薄,图像更加逼真,这变化的一切都建立在计算机图形学的架构下,了解了基础原理,才能更高效地做高质量的建筑设计。

 计算机图形学的理论知识

1.相关概念

计算机图形学是主要研究通过计算机处理用集合数据和数学模型所描述的图形的原理、算法和系统。包括图形的输入、存储、运算、转换、传送和输出。数字化技术是泛指在某特定领域利用包括硬件、软件在内的计算机与电子技术以及数学或数字模型等描述的问题进行求解、模拟或分析活动的一切应用技术。

建筑数字化技术研究应用包括建筑的数字化设计和反映建筑的数字化特征在内的数字技术。而建筑数字化技术的核心几何学科就是计算机图形学。2.反映建筑数字化特征的典型图形技术

建筑的动态特征——图形显示:如奥地利格拉茨美术馆的925盏灯形成的外墙面显示屏 建筑的互动特征——图形显示:如杜瑟赫姆市的随情感变化而色彩变化的建筑物

建筑的数字特征——几何运算:如柏林Max Reinhardt大楼模型及“莫比乌斯环”变换 建筑的虚实特征——交互式图形:如法国国立图书馆(实体与网络图书馆)

设计手段和设计媒体的数字化特征——交互式图形:如纽约韩国基督教长老会教堂 而建筑性能如声环境、热环境、光环境、风环境模拟的可视化分析中都用到了图形学。3.虚拟现实技术(VR)

虚拟现实技术是计算机生成的给人多种感官刺激的虚拟世界(环境),是一种高级的人机交互系统。

虚拟现实技术的三个基本特征:沉浸感、交互性、想象力 它具有多学科的综合性,正如建筑学是一门综合的艺术,虚拟现实技术包括图像处理、图形学、计算几何、多传感器、网络、多媒体和仿真技术等。

正如课堂上老师放映的《碟中谍4》,逼真的爆炸场景,以及从皮克斯动画开始的动物毛发到最近火热的《少年派》逼真的老虎与人共存画面,虚拟现实技术的进步影响到了我们生活的方方面面,触到了我们原来想都不敢想的世界。

而VR技术在建筑行业中,有以下作用:(1)指导设计:让建筑师通过浏览观察和了解空间关系,特别是对空间大小、方向、形状和建筑元素行为的理解。(2)建筑表现与环境仿真(3)仿真施工:检查和修改施工细节、合理性和有效性

4.虚拟现实的基础与关键技术:建模与描绘

基于几何和图形学的建模和描绘技术

直接几何建模

3D扫描建模

投影视图建模

基于图像的场景描绘技术(IBR)

图像投影变形技术 光场重建技术

混合式IBR技术

IBR技术图形的绘制独立于场景的复杂性,仅仅与所要生成画面的分辨率有关。

第四篇:计算机图形学实验

实验三 MFC画直线

最近自己在学习如何在VC 6.0 开发环境下的使用MFC AppWizard(exe)来绘画一条直线,虽然比较简单,通过这样的练习可以帮助你熟悉MFC的开发环境以及其中的消息传递机制,希望对于像我一样初入MFC图形绘制学习的人有帮

第一步:构建MFC窗体

打开Visual C++ 6.0编译器 新建→工程→MFC AppWizard(exe),工程名以DrawLine为例,然后确定。为了方便,在MFC应用程序向导—步骤1当中选择“单文档”,其余所有的步骤都为默认值,直接“完成”。这样一个简单的MFC窗体就构建好了,自己不妨Compile—Build—BuildExecute一下。

第二步:编辑菜单项

选择ResourceView视窗展开Menu文件夹,左键双击IDR_DRAWLITYPE,右边就会出现菜单图形编辑界面,为了简化,我们只在添加帮助→DrawLine功能选择项。双击空白会弹出“菜单项目 属性”对话框。ID:ID_DRAW_LINE;标明:

DrawLine(&D),其它的为缺省。

第三步:建立消息命令

如果此时运行该程序,你会发现帮助—DrawLine的功能选项是灰色的,原因就在于我们还没有添加该功能的消息命令相应函数。通过“查看—Message Maps—Project:DrawLine—Class name:CDrawLineView—Object IDs:ID_DRAW_LINE—选定COMMAND—Add Function„”,其它为默认,最后确定完成。现在如果再重新运行该程序的话,会发现原来的灰色已经消除了。

第四步:添加鼠标消息响应

打开ClassView视窗,右键选定CDrawLineView,选择Add Windows Messsage Handler会弹出对话框,完成CDrawLineView类的WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP三个Windows消息事件的新建。

第五步:添加响应代码

首先,在ClassView视窗中双击CDrawLineView会定位到“DrawLineView.h : interface of the CDrawLineView class”的文件,添加CDrawLineView类的成员:protected: int m_Drag;POINT m_pPrev;POINT m_pOrigin;三个成员变量。视窗中展开CDrawLineView类,双击定位OnLBUTTONDOWN()函数。在该函数消息响应

处添加如下代码:

//建立好绘图的设备环境

CClientDC dc(this);OnPrepareDC(&dc);

dc.DPtoLP(&point);

//获取起始点坐标 m_pPrev=point;m_pOrigin=point;

m_Drag=1;

然后,定位于OnMouseMove(),添加如下代码(其中关键用到了橡皮筋技术):

//建立好绘图的设备环境

CClientDC dc(this);

OnPrepareDC(&dc);dc.DPtoLP(&point);

dc.SetROP2(R2_NOT);//橡皮筋绘图技术

//判断是否BUTTONDOWN

if(m_Drag)

{

dc.MoveTo(m_pOrigin);dc.LineTo(m_pPrev);dc.MoveTo(m_pOrigin);dc.LineTo(point);

}

m_pPrev=point;

最后,在OnLBUTTONDOWN()添加代码: m_Drag=0;

程序运行效果图

实验4 实现圆的生成算法

一、实验目的

1.熟悉CDC图形程序库; 2.掌握中点画圆生成算法; 3.掌握Bresenham画圆算法。

二、实验内容

利用VisualC++6.0设计一个简易画圆绘图板,验证圆生成算法。

三、实验指导

1.生成绘图应用程序的框架,如下图所示。具体实现见第二次实验,过程不再详细说明。

2.在应用程序中增加菜单

完成相关菜单的设计,具体的效果如下图所示,并设置好相关菜单消息的映射,具体的实现在前面的实验中介绍过,再此不在详细说明。

3.在绘图函数中添加代码

通过以上步骤,得到了与菜单对应的消息映射,就可以在函数中添加代码绘制图形了。(1)利用中点画圆算法实现圆的生成(算法原理见教材)。void CDraw_CirView::OnMid(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到绘图类指针

RedrawWindow();//重绘窗口

int x,y,x0=200,y0=200,r=100;//圆的圆心为(x0,y0),半径为r float d;x=0;y=r;d=1.25-r;

pDC->SetPixel(x+x0,y+y0,RGB(255,0,0));pDC->SetPixel(y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));while(x<=y){

if(d<0)

{

d=d+2*x+3;

x++;

}

else

{

d=d+2*(x-y)+5;

x++;

y--;}

pDC->SetPixel(x+x0,y+y0,RGB(255,0,0));

pDC->SetPixel(y+x0,x+y0,RGB(255,0,0));

pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0));

pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0));

pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0));

pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0));

pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0));

pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));} } 由以上代码绘出的图形如下:

(2)利用Bresenham算法生成圆(算法原理见教材)。void CDraw_CirView::OnBre(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到绘图类指针

//RedrawWindow();//重绘窗口

int x,y,x0=200,y0=200,r=50;//圆的圆心为(x0,y0),半径为r int delta,delta1,delta2,direction;x=0;y=r;delta=2*(1-r);while(y>=0){

pDC->SetPixel(x+x0,y+y0,RGB(0,0,255));

pDC->SetPixel(x+x0,-y+y0,RGB(0,0,255));

pDC->SetPixel(-x+x0,y+y0,RGB(0,0,255));

pDC->SetPixel(-x+x0,-y+y0,RGB(0,0,255));

if(delta<0)

{

delta1=2*(delta+y)-1;

if(delta<=0)direction=1;

else direction=2;

}

else if(delta>0)

{

delta2=2*(delta-x)-1;

if(delta2<=0)direction=2;

else direction=3;

}

else direction=2;

switch(direction)

{

case 1:x++;

delta+=2*x+1;

break;

case 2:x++;y--;

delta+=2*(x-y+1);

break;

case 3:y--;

delta+=(-2*y+1);

break;

} } }

由以上代码绘出的图形如下:

(3)以上是本次实验的基本部分,利用中点画圆和Bresenham画圆算法实现的基本图形的绘制。能不能利用该算法,完成一些复杂图形的生成,比如利用基本的画圆算法绘制一个奥运五环。甚至根据画圆算法,实现二次曲线的生成,如椭圆的生成等等。请同学们认真考虑,完成这部分的内容,上机调试。

四、思考

1.如何实现圆心为任意位置的圆的绘制; 2.两种画圆算法的比较。

第五篇:计算机图形学实验报告

实 验 报 告

一、实验目的

1、掌握有序边表算法填充多边形区域;

2、理解多边形填充算法的意义;

3、增强C语言编程能力。

二、算法原理介绍

根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。

判断扫描线上的点是否在多边形之内,对于一条扫描线,多边形的扫描转换过程可以分为四个步骤:

(1)求交:计算扫描线与多边形各边的交点;(2)排序:把所有交点按x值递增顺序排序;

(3)配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边 形的一个相交区间;(4)着色:把相交区间内的象素置成多边形颜色,把相交区间外的象素置成背景色。

p1,p3,p4,p5属于局部极值点,要把他们两次存入交点表中。如扫描线y=7上的交点中,有交点(2,7,13),按常规方法填充不正确,而要把顶点(7,7)两次存入交点表中(2,7,7,13)。p2,p6为非极值点,则不用如上处理。

为了提高效率,在处理一条扫描线时,仅对与它相交的多边形的边进行求交运算。把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。

对每一条扫描线都建立一个与它相交的多边形的活性边表(AET)。每个AET的一个节点代表一条活性边,它包含三项内容

1.x-当前扫描线与这条边交点的x坐标;

2.Δx-该边与当前扫描线交点到下一条扫描线交点的x增量; 3.ymax-该边最高顶点相交的扫描线号。

每条扫描线的活性边表中的活性边节点按照各活性边与扫描线交点的x值递增排序连接在一起。

当扫描线y移动到下一条扫描线y = y+1时,活性边表需要更新,即删去不与新扫

描线相交的多边形边,同时增加与新扫描线相交的多边形边,并根据增量法重新计算扫描线与各边的交点x。

当多边形新边表ET构成后,按下列步骤进行:

① 对每一条扫描线i,初始化ET表的表头指针ET[i]; ② 将ymax = i的边放入ET[i]中;

③ 使y =多边形最低的扫描线号; ④ 初始化活性边表AET为空; ⑤ 循环,直到AET和ET为空。

 将新边表ET中对应y值的新边节点插入到AET表。 遍历AET表,将两两配对的交点之间填充给定颜色值。

 遍历AET表,将 ymax= y的边节点从AET表中删除,并将ymax> y的各边节点的x值递增Δx;并重新排序。 y增加1。

三、程序源代码

#include “graphics.h” #define WINDOW_HEIGHT 480 #define NULL 0 #include “alloc.h” #include “stdio.h” #include “dos.h” #include “conio.h” typedef struct tEdge /*typedef是将结构定义成数据类型*/ { int ymax;/* 边所交的最高扫描线号 */ float x;/*当前扫描线与边的交点的x值 */ float dx;/*从当前扫描线到下一条扫描线之间的x增量*/ struct tEdge *next;}Edge;

typedef struct point{int x,y;}POINT;/*将结点插入边表的主体函数*/

void InsertEdge(Edge *list,Edge *edge)/*活性边edge插入活性边表list中*/ { Edge *p,*q=list;p=q->next;/*记住q原来所指之结点*/ while(p!=NULL)/*按x值非递减顺序增加边表*/ {

if(edge->x

x)/*要插入的边的x较大不应该在当前插入*/

p=NULL;

else /*要插入的边的x较小应该在当前插入*/

{q=p;

p=p->next;

} } edge->next=q->next;/*使欲插入之结点edge指向q原来所指之结点*/ q->next=edge;/*使q指向插入之结点*/ }

int yNext(int k,int cnt,POINT *pts)/*对于多边形中的某个顶点序号k(0,1...6),返回下一顶点的纵坐标,如果这2个顶点所在边是 水平的,则顺延,即返回第(k+2)个顶点的纵坐标),cnt是顶点个数+1,pts指向多边形顶点结构体的指针*/

{ int j;if((k+1)>(cnt-1))/*当前顶点为最后一个顶点,则下一个顶点为第0个顶点 */

j=0;else

j=k+1;/*当前顶点不是最后一个顶点,下一个顶点为数组下标加一*/ while(pts[k].y==pts[j].y)/*扫描线扫过平行顶点,需分情况找到当前顶点下下个顶点*/ if((j+1)>(cnt-1))

j=0;

else

j++;return(pts[j].y);/*返回下一个顶点的y值 */ }

/* 计算增量,修改AET*/ /*生成边表结点,并插入到边表中的主体函数*/ void MakeEdgeRec(POINT lower,POINT upper,int yComp,Edge *edge,Edge *edges[])/*把边结点edge,放到lower.y扫描线所在的边结点指针数组edges[]中 */ {edge->dx=(float)(upper.x-lower.x)/(upper.y-lower.y);edge->x=lower.x;if(upper.yymax=upper.y-1;/*缩短上层顶点*/ /*奇点,应该把这点当作两个点而分开,所以把y的最大值减一,向下移动*/ else edge->ymax=upper.y;/*不是奇点,不需改变y值 */ insertEdge(edges[lower.y],edge);/*插入一个边缘扫描线,插入到列表 */ }

/*创建边表的主体函数*/ void BuildEdgeList(int cnt,POINT *pts,Edge *edges[])/*建立新边表,cnt:多边形顶点个数+1,edges[]:指向活性边结点的指针数组*/ { Edge *edge;POINT v1,v2;int i,yPrev=pts[cnt-2].y;/*当前顶点的前一个顶点的y值,在当前顶点不是奇点时使用该参数*/ v1.x=pts[cnt-1].x;v1.y=pts[cnt-1].y;for(i=0;i

edge=(Edge *)malloc(sizeof(Edge));

edge=(Edge*)malloc(sizeof(Edge));if(v1.y

yNext*/ MakeEdgeRec(v1,v2,yNext(i,cnt,pts),edge,edges);/*确定v1,v2边较高端点的开闭*/

else

MakeEdgeRec(v2,v1,yPrev,edge,edges);/*当前顶点

是奇点*/ } yPrev=v1.y;v1=v2;} }

/*建立活性边表的主体函数:建立第scan条扫描线的活性边表*/ void BuildActiveList(int scan,Edge *active,Edge *edges[])/*建立扫描线scan的活性边表,把活性边结点放入扫描线scan的结点指针数组 edges[scan]中*/ { Edge *p,*q;p=edges[scan]->next;/*查找当前扫描线对应的y桶*/ while(p)/*y桶不空*/

{q=p->next;/*找到最后一个边结点,插入*/

InsertEdge(active,p);/*把更新后的边表重新插入边表中保存*/

p=q;

} }

/*填充一对交点的主体函数*/ void FillScan(int scan,Edge *active,int color)/*填充扫描线:填充扫描线上,且在下一结点到再下一结点之间的点*/ { Edge *p1,*p2;int i;p1=active->next;while(p1){

p2=p1->next;

for(i=p1->x;i

x;i++)

putpixel((int)i,scan,color);/*画出图形内部的点*/ p1=p2->next;/*活性表的下一条边表 */ } }

void DeleteAfter(Edge *q)/*删除链表中结点,删除边结点q的后续结点p*/ { Edge *p=q->next;q->next=p->next;/*删除结点*/ free(p);} /* 删除 y=ymax 的边 */

/*填充完后,更新活动边表的主体函数*/ void UpdateActiveList(int scan,Edge *active)/*删除扫描线scan完成交点计算的活性边,同时更新交点x域*/ { Edge *q=active,*p=active->next;while(p)if(scan>=p->ymax)/*扫描线超过边的最大y值,此条边的节点应该删掉*/ { p=p->next;deleteAfter(q);} else /*扫描线未超过边的最大y值,相应的x值增加*/ { p->x=p->x+p->dx;q=p;p=p->next;} }

/*对活性边表结点重新排序的主体函数*/ void ResortActiveList(Edge *active)/*活性边表active中的结点按x域从小到大重新排序*/ { Edge *q,*p=active->next;active->next=NULL;while(p){q=p->next;InsertEdge(active,p);/*把更新后的边表重新插入边表中保存 */ p=q;} }

/*多边形填充的主体程序*/ void ScanFill(int cnt,POINT *pts,int color)/*填充函数,输入:多边形顶点个数+1=cnt, 指向多边形顶点的指针数组pts*/

{ Edge *edges[WINDOW_HEIGHT],*active;int i,scan,scanmax=0,scanmin=WINDOW_HEIGHT;for(i=0;i

{if(scanmax

if(scanmin>pts[i].y)scanmin=pts[i].y;

} for(scan=scanmin;scan<=scanmax;scan++)/*初始化每条扫面线的边链表*/ {edges[scan]=(Edge *)malloc(sizeof(Edge));/*建

edges[scan]->next=NULL;

} BuildEdgeList(cnt,pts,edges);/*建立有序边表*/ active=(Edge *)malloc(sizeof(Edge));“桶”*/ active->next=NULL;for(scan=scanmin;scan<=scanmax;scan++)/*扫描每条扫描线,求活性表*/ {

BuildActiveList(scan,active,edges);/*建立活性边表*/

if(active->next)/*活性边表不为空*/

{ FillScan(scan,active,color);/*填充当前扫描线*/ UpdateActiveList(scan,active);/*更新活化边表*/ ResortActiveList(active);/*重排活化边表*/

} } }

/*开始菜单*/ void main(){ POINT pts[7];/*保存数组*/ int gdrive=DETECT,gmode;pts[0].x=100;pts[0].y=40;/*多边形顶点x、y坐标*/ pts[1].x=220;pts[1].y=140;pts[2].x=280;pts[2].y=80;pts[3].x=350;pts[3].y=300;pts[4].x=200;pts[4].y=380;pts[5].x=50;pts[5].y=280;pts[6].x=100;pts[6].y=40;/*合并桶中的新边,按次序插入到 AET 中*/ initgraph(&gdrive,&gmode,“C:TC3.0BGI”);/*设置graphic模式*/ ScanFill(7,pts,2);getch();}

四、实验结果

图1 用有序边表算法生成的多边形

五、总结与体会

实验步骤

1)分析多边形区域扫描线填充算法的原理,确定算法流程

① 初始化:构造边表,AET表置空

② 将第一个不空的ET表中的边插入AET表

③ 由AET表取出交点进行配对(奇偶)获得填充区间,依次对这些填充区间着色

④ y=yi+1时,根据x=xi+1/k修改AET表所有结点中交点的x坐标。同时如果相 应的ET表不空,则将其中的结点插入AET表,形成新的AET表 ⑤ AET表不空,则转(3),否则结束。2)编程实现

① 首先确定多边形顶点和ET/AET表中结点的结构

② 编写链表相关操作(如链表结点插入、删除和排序等)

③ 根据1)中的算法结合上述已有的链表操作函数实现多边形区域扫描线填充的主体功能

④ 编写主函数,测试该算法 通过运用C语言环境下的图像显示设置,本次实验我学会了多边形区域扫描线填充的有序边表算法,设计相关的数据结构(如链表结构、结点结构等),并将实现的算法应用于任意多边形的填充,为深一步的学习做好了铺垫。

六、参考文献

[1]张家广 等编著.计算机图形学(第3版).北京:清华大学出版社,1998年9月.[2]陈传波,陆枫主编,《计算机图形学基础》,电子工业出版社,2002年3月.

下载计算机图形学学习体会word格式文档
下载计算机图形学学习体会.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    计算机图形学论文

    工欲善其事,必先利其器 ——浅析计算机图形学及其作用 本学期学校开设了计算机图形学,一开始不知计算机图形学为何物的我不是很理解为什么要有这门课,但是经过一学期的洗礼过后......

    计算机图形学实验报告

    0908141020 试验092 尤洋 实验1-1: 通过循环画线,实现了画四边形的功能 实验1-2: 通过循环设置顶点坐标,循环画线,实现了画7个顶点的金刚石 实验1-3: 通过填充实现了画三彩多边形......

    计算机图形学心得体会

    计算机图形学心得体会 姓名: 学号: 201203284 班级: 计科11202 序号: 31 院系: 计算机科学学院 通过一个学期的学习,经过老师细心的讲解,我对图形学这门课有了基础的认识,从......

    对于计算机图形学感想

    计算机图形学 1045532136 朱啸林 我们班是计算机科学与技术,刚开始知道要上图形学的时候我还是一头雾水,觉得没什么联系,经过老师的点拨和自己的领悟,我明白了其中的道理。计算......

    计算机图形学中英文关键词

    Computer graphics 计算机图形学 Two-dimensional 二维 Three-dimensional 三维 geometric transformation 几何变换 composite transformations 复合变换 Two-dimensional......

    计算机图形学的简单认识

    计算机图形学的简单认识 090600304229计科0942卿文玲第一周,我们上了一节计算机图形学。记得刚开始领到书的时候,翻看里面的内容,发现好多数学公式,心想:“完了,这不就是变相数学......

    计算机图形学模拟太阳系源代码

    #include #include #include #include //行星 GLfloat rot0 = 30.0; GLfloat rot1 = 0.0; GLfloat rot2 = 0.0; GLfloat rot3 = 0.0; GLfloat rot4 = 0.0; GLfloat rot5......

    2012级硕士研究生计算机图形学试题

    2012级硕士研究生计算机图形学试题问答题 1、 简述中点划线法。10分 2、 绘图说明多边形扫描填充算法过程。10分 3、 Hermite曲线公式及说明。10分 4、 编码裁剪过程。10分......