计算机图形学实验5实验报告

合集下载

计算机图形学实验报告模板

计算机图形学实验报告模板

巢湖学院计算机图形学实验报告(模板>本课程实验包括:以下为实验二和实验三模板实验一:基本图元绘制一、实验目的了解OpenGL图形软件包绘制图形的基本过程及其程序框架,并在已有的程序框架中添加代码实现直线和圆的生成算法,演示直线和圆的生成过程,从而加深对直线和圆等基本图形生成算法的理解。

b5E2RGbCAP二、实验内容实验操作和步骤:本次实验主要的目的是为了掌握基本画线和画圆算法,对于书上给出的代码,要求通过本次实验来具体的实现。

由于实验已经给出大体的框架,所以只需要按照书上的算法思想来设计具体实现代码,对于直线DDA算法,中点Bresenham算法及其改进算法,以及Bresenham画圆算法都有进一步的体会。

DDA算法是对每一步都要进行增量处理,然后取整,绘制,而Bresenham通过判断误差函数和求取递推公式来实现。

特别是对于整数的选择取舍,以及代码的流程和循环的控制有一个深入的了解。

同时也熟练运用OpenGL基本的绘图函数。

p1EanqFDPw三、体会通过本次实验,我进一步加深了对于基本画图算法的理解。

特别是对于DDA,Bresenham和画圆算法。

其中,DDA算法由于每一步都要处理浮点数的四舍五入,所以在绘图时要进行取整,效率较低,但是代码直观好懂,符合原理。

而对于Bresenham及其改进算法,都是在理论推导的基础上来实现的,然后经过整数化,形成了一个高效率的画图算法,所以需要适当的理解,特别是对于取整操作判断比较巧妙,实现了避免多次判断计算浮点数的目的,所以比较高效。

而绘制圆形的时候,用到的基本思想还是和Bresenham画图算法一样,只不过需要注意的是八分法画圆,这样只需要绘制其中的八分之一就可以利用对称的关系来绘制出整个图形。

而对于是否走下一步,或者是停留,判断的依据还是误差函数,和前面的思想是类似。

另外,通过实验训练了自己的编程能力,同时熟悉了OpenGL绘图的函数和流程,也进一步巩固了相关的知识。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学(computer graphics)的基本含义是使用计算机通过算法和程序在显示设备上构造图形。

图形是人们通过计算机设计和构造出来的,不是通过摄像机、扫描仪等设备输入的图像。

这里的图形可以是现实中存在的图形,也可以是完全虚拟构造的图形。

以矢量图的形式呈现,更强调场景的几何表示,记录图形的形状参数与属性参数。

例如,工程图纸(drawing),其最基本的图形单元是点、线、圆/弧等,其信息包含图元的几何信息与属性信息(颜色、线型、线宽等显式属性和层次等隐式属性)。

图像处理(image processing)则是研究图像的分析处理过程,图像处理研究的是图像增加、模式识别、景物分析等,研究对象一般为二维图像。

图像以点阵图形式呈现,并记录每个点的灰度或色彩。

例如,照片、扫描图片和由计算机产生的真实感和非真实感图·形等,最基本的图像单元(pels,picture elements)是点—像素(pixel),其信息实际上是点与它的属性信息(颜色、灰度、亮度等)。

计算机视觉(computer vision)包括获取、处理、分析和理解图像或者更一般意义的真实世界的高维数据方法,它的目的是产生决策形式的数字或者符号信息。

计算机图形学和计算机视觉是同一过程的两个方向。

计算机图形学将抽象的语义信息转化成图形,计算机视觉则从图形中提取抽象的语义信息,图像处理研究的则是一个图像或一组图像之间的相互转化和关系,与语义信息无关。

下表从输入和输出的角度对三者的区别进行辨析:表2 图像处理&计算机视觉&计算机图形学对比计算机图形学,输入的是对虚拟场景的描述,通常为多边形数组,而每个多边形由三个顶点组成,每个顶点包括三维坐标、贴图坐标、RGB 颜色等。

输出的是图像,即二维像素数组。

计算机视觉,输入的是图像或图像序列,通常来自相机、摄像头或视频文件。

输出的是对于图像序列对应的真实世界的理解,比如检测人脸、识别车牌。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学实验报告
在计算机图形学课程中,实验是不可或缺的一部分。

通过实验,我们可以更好地理解课程中所学的知识,并且在实践中掌握这些
知识。

在本次实验中,我学习了如何使用OpenGL绘制三维图形,并了解了一些基本的图形变换和视图变换。

首先,我们需要通过OpenGL的基本命令来绘制基本图形,例
如线段、矩形、圆等。

这些基本的绘制命令需要首先设置OpenGL 的状态,例如绘制颜色、线段宽度等,才能正确地绘制出所需的
图形。

然后,在实验中我们学习了图形的变换。

变换是指通过一定的
规则将图形的形状、位置、大小等进行改变。

我们可以通过平移、旋转、缩放等变换来改变图形。

变换需要按照一定的顺序进行,
例如先进行旋转再进行平移等。

在OpenGL中,我们可以通过设
置变换矩阵来完成图形的变换。

变换矩阵包含了平移、旋转、缩
放等信息,通过矩阵乘法可以完成图形的复合变换。

最后,视图变换是指将三维场景中的图形投影到二维平面上,
成为我们所见到的图形。

在实验中,我们学习了透视投影和正交
投影两种方式。

透视投影是指将场景中的图形按照视点不同而产
生不同的远近缩放,使得图形呈现出三维感。

而正交投影则是简单地将场景中的图形按照平行投影的方式呈现在屏幕上。

在OpenGL中,我们可以通过设置视图矩阵和投影矩阵来完成视图变换。

通过本次实验,我对于计算机图形学有了更深入的了解,并掌握了一些基本的图形绘制和变换知识。

在今后的学习中,我将继续学习更高级的图形绘制技术,并应用于实际的项目中。

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

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

《计算机图形学》实验报告实验十一真实感图形一、实验教学目标与基本要求初步实现真实感图形, 并实践图形的造型与变换等。

二、理论基础运用几何造型, 几何、投影及透视变换、真实感图形效果(消隐、纹理、光照等)有关知识实现。

1.用给定地形高程数据绘制出地形图;2.绘制一(套)房间,参数自定。

三. 算法设计与分析真实感图形绘制过程中, 由于投影变换失去了深度信息, 往往导致图形的二义性。

要消除这类二义性, 就必须在绘制时消除被遮挡的不可见的线或面, 习惯上称之为消除隐藏线和隐藏面, 或简称为消隐, 经过消隐得到的投影图称为物体的真实图形。

消隐处理是计算机绘图中一个引人注目的问题, 目前已提出多种算法, 基本上可以分为两大类:即物体空间方法和图象空间方法。

物体空间方法是通过比较物体和物体的相对关系来决定可见与不可见的;而图象空间方法则是根据在图象象素点上各投影点之间的关系来确定可见与否的。

用这两类方法就可以消除凸型模型、凹形模型和多个模型同时存在时的隐藏面。

1).消隐算法的实现1.物体空间的消隐算法物体空间法是在三维坐标系中, 通过分析物体模型间的几何关系, 如物体的几何位置、与观察点的相对位置等, 来进行隐藏面判断的消隐算法。

世界坐标系是描述物体的原始坐标系, 物体的世界坐标描述了物体的基本形状。

为了更好地观察和描述物体, 经常需要对其世界坐标进行平移和旋转, 而得到物体的观察坐标。

物体的观察坐标能得到描述物体的更好视角, 所以物体空间法通常都是在观察坐标系中进行的。

观察坐标系的原点一般即是观察点。

物体空间法消隐包括两个基本步骤, 即三维坐标变换和选取适当的隐藏面判断算法。

选择合适的观察坐标系不但可以更好地描述物体, 而且可以大大简化和降低消隐算法的运算。

因此, 利用物体空间法进行消隐的第一步往往是将物体所处的坐标系转换为适当的观察坐标系。

这需要对物体进行三维旋转和平移变换。

常用的物体空间消隐算法包括平面公式法、径向预排序法、径向排序法、隔离平面法、深度排序法、光线投射法和区域子分法。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学实验报告
实验目的:通过本次实验,深入了解并掌握计算机图形学的基本原理和相关技术,培养对图形处理的理解和能力。

实验内容:
1. 图像的基本属性
- 图像的本质及表示方法
- 像素和分辨率的概念
- 灰度图像和彩色图像的区别
2. 图像的处理技术
- 图像的采集和处理
- 图像的变换和增强
- 图像的压缩和存储
3. 计算机图形学的应用
- 图像处理在生活中的应用
- 计算机辅助设计中的图形学应用
- 三维建模和渲染技术
实验步骤和结果:
1. 在计算机图形学实验平台上加载一张测试图像,分析其像素构成
和基本属性。

2. 运用图像处理技术,对测试图像进行模糊、锐化、色彩调整等操作,观察处理后的效果并记录。

3. 学习并掌握计算机图形学中常用的处理算法,如卷积、滤波等,
尝试应用到测试图像上并进行实验验证。

4. 探讨计算机图形学在数字媒体制作、虚拟现实、计算机辅助设计
等领域的应用案例,并总结其在实践中的重要性和价值。

结论:
通过本次实验,我对计算机图形学有了更深入的了解,掌握了图像
处理技术的基本原理和应用方法。

计算机图形学作为一门重要的学科,对多个领域有着广泛的应用前景,有助于提高数字媒体技术、虚拟现
实技术等领域的发展水平。

希望在未来的学习和工作中能进一步深化
对计算机图形学理论和实践的研究,不断提升自己在这一领域的专业
能力和创新意识。

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

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

实验报告模板《计算机图形学》实验报告一、实验目的及要求1.实习三维图形的坐标系之间的变换;2.三维图形几何变换;3.掌握三维图形的坐标系之间的变换算法及三维图形几何变换的原理和实现;4.实现二维图形的基本变换(平移、旋转、缩放、错切、对称、复合等);5.实现三维图形的基本变换(平移、旋转、缩放、复合等);二、理论基础在齐次坐标理论下,二维图形几何变换矩阵可用下式表示:⎪⎪⎪⎭⎫⎝⎛===ifchebgdaTnkxx kk2,1,0,)(ϕ平移变换:[x* y* 1] =[x y 1] *0000001ts⎛⎫⎪⎪⎪⎝⎭=[t*x s*y 1]比例变换:[x* y* 1]=[x y 1] *1000101m n⎛⎫⎪⎪⎪⎝⎭=[m+x n+y 1]旋转变换:在平面上的二维图形饶原点逆时针旋转Ө角,变换矩阵为[x* y* 1]=[x y 1] *cos sin0sin cos0001θθθθ⎛⎫⎪- ⎪⎪⎝⎭= [x*cosө-y*sinө]复合变换:以上各种变换矩阵都是以原点为参照点,当以任意参照点进行变换的时候,我们就要用到复合变换矩阵。

三维变换类似于二维,在画图时,把三维坐标转换为二维即可。

三、算法设计与分析二维变换:#define dx 50#define dy 100void CCGWithVCView::OnTransScale() //平移(50,100){// TODO: Add your command handler code here// AfxMessageBox(_T("Please Insert The Move Change Code!")) ;int m[4][2]={{100,50},{50,100},{150,100},{100,50}};int i;int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<3;i++){a[0]=m[i][0];a[1]=m[i][1];b[0]=m[i+1][0];b[1]=m[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for(i=0;i<3;i++){a[0]=m[i][0]+dx;a[1]=m[i][1]+dy;b[0]=m[i+1][0]+dx;b[1]=m[i+1][1]+dy;DDALine(a,b, RGB(0, 200, 255), pDC);}}#define h 0.1745#include<math.h>void CCGWithVCView::OnTransRotate() //旋转{// TODO: Add your command handler code here// AfxMessageBox(_T("Please Insert The Rotate Change Code!")) ;int m[4][2]={{100,50},{50,100},{150,100},{100,50}};int i;int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<3;i++){a[0]=m[i][0];a[1]=m[i][1];b[0]=m[i+1][0];b[1]=m[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for(i=0;i<3;i++){a[0]=m[i][0]*cos(h)-m[i][1]*sin(h);a[1]=m[i][1]*cos(h)+m[i][0]*sin(h);b[0]=m[i+1][0]*cos(h)-m[i+1][1]*sin(h);b[1]=m[i+1][1]*cos(h)+m[i+1][0]*sin(h);DDALine(a,b, RGB(0, 200, 255), pDC);}}#define k 2;#define f 2.5void CCGWithVCView::OnTransMove() //缩放{// TODO: Add your command handler code here//AfxMessageBox(_T("Please Insert The Scale Change Code!")) ;int m[4][2]={{100,50},{50,100},{150,100},{100,50}};int i;int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<3;i++){a[0]=m[i][0];a[1]=m[i][1];b[0]=m[i+1][0];b[1]=m[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for(i=0;i<3;i++){a[0]=m[i][0]*k;a[1]=m[i][1]*f;b[0]=m[i+1][0]*k;b[1]=m[i+1][1]*f;DDALine(a,b, RGB(0, 200, 255), pDC);}}#define n 2#define d 0void CCGWithVCView::OnTransOther(){// TODO: Add your command handler code here//AfxMessageBox(_T("Please Insert The Other Change Code!")) ;int m[4][2]={{100,50},{50,100},{150,100},{100,50}};int i;int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<3;i++){a[0]=m[i][0];a[1]=m[i][1];b[0]=m[i+1][0];b[1]=m[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for(i=0;i<3;i++){a[0]=m[i][0]+n*m[i][1];a[1]=m[i][1]+d*m[i][0];b[0]=m[i+1][0]+n*m[i+1][1];b[1]=m[i+1][1]+d*m[i+1][0];DDALine(a,b, RGB(0, 200, 255), pDC);}}三维变换:#include<math.h>#define dx 100#define dy 100#define dz 0void CCGWithVCView::OnTransScale() //平移(50,100){// TODO: Add your command handler code here// AfxMessageBox(_T("Please Insert The Move Change Code!")) ;int i;int p2d[6][2];int p3d[6][3]={{400,300,0},{300,400,0},{300,300,10},{275,300,0},{400,300,0},{300,300,10}};for( i=0;i<6;i++){p2d[i][0]=p3d[i][1]-p3d[i][0]/sqrt(2);p2d[i][1]=p3d[i][2]+p3d[i][0]/sqrt(2);}int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<5;i++){a[0]=p2d[i][0];a[1]=p2d[i][1];b[0]=p2d[i+1][0];b[1]=p2d[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for( i=0;i<6;i++){p2d[i][0]=p3d[i][1]+dy-p3d[i][0]+dx/sqrt(2);p2d[i][1]=p3d[i][2]+dz+p3d[i][0]+dx/sqrt(2);}for(i=0;i<5;i++){a[0]=p2d[i][0];a[1]=p2d[i][1];b[0]=p2d[i+1][0];b[1]=p2d[i+1][1];DDALine(a,b, RGB(0, 0, 255), pDC);}}#define k 0.1745void CCGWithVCView::OnTransRotate() //旋转{// TODO: Add your command handler code here// AfxMessageBox(_T("Please Insert The Rotate Change Code!")) ;int i;int p2d[6][2];int p3d[6][3]={{400,300,0},{300,400,0},{300,300,10},{275,300,0},{400,300,0},{300,300,10}};for( i=0;i<6;i++){p2d[i][0]=p3d[i][1]-p3d[i][0]/sqrt(2);p2d[i][1]=p3d[i][2]+p3d[i][0]/sqrt(2);}int a[2],b[2];CDC * pDC = GetDC();for(i=0;i<5;i++){a[0]=p2d[i][0];a[1]=p2d[i][1];b[0]=p2d[i+1][0];b[1]=p2d[i+1][1];DDALine(a,b, RGB(0, 200, 255), pDC);}for( i=0;i<6;i++){p2d[i][0]=p3d[i][1]*cos(k)-p3d[i][2]*sin(k)-p3d[i][0]/sqrt(2);p2d[i][1]=p3d[i][2]*cos(k)+p3d[i][1]*sin(k)+p3d[i][0]/sqrt(2);}for(i=0;i<5;i++){a[0]=p2d[i][0];a[1]=p2d[i][1];b[0]=p2d[i+1][0];b[1]=p2d[i+1][1];DDALine(a,b, RGB(0, 0, 255), pDC);}}四、程序调试及结果的分析二维:三维:五、实验心得及建议在实验过程中,尽管过程中任由许多不会的地方,而且有待于今后的提高和改进,但我加深了对书本上知识的理解与掌握,同时也学到了很多书本上没有东西,并积累了一些宝贵的经验,这对我以后的学习与工作是不无裨益的。

图形学实验报告

图形学实验报告

图形学实验报告图形学实验报告概述:在本次图形学实验中,我们将探索和学习计算机图形学的基本概念和技术。

通过实验,我们深入了解了图形学的原理和应用,以及如何使用计算机生成和处理图像。

实验一:像素和颜色在这个实验中,我们学习了图像是由像素组成的,每个像素都有自己的颜色值。

我们使用了Python编程语言和PIL库来创建一个简单的图像,并设置了不同的像素颜色。

通过改变像素的颜色值,我们可以创建出各种各样的图像效果。

实验二:坐标系统和变换在这个实验中,我们学习了坐标系统和图形变换。

我们使用OpenGL库来创建一个简单的二维图形,并通过平移、旋转和缩放等变换操作来改变图形的位置和形状。

这些变换操作使我们能够在屏幕上创建出各种不同的图案和效果。

实验三:线段和多边形在这个实验中,我们学习了如何使用线段和多边形来绘制图形。

我们使用了Bresenham算法来绘制直线,并学习了如何使用多边形填充算法来填充图形。

通过这些技术,我们可以创建出更加复杂和精细的图像。

实验四:光照和阴影在这个实验中,我们学习了光照和阴影的原理和应用。

我们使用了光照模型来模拟光线的传播和反射,以及计算物体的明暗效果。

通过调整光照参数和材质属性,我们可以创建出逼真的光照和阴影效果。

实验五:纹理映射和渲染在这个实验中,我们学习了纹理映射和渲染的概念和技术。

我们使用了纹理映射来将图像贴到三维物体表面,以增加物体的细节和真实感。

通过渲染技术,我们可以模拟光线的折射和反射,以及创建出逼真的材质效果。

实验六:三维建模和动画在这个实验中,我们学习了三维建模和动画的基本原理和方法。

我们使用了三维建模工具来创建三维模型,并学习了如何使用关键帧动画来实现物体的运动和变形。

通过这些技术,我们可以创建出逼真的三维场景和动画效果。

总结:通过这次图形学实验,我们深入了解了计算机图形学的原理和应用。

我们学习了像素和颜色、坐标系统和变换、线段和多边形、光照和阴影、纹理映射和渲染,以及三维建模和动画等技术。

哈工大威海 计算机图形学实验报告

哈工大威海 计算机图形学实验报告

计算机图形学实验报告实验一、二技术之三维变换计算机图形学基础知识-三维变换变换是计算机图形学中重要概念,包括最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换。

1.从三维空间到二维平面1.1 相机模拟在真实世界里,所有的物体都是三维的。

但是,这些三维物体在计算机世界中却必须以二维平面物体的形式表现出来。

那么,这些物体是怎样从三维变换到二维的呢?下面我们采用相机(Camera)模拟的方式来讲述这个概念。

实际上,从三维空间到二维平面,就如同用相机拍照一样,通常都要经历以下几个步骤(括号内表示的是相应的图形学概念):第一步,将相机置于三角架上,让它对准三维景物(视点变换,Viewing Transformation)。

第二步,将三维物体放在适当的位置(模型变换,Modeling Transformation)。

第三步,选择相机镜头并调焦,使三维物体投影在二维胶片上(投影变换,Projection Transformation)。

第四步,决定二维像片的大小(视口变换,Viewport Transformation)。

这样,一个三维空间里的物体就可以用相应的二维平面物体表示了,也就能在二维的电脑屏幕上正确显示了。

1.2 三维图形显示流程运用相机模拟的方式比较通俗地讲解了三维图形显示的基本过程,但在具体编程时,还必须了解三维图形世界中的几个特殊坐标系的概念,以及用这些概念表达的三维图形显示流程。

计算机本身只能处理数字,图形在计算机内也是以数字的形式进行加工和处理的。

大家都知道,坐标建立了图形和数字之间的联系。

为了使被显示的物体数字化,要在被显示的物体所在的空间中定义一个坐标系。

这个坐标系的长度单位和坐标轴的方向要适合对被显示物体的描述,这个坐标系称为世界坐标系。

计算机对数字化的显示物体作了加工处理后,要在图形显示器上显示,这就要在图形显示器屏幕上定义一个二维直角坐标系,这个坐标系称为屏幕坐标系。

这个坐标系坐标轴的方向通常取成平行于屏幕的边缘,坐标原点取在左下角,长度单位常取成一个象素的长度,大小可以是整型数。

【2018最新】实验5 计算机图形学 实验报告-实用word文档 (12页)

【2018最新】实验5 计算机图形学 实验报告-实用word文档 (12页)

本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!== 本文为word格式,下载后可方便编辑和修改! ==实验5 计算机图形学实验报告实验5 实验报告格式《计算机图形学》实验5实验报告xxxxxxxxxxxxxxxx实验题目:多边形裁剪与填充实验内容:1 阅读理解提供的参考资料。

2编写并调通一个多边形裁剪的java程序。

3编写并调通一个多边形填充的java程序。

参考资料:1 fillPolygon.java2 clipSC2.java2变换与剪裁.ppt3多边形的填充.ppt基本概念:(详细叙述自己对实验内容的理解)变换与裁剪基本概念的理解:矢量:矢量是一个n元组,在坐标系中它对应于n维空间的一个点,这个点可以代表物体在空间的位置,也可以代表其运动状态等。

模型坐标系(局部坐标系):当构造单个对象的数字模型时,为了方便,可以将其置于一个特定的坐标系下,即模型坐标系或局部坐标系.世界坐标系:为描述图形场景中所有图形之间的空间关系,将它们置于一个统一的坐标系中,该坐标系被称为世界坐标系。

标准化设备坐标系:有些图形系统,对设备坐标系进行了规范化,将坐标范围限定在区间{x,y,z | 0≤x≤1, 0≤y≤1, 0≤z≤1}内,称标准化设备坐标系投影: 三维空间中的对象要在二维的屏幕或图纸上显示出来,就必须通过投影。

投影的方法有两种,平行投影和透视投影。

视区:在屏幕或绘图纸上定义一个矩形,称为视区,也称为视口,窗口内的景物在视区中显示。

平移:点(x′,y′,z′)由点(x, y, z)在x, y和z轴方向分别移动距离Δx,Δy和Δz得到。

两点坐标间的关系为x′=x+Δxy′=y+Δy (4.1)z′=z+Δz放大和缩小—以原点为中心的缩放:设点(x, y, z)经缩放变换后得点(x′,y′,z′)。

两点坐标间的关系为其中sx,sy和sz 分别为沿x, y和z轴方向放缩的比例。

计算机图形学实验报告-实验5Phong光照模型

计算机图形学实验报告-实验5Phong光照模型

计算机图形学实验报告班级计算机工硕班学号 **********姓名王泽晶实验五: Phong光照模型实验目的通过本次试验,学生可以掌握简单光照明模型的计算,以及真实感绘制中三维场景搭建的初步知识。

实验内容:对给定的光源、相机状态,对球进行Phong光照明模型绘制。

搭建三维场景:a)在三维空间中摆放1个球,半径为R,默认为50 ,摆放位置为(0,0,0)b)球的材质默认值为Ka = (0.1,0.1,0.1), Kd = (0,0,0.8), Ks = 0.2, n = 10c)视点方向初始为(0,0,1),光源方向初始为(1,1,1)d)视口设置为x0 = -100, y0 = -75, w = 200, h = 150使用phong模型绘制场景试验步骤:添加成员函数,编写成员数代码为override public function computeIntersection( viewStart:Vec3, viewDir:Vec3):Boolean {// See /geometry/sphereline/var viewEnd:Vec3 = viewStart.add(viewDir);var A:Number = Math.pow(viewEnd.getVec(0) - viewStart.getVec(0), 2)+Math.pow(viewEnd.getVec(1) - viewStart.getVec(1), 2) +Math.pow(viewEnd.getVec(2) - viewStart.getVec(2), 2);var B:Number =((viewEnd.getVec(0) - viewStart.getVec(0)) * (viewStart.getVec(0) - _position.getVec(0)) +(viewEnd.getVec(1) - viewStart.getVec(1)) * (viewStart.getVec(1) -_position.getVec(1)) +(viewEnd.getVec(2) - viewStart.getVec(2)) * (viewStart.getVec(2) -_position.getVec(2))) * 2.0;var C:Number = Math.pow(_position.getVec(0) - viewStart.getVec(0), 2) + Math.pow(_position.getVec(1) - viewStart.getVec(1), 2) +Math.pow(_position.getVec(2) - viewStart.getVec(2), 2) - _radius*_radius;// Solve C + Bt + At^2 = 0var delta:Number = B*B - 4*A*C;if ( delta<0.0 || A==0.0 ) return false;// We don't consider whether 0<t<1 here because real viewer is at infinite place var t1:Number = (-B + Math.sqrt(delta)) / (2*A);var t2:Number = (-B - Math.sqrt(delta)) / (2*A);if ( t1<t2 )point = viewStart.multiplyk(1.0 - t1).add(viewEnd.multiplyk(t1));elsepoint = viewStart.multiplyk(1.0 - t2).add(viewEnd.multiplyk(t2));normal = Vec3.normalize(point.minus(_position));return true;}public var _width :Number =0.0;public var _height:Number = 0.0;public var data:Array = new Array();protected function group1_creationCompleteHandler(event:FlexEvent):void{draw();}public function draw():void{graphics.clear();if(txtViewDir.text == "")return;var ary:Array = txtViewDir.text.split(",");var flag:Boolean = false;for(var i:int= 0;i<ary.length;i++){if(ary[i] == "" || isNaN(ary[i])){flag = true;break;}}if(flag)txtViewDir.setStyle("color",0xff0000);return;}txtViewDir.setStyle("color",0x000000);var viewDir:Vec3 = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));ary = txtLight.text.split(",");flag = false;for(i= 0;i<ary.length;i++){if(ary[i] == "" || isNaN(ary[i])){flag = true;break;}}if(flag){txtLight.setStyle("color",0xff0000);return;}txtLight.setStyle("color",0x000000);var light:Light = new Light();light.direction = new Vec3(Number(ary[0]), Number(ary[1]),Number(ary[2])).negative();light.ambient = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));light.intensity = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));var material:Material = new Material();material.diffuse =new Vec3(0.0, 0.0, 0.8);material.specular =new Vec3(0.2, 0.2, 0.2);material.ambient =new Vec3(0.1, 0.1, 0.1);data = createSceneImage( 200, 150, viewDir, light, material );drawImg();}public function drawImg():void{for(var y:int = 0 ;y<150;y++)for(var x:int =0;x<200;x++){var index:int = (y*200 + x) * 3;var r:Number = data[index+0];var g:Number = data[index+1];var b:Number = data[index+2];var cl:uint =(r << 16) | (g << 8) | b;this.graphics.beginFill(cl)this.graphics.drawCircle(x,y,1);this.graphics.endFill();}}}public function allocateBuffer( width:int,height: int ):Array{var data:Array = new Array();data.length = width * height * 3;_width = width;_height = heightreturn data;}public function createSceneImage( width:int,height: int ,viewDir:Vec3, light:Light, material:Material ):Array{var data:Array = new Array();var sphere:SphereObject = new SphereObject(50.0);sphere.setPosition(new Vec3(0.0, 0.0, 0.0) );sphere.setMaterial( material );var halfW:int = width / 2var halfH:int = height / 2;for ( var y:int=0; y<height; ++y ){for ( var x:int=0; x<width; ++x ){var viewStart:Vec3 = new Vec3(Number(x - halfW), Number(y - halfH), 0.0);if ( puteIntersection(viewStart, viewDir) )sphere.color = puteColor(light, viewDir, sphere.normal);elsesphere.color = new Vec3(0.1, 0.1, 0.1);var index:int = (y*width + x) * 3;data[index+0] = (sphere.color.getVec(0) * 255.0);data[index+1] = (sphere.color.getVec(1) * 255.0);data[index+2] = (sphere.color.getVec(2) * 255.0);}}return data;}protected function button1_clickHandler(event:MouseEvent):void {// TODO Auto-generated method stubdraw();}编译运行得到如下结果:。

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

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

《计算机图形学》实验报告一、实验目的计算机图形学是一门研究如何利用计算机生成、处理和显示图形的学科。

通过本次实验,旨在深入理解计算机图形学的基本原理和算法,掌握图形的生成、变换、渲染等技术,并能够运用所学知识解决实际问题,提高对图形学的应用能力和编程实践能力。

二、实验环境本次实验使用的编程语言为 Python,使用的图形库为 Pygame。

开发环境为 PyCharm。

三、实验内容1、直线的生成算法DDA 算法(Digital Differential Analyzer)Bresenham 算法DDA 算法是通过计算直线的斜率来确定每个像素点的位置。

它的基本思想是根据直线的斜率和起始点的坐标,逐步计算出直线上的每个像素点的坐标。

Bresenham 算法则是一种基于误差的直线生成算法。

它通过比较误差值来决定下一个像素点的位置,从而减少了计算量,提高了效率。

在实验中,我们分别实现了这两种算法,并比较了它们的性能和效果。

2、圆的生成算法中点画圆算法中点画圆算法的核心思想是通过判断中点的位置来确定圆上的像素点。

通过不断迭代计算中点的位置,逐步生成整个圆。

在实现过程中,需要注意边界条件的处理和误差的计算。

3、图形的变换平移变换旋转变换缩放变换平移变换是将图形在平面上沿着指定的方向移动一定的距离。

旋转变换是围绕一个中心点将图形旋转一定的角度。

缩放变换则是改变图形的大小。

通过矩阵运算来实现这些变换,可以方便地对图形进行各种操作。

4、图形的填充种子填充算法扫描线填充算法种子填充算法是从指定的种子点开始,将相邻的具有相同颜色或属性的像素点填充为指定的颜色。

扫描线填充算法则是通过扫描图形的每一行,确定需要填充的区间,然后进行填充。

在实验中,我们对不同形状的图形进行了填充,并比较了两种算法的适用情况。

四、实验步骤1、直线生成算法的实现定义直线的起点和终点坐标。

根据所选的算法(DDA 或Bresenham)计算直线上的像素点坐标。

计算机图形学实验报告

计算机图形学实验报告

实验结果与结论
• 在本次实验中,我们成功地实现了复杂场景的渲染,得到了具有较高真实感和视觉效果的图像。通过对比 实验前后的效果,我们发现光线追踪和着色器的运用对于提高渲染质量和效率具有重要作用。同时,我们 也发现场景图的构建和渲染脚本的编写对于实现复杂场景的渲染至关重要。此次实验不仅提高了我们对计 算机图形学原理的理解和实践能力,也为我们后续深入研究渲染引擎的实现提供了宝贵经验。
2. 通过属性设置和变换操作,实现了对图形的定 制和调整,加深了对图形属性的理解。
4. 实验的不足之处:由于时间限制,实验只涉及 了基本图形的绘制和变换,未涉及更复杂的图形 处理算法和技术,如光照、纹理映射等。需要在 后续实验中进一步学习和探索。
02
实验二:实现动画效果
实验目的
掌握动画的基本原 理和实现方法
04
实验四:渲染复杂场景
实验目的
掌握渲染复杂场景的基本流程和方法 理解光线追踪和着色器在渲染过程中的作用
熟悉渲染引擎的实现原理和技巧 提高解决实际问题的能力
实验步骤
• 准备场景文件 • 使用3D建模软件(如Blender)创建或导入场景模型,导出为常用的3D格式(如.obj或.fbx)。 • 导入场景文件 • 在渲染引擎(如Unity或Unreal Engine)中导入准备好的场景文件。 • 构建场景图 • 根据场景的层次结构和光照需求,构建场景图(Scene Graph)。 • 设置光照和材质属性 • 为场景中的物体设置光照和材质属性(如漫反射、镜面反射、透明度等)。 • 编写渲染脚本 • 使用编程语言(如C或JavaScript)编写渲染脚本,控制场景中物体的渲染顺序和逻辑。 • 运行渲染程序 • 运行渲染程序,观察渲染结果。根据效果调整光照、材质和渲染逻辑。 • 导出渲染图像 • 将渲染结果导出为图像文件(如JPEG或PNG),进行后续分析和展示。

计算机图形学实验报告实验五

计算机图形学实验报告实验五

贵州大学实验报告学院:计算机科学与信息专业:计科班级:计科101姓名徐艳学号1008060042 实验五实验时间2011-5-6 指导教师吴云成绩实验项目名称常用曲线和曲面的生成算法实验目的1、通过实验,进一步理解和掌握生成Hermit、Bezier和B样条曲线及Bezier曲面的生成算法2、掌握Hermit、Bezier、B样条曲线及Bezier曲面的基本生成过程3、通过编程,会在一种语言环境下编程实现三次Hermit、Bezier、B样条曲线及Bezier曲面的绘制实验要求1、编程实现Hermit曲线的绘制;2、编程实现B样条曲线的绘制。

3、编程实现Bezier曲线的绘制。

4、编程实现Bezier曲面的绘制。

5、写出实验报告实验原理三次Hermite曲线算法:1、根据型值点的坐标值绘制多边形;2、给Hermite矩阵M h赋值M h ={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};3、先计算边界条件矩阵TiiiiRRPP),,,(11++,然后计算TiiiihRRPPM),,,(11++∙;4、计算∙=],,,[)(123tttttP TiiiihRRPPM),,,(11++∙;5、根据(x,y)的坐标值绘制三次参数样条曲线。

当循环到第8 个型值点,程序结束,否则,执行步骤3.程序主要代码:void CQuxianmianView::Hermite(CDC *pDC){int a[4][4]={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};int b[4][2];for(int i=0;i<8;i++){b[0][0]=p1[i][0];b[0][1]=p1[i][1];//起点坐标b[1][0]=p1[i+1][0];b[1][1]=p1[i+1][1];//终点坐标b[2][0]=p2[i][0];b[2][1]=p1[i][1];//起点的导数b[3][0]=p2[i+1][0];b[3][1]=p1[i+1][1];//终点的导数MultiMatrix(a,b);CPen MyPen,*pOldPen;MyPen.CreatePen(PS_SOLID,1,RGB(225,125,0));pDC->MoveTo(p1[i][0],p1[i][1]);for(double t=0.0;t<=1;t+=1.0/400){intx=ROUND(pow(t,3)*result[0][0]+pow(t,2)*result[1][0])+t*result[2][0]+result[3][0];inty=ROUND(pow(t,3)*result[0][1]+pow(t,2)*result[1][1])+t*result[2][1]+result[3][1];pDC->LineTo(x,y);}pDC->SelectObject(&pOldPen);MyPen.DeleteObject();}}void CQuxianmianView::MultiMatrix(int a[][4], int b[][2]){int i,j,k;for(i=0;i<4;i++)for(j=0;j<2;j++)result[i][j]=0;for(i=0;i<2;i++)for(j=0;j<4;j++)for(k=0;k<4;k++)result[j][i]+=a[j][k]*b[k][i];}三次Bezier曲线算法:1、设置CPoint数组Pt保存控制顶点的坐标,在鼠标左键函数中为控制顶点坐标赋值;2、使用选择合适的颜色点绘制屏幕控制点;3、屏幕控制点绘制完后,自动调用Bezier函数,生成三次Bezier样条曲线;4、分别计算n的阶乘,i的阶乘和(n-i)的阶乘;5、对于屏幕像素点(x,y),分别计算iniintttCxPxx--∙∙+=)1(.和i n i i n t t t C y P y y --∙∙+=)1(.;6、 建立二重循环,外循环为t=0~1,步长为800,内循环为0~n ;7、 使用指定的颜色调用SetPixle 函数绘制(Pt.x,Pt.y )点,完成Bezier 曲线的绘制。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学实验报告引言计算机图形学是计算机科学中一个重要的研究领域,它涉及了计算机图像的生成、处理和显示等方面的技术。

本次实验旨在通过实际操作学习计算机图形学的相关知识,并利用图形学算法实现一些有趣的效果。

实验目的1. 了解计算机图形学的基本概念和发展历程;2. 掌握图形学中的基本几何变换,如平移、旋转和缩放等;3. 实现一些常见的图形学算法,如光照模型、三角形剪裁和绘制等。

实验准备在开始实验之前,我们需要准备一些实验所需的工具和环境。

首先,确保计算机上安装了图形学相关的软件,如OpenGL或DirectX等。

其次,为了编写和运行图形学程序,我们需要掌握基本的编程技巧,如C++或Python语言,并了解相关的图形库和API。

实验过程1. 实现平移、旋转和缩放首先,我们需要掌握图形学中的基本几何变换,如平移、旋转和缩放。

通过矩阵运算,我们可以很方便地实现这些变换。

例如,对于一个二维点P(x, y),我们可以通过以下公式实现平移:P' = T * P其中,P'是平移后的点,T是平移矩阵。

类似地,我们可以用旋转矩阵和缩放矩阵来实现旋转和缩放效果。

2. 实现光照模型光照模型是指在计算机图形学中模拟现实光照效果的一种方法。

它可以提供更真实的视觉效果,让计算机生成的图像更加逼真。

其中,常用的光照模型有环境光照、漫反射光照和镜面光照等。

通过计算每个像素的光照强度,我们可以实现阴影效果和光源反射等功能。

3. 实现三角形剪裁三角形剪裁是计算机图形学中一种常用的几何算法,用于确定哪些像素需要绘制,哪些像素需要剔除。

通过对三角形的边界和视口进行比较,我们可以快速计算出剪裁后的三角形顶点,以提高图形渲染的效率。

4. 实现图形绘制图形绘制是计算机图形学中的核心内容,它包括了点、线和面的绘制等。

通过设定顶点坐标和属性(如颜色、纹理等),我们可以使用算法绘制出各种形状的图像。

其中,常用的绘制算法有Bresenham算法和扫描线算法等。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学实验报告计算机图形学实验报告引言计算机图形学是研究计算机生成和处理图像的学科,它在现代科技和娱乐产业中扮演着重要的角色。

本实验报告旨在总结和分享我在计算机图形学实验中的经验和收获。

一、实验背景计算机图形学实验是计算机科学与技术专业的一门重要课程,通过实践操作和编程,学生可以深入了解图形学的基本原理和算法。

本次实验主要涉及三维图形的建模、渲染和动画。

二、实验内容1. 三维图形建模在实验中,我们学习了三维图形的表示和建模方法。

通过使用OpenGL或其他图形库,我们可以创建基本的几何体,如立方体、球体和圆柱体,并进行变换操作,如平移、旋转和缩放。

这些基本操作为后续的图形处理和渲染打下了基础。

2. 光照和着色光照和着色是图形学中重要的概念。

我们学习了不同的光照模型,如环境光、漫反射和镜面反射,并了解了如何在三维场景中模拟光照效果。

通过设置材质属性和光源参数,我们可以实现逼真的光照效果,使物体看起来更加真实。

3. 纹理映射纹理映射是一种将二维图像映射到三维物体表面的技术。

通过将纹理图像与物体的顶点坐标相对应,我们可以实现更加细致的渲染效果。

在实验中,我们学习了纹理坐标的计算和纹理映射的应用,使物体表面呈现出具有纹理和细节的效果。

4. 动画和交互动画和交互是计算机图形学的重要应用领域。

在实验中,我们学习了基本的动画原理和算法,如关键帧动画和插值技术。

通过设置动画参数和交互控制,我们可以实现物体的平滑移动和变形效果,提升用户体验。

三、实验过程在实验过程中,我们首先熟悉了图形库的使用和基本的编程技巧。

然后,我们按照实验指导书的要求,逐步完成了三维图形建模、光照和着色、纹理映射以及动画和交互等任务。

在实验过程中,我们遇到了许多挑战和问题,但通过不断的尝试和调试,最终成功实现了预期的效果。

四、实验结果通过实验,我们成功实现了三维图形的建模、渲染和动画效果。

我们可以通过键盘和鼠标控制物体的移动和变形,同时观察到真实的光照效果和纹理映射效果。

计算机图形实验报告

计算机图形实验报告

计算机图形实验报告计算机图形实验报告引言:计算机图形学是一门研究如何使用计算机生成、处理和显示图像的学科。

在现代科技的发展中,计算机图形学的应用越来越广泛,涉及到许多领域,如电影制作、游戏开发、虚拟现实等。

本实验报告将介绍我在计算机图形实验中的学习和实践经验。

一、实验目的本次实验的主要目的是通过学习和实践,掌握计算机图形学的基本概念和技术。

具体来说,我们将学习如何使用计算机编程语言实现简单的图形绘制、变换和渲染等功能。

二、实验过程1. 学习基本概念在开始实验之前,我们首先学习了计算机图形学的基本概念,包括点、线、多边形等基本图元的表示方法,以及坐标系统和颜色模型等相关知识。

这些基础概念为后续的实验操作打下了坚实的基础。

2. 图形绘制在实验中,我们使用了一种编程语言来实现图形的绘制。

通过编写代码,我们可以在计算机屏幕上绘制出各种形状的图形,如直线、矩形、圆等。

这些图形的绘制是通过计算机的像素点来实现的,我们可以通过改变像素点的颜色和位置来绘制出不同的图形。

3. 图形变换除了图形的绘制,我们还学习了图形的变换技术。

通过对图形进行平移、旋转、缩放等操作,我们可以改变图形的位置、大小和形状。

这些变换操作可以通过矩阵运算来实现,通过改变矩阵的数值,我们可以对图形进行不同的变换操作。

4. 图形渲染图形渲染是计算机图形学中的一个重要环节。

通过对图形进行光照、阴影和纹理等处理,我们可以使图形看起来更加真实和逼真。

在实验中,我们学习了一些基本的渲染算法,如平均法线法、Phong光照模型等,通过应用这些算法,我们可以实现不同材质和光照条件下的图形渲染效果。

三、实验结果通过实验,我们成功地实现了一些基本的图形绘制、变换和渲染功能。

我们可以在计算机屏幕上绘制出各种形状的图形,并对其进行平移、旋转、缩放等操作。

同时,我们还实现了简单的光照和阴影效果,使图形看起来更加真实和立体。

四、实验总结通过本次实验,我对计算机图形学有了更深入的了解。

计算机图形学实验报告

计算机图形学实验报告

计算机图形学实验报告一、实验目的本次计算机图形学实验旨在深入了解和掌握计算机图形学的基本原理、算法和技术,通过实际操作和编程实现,提高对图形生成、处理和显示的能力,培养解决实际图形问题的思维和实践能力。

二、实验环境本次实验使用的编程语言为 Python,借助了相关的图形库如Pygame 或 matplotlib 等。

开发环境为 PyCharm 或 Jupyter Notebook。

三、实验内容(一)二维图形的绘制1、直线的绘制使用 DDA(Digital Differential Analyzer)算法或 Bresenham 算法实现直线的绘制。

通过给定直线的起点和终点坐标,在屏幕或图像上绘制出直线。

比较两种算法的效率和准确性,分析其优缺点。

2、圆的绘制采用中点画圆算法或 Bresenham 画圆算法绘制圆。

给定圆心坐标和半径,生成圆的图形。

研究不同半径大小对绘制效果和计算复杂度的影响。

(二)图形的填充1、多边形填充实现扫描线填充算法,对任意多边形进行填充。

处理多边形的顶点排序、交点计算和填充颜色的设置。

测试不同形状和复杂度的多边形填充效果。

2、图案填充设计自定义的填充图案,如纹理、条纹等,并将其应用于图形填充。

探索如何通过改变填充图案的参数来实现不同的视觉效果。

(三)图形的变换1、平移、旋转和缩放对已绘制的图形(如矩形、三角形等)进行平移、旋转和缩放操作。

通过矩阵运算实现这些变换。

观察变换前后图形的位置、形状和方向的变化。

2、组合变换将多个变换组合应用于图形,如先旋转再平移,或先缩放再旋转等。

分析组合变换的顺序对最终图形效果的影响。

(四)三维图形的表示与绘制1、三维坐标变换学习三维空间中的平移、旋转和缩放变换矩阵,并将其应用于三维点的坐标变换。

理解如何将三维坐标映射到二维屏幕上显示。

2、简单三维图形绘制尝试绘制简单的三维图形,如立方体、球体等,使用线框模型或表面模型。

探讨不同的绘制方法和视角对三维图形显示的影响。

计算机图形学-实验五 直线和多边形的裁剪

计算机图形学-实验五 直线和多边形的裁剪

大学实验报告学院:计算机科学与信息学院专业:软件工程班级:102班学号实验组实验时间指导教师成绩实验项目名称实验五直线和多边形的裁剪实验目的掌握直线段的裁剪算法以及多边形的裁剪算法实验要求熟练掌握直线段的裁剪算法以及多边形的裁剪算法的基本原理,并编写测试代码进行实验。

实验原理Cohen-Sutherland直线剪裁算法以区域编码为基础,将窗口及其周围的,8个方向以4 bit的二进制数进行编码。

右图所示的编码方法将窗口及其邻域分为5个区域:⑴域:区域(0000)。

⑵上域:区域(1001, 1000, 1010)。

⑶下域:区域(0101, 0100, 0110)。

⑷左域:区域(1001, 0001, 0101)。

⑸右域:区域(1010, 0010, 0110)。

当线段的两个端点的编码的逻辑“与”非零时,线段为显然不可见的,对某线段的两个端点的区号进行位与运算,可知这两个端点是否同在视区的上、下、左、右;Cohen-Sutherland直线剪裁算法的算法思想是:对于每条线段P1P2分为三种情况处理。

(1)若P1P2完全在窗口,则显示该线段P1P2简称“取”之。

(2)若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。

(3)若线段既不满足“取”的条件,也不满足“弃”的条件,则在交点处把线段分为两段。

其中while (code1 != 0 || code2 != 0) {if ((code1 & code2) != 0) {// 两端点的编码相与不为0,表示直线在窗口外return;}if (code1 != 0) {code = code1;} else {code = code2;}if ((LEFT & code) != 0) {// 直线的端点与矩形窗口的左边编码相与!=0 x = XL;y = y1 + (y2 - y1) * (XL - x1) / (x2 - x1);// 求直线与矩形窗口的左边界的交点} else if ((RIGHT & code) != 0) {// 直线的端点与矩形窗口的右边编码相与!=0x = XR;y = y1 + (y2 - y1) * (XR - x1) / (x2 - x1);// 求直线与矩形窗口的右边界的交点} else if ((BOTTOM & code) != 0) {// 直线的端点与矩形窗口的下边编码相与!=0y = YB;x = x1 + (x2 - x1) * (YB - y1) / (y2 - y1);// 求直线与矩形窗口的下边界的交点} else if ((TOP & code) != 0) {// 直线的端点与矩形窗口的上边编码相与!=0y = YT;x = x1 + (x2 - x1) * (YT - y1) / (y2 - y1);// 直线的端点与矩形窗口的上// 边编码相与!=0}if (code == code1) {x1 = x;y1 = y;code1 = encode(x, y);} else {x2 = x;y2 = y;code2 = encode(x, y);}}g.drawLine((int) (x1 + 0.5), (int) (y1 + 0.5), (int) (x2 + 0.5),(int) (y2 + 0.5));}二、多边形裁剪的核心代码为:通过点集画直线或者多边形:private void draw() {//通过点集画直线或者多边形for (int i = 1; i < points.size(); i++) {Point p1 = new Point();p1 = points.get(i);int x1 = (int) p1.getX();int y1 = (int) p1.getY();Point p2 = new Point();p2 = points.get(i - 1);int x2 = (int) p2.getX();int y2 = (int) p2.getY();g.drawLine(x1, y1, x2, y2);}}多边形的裁剪函数:private Point[] cutPicture(Point[] point, Point[] edge) {// 剪裁函数,参数为(点集,边)Point[] intersectPoint = new Point[20];//存放交点的集合for (int j = 0; j < 20; j++) {intersectPoint[j] = new Point();}Point s = new Point();Point p = new Point();Point t = new Point();int i = 0;int length = point.length;s = point[length - 1];for (int j = 0; j < length; j++) {p = point[j];if (inside(p, edge)) {// sp在窗口,情况1if (inside(s, edge)) {intersectPoint[i] = p;i += 1;} else {// s在窗口外,情况4t = intersect(s, p, edge);intersectPoint[i] = t;i += 1;intersectPoint[i] = p;i += 1;}} else if (inside(s, edge)) {// s在窗口,p在窗口外,情况3t = intersect(s, p, edge);intersectPoint[i] = t;i += 1;}// 情况2没有输出s = p;}List<Point> tempList = new ArrayList<Point>();for (int k = 0; k < i; k++) {if (intersectPoint[k] != null) {Point pt = intersectPoint[k];tempList.add(pt);}}Point[] temp = new Point[tempList.size()];for (int j = 0; j < tempList.size(); j++) {temp[j] = new Point();temp[j] = tempList.get(j);}intersectPoint = temp;return intersectPoint;}判断点是否在裁剪边的可见侧:private boolean inside(Point point, Point[] edge) {//判断点是否在裁剪边的可见侧// 裁剪边为窗口下边if ((edge[0].y == edge[1].y) && (edge[0].x < edge[1].x)) {if (point.y >= edge[0].y) {return true;}}// 裁剪边为窗口上边if ((edge[0].y == edge[1].y) && (edge[0].x > edge[1].x)) {if (point.y <= edge[0].y) {return true;}}// 裁剪边为窗口右边if ((edge[0].x == edge[1].x) && (edge[0].y < edge[1].y)) {if (point.x <= edge[0].x) {return true;}}// 裁剪边为窗口左边if ((edge[0].x == edge[1].x) && (edge[0].y > edge[1].y)) {if (point.x >= edge[0].x) {return true;}}return false;}直线段与窗口边界求交:private Point intersect(Point s, Point p, Point[] edge) {//直线段与窗口边界求交,并返回交点Point t = new Point();if (edge[0].y == edge[1].y) {// 水平裁剪边t.y = edge[0].y;t.x = s.x + (edge[0].y - s.y) * (p.x - s.x) / (p.y - s.y);} else if (edge[0].x == edge[1].x) {// 垂直裁剪边t.x = edge[0].x;t.y = s.y + (edge[0].x - s.x) * (p.y - s.y) / (p.x - s.x);}return t;}鼠标的监听类(部类):class MouseMonitor extends MouseAdapter {//通过鼠标的单击获取点,并画出直线或者多边形public void mouseClicked(MouseEvent e) {points.add(e.getPoint());if (points.size() > 1) {draw();}}}键盘的监听类(部类):class KeyMonitor extends KeyAdapter {// 键盘控制public void keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_R:// 清空画布和点集panel.repaint();points.removeAll(points);break;case KeyEvent.VK_W://对裁剪窗口的处理g.setColor(Color.RED);g.drawRect(XL, YB, XR - XL, YT - YB);//存放裁剪窗口的边top = new Point[2];// 存放裁剪窗口的上边top[0] = new Point(XL, YB);top[1] = new Point(XR, YB);right = new Point[2];//存放裁剪窗口的右边right[0] = new Point(XR, YB);right[1] = new Point(XR, YT);bottom = new Point[2];//存放裁剪窗口的下边bottom[0] = new Point(XR, YT);bottom[1] = new Point(XL, YT);left = new Point[2];//存放裁剪窗口的左边left[0] = new Point(XL, YT);left[1] = new Point(XL, YB);break;case KeyEvent.VK_A://对直线段进行裁剪g.setColor(Color.GREEN);Point p1 = points.get(0);Point p2 = points.get(1);lineCut(p1.getX(), p1.getY(), p2.getX(), p2.getY());break;case KeyEvent.VK_B://对多边形进行裁剪source = new Point[points.size()];//得到多边形的点for (int i = 0; i < points.size(); i++) {source[i] = points.get(i);}g.setColor(Color.GREEN);wT = cutPicture(source, top);//得到多边形与裁剪窗口上边的交点wR = cutPicture(wT, right);//得到多边形与裁剪窗口右边的交点wB = cutPicture(wR, bottom);//得到多边形与裁剪窗口下边的交点wL = cutPicture(wB, left);//得到多边形与裁剪窗口左边的交点第二种情况:线段在裁剪窗口的部,线段完全可见。

【2018最新】实验5 计算机图形学 实验报告-实用word文档 (12页)

【2018最新】实验5 计算机图形学 实验报告-实用word文档 (12页)

本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除!== 本文为word格式,下载后可方便编辑和修改! ==实验5 计算机图形学实验报告实验5 实验报告格式《计算机图形学》实验5实验报告xxxxxxxxxxxxxxxx实验题目:多边形裁剪与填充实验内容:1 阅读理解提供的参考资料。

2编写并调通一个多边形裁剪的java程序。

3编写并调通一个多边形填充的java程序。

参考资料:1 fillPolygon.java2 clipSC2.java2变换与剪裁.ppt3多边形的填充.ppt基本概念:(详细叙述自己对实验内容的理解)变换与裁剪基本概念的理解:矢量:矢量是一个n元组,在坐标系中它对应于n维空间的一个点,这个点可以代表物体在空间的位置,也可以代表其运动状态等。

模型坐标系(局部坐标系):当构造单个对象的数字模型时,为了方便,可以将其置于一个特定的坐标系下,即模型坐标系或局部坐标系.世界坐标系:为描述图形场景中所有图形之间的空间关系,将它们置于一个统一的坐标系中,该坐标系被称为世界坐标系。

标准化设备坐标系:有些图形系统,对设备坐标系进行了规范化,将坐标范围限定在区间{x,y,z | 0≤x≤1, 0≤y≤1, 0≤z≤1}内,称标准化设备坐标系投影: 三维空间中的对象要在二维的屏幕或图纸上显示出来,就必须通过投影。

投影的方法有两种,平行投影和透视投影。

视区:在屏幕或绘图纸上定义一个矩形,称为视区,也称为视口,窗口内的景物在视区中显示。

平移:点(x′,y′,z′)由点(x, y, z)在x, y和z轴方向分别移动距离Δx,Δy和Δz得到。

两点坐标间的关系为x′=x+Δxy′=y+Δy (4.1)z′=z+Δz放大和缩小—以原点为中心的缩放:设点(x, y, z)经缩放变换后得点(x′,y′,z′)。

两点坐标间的关系为其中sx,sy和sz 分别为沿x, y和z轴方向放缩的比例。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《计算机图形学》实验5实验报告实验题目:多边形裁剪与填充实验内容:1 阅读理解提供的参考资料。

2编写并调通一个多边形裁剪的java 程序。

3编写并调通一个多边形填充的java 程序。

参考资料:1 fillPolygon.java2 clipSC2.java2变换与剪裁.ppt3多边形的填充.ppt基本概念:变换与裁剪基本概念的理解:矢量:矢量是一个n 元组,在坐标系中它对应于n 维空间的一个点,这个点 可以代表物体在空间的位置,也可以代表其运动状态等。

模型坐标系(局部坐标系):当构造单个对象的数字模型时,为了方便,可以将其置于一个特定的坐标系下,即模型坐标系或局部坐标系.世界坐标系:为描述图形场景中所有图形之间的空间关系,将它们置于一个统一的坐标系中,该坐标系被称为世界坐标系。

标准化设备坐标系:有些图形系统,对设备坐标系进行了规范化,将坐标范围限定在区间{x,y,z | 0≤x ≤1, 0≤y ≤1, 0≤z ≤1}内,称标准化设备坐标系投影: 三维空间中的对象要在二维的屏幕或图纸上显示出来,就必须通过投影。

投影的方法有两种,平行投影和透视投影。

视区:在屏幕或绘图纸上定义一个矩形,称为视区,也称为视口,窗口内的景物在视区中显示。

平移:点(x ′,y ′,z ′)由点(x, y, z)在x, y 和z 轴方向分别移动距离Δx, Δy 和Δz 得到。

两点坐标间的关系为x ′=x+Δxy ′=y+Δy (4.1)z ′=z+Δz放大和缩小—以原点为中心的缩放:设点(x, y, z)经缩放变换后得点(x ′,y ′,z ′)。

两点坐标间的关系为其中sx,sy 和sz 分别为沿x, y 和z 轴方向放缩的比例。

其矩阵形式是图形模式:矩阵合并时,先调用的矩阵放在右边,后调用的矩阵放在左边.也称为固定坐标系模式。

这种模式的特点是每一次变换均可看成相对于原始坐标系执行的。

空间模式:又称活动坐标系模式。

先调用的矩阵放在左边,后调用的矩阵放在右边,连续执⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡'''z y x s s s z y x z y x 000000行几次变换时,每一次变换均可看成是在上一次变换形成的新坐标系中进行的。

多边形的填充:多边形的表示方法:1)顶点表示是用多边形的顶点的序列来描述多边形,该表示几何意义强、占内存少,但它不能直观地说明哪些像素在多边形内。

2)点阵表示是用位于多边形内的象素的集合来刻划多边形,该方法虽然没有多边形的几何信息,是面着色所需要的图像表示形式。

区域是指已经表示成点阵形式的像素集合。

在光栅图形中,区域可采用内点表示和边界表示两种形式进行描述。

内点表示法:把位于给定区域内的所有像素一一列举出来的方法称为内点表示法。

边界表示法:把位于给定区域边界上的像素一一列举出来的方法称为边界表示法。

算法设计:多边形裁剪算法分析:基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:可见一侧,不可见一侧。

用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。

对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。

多边形裁剪的Sutherland—Hodgman算法 1>. Sutherland—Hodgman多边形裁剪算法思想该算法的基本思想是每次用窗口的一条边界及其延长线来裁剪多边形的各边。

多边形通常由它的顶点序列来表示,经过裁剪规则针对某条边界裁剪后,结果形成新的顶点序列,又留待下条边界进行裁剪,…,直到窗口的所有边界都裁剪完毕,算法形成最后的顶点序列,才是结果多边形(它可能构成一个或多个多边形)。

当多边形一个顶点Pi相对于窗口某条边界及其延长线进行剪裁时,不外乎下列四种情况(即裁剪规则):1、顶点Pi在内侧,前一顶点Pi-1也在内侧,则将Pi纳入新的顶点序列;2、顶点Pi在内侧,前一顶点Pi-1在外侧,则先求交点Q,再将Q、Pi依次纳入新的顶点序列;3、顶点Pi在外侧,前一顶点Pi-1在内侧,则先求交点Q,再将Q纳入新的顶点序列;4、顶点Pi与前一顶点Pi-1均在外侧,则顶点序列中不增加新的顶点。

多边形填充算法分析:确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。

对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间填色。

扫描多边形填充算法的基本原理——在直角坐标系中,假设有一条从左至右的扫描线穿过多边形,从左至右开始计数,与多边形交点为奇数时,开始进入多边形,与多边形交点为偶数时,走出多边形。

这样在这相邻配对的奇偶交点间的所有象素都在多边形内。

如图,奇数交点a,c,都是入多边形,偶数交点b,d都是走出多边形,相邻的奇偶交点配对,a,b之间,c,d之间的象素都多边形内,可见一条扫描线上,与多边形交点个数需要为偶数。

依据这样的思路,扫描线从上到下从左到右依次扫过多边形即可求得多边形所占据的象素。

(注意退化情况的处理,也就是扫描线刚好经过顶点或者多边形的边本身就是水平的情况)代码://Sutherland_Cohen裁减算法public void Sutherland_Cohen(Graphics g,float x0,float y0,float x2,float y2){int c1,c2,c;float x,y,wx,wy;boolean accept=false,done=false;c1=code(x0,y0);c2=code(x2,y2);do {if ((c1|c2)==0)//两个编码都为0,表明在窗口内{accept=true;done=true;}else if((c1&c2)!=0)done=true;//两个编码的某一位为1,则必然在外侧显然在窗口外else{c=c1;if(c==0)c=c2;wx=x2-x0;wy=y2-y0;if ((c&8)==8) //求交点{x=x0+wx*(yT-y0)/wy;y=yT;}else if ((c&4)==4){x=x0+wx*(yB-y0)/wy;y=yB;}else if ((c&1)==1){y=y0+wy*(xL-x0)/wx;x=xL;}else//即(c&2)==2{y=y0+wy*(xR-x0)/wx;x=xR;}if (c==c1) //表明c1!=0,起始点不在窗口内,将交点作为新的起点重复判断步骤;{x0=x;y0=y;c1=code(x0,y0);}else //终点不在窗口内,交点作为新的终点{x2=x;y2=y;c2=code(x2,y2);}}//else} while (done==false);if(accept)g.drawLine((int)100,(int)150,(int)200,(int)150);}}//fillPolygon.java//***定义多边形单链表类activeEdgeListclass activeEdgeList {activeEdgeListEntry header=null; //链表头指针activeEdgeListEntry tailer=null; //链表尾指针//构造方法public activeEdgeList(activeEdgeListEntry element) {header=tailer=element; //指向第一个边结点}//把新结点插入有序排列的多边形单链表public void insert(activeEdgeListEntry element) {activeEdgeListEntry sentinel; //当前结点指针if(element==null || this.header==null) //新结点异常或者链表空throw new NullPointerException(); //出错,抛出异常sentinel=this.header; //当前指针指向表头结点int xt=element.topx; //新结点的topxint xtold=sentinel.topx;double oldDelta=sentinel.delta; //当前结点的deltadouble newDelta=element.delta;/* 排序第一关键字结点的topx,第二关键字结点的delta *//* 两个关键字由小到大*/if((xtold<xt)||((xtold==xt)&&(oldDelta<newDelta))){while(true){ //在链表头指针之后寻找新结点element的位置if(sentinel.next==null) { //当前位置是表尾sentinel.next=element; //追加到表尾this.tailer=element;break; //结束while循环}activeEdgeListEntry mp=sentinel.next; //下一结点int xmt=mp.topx;double midDelta=mp.delta;if((xmt<xt)||((xmt==xt)&&(midDelta<newDelta))){sentinel=mp; //新结点仍然大于下一结点,当前结点指针后移,继续循环}else { //否则,新结点就应该插入当前位置sentinel.next=element;element.next=mp;break; //结束while循环,尾指针不动}} //结束while}else { //新结点作为单链表头结点sentinel=this.header;this.header=element;element.next=sentinel;}} //插入新结点结束//把新结点作为多边形链表的头结点或者尾结点public void append(activeEdgeListEntry element) {if(element==null) throw new NullPointerException();if(tailer==null) { //如果单链表是空tailer=element;header=element;}else { //否则把新结点作为单链表尾结点tailer.next=element;tailer=element;}}//两个多边形单链表的合并:自身单链表与list单链表的合并public activeEdgeList merge(activeEdgeList list,int y) {if(list==null) return this;activeEdgeListEntry a=this.header; //自身单链表的头指针activeEdgeListEntry b=list.header; //单链表list的头指针activeEdgeListEntry save=null; //指向链表结点的工作指针activeEdgeListEntry anext,bnext; //指向链表结点的工作指针activeEdgeList result=null; //合并结果链表while(true) {if(a==null&&b==null) return result; //两个空表else if(a==null) { //自身为空表if(save!=null) {save.next=b;result.tailer=list.tailer;return result;}}else if(b==null){ //list为空表if(save!=null) {save.next=a;result.tailer=this.tailer;return result;}}/*两个表都不空*/int xa=(int)(a.topx+(a.topy-y)*a.delta); //自身链表int xb=b.topx; //list链表头结点的topxif(xa<=xb) { //决定合并后两个表的先后anext=a.next;a.next=null;if(result==null) { //结果链表为空,则a表在前result=new activeEdgeList(a);save=result.tailer;}else result.append(a); //结果链表不空,则a表在后save=a;a=anext;}else {bnext=b.next;b.next=null;if(result==null) { //结果链表为空,则b表在前result=new activeEdgeList(b);save=result.tailer;}else result.append(b); //结果链表不空,则b表在后save=b;b=bnext;}} //结束while} //单链表合并结束//删除多边形单链表的结点public void remove(activeEdgeListEntry element) {activeEdgeListEntry p,q;if(header==element) { //要删除的是头结点header=element.next;if(tailer==element) tailer=header;return;}p=q=header;while(p!=element) {q=p;p=p.next;if(p==null) throw new NullPointerException(); //查无此结点}if(element==tailer) tailer=q; //要删除的是尾结点q.next=p.next; //要删除的是非头尾结点}//多边形单链表的相邻结点public void traverse() {activeEdgeListEntry p,q,r,tmp;p=r=header;while(p!=null){q=p.next;if(q==null) break; //到达末尾if(q.x<p.x) { //多边形单链表相邻结点的x坐标要由小到大tmp=q.next; //交换两个结点if(p==header) header=q; else r.next=q;q.next=p;p.next=tmp;}r=p; //指向尾结点p=p.next; //下一个结点} //结束whiletailer=r; //多边形单链表新的尾指针}} //结束多边形单链表类//*****定义直线类class Line {public double x1,y1;public double x2,y2;public Line(double x1,double y1,double x2,double y2) {this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;}} //结束直线类//***********定义多边形的填充类*******//public class fillPolygon extends Applet //继承鼠标事件监听接口implements MouseListener,MouseMotionListener {protected MyCanvas m; //定义MyCanvas的对象//扫描行处理用数据protected activeEdgeListEntry[] edgeData=null; //边结点数组protected activeEdgeList[] bucket=null; //多边形单链表数组protected activeEdgeList activeHeader=null; //当前边单链表的头指针protected int numEdge=5; //多边形的边数//鼠标相关数据protected boolean isFirstClicked=true; //鼠标最初点击protected boolean isDoubleClicked=false; //双击标志protected boolean isSingleClicked=false; //单击标志//绘图区域protected int width,height; //Applet绘图区的大小protected Image image=null; //图像区域protected MemoryImageSource mis=null; //内存图像protected int[] pixel=null; //内存图像配色数组protected int pixelWidth; //图像宽度protected int pixelHeight; //图像高度protected int xoffset; //pixel数据的窗口内显示偏移量protected int yoffset;protected double leftTopx; //pixel数据的起始点protected double leftTopy;//多边形的绘图数据protected double x0,y0; //边的起点protected double lastx,lasty; //边的终点位置protected double movingx,movingy; //用户坐标系下一个点的坐标protected int numPoints=0; //顶点计数器protected boolean isPolygonMode=true; //标志protected Vector lines=new Vector(256,256); //Java的向量类//APPLET程序的初始化public void init(){m=new MyCanvas(this); //本APPLET容器的MyCanvas对象addMouseListener(this); //定义鼠标按钮监听器addMouseMotionListener(this); //定义鼠标按钮监听器Dimension d=getSize(); //本APPLET容器的大小width=d.width; height=d.height;}//成员变量初始化public void initData(){isFirstClicked=true; //鼠标最初点击isPolygonMode=true; //标志描绘多边形numPoints=0; //多边形顶点计数器bucket=new activeEdgeList[height+1]; //边的单链表数组for(int i=0;i<height+1;i++) bucket[i]=null;if(lines.size()>0) lines.removeAllElements(); //向量类的对象}//APPLET程序的绘图public void paint(Graphics g) {if(isFirstClicked) { //初始状态initData();Font f=m.MyFont(m.getFont().getName(),Font.BOLD+Font.ITALIC,3);m.setFont(f);m.drawString("单击画多边形",-1,0.2);m.drawString("双击填充多边形",-4,-6);}m.setBackground(new Color(220,220,220)); //背景色m.setColor(Color.black);//前景色for(int i=0;i<lines.size();i++) {Line l=(Line)lines.elementAt(i); //转换第i个向量m.drawLine(l.x1,l.y1,l.x2,l.y2);}if(isPolygonMode&&!isFirstClicked) //画线m.drawLine(lastx,lasty,movingx,movingy);if((!isPolygonMode)&&(image!=null)) //填充m.myDrawImage(image,leftTopx,leftTopy,this);} //APPLET程序的绘图//把多边形顶点数据生成边结点public void registerActiveEdgeEntry() {numEdge=lines.size(); //多边形边的数量edgeData=new activeEdgeListEntry[numEdge];for(int i=0;i<numEdge;i++) //每个边的单链表头结点edgeData[i]=new activeEdgeListEntry();/* 四个极值用于确定显示图像的大小和范围*/int LARGE=0x0ffffffff;int xmin=LARGE,xmax=-1,ymin=LARGE,ymax=-1;double dxmin=LARGE,dxmax=-1,dymin=LARGE,dymax=-1;for(int i=0;i<numEdge;i++) { //对每个边结点数组赋值Line l=(Line)lines.elementAt(i); //转换第i个向量int ix1=m.getX(l.x1); //将用户坐标的点转换到Java AWT坐标int iy1=height-m.getY(l.y1);int ix2=m.getX(l.x2);int iy2=height-m.getY(l.y2);edgeData[i].topx=0;edgeData[i].name=i;edgeData[i].next=null;if(iy1>iy2) { //边的斜向edgeData[i].isHorizontal=false;edgeData[i].topy=iy1;edgeData[i].topx=ix1;edgeData[i].x=ix1;edgeData[i].boty=iy2;edgeData[i].delta=(double)(-(ix2-ix1))/(iy2-iy1);if(iy2<ymin) { //进行yMin yMax 计算ymin=iy2;dymin=l.y2;}if(iy1>ymax) {ymax=iy1;dymax=l.y1;}}else if(iy1<iy2) { //边的斜向edgeData[i].isHorizontal=false;edgeData[i].topy=iy2;edgeData[i].topx=ix2;edgeData[i].x=ix2;edgeData[i].boty=iy1;edgeData[i].delta=(double)(-(ix1-ix2))/(iy1-iy2);if(iy1<ymin) { //进行yMin yMax 计算ymin=iy1;dymin=l.y1;}if(iy2>ymax) {ymax=iy2;dymax=l.y2;}}else { //水平边y1==iy2edgeData[i].isHorizontal=true;if(iy1<ymin) { //进行yMin yMax 计算ymin=iy1;dymin=l.y1;}if(iy1>ymax) {ymax=iy1;dymax=l.y1;}}if(ix1<ix2) { //进行xMin xMax 计算if(ix1<xmin) {xmin=ix1;dxmin=l.x1;}if(ix2>xmax) {xmax=ix2;dxmax=l.x2;}}else if(ix2<ix1) {if(ix2<xmin) {xmin=ix2;dxmin=l.x2;}if(ix1>xmax) {xmax=ix1;dxmax=l.x1;}}else { //垂直边ix2==ix1if(ix1<xmin) {xmin=ix1;dxmin=l.x1;}if(ix1>xmax) {xmax=ix1;dxmax=l.x1;}}} //结束for循环/*内存图像的数组空间及相关数据*/pixelWidth=xmax-xmin+1;pixelHeight=ymax-ymin+1;pixel=new int[pixelWidth*pixelHeight]; //图像的个点颜色for(int k=0;k<pixelWidth*pixelHeight;k++)pixel[k]=0x00000000; //初值透明色xoffset=xmin;yoffset=ymin;leftTopx=dxmin; //用于显示图像方法myDrawImage();leftTopy=dymax;} //生成边结点registerActiveEdgeEntry()//多边形单链表数组bucketd初始化public void bucketSort() {for(int i=0;i<lines.size();i++) {Line l=(Line)lines.elementAt(i); //转换第i个向量if(edgeData[i].isHorizontal) continue; //水平边不处理int yt=edgeData[i].topy;if(bucket[yt]==null) { //该行未建立链表bucket[yt]=new activeEdgeList(edgeData[i]);continue;}bucket[yt].insert(edgeData[i]); //该行有链表,按顺序插入到链表i } //结束for循环}//多边形的扫描转换public void scanPolygon() {activeHeader=null; //当前要处理的单链表for(int y=height-1;y>=0;y--) {if(bucket[y]!=null) { //该指针元素存在makeActiveEdgeList(bucket[y],y); //建立该行的边链表processActiveEdgeList(y); //处理该行的边链表}else if(activeHeader!=null&&activeHeader.header!=null)processActiveEdgeList(y); //处理该行的边链表} //结束for循环} //多边形的扫描转换//处理给定行的边链表public void processActiveEdgeList(int y) {int xleft,xright;double xl,xr;activeEdgeListEntry left=activeHeader.header;activeEdgeListEntry right=left.next;if(right==null) return;while(true) {xl=left.x;xr=right.x;xleft=(int)xl;xright=(int)(xr+0.5);if(xleft<=xright)fillScanline(xleft,xright,y); //填充y行像素列left.x+=left.delta; //起终点右移一个步长right.x+=right.delta;if(left.boty>=y-1 && right.boty>=y-1) {xleft=(int)left.x;xright=(int)(right.x+0.5);if(xleft<=xright)fillScanline(xleft,xright,y-1); //填充y-1行像素列}if(left.boty>=y-1) //将左面的边从当前链表中删去activeHeader.remove(left);if(right.boty>=y-1) //将左面的边从当前链表中删去activeHeader.remove(right);left=right.next; //选择当前链表中下一对结点if(left==null) break; //到达链表末尾,退出循环right=left.next;if(right==null) //边链表的结点数一定为偶数throw new NullPointerException(); //出错} //结束whileactiveHeader.traverse(); //边封闭后,重新整理单链表} //处理给定行的边链表//建立指定行的边链表public void makeActiveEdgeList(activeEdgeList list,int y) { if(activeHeader==null)activeHeader=list; //指定为当前单链表else //把list与当前单链表合并activeHeader=activeHeader.merge(list,y);}//填充何种图案public boolean isTilePattern(int i,int j) {if( i%8==0 || j%8==0 || i%8==1 || j%8==1 ||i%8==2 || j%8==2 ) return true; // 填充图案1 return false; // 填充图案2}//设定像素颜色public void putPixel(int i,int j) {int r,g,b;if(isTilePattern(i,j))r=g=b=0; //黑色else {r=(int)(Math.random()*255); //0到255之间的随机数g=(int)(Math.random()*255);b=(int)(Math.random()*255);}int a=0xff000000|(r<<16)|(g<<8)|b; //像素颜色/*图像的i行j列处的颜色*/pixel[(pixelHeight-1-(j-yoffset))*pixelWidth+(i-xoffset)]=a; }//填充指定行的像素列public void fillScanline(int xleft,int xright,int y) {for(int x=xleft;x<=xright;x++)putPixel(x,y); //调用putPixel(),设定改点像素颜色}//------多边形填充总控程序----public void scanLineFillPolygon() {registerActiveEdgeEntry(); //生成边结点bucketSort(); //单链表数组bucketd初始化scanPolygon(); //多边形的扫描转换repaint(); //paint绘图}//响应鼠标击键事件public void mousePressed(MouseEvent e) {int ix=e.getX(); //鼠标的Jawa AWT坐标int iy=e.getY();if(isPolygonMode) { //正在进行多边形填充double x,y; //鼠标的当前位置if(e.getClickCount()>=2) { //双击,添加多边形的顶点isDoubleClicked=true; //标记/* 给光栅向量表增加一行,这个向量成员方法导致编译要加上参数-Xlint,会出现警告错误*/lines.addElement(new Line(lastx,lasty,x0,y0));isPolygonMode=false;scanLineFillPolygon(); //多边形填充总控程序if(numEdge>2) { //内存图像生成mis=new MemoryImageSource(pixelWidth,pixelHeight,pixel,0,pixelWidth);image=createImage(mis);}}else { //单击,准备开始if(isFirstClicked) { //初次点击isFirstClicked=false;/*先按照Jawa AWT坐标ix iy得到视图索引号,再由视图反向转换得到用户坐标系下的lastx lasty*/ lastx=x0=m.getUserX(ix,m.getViewport(ix,iy));lasty=y0=m.getUserY(iy,m.getViewport(iy,iy));movingx=lastx; movingy=lasty;}else { //非初次点击/*ix iy所对应的用户坐标系下的坐标*/x=m.getUserX(ix,m.getViewport(ix,iy));y=m.getUserY(iy,m.getViewport(iy,iy));/* 给光栅向量表增加一行*/lines.addElement(new Line(lastx,lasty,x,y));lastx=x; lasty=y;}numPoints++;}repaint(); //paint绘图} //结束if(isPolygonMode)语句} //响应鼠标击键事件//响应鼠标移动事件public void mouseMoved(MouseEvent e) {if(!isFirstClicked && isPolygonMode) {int ix,iy;ix=e.getX(); //鼠标的Jawa AWT坐标iy=e.getY();/*ix iy所对应的用户坐标系下的坐标*/movingx=m.getUserX(ix,m.getViewport(ix,iy));movingy=m.getUserY(iy,m.getViewport(ix,iy));repaint();}} //响应鼠标移动事件//****java语法列出有关鼠标接口中的虚方法public void mouseClicked(MouseEvent e){}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e){}public void mouseReleased(MouseEvent e){}public void mouseDragged(MouseEvent e){}} //结束多边形填充类运行结果:g2.drawLine(50,10,280,280);Sutherland_Cohen(g2,50,10,280,280);Sutherland_Cohen(g2,50,30,280,280);Sutherland_Cohen(g2,60,30,280,280);g2.drawLine(60,30,280,280); Sutherland_Cohen(g2,60,30,280,280);g2.drawLine(50,50,280,280); Sutherland_Cohen(g2,60,30,280,280);g2.drawLine(50,50,280,280);Sutherland_Cohen(g2,50,50,280,280);g2.drawLine(10,150,280,150);Sutherland_Cohen(g2,10,150,280,150);if(accept)g.drawLine((int)100,(int)150,(int)200,(int)150); 或g2.drawLine(10,150,280,150);Sutherland_Cohen(g2,50,30,280,280);if(accept)g.drawLine((int)100,(int)150,(int)200,(int)150);实验体会:本次实验练习的是多边形的裁剪与填充,程序是老师给定的程序,需要自己读懂程序所实现的功能,代码是死的程序是活的,只有读懂程序才能理解实验,才能使自己的程序设计进一步加强。

相关文档
最新文档