计算机图形学实验报告.docx
《计算机图形学实验报告.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验报告.docx(30页珍藏版)》请在冰点文库上搜索。
![计算机图形学实验报告.docx](https://file1.bingdoc.com/fileroot1/2023-5/11/11820222-43eb-47f2-b40a-44e314a5ae0e/11820222-43eb-47f2-b40a-44e314a5ae0e1.gif)
计算机图形学实验报告
计算机图形学实验报告
班级2011010
专业地理信息系统
组别
组员
华北水利水电学院资源与环境学院GIS教研室
实验一
基本图形的生成和几何变换算法实现
实验目的:
1、利用c#程序实现输出直线、三角形、矩形等简单图形。
2、利用二维基本图形变换的原理实现简单图形的缩放、旋转等简单变换。
实验原理:
数学原理
1、调用DrawLines可以实现直线的绘制;调用DrawPolygon可以实现多边形的绘制;调用DrawRectangle可以实现矩形的绘制。
2、基本几何变换:
假设
表示三维空间上一个未被变换的点,而该点经过某种变换后得到新的点用
表示。
1 平移变换:
如果点
是由点
在x轴,y轴和z轴分别移动
、
、
距离得到的,则两点坐标关系为:
则矢量形式为:
其中
,
,
2 缩放变换:
缩放变换改变物体的大小。
有坐标关系
其中,
,
,
分别为沿x,y和z轴方向放大或缩小的比例。
得到矩阵形式为
3 旋转变换:
设给定点P的坐标为
,则它绕z轴旋转
角后得到
有
有矩阵形式
设计思路:
1、对于图形的几何变换,将原始图形的坐标值写成矩阵的形式,并用数组a表示,将数组a的元素放入point型数组中,如:
数组a=newint[,]{{50,10,0}
{50,90,0},{100,90,0}};代表点(50,10),(50,90),(100,90)。
将数组a的元素放入point型数组中,如:
newPoint(a[0,0],a[0,1])。
2、定义变换矩阵b,根据以上数学原理将各值放入b中。
3、定义中间变量c,通过for循环将数组a与b相乘,并重新返回与a中。
4、再次输出时就是变换后的图形。
实验步骤:
程序1:
1、定义全局变量startPt与endPt;,作为记录鼠标点坐标的中间变量。
2、在mousedown中,记录鼠标点的坐标。
如果鼠标左击,则将该点坐标的x与y值分别赋于startPt.X与startPt.Y。
如果鼠标右击则分别赋于endPt.X与endPt.Y。
3、在Form1_Click中,将startPt与endPt分别赋予int型变量x1,x2,x3,x4中。
调用DrawLine(blackpen,x1,y1,x2,y2),画出(x1,y1)与(x1,y2)间线段。
4、调用DrawRectangle,将上一次确定的x1,y1作为矩形的一个顶点,画出边长为100的正方形。
调用DrawPolygon,在point数组中输入x1、y1相关的数值,画出三角形。
程序2:
1、定义全局变量数组a,用于存储坐标为(50,10),(50,90),(100,90)的三角形。
定义数组b,用于存储变换矩阵。
本程序将原图形放大2倍,旋转60度,X与Y坐标分别平移50与90。
2、在privatevoidForm1_Click中定义数组point,将数组a的元素添加到数组point中。
调用DrawPolygon函数画出三角形。
3、定义int型中间变量c,用3次for循环将数组a与数组b相乘,并将对应结果赋值于变量c,再将c复赋值于数组a。
4、再次调用DrawPolygon函数画出变换后的图形。
实验代码:
程序1基本图形的生成
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
namespaceWindowsFormsApplication31
{
publicpartialclassForm1:
Form
{
PointstartPt;
PointendPt;
publicForm1()
{
InitializeComponent();
}
privatevoidForm1_Paint(objectsender,PaintEventArgse)
{
//Graphicsg;
//g=this.CreateGraphics();
//Penblackpen=newPen(Color.Black);
//intx1=0;
//inty1=0;
//intx2=200;
//inty2=200;
//g.DrawLine(blackpen,x1,y1,x2,y2);
}
privatevoidForm1_Load(objectsender,EventArgse)
{
}
privatevoidForm1_MouseDown(objectsender,MouseEventArgse)
{
if(e.Button==MouseButtons.Left)
{
startPt=newPoint();
startPt.X=e.X;
startPt.Y=e.Y;
}
elseif(e.Button==MouseButtons.Right)
{
endPt=newPoint();
endPt.X=e.X;
endPt.Y=e.Y;
}
}
privatevoidForm1_Click(objectsender,EventArgse)
{
Graphicsg;
g=this.CreateGraphics();
Penblackpen=newPen(Color.Blue,2);
intx1=startPt.X;
inty1=startPt.Y;
intx2=endPt.X;
inty2=endPt.Y;
g.DrawLine(blackpen,x1,y1,x2,y2);
g.DrawRectangle(blackpen,x1+150,y1,100,100);
Point[]point=
{
newPoint(x1,y2),
newPoint(x1-50,200),
newPoint(x1+150,200)
};
g.DrawPolygon(blackpen,point);
}
}
}
程序2:
图形的几何变换
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
namespaceWindowsApplication2
{
publicpartialclassForm1:
Form
{
int[,]a=newint[,]{{50,10,0},{50,90,0},{100,90,0}};
double[,]b=newdouble[,]{{2,1.0471,0},{-1.0471,2,0},{50,90,1,}};
publicForm1()
{
InitializeComponent();
}
privatevoidForm1_Load(objectsender,EventArgse)
{
}
privatevoidForm1_Click(objectsender,EventArgse)
{
Graphicsg;
g=this.CreateGraphics();
Penblackpen=newPen(Color.Black,2);
Point[]point=
{
newPoint(a[0,0],a[0,1]),
newPoint(a[1,0],a[1,1]),
newPoint(a[2,0],a[2,1])
};
g.DrawPolygon(blackpen,point);
intc;
for(inti=0;i<3;i++)
{
for(intj=0;j<3;j++)
{
c=0;
for(intk=0;k<3;k++)
{
c+=(int)(a[i,k]*b[k,j]);
}
a[i,j]=c;
}
}
g.DrawPolygon(blackpen,point);
}
protectedoverridevoidOnPaint(PaintEventArgse)
{
Fontfnt=newFont("Verdana",16);
Graphicsg=e.Graphics;
g.DrawString("单击屏幕一点",fnt,newSolidBrush(Color.Red),14,10);
}
}
}
实验结果:
参数设置:
程序1中startPt与endPt为point型变量,记录鼠标点击的坐标。
程序2:
1、数组a存储图形坐标点。
表示{50,10,0},{50,90,0},{100,90,0};代表起始坐标点为(50,10),(50,90),(100,90);数组b存储变换矩阵。
为{2,1.0471,0},{-1.0471,2,0},{50,90,1,};其中2代表将图形放大2倍,1.0471为60度的弧度值,代表图形旋转60度。
50与90分别代表X轴与Y轴分别平移50与90.
2、数组point存储图形的坐标值。
Blackpen为黑色字体,2号。
3、int型数c为中间变量,作用为将矩阵相乘后的值重新赋值于a。
程序运行后的结果:
程序1:
基本图形的生成
图一
利用鼠标点击图中线段右短点,生成如图线段,以该点的y值作为三角形的上顶点y值,即(0,y1),(x1-50,200),(x1+150,200)。
矩形顶点坐标:
(x1+150,y1),长与宽均为100.
程序2:
图形的几何变换
图二图三
调试程序后出现图一(画出原始图形),点击对话框任一点后出现图二(经过变换后的图形)。
小组分工:
本次实验由编写程序源代码,写文稿,整理排版。
=
性能分析及心得:
基本图形的生成与几何变换的程序都已经运行出正确结果。
基本图形的生成的程序中矩形与三角形的参数利用了绘制直线中的数据,两次实验都没有进行大规模的乘除运算,节省了时间与空间。
时间与空间利用率较高。
通过这次实验,本组成员对基本图形的生成和几何变换的方法和原理有了更加深刻的理解。
本次实验指导教师评语及成绩:
评语:
成绩:
指导教师签名:
批阅日期:
实验二
折线的分段抛物线插值
实验目的:
运用拉格朗日插值算法实现折线的分段抛物线插值。
实验原理:
拉格朗日插值法:
已知函数y=f(x)在n+1个不同的点x0 ,x1 ,…,x2 上的函数值分别为:
y0 ,y1 ,…,yn ,求一个次数不超过n的多项式Pn (x),使其满足:
Pn (xi )=yi ,(i=0,1,…,n),
即n+1个不同的点可以唯一决定一个n次多项式。
(1).插值基函数
过n+1个不同的点分别决定n+1个n次插值基函数
l0 (x),l1 (x),…,ln (X)
每个插值基本多项式li (x)满足:
(1) li (x)是n次多项式;
(2) li (xi )=1,而在其它n个li (xk )=0,(k≠i)。
由于li (xk )=0,(k≠i),故有因子:
(x-x0 )…(x-xi-1 )(x-xi+1 )…(x-xn )
因其已经是n多项式,故而仅相差一个常数因子。
令:
li (x)=a(x-x0 )…(x-xi-1 )(x-xi+1 )…(x-xn )
由li (xi )=1,可以定出a,进而得到:
(x)=
(2). n次拉格朗日型插值多项式Pn (x)
Pn (x)是n+1个n次插值基本多项式l0 (x),l1 (x),…,ln (X)的线性组合,相应的组合系数是y0 ,y1 ,…,yn 。
即:
Pn (x)=y0 l0 (x)+y1 l1 (x)+…+yn ln (x) ,
从而Pn (x)是一个次数不超过n的多项式,且满足
Pn (xi )=yi ,(i=0,1,2,…,n).
实验步骤:
(1)用六个int型变量表示三个坐标点的X、Y值。
画出两条相应折线。
(2)将x从x0开始,每次递增1个单位,计算a=(x-x1)(x-x2)/((x0-x1)(x0-x2))和b、c的值,通过for循环计算与每个x对应的y=a*y0+b*y1+c*y2,加上强制类型转换。
将所得x与y值与(x0,y0)连接,然后将该x与y值复制给中间变量temp。
实验代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
namespaceWindowsFormsApplication38
{
publicpartialclassForm1:
Form
{
publicForm1()
{
InitializeComponent();
}
privatevoidForm1_Load(objectsender,EventArgse)
{
}
privatevoidForm1_Click(objectsender,EventArgse)
{
Graphicsg=this.CreateGraphics();
Penpen=newPen(Color.Red,2);
g.Clear(this.BackColor);
intx0=20,y0=350,x1=120,y1=100,x2=220,y2=350;
PointPoint1=newPoint(x0,y0);
PointPoint2=newPoint(x1,y1);
PointPoint3=newPoint(x2,y2);
g.DrawLine(pen,Point1,Point2);
g.DrawLine(pen,Point2,Point3);
inttemp1=x0,temp2=y0;
intx=x0,y=0;
for(inti=1;i{
x++;
doublea=((x-x1)*(x-x2))/((x0-x1)*(x0-x2)+0.5);
doubleb=((x-x0)*(x-x2))/((x1-x0)*(x1-x2)+0.5);
doublec=((x-x0)*(x-x1))/((x2-x0)*(x2-x1)+0.5);
y=(int)(a*y0+b*y1+c*y2);
PointstartPoint=newPoint(temp1,temp2);
PointendPoint=newPoint(x,y);
g.DrawLine(pen,startPoint,endPoint);
temp1=x;
temp2=y;
}
}
}
}
实验结果
:
小组分工:
本次实验由编写程序源代码,写文稿;整理排版。
性能分析及心得:
经过调试,本程序能够运行出正确结果。
使用拉格朗日算法,有较多的乘法运算,因此复杂度较高。
但本程序的for运算较少,因此时间复杂度不高。
这次实验使我们对拉格朗日算法有了一个更加深刻的了解。
本次实验指导教师评语及成绩:
评语:
成绩:
指导教师签名:
批阅日期:
实验三
基于OpenGL的简单几何造型
实验目的:
利用opengl实现绘制三维物体,使该物体看起来真实逼真。
本次我们绘制一个可旋转的三棱锥。
实验原理:
调用OpenGL函数来实现图形的绘制。
主要通过使用glRotatef函数使所绘制的绕轴旋转,使用glVertex3f函数构造三棱锥的各个面等。
实验步骤:
1.创建一个新的Win32程序
2.设置我的的程序中使用的所有变量。
第一行设置的变量是RenderingContext(着色描述表)。
每一个OpenGL都被连接到一个着色描述表上。
着色描述表将所有的OpenGL调用命令连接到DeviceContext(设备描述表)上。
我将OpenGL的着色描述表定义为hRC。
再创建一个设备描述表,Windows的设备描述表被定义为hDC。
DC将窗口连接到GDI(GraphicsDeviceInterface图形设备接口)。
而RC将OpenGL连接到DC。
第三行的变量hWnd将保存由Windows给我们的窗口指派的句柄。
第四行为我们的程序创建了一个Instance
HGLRChRC=NULL;
HDChDC=NULL;
HWNDhWnd=NULL;
HINSTANCEhInstance;
3.设置一个用来监控键盘动作的数组。
active变量用来告知程序窗口是否处于最小化的状态。
fullscreen变量的作用相当明显。
如果我们的程序在全屏状态下运行,fullscreen的值为TRUE,否则为FALSE。
boolkeys[256];
boolactive=TRUE;
boolfullscreen=TRUE;
4.定义WndProc()。
这么做是因为是CreateGLWindow()有对WndProc()的引用,但WndProc()在CreateGLWindow()之后才出现。
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
5.重新设置OpenGL场景的大小,不管窗口的大小是否已经改变。
GLvoidReSizeGLScene(GLsizeiwidth,GLsizeiheight)
{
if(height==0)
{
height=1;
}
glViewport(0,0,width,height);
6.为透视图设置屏幕。
意味着越远的东西看起来越小。
这么是为创建了一个现实外观的场景。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
7.对OpenGL进行所有的设置。
我们将设置清除屏幕所用的颜色,打开深度缓存,启用smoothshading(阴影平滑)。
此过程将有返回值。
glShadeModel(GL_SMOOTH);
8.清除屏幕,且将深度缓存设想为屏幕后面的层。
深度缓存不断的对物体进入屏幕内部有多深进行跟踪。
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
9.透视修正,使得透视图看起来好一点,返回TRUE。
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
returnTRUE;
10.添写旋转,颜色代码和编写三棱锥绘图代码。
intDrawGLScene(GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
glbegin(gl_triangles);
glcolor3f(1.0f,0.0f,0.0f);
glvertex3f(0.0f,1.0f,0.0f);
glcolor3f(0.0f,1.0f,0.0f);
glvertex3f(-1.0f,-1.0f,1.0f);
glcolor3f(0.0f,0.0f,1.0f);
glvertex3f(1.0f,-1.0f,1.0f);
glcolor3f(1.0f,0.0f,0.0f);
glvertex3f(0.0f,1.0f,0.0f);
glcolor3f(0.0f,0.0f,1.0f);
glvertex3f(1.0f,-1.0f,1.0f);
glcolor3f(0.0f,1.0f,0.0f);
glvertex3f(1.0f,-1.0f,-1.0f);
glcolor3f(1.0f,0.0f,0.0f);
glvertex3f(0.0f,1.0f,0.0f);
glcolor3f(0.0f,1.0f,0.0f);
glvertex3f(1.0f,-1.0f,-1.0f);
glcolor3f(0.0f,0.0f,1.0f);
glvertex3f(-1.0f,-1.0f,-1.0f);
glcolor3f(1.0f,0.0f,0.0f);
glvertex3f(0.0f