计算机图形学 实验二要点

合集下载

计算机图形学实验二:直线的生成算法的实现

计算机图形学实验二:直线的生成算法的实现

实验二: 直线的生成算法的实现班级 08信计2班学号 20080502055 姓名分数一、实验目的和要求:1.理解直线生成的原理;2.掌握几种常用的直线生成算法;3.利用C实现直线生成的DDA算法。

二、实验内容:1.了解直线的生成原理2、掌握几种基本的直线生成算法: DDA画线法、中点画线法、Bresenham画线法。

3、仿照教材关于直线生成的DDA算法, 编译程序。

4.调试、编译、运行程序。

三、实验过程及结果分析1.直线DDA算法:算法原理:已知过端点P0(x0,y0), P1(x1,y1)的直线段L(P0,P1), 斜率为k=(y1-y0)/(x1-x0), 画线过程从x的左端点x0开始, 向x右端点步进, 步长为1个像素, 计算相应的y坐标为y=kx+B。

计算y i+1 = kx i+B=kx i +B+kx=y i +kx当x=1,yi+1=yi+k, 即当x每递增1, y递增k。

由计算过程可知, y与k可能为浮点数, 需要取y整数, 源程序中round(y)=(int)(y+0.5)表示y四舍五入所得的整数值。

(1)程序代码:#include"stdio.h"#include"graphics.h"void linedda(int x0,int y0,int x1,int y1,int color){int x,dy,dx,y;float m;dx=x1-x0;dy=y1-y0;m=dy/dx;y=y0;for(x=x0;x<=x1;x++){putpixel(x,(int)(y+0.5),color);y+=m;setbkcolor(7);}}main(){int a,b,c,d,e;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode,"");a=100;b=100;c=200;d=300;e=5;linedda(a,b,c,d,e);getch();closegraph();}运行结果:2.中点画线算法:假定所画直线的斜率为k∈[0,1], 如果在x方向上增量为1, 则y方向上的增量只能在0~1之间。

计算机图形学实验报告 (2)

计算机图形学实验报告 (2)

实验一Window图形编程根底一、实验类型:验证型实验二、实验目的1、熟练使用实验主要开发平台VC6.0;2、掌握如何在编译平台下编辑、编译、连接和运行一个简单的Windows图形应用程序;3、掌握Window图形编程的根本方法;4、学会使用根本绘图函数和Window GDI对象;三、实验内容创立基于MFC的Single Document应用程序〔Win32应用程序也可,同学们可根据自己的喜好决定〕,程序可以实现以下要求:1、用户可以通过菜单项选择择绘图颜色;2、用户点击菜单项选择择绘图形状时,能在视图中绘制指定形状的图形;四、实验要求与指导1、建立名为“颜色〞的菜单,该菜单下有四个菜单项:红、绿、蓝、黄。

用户通过点击不同的菜单项,可以选择不同的颜色进行绘图。

2、建立名为“绘图〞的菜单,该菜单下有三个菜单项:直线、曲线、矩形其中“曲线〞项有级联菜单,包括:圆、椭圆。

3、用户通过点击“绘图〞中不同的菜单项,弹出对话框,让用户输入绘图位置,在指定位置进行绘图。

五、实验结果:六、实验主要代码1、画直线:CClientDC *m_pDC;再在OnDraw函数里给变量初始化m_pDC=new CClientDC(this);在OnDraw函数中添加:m_pDC=new CClientDC(this);m_pDC->MoveTo(10,10);m_pDC->LineTo(100,100);m_pDC->SetPixel(100,200,RGB(0,0,0));m_pDC->TextOut(100,100);2、画圆:void CMyCG::LineDDA2(int xa, int ya, int xb, int yb, CDC *pDC){int dx = xb - xa;int dy = yb - ya;int Steps, k;float xIncrement,yIncrement;float x = xa,y= ya;if(abs(dx)>abs(dy))Steps = abs(dx);elseSteps = abs(dy);xIncrement = dx/(float)Steps;yIncrement = dy/(float)Steps;pDC->SetPixel(ROUND(x),ROUND(y),RGB(0,0,0));for(k=0;k<Steps;k++){x +=xIncrement;y +=yIncrement;sleep(10);pDC->SetPixel(ROUND(x),ROUND(y),RGB(0,0,0));}3、画矩形void CRectangleDlg::OnLButtonDown(UINT nFlags, CPoint point){lButtonDownNotUp = TRUE;RECT rect;m_showRectangle. GetClientRect( &rect ) ;if( (point. x<rect. right) && (point. x>rect. left) && (point. y<rect. bottom) && (point. y>rect. top) ){regionLeftTopTemp = point;}CDialog::OnLButtonDown(nFlags, point);}void CRectangleDlg::OnMouseMove(UINT nFlags, CPoint point){RECT rect;m_showRectangle. GetClientRect( &rect );if( ( point.x<rect.right ) && ( point.x>rect.left ) && ( point.y<rect.bottom ) && ( point.y>rect.top ) ){if( ( lButtonDownNotUp == TRUE ){regionRightBottomTemp = point;CDC * pDC = m_showRectangle. GetWindowDC ();pDC -> Rectangle( CRect( regionLeftTopTemp, regionRightBottomTemp ) ) ;}}CDialog::OnMouseMove(nFlags, point);}void CRectangleDlg::OnLButtonUp(UINT nFlags, CPoint point){lButtonDownNotUp=FALSE;CDialog::OnLButtonUp(nFlags, point);}实验二根本图形生成算法一、实验类型:验证型实验二、实验目的1、掌握DDA、Bresenham直线生成算法;2、掌握Bresenham或中点圆生成算法;3、掌握Bresenham或中点椭圆生成算法;三、实验内容1、实现DDA、Bresenham直线生成算法;2、实现Bresenham画圆法或中点画圆法;3、实现Bresenham或中点法椭圆生成算法;4、利用1、2、3实现的直线、圆、椭圆图形生成函数进行图形绘制;四、实验要求与指导1、按照实验指导书1.6节创立一个基于MFC的Single Document应用程序。

计算机图形学实验二 直线的生成算法的实现

计算机图形学实验二 直线的生成算法的实现

实验二直线的生成算法的实现班级 08信计二班学号 20080502086 姓名分数一、实验目的和要求:1、理解直线生成的基本原理2、熟悉直线的生成算法,掌握直线的绘制3、实现直线生成的DDA 中点画法 Bresenham算法4、了解Visual C++等编程环境中常用控件命令与绘图函数,初步掌握在试验设计集成下进行图形处理程序的设计方法二、实验内容:1、了解直线生成的原理直线DDA算法,中点画线算法,Bresenham画线算法2、编程实现DDA算法、Bresenham算法、中点画法绘制直线段三、实验结果分析1.DDA算法// 程序名称:基于 DDA 算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 四舍五入int Round(float x){return (int)(x < 0 ? x - 0.5 : x + 0.5);}// 使用 DDA 算法画任意斜率的直线(包括起始点,不包括终止点)void Line_DDA(int x1, int y1, int x2, int y2, int color){float x, y; // 当前坐标点float cx, cy; // x、y 方向上的增量int steps = abs(x2 - x1) > abs(y2 - y1) ? abs(x2 - x1) : abs(y2 - y1);x = (float)x1;y = (float)y1;cx = (float)(x2 - x1) / steps;cy = (float)(y2 - y1) / steps;for(int i = 0; i < steps; i++){putpixel(Round(x), Round(y), color); // 在坐标 (x, y) 处画一个 color 颜色的点x += cx;y += cy;}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_DDA(100, 1, 1, 478, GREEN);Line_DDA(1, 478, 638, 1, GREEN);// 按任意键退出getch();closegraph();}2.中点算法// 程序名称:基于中点算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)void Line_Midpoint(int x1, int y1, int x2, int y2, int color){int x = x1, y = y1;int a = y1 - y2, b = x2 - x1;int cx = (b >= 0 ? 1 : (b = -b, -1));int cy = (a <= 0 ? 1 : (a = -a, -1));putpixel(x, y, color);int d, d1, d2;if (-a <= b) // 斜率绝对值 <= 1{d = 2 * a + b;d1 = 2 * a;d2 = 2 * (a + b);while(x != x2){if (d < 0)y += cy, d += d2;elsed += d1;x += cx;putpixel(x, y, color);}}else // 斜率绝对值 > 1{d = 2 * b + a;d1 = 2 * b;d2 = 2 * (a + b);while(y != y2){if(d < 0)d += d1;elsex += cx, d += d2;y += cy;putpixel(x, y, color);}}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_Midpoint(100, 1, 1, 478,YELLOW);Line_Midpoint(1, 478, 638, 1, YELLOW);// 按任意键退出getch();closegraph();}3. Bresenham 算法// 程序名称:基于 Bresenham 算法画任意斜率的直线#include <graphics.h>#include <conio.h>// 使用 Bresenham 算法画任意斜率的直线(包括起始点,不包括终止点)void Line_Bresenham(int x1, int y1, int x2, int y2, int color){int x = x1;int y = y1;int dx = abs(x2 - x1);int dy = abs(y2 - y1);int s1 = x2 > x1 ? 1 : -1;int s2 = y2 > y1 ? 1 : -1;bool interchange = false; // 默认不互换 dx、dyif (dy > dx) // 当斜率大于 1 时,dx、dy 互换{int temp = dx;dx = dy;dy = temp;interchange = true;}int p = 2 * dy - dx;for(int i = 0; i < dx; i++){putpixel(x, y, color);if (p >= 0){if (!interchange) // 当斜率 < 1 时,选取上下象素点y += s2;else // 当斜率 > 1 时,选取左右象素点x += s1;p -= 2 * dx;}if (!interchange)x += s1; // 当斜率 < 1 时,选取 x 为步长elsey += s2; // 当斜率 > 1 时,选取 y 为步长p += 2 * dy;}}// 主函数void main(){initgraph(640, 480);// 测试画线Line_Bresenham(100, 1, 1, 478, RED);Line_Bresenham(1, 478, 638, 1, RED);// 按任意键退出getch();closegraph();}实验结果分析三种算法运算结果比较:像素逼近效果由好到差依次为:B算法、DDA算法、中点算法执行速度由快到慢依次为:中点算法、DDA算法、B算法。

实验二:图形填充算法实验报告

实验二:图形填充算法实验报告

《计算机图形学》实验报告(实验二:图形填充算法)一、实验目的及要求用两种方法做图形的填充算法!二、理论基础1.边填充算法对于每一条扫描线和每条多边形的交点(x1,y1),将该扫描线上的交点右方的所有像素取补。

2.种子填充算法利用栈来实现种子填充算法。

种子像素入栈,当栈非空时重复执行如下步骤:将栈顶像素出栈,将出栈像素置成多边形色,按左,上,右,下顺序检查与出栈像素相邻的四个像素,若其中某个像素不再边界且未置成多边形,则把该像素入栈!三、算法设计与分析1、边填充算法void CEdge_mark_fillView::OnDraw(CDC* pDC){CEdge_mark_fillDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);int d[500][500]={0};int inside;int x,y;Bresenham(80,101,100,400,d);Bresenham(100,300,290,400,d);Bresenham(292,400,382,50,d);Bresenham(380,50,202,150,d);Bresenham(200,150,82,101,d);for(y=0;y<500;y++){inside=0;for(x=0;x<500;x++){if(d[x][y]==1)if(d[x+1][y]!=1){inside=!(inside);}if(inside!=0)pDC->SetPixel(x,y,12);}}}2、种子填充int x=299,y=51;COLORREF oldcolor;COLORREF newcolor;oldcolor=RGB(256,256,256);newcolor=RGB(123,123,123);pDC->MoveTo (40,40);pDC->LineTo (80,40);pDC->LineTo (70,80);pDC->LineTo (40,40);FloodFill(51,51,RGB(255,255,255),RGB(0,0,255));pDC->LineTo (40,40);void CMyView::FloodFill(int x,int y,COLORREF oldcolor,COLORREF newcolor) {CDC* pDC;pDC=GetDC();if(pDC->GetPixel(x,y)==oldcolor){pDC->SetPixel(x,y,newcolor);FloodFill(x,y-1,oldcolor,newcolor);FloodFill(x,y+1,oldcolor,newcolor);FloodFill(x-1,y,oldcolor,newcolor);FloodFill(x+1,y,oldcolor,newcolor);}四、程序调试及结果的分析1、2、四、实验心得及建议由于很多不会,所以这次没能按时当堂完成,下来花了不少时间才弄出来,第二种尤其比较麻烦,在同学的帮助下才做出来了。

计算机图形学_实验2_二维图形绘制

计算机图形学_实验2_二维图形绘制

深圳大学实验报告课程名称:计算图形学实验名称:二维图形绘制学院:计算机与软件学院专业:计算机科学与技术报告人:学号:班级:同组人:无指导教师:周虹实验时间:2014/10/31实验报告提交时间:2014/11/3教务处制一.实验目的1、能正确使用OpenGL图元产生图画,并且学会使用多种生成图案的方式。

2、能正确设置图元属性,得到不同的绘制效果。

二.实验步骤1、用三角形模式画有颜色填充的太阳,圆心为(-0.5,0.7)2、直线模式,以-0.5,0.7为圆心画一些列直线作为太阳光3、用三角形画树,多边形画树干4、直线模式,以-0.5,0.7为圆心画一小花点缀树5、以三角形模式画一个小山坡,用天蓝色填充6、直线模式,以-0.5,0.7为圆心,以不同大小的直线画一系列小花点缀小山坡7、以不同大小的点形成双色围栏8、用不同的多边形模式画小树,用多边形模式画树干,并染上特别的颜色9、用虚线画零星的小草三.实验结果1、用三角形模式画有颜色填充的太阳,圆心为(-0.5,0.7)2、直线模式,以-0.5,0.7为圆心画一些列直线作为太阳光3、用三角形画树,多边形画树干4、直线模式,以-0.5,0.7为圆心画一小花点缀树5、以三角形模式画一个小山坡,用天蓝色填充6、直线模式,以-0.5,0.7为圆心,以不同大小的直线画一系列小花点缀小山坡7、以不同大小的点形成双色围栏8、用不同的多边形模式画小树,用多边形模式画树干,并染上特别的颜色9、用虚线画零星的小草四.实验心得通过这次实验,我比较深入地理解了二维图形的绘制过程和不同图元相关属性的设置,并学会运用不同的图元组合得到自己想要的画。

本次实验收获良多,主要体现在以下方面:作图时要善于运用函数。

例如在本次实验中涉及到画圆,可是opengl中并没有提供画圆的工具,这时函数就显得尤为重要了。

可是,有了函数还不够,得到函数后要根据自己要的属性选择适当的作图模式。

例如本次画太阳的过程中,一开始我选用GL_LINES的模式,当n趋向无穷大时得到一个圆,可是问题是这个圆是空心的,无法填充红色。

计算机图形学实验报告_2

计算机图形学实验报告_2

计算机图形学实验报告学号:********姓名:班级:计算机 2班指导老师:***2010.6.19实验一、Windows 图形程序设计基础1、实验目的1)学习理解Win32 应用程序设计的基本知识(SDK 编程);2)掌握Win32 应用程序的基本结构(消息循环与消息处理等); 3)学习使用VC++编写Win32 Application 的方法。

4)学习MFC 类库的概念与结构;5)学习使用VC++编写Win32 应用的方法(单文档、多文档、对话框);6)学习使用MFC 的图形编程。

2、实验内容1)使用WindowsAPI 编写一个简单的Win32 程序,调用绘图API 函数绘制若干图形。

(可选任务)2 )使用MFC AppWizard 建立一个SDI 程序,窗口内显示"Hello,Thisis my first SDI Application"。

(必选任务)3)利用MFC AppWizard(exe)建立一个SDI 程序,在文档视口内绘制基本图形(直线、圆、椭圆、矩形、多边形、曲线、圆弧、椭圆弧、填充、文字等),练习图形属性的编程(修改线型、线宽、颜色、填充样式、文字样式等)。

定义图形数据结构Point\Line\Circle 等保存一些简单图形数据(在文档类中),并在视图类OnDraw 中绘制。

3、实验过程1)使用MFC AppWizard(exe)建立一个SDI 程序,选择单文档;2)在View类的OnDraw()函数中添加图形绘制代码,说出字符串“Hello,Thisis my first SDI Application”,另外实现各种颜色、各种边框的线、圆、方形、多边形以及圆弧的绘制;3)在类视图中添加图形数据point_pp,pp_circle的类,保存简单图形数据,通过在OnDraw()函数中调用,实现线、圆的绘制。

4、实验结果正确地在指定位置显示了"Hello,This is my first SDI Application"字符串,成功绘制了圆,椭圆,方形,多边形以及曲线圆弧、椭圆弧,同时按指定属性改绘了圆、方形和直线。

图形学实验报告

图形学实验报告

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

图形学实验报告2

图形学实验报告2
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTransformView drawing
三、实验要求:
实验前须规划程序界面和按钮的相关事件的编写代码。实验时进行代码的调试。
四、实验代码
1,图形的变换
// TransformView.cpp : implementation of the CTransformView class
//
#include "stdafx.h"
#include "Transform.h"
#include "TransformDoc.h"
#include "TransformView.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
for(i=1; i<3; i++)
{
Pt[i].x *= 0.5;
Pt[i].y *= 0.5;
}
Pt[0] = TmpPt;
Pt[1] = Pt[1] + Pt[0];
Pt[2] = Pt[2] + Pt[0];
break;
case 0X58://X的ASCII码

山东大学计算机图形学实验报告实验二

山东大学计算机图形学实验报告实验二
山东大学计算机科学与技术学院 计算机图形学课程实验报告
学号:2420430689 姓名: QQ
班级: 2014 级
实Байду номын сангаас题目:实现二维平面的基本变换
实验学时:4
实验日期: 2017 年 3 月 28 日
实验目的: 1. 掌握配置 OpenGL 环境的方法; 2. 熟悉 OpenGL 应用程序基本架构; 3. 学习 OpenGL 中的 gl、glu、glut 等库函数进行图形学算法编程和实现。
//填充右部 while (!judgeIfBoundary(x, y)) {
glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); glFlush(); x = x + 1; } int xright = x - 1;
//填充左部 x = savex - 1; while (!judgeIfBoundary(x, y)) {
#include <cmath> #include <stack> #include <glut.h>
using namespace std;
struct mypoint {
GLint x; GLint y;
mypoint(GLint _x, GLint _y) :x(_x), y(_y) {}; mypoint() {}; };
x = x + 1; } } } } } 最后效果
结论分析与体会: 这次实验总的来讲比较繁琐,尤其是在计算校徽坐标的时候,当时是从学校官网 上找了一个比较正规的校徽,用 Windows 的画图工具打开,找出点的坐标然后用 数学方法变换的。
return true; else

计算机图形学实验报告

计算机图形学实验报告

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

计算机图形学实验报告2

计算机图形学实验报告2

计算机图形学实验报告2计算机图形学实验报告实验⼆、三维⽹格模型光顺⼀、实验⽬的与基本要求:(1)掌握Obj⽂件的读⼊;(2)利⽤给定的数据结构类,建⽴读⼊⽹格模型数据结构;(3)利⽤OpenGL类库,对三维模型进⾏绘制;(4)利⽤OpenGL类库,增加采⽤⿏标交互⽅式对三维模型进⾏旋转、放缩、平移等操作;(5)实现Laplacian⽅法的三维模型光顺操作,并观察三维模型光顺过程;⼆、实验设备(环境)及要求1. 操作系统:Windows XP 或Windows 72. 编程环境:Microsoft Visual Studio 2010,OpenGL 库函数3. 界⾯框架:Win32,MFC,QT选择其中⼀种三、实验内容与步骤实验分为以下⼏个步骤:(1)掌握Obj⽂件的读⼊顶点和⾯的个数;(2)建⽴数组存储点的坐标及⾯上的点数;(3)存储顶点的邻接⾯数,并记录每个顶点周围的邻接点(4)计算每个⾯的法向利⽤OpenGL类库,增加采⽤⿏标交互⽅式对三维模型进⾏旋转、放缩、平移等操作;(5)利⽤⾯法向及顶点坐标进⾏绘制⼏何体(6)实现⿏标对物体旋转、平移、缩放的算法(7)实现Laplacian⽅法的三维模型光顺操作,并观察三维模型光顺过程;四、实现过程说明及成果展⽰:(1)掌握Obj⽂件的读⼊顶点和⾯的个数;由于obj⽂件的存储形式是v x1 x2 x3;…f v1 v2 v3;…这种形式,所以在记录点和⾯的数量时,只需按⾏读取,然后再判断⾸字母是v/f即可实现代码如下:(2)建⽴数组存储点的坐标及⾯上的点数;数组的⼤⼩由点数和⾯数决定,点数组和⾯数组均由0开始记录,故后⾯再⽤⾯对应点的时候,由于⾯上点是从1开始记录,故需要减1然后使⽤,代码如下:(3)存储顶点的邻接⾯数,并记录每个顶点周围的邻接点记录点邻接⾯的是新建⼀个数组,在读⾯的时候,将该⾯的序号存⼊对应点的数组中,然后再在每个⾯上取⼀点,记录到点的邻接点数组中,在每个⾯上取得的点为向外右⼿⽅向的下⼀个点,实现代码如下:(4)计算每个⾯的法向计算⾯的法向⽅式为⾯上右⼿⽅向上的两向量的叉乘得到,即所⽤代码为:(8)利⽤⾯法向及顶点坐标进⾏绘制⼏何体⽤法向绘制的⽅式是先⽤glNormal3fv(v)指出⾯的法向;再⽤glVertex3f传⼊⾯上点的坐标;由于我将glNormal3fv(v)中写在算法向所以我直接对此直接调⽤即可,代码如下:(9)实现⿏标对物体旋转、平移、缩放的算法平移:利⽤Transform函数和键盘事件来改变参数,w,s,a,d分别控制绘制的kitty猫的上下左右的移动:实现代码如下:旋转:利⽤gllookat();函数设定了观察⾓度,并⽤⿏标事件改变参数,⽤实现观察视⾓的变化实现物体的旋转,代码如下:缩放:运⽤glScalef⽅法和键盘事件改变参数,实现物体的放⼤和缩⼩,代码如下:(10)实现Laplacian⽅法的三维模型光顺操作,并观察三维模型光顺过程;Laplacian⽅法的原理是利⽤⽬标点与其所有邻接点平均后的点的差向量,对⽬标点的坐标进⾏变换的过程,具体⽅法是:①建⽴每个点的邻接顶点数组,存储每个点的邻接点②对每个顶点的邻接点进⾏求平均,即将邻接点的坐标求和后除以邻接点个数,从⽽得到邻接平均点③得到优化向量优化向量= 邻接平均点-⽬标点④设定优化度参数λ,得到优化后的新坐标新坐标= ⽬标点+ λ*优化向量在程序中,对于第num个顶点,我设定的变量为邻接平均点v0优化向量l新坐标数组vNewArr具体代码如下:五、结果展⽰及说明计算⾯法向后直接绘制(未光顺):光顺进⾏⼀次后光顺多次后利⽤点绘制结果为旋转后缩放后平移后六、⼼得体会(1)计算⾯法向时法向量的⽅向没有运⽤右⼿⽅向,导致有的⾯法向向⾥,从⽽出现雪花(2)在运⽤Laplacian算法进⾏求邻接平均点时未初始化邻接平均点数组,导致平均点的累加从⽽出现越光顺越粗糙的现象(3)在obj⽂件中⾯对应顶点数和顶点数组的标号相差1.在运⽤的时候需减1,⾯从1开始记顶点,顶点数组从0开始记顶点七、实验代码#define GLUT_DISABLE_ATEXIT_HACK#include#include#include#include#include#include#include#includeusing namespace std;int v_num = 0; //记录点的数量int f_num = 0; //记录⾯的数量int vn_num = 0;//记录法向量的数量int vt_num = 0;GLfloat **vArr; //存放点的⼆维数组GLfloat **vNewArr;//存放点的⼆维数组int **fvArr; //存放⾯顶点的⼆维数组GLfloat **fnArr;//存放⾯法向量的⼆维数组int **ftArr;int **vfArr;//存放顶点临接的⾯数的数组int **nextVArr;//存放下⼀个临界顶点的数组GLfloat **vnArr;//存放点法向量的⼆维数组string s1, s2, s3, s4;GLfloat f2, f3, f4;int num1, num2, num3;typedef GLfloat point3[3];point3 x, y,l;//平⾯上的两个向量x,y和拉普拉斯向量lstatic GLfloat theta[] = { 0.0,0.0,0.0 };static GLint axis = 2;static GLdouble viewer[] = { 0.0, 0.0, 5.0 }; /* initial viewer location */ static GLdouble Tran[] = { 0.0,0.0,0.0 }; static GLdouble sca = 1.0;void getLineNum(string addrstr) //获取点和⾯的数量{ifstream infile(addrstr.c_str()); //打开指定⽂件if (!infile) {cout <<"open error!"<< endl;}string sline;//每⼀⾏int i = 0, j = 0;while (getline(infile, sline)) //从指定⽂件逐⾏读取{if (sline[0] == 'v'){v_num++;}if (sline[0] == 'f'){f_num++;}}}int readfile(string addrstr) //将⽂件内容读到数组中去{//getLineNum(addrstr);//new⼆维数组vArr = new GLfloat*[v_num];for (int i = 0; i < v_num; i++) {vArr[i] = new GLfloat[3];}vNewArr = new GLfloat*[v_num];for (int i = 0; i < v_num; i++) {vNewArr[i] = new GLfloat[3]; }vnArr = new GLfloat*[vn_num];for (int i = 0; i < vn_num; i++) {vnArr[i] = new GLfloat[3];}vfArr = new int*[v_num];for (int i = 0; i < v_num; i++) {vfArr[i] = new int[10];for (int j = 0; j < 10; j++) { vfArr[i][j] = -1;}}nextVArr = new int*[v_num];for (int i = 0; i < v_num; i++) {nextVArr[i] = new int[10];for (int j = 0; j < 10; j++) { nextVArr[i][j] = -1; }}fvArr = new int*[f_num];fnArr = new GLfloat*[f_num];ftArr = new int*[f_num];for (int i = 0; i < f_num; i++) {fvArr[i] = new int[3];fnArr[i] = new GLfloat[3];ftArr[i] = new int[10];}ifstream infile(addrstr.c_str()); if (!infile) { cout <<"open error!"<< endl;exit(1);}string sline;//每⼀⾏int ii = 0, jj = 0, kk = 0, mm = 0;while (getline(infile, sline)){if (sline[0] == 'v')//存储点{istringstream sin(sline);sin >> s1 >> f2 >> f3 >> f4;vArr[ii][0] = f2;vArr[ii][1] = f3;vArr[ii][2] = f4;ii++;}if (sline[0] == 'f') //存储⾯{istringstream in(sline);GLfloat a;in >> s1>>num1>>num2>>num3;//去掉f fvArr[kk][0] = num1;fvArr[kk][1] = num2;fvArr[kk][2] = num3;for (int i = 0; i < 10; i++) {if (vfArr[num1-1][i] == -1) {vfArr[num1-1][i] = kk;nextVArr[num1-1][i] = num2;break;}}for (int j = 0; j < 10; j++) {if (vfArr[num2-1][j] == -1) {vfArr[num2-1][j] = kk;nextVArr[num2-1][j] = num3;break;}}for (int i = 0; i < 10; i++) {if (vfArr[num3-1][i] == -1) {vfArr[num3-1][i] = kk;nextVArr[num3-1][i] = num1;break;}}kk++;}}return 0;}//计算⾯法向void nomal(point3p) {/*⽮量的归⼀化*///double sqrt();float d = 0.0;int i;for (i = 0; i < 3; i++)d += p[i] * p[i];d = sqrt(d);if (d > 0.0)for (i = 0; i < 3; i++)p[i] /= d;}void getFaceNormal(point3A, point3B, point3C) { x[0] = C[0] - A[0]; x[1] = C[1] - A[1];x[2] = C[2] - A[2];y[0] = A[0] - B[0];y[1] = A[1] - B[1];y[2] = A[2] - B[2];point3 v;v[0] = x[1] * y[2] - x[2] * y[1];v[1] = x[2] * y[0] - x[0] * y[2];v[2] = x[0] * y[1] - x[1] * y[0];nomal(v);glNormal3fv(v);}void Laplacian() {for (int num = 0; num < v_num; num++) {int m = 0;//求得点的邻接⾯数for (int i = 0; i < 10; i++) {if (nextVArr[num][i] != -1) {m++;}else {break;}}point3 v0;for (int i = 0; i < 3; i++) {v0[i] = 0;}for (int i = 0; i < m; i++) {v0[0] += vArr[nextVArr[num][i] - 1][0];v0[1] += vArr[nextVArr[num][i] - 1][1];v0[2] += vArr[nextVArr[num][i] - 1][2];}if (m != 0) {for (int i = 0; i < 3; i++)v0[i] /= m;}l[0] = v0[0] - vArr[num][0];l[1] = v0[1] - vArr[num][1];l[2] = v0[2] - vArr[num][2];vNewArr[num][0] = vArr[num][0] + l[0] * 0.3;vNewArr[num][1] = vArr[num][1] + l[1] * 0.3;vNewArr[num][2] = vArr[num][2] + l[2] * 0.3;}for (int i = 0; i < v_num; i++) {vArr[i][0] = vNewArr[i][0];vArr[i][1] = vNewArr[i][1];vArr[i][2] = vNewArr[i][2];}}void init(void){getLineNum("H:\\kitten_noisy.obj");readfile("H:\\kitten_noisy.obj");double viewer[] = { 0.0, 0.0, 8.0 }; /* initial viewer location */GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat mat_shininess[] = { 50.0 };//材料的镜⾯指数,其值越⼤越精细GLfloat light_position[] = { 1.0, 1.0f, 1.0, 0.0 };GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 };glClearColor(0.0, 0.0, 0.0, 0.0);glShadeModel(GL_SMOOTH);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);glLightfv(GL_LIGHT0, GL_POSITION, light_position);//光源位置glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);//漫反射光源glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);//镜⾯反射光源glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);//环境光源// glEnable(glMaterialf);glEnable(GL_LIGHTING);//启动光照glEnable(GL_LIGHT0);//启⽤0度光源glEnable(GL_DEPTH_TEST);//启动深度测试/*glShadeModel(GL_SMOOTH); // Enable Smooth ShadingglClearColor(0.0f, 0.0f, 0.0f, 0.5f); // ⿊⾊背景glClearDepth(1.0f);// 深度缓冲区设置glEnable(GL_DEPTH_TEST); // 允许深度测试glDepthFunc(GL_LEQUAL);// 定义深度测试类型glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculation */}。

计算机图形学--实验二---基本图形

计算机图形学--实验二---基本图形

实验二基本图形(元)生成技术(一)直线生成算法一、实验目的在一个图形系统中,基本图形(也称为图元、图素等)的生成技术是最基本的,任何复杂的图形都是由基本图形组成的,基本图形生成的质量直接影响该图形系统绘图的质量。

所以,需要设计出精确的基本图形生成算法,以确保图形系统绘图的精确性。

本次实验的目的就是验证直线生成的三种扫描算法,并要求对基本算法进行扩充和改进,包括:利用Visual C++实现三种直线生成算法,验证算法的正确性;二、实验任务1.理解三种直线生成算法思想,写出实现程序;2.添加鼠标功能,实现交互式画直线程序;3.将10个像素作为步距单位,编出Bresenham算法的示例。

三、基本知识和实验步骤任务一:实现DDA画线程序实验步骤:1.建立一个DDALine的工程文件;2.添加ddaline()成员函数方法:在工作区中选择CLASSVIEW类窗口,右击CDDAlineView类,选择“add member function…”,定义如下的成员函数:void ddaline(CDC* pDC,int x0,int y0,int x1,int y1,COLORREF color);3.编写自定义的成员函数ddaline()程序void CDDALineView::ddaline(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color) {int length,i;float x,y,dx,dy;length=abs(x1-x0);if (abs(y1-y0)>length)length=abs(y1-y0);dx=(x1-x0)/length;dy=(y1-y0)/length;x=x0+0.5;y=y0+0.5;for (i=1;i<=length;i++){pDC->SetPixel((int)x,(int)y,color);x=x+dx;y=y+dy;}}4.编写OnDraw()函数void CDDALineView::OnDraw(CDC* pDC){CDDALineDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereddaline(pDC,100,100,400,100,RGB(255,0,0));ddaline(pDC,400,100,400,400,RGB(0,255,0));ddaline(pDC,400,400,100,400,RGB(0,0,255));ddaline(pDC,100,400,100,100,RGB(255,255,0));ddaline(pDC,100,100,400,400,RGB(255,0,255));ddaline(pDC,100,400,400,100,RGB(0,255,255));}}5.编译、调试和运行程序,查看程序结果。

计算机图形学实验报告

计算机图形学实验报告

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

计算机图形学实验指导(一、二)

计算机图形学实验指导(一、二)

电脑图形学实验指导实验一、直线的扫描转换算法实验实验目的掌握中点Bresenham直线扫描转换算法的思想。

实验环境实验内容问题描述:给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。

中点Bresenham直线扫描转换算法原理见课本。

实验基本步骤首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下:void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y);在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。

COLORREF SetPixel(int x, int y, COLORREF crColor );再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine函数画出不同斜率情况的直线,如下列图:最后、调试程序直至正确画出直线。

实验要求1写出中点Bresenham直线扫描转换算法的程序并在vc6下编译和调试通过,画出具有各种斜率范围的直线(仅使用GDI函数SetPixel函数)。

2按规定的实验格式写出实验报告,包含实验代码〔自己写的画线函数〕,结果〔截图〕。

实验二、多边形填充算法实验实验目的掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。

实验环境实验内容问题描述:给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)…使用边标志算法或有效边表算法进行多边形填充。

边标志算法或有效边表算法原理见课本。

实验基本步骤首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。

其次、实现边标志算法或有效边表算法函数,如下:void FillPolygon(CDC *pDC, int px[], int py[], int ptnumb);px:该数组用来表示每个顶点的x坐标py :该数组用来表示每个顶点的y坐标ptnumb:表示顶点个数注意实现函数FillPolygon可以直接通过窗口的DC〔设备描述符〕来进行多边形填充,不需要使用帧缓冲存储。

计算机图形学实验二报告

计算机图形学实验二报告

计算机科学与通信工程学院实验报告课程计算机图形学实验题目曲线拟合学生姓名学号专业班级指导教师日期成绩评定表曲线拟合1. 实验内容1. 绘制三次Bezier曲线(1)给定四个已知点P1—P4,以此作为控制顶点绘制一段三次Bezier曲线。

(2)给定四个已知点P1—P4,以此作为曲线上的点绘制一段三次Bezier曲线。

2. 绘制三次B样条曲线给定六个已知点P1—P6,以此作为控制顶点绘制一条三次B样条曲线。

2. 实验环境软硬件运行环境:Windows XP开发工具:visual studio 20083. 问题分析1. 绘制三次Bezier曲线Bezier曲线是用N+1个顶点(控制点)所构成的N根折线来定义一根N阶曲线。

本次实验中的三次Bezier曲线有4个顶点,设它们分别为P0,P1,P2,P3,那么对于曲线上各个点Pi(x,y)满足下列关系:P(t)=[(-P0+3P1-3P2+3P3)t3+(3P0-6P1+3P2)t2+(-3P0+3P2)t+(P0+4P1+P2)]/6X(t)=[(-X0+3X1-3X2+3X3)t3+(3X0-6X1+3X2)t2+(-3X0+3X2)t+(X0+4X1+X2)]/6Y(t)=[(-Y0+3Y1-3Y2+3Y3)t3+(3Y0-6Y1+3Y2)t2+(-3Y0+3Y2)t+(Y0+4Y1+Y2)]/6其中P0、P1、P2、P3为四个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2) 、(X3、Y3)。

所以只要确定控制点的坐标,该曲线可通过编程即可绘制出来。

2. 绘制三次B样条曲线三次B样条函数绘制曲线的光滑连接条件为:对于6个顶点,取P1、P2、P3、P4 4个顶点绘制在第一段三次样条曲线,再取P2、P3、P4、P5 这4个顶点绘制在第二段三次样条曲线,总计可绘制3段光滑连接的三次样条曲线。

4. 算法设计程序框架//DiamondView.hclass CDiamondView : public CView{ ……public://参数输入和提示对话框CDlgBezier dlgBezier;//Bezier曲线绘制中的参数输入对话框CDlgB dlgB;//B样条曲线绘制中的参数输入对话框//绘图函数,需要实现void DrawBezier1(POINT p[4]);//已知点作为控制点绘制Bezier曲线void DrawBezier2(POINT p[4]);//已知点作为曲线上的点绘制Bezier曲线void DrawBCurve(POINT p[6]);//绘制B样条曲线//DiamondView.cppvoid CDiamondView::OnMenuDiamond(){IsCutting = FALSE;if(dlgDiamond.DoModal()==IDOK)DrawDiamond(dlgDiamond.m_nVertex,dlgDiamond.m_nRadius,100);//调用绘制金刚石的函数} void CDiamondView::OnMenuBezier1(){IsCutting = FALSE;if(dlgBezier.DoModal() == IDOK)DrawBezier1(dlgBezier.m_nPoint);//调用已知点作为控制点绘制Bezier曲线的函数} //以已知的四个点为控制点绘制Bezier曲线//p:已知的四个控制点void CDiamondView::DrawBezier1(POINT p[4]){ }void CDiamondView::OnMenuBezier2(){IsCutting = FALSE;if(dlgBezier.DoModal() == IDOK)DrawBezier2(dlgBezier.m_nPoint);//调用已知点作为曲线上的点绘制Bezier曲线的函数}//以已知的四个点为Bezier曲线上的点来绘制Bezier曲线//p:已知的四个点void CDiamondView::DrawBezier2(POINT p[4]){ }void CDiamondView::OnMenuB(){IsCutting = FALSE;if(dlgB.DoModal() == IDOK)DrawBCurve(dlgB.m_nPoint);//调用绘制B样条曲线的函数} //以已知的六个点为控制点来绘制B样条曲线//p:已知的六个控制点void CDiamondView::DrawBCurve(POINT p[6]){ }5. 源代码//以已知的四个点为控制点绘制Bezier曲线//p:已知的四个控制点void CDiamondView::DrawBezier1(POINT p[4]){CDC *pDC = GetDC();CPen newPen,*oldPen;newPen.CreatePen(PS_SOLID,2,RGB(255,0,0));oldPen = pDC->SelectObject(&newPen);pDC->Polyline(p, 4);pDC->SelectObject(oldPen);newPen.DeleteObject();newPen.CreatePen(PS_SOLID,2,RGB(0,0,255));oldPen = pDC->SelectObject(&newPen);int x0=p[0].x;int y0=p[0].y;int x1=p[1].x;int y1=p[1].y;int x2=p[2].x;int y2=p[2].y;int x3=p[3].x;int y3=p[3].y;double x,y;int ax,ay,bx,by,cx,cy,dx,dy;int rate=1000;ax=-x0+3*x1-3*x2+x3;ay=-y0+3*y1-3*y2+y3;bx=3*x0-6*x1+3*x2;by=3*y0-6*y1+3*y2;cx=-3*x0+3*x1;cy=-3*y0+3*y1;dx=x0;dy=y0;pDC->MoveTo(x0,y0);for(double t=0;t<=1;t+=1.0/rate){x=ax*pow(t,3)+bx*pow(t,2)+cx*t+dx;y=ay*pow(t,3)+by*pow(t,2)+cy*t+dy;pDC->LineTo(Round(x),Round(y));Sleep(10);}pDC->SelectObject(oldPen);}//以已知的四个点为Bezier曲线上的点来绘制Bezier曲线//p:已知的四个点void CDiamondView::DrawBezier2(POINT p[4]){ InvalidateRgn(NULL);UpdateWindow();CDC *pDC = GetDC();CPen newPen,*oldPen;newPen.CreatePen(PS_DASH,1,RGB(0,0,0));oldPen=pDC->SelectObject(&newPen);CBrush newBrush,*oldBrush;newBrush.CreateSolidBrush(RGB(0,0,0));oldBrush=pDC->SelectObject(&newBrush);for(int i=0;i<=3;i++){pDC->Ellipse(p[i].x-3,p[i].y-3,p[i].x+3,p[i].y+3);} pDC->SelectObject(oldPen);pDC->SelectObject(oldBrush);Sleep(50);POINT q[4];q[0].x=p[0].x;q[0].y=p[0].y;q[1].x=(-5*p[0].x+18*p[1].x-9*p[2].x+2*p[3].x)/6;q[1].y=(-5*p[0].y+18*p[1].y-9*p[2].y+2*p[3].y)/6;q[2].x=(2*p[0].x-9*p[1].x+18*p[2].x-5*p[3].x)/6;q[2].y=(2*p[0].y-9*p[1].y+18*p[2].y-5*p[3].y)/6;q[3].x=p[3].x;q[3].y=p[3].y;DrawBezier1(q);}//以已知的六个点为控制点来绘制B样条曲线//p:已知的六个控制点void CDiamondView::DrawBCurve(POINT p[6]){InvalidateRgn(NULL);UpdateWindow();CDC *pDC = GetDC();CPen newPen,*oldPen;newPen.CreatePen(PS_SOLID,2,RGB(255,0,0)); oldPen = pDC->SelectObject(&newPen);int rate=1000;int ax,ay,bx,by,cx,cy,dx,dy;double x,y;pDC->Polyline(p, 6);pDC->SelectObject(oldPen);newPen.DeleteObject();newPen.CreatePen(PS_SOLID,3,RGB(0,0,255)); oldPen = pDC->SelectObject(&newPen);for(int i=0;i<3;i++){ax=-(p[i].x-3*p[i+1].x+3*p[i+2].x-p[i+3].x)/6;bx=(p[i].x-2*p[i+1].x+p[i+2].x)/2;cx=-(p[i].x-p[i+2].x)/2;dx=(p[i].x+4*p[i+1].x+p[i+2].x)/6;ay=-(p[i].y-3*p[i+1].y+3*p[i+2].y-p[i+3].y)/6;by=(p[i].y-2*p[i+1].y+p[i+2].y)/2;cy=-(p[i].y-p[i+2].y)/2;dy=(p[i].y+4*p[i+1].y+p[i+2].y)/6;for(double t=0;t<=1;t+=1.0/rate){x=ax*pow(t,3)+bx*pow(t,2)+cx*t+dx;y=ay*pow(t,3)+by*pow(t,2)+cy*t+dy;pDC->MoveTo(Round(x),Round(y));pDC->LineTo(Round(x),Round(y));Sleep(2); }}pDC->SelectObject(oldPen);}6. 程序运行结果图1 控制顶点一段三次Bezier曲线绘制图2 控制顶点一段三次Bezier曲线绘制图3 曲线上的点一段三次Bezier曲线的绘制—图4 控制顶点一条三次B样条曲线的绘制图5 控制顶点一条三次B样条曲线的绘制7. 总结通过这次实验,我对Bezier曲线有了一定的了解,同时也懂得了Bezier曲线和B样条曲线的参数表示法。

计算机图形学实验二

计算机图形学实验二

计算机图形学实验指导书信息科学技术学院二○一三年十一月计算机图形学实验报告实验名称直线、圆弧及曲线的生成算法评分实验日期2013 年11 月 6 日指导教师姓名专业班级11地信学号2011083027一、实验目的1、几种直线生成算法的比较,特别掌握用Bresenham直线生成算法。

2、掌握用像素点法直接生成其它曲线的方法。

二、实验要求1、用不同的生成算法在屏幕上绘制出直线的图形,对不同的算法可设置不同的线形或颜色表示区别。

2、用Bresenham生成算法在屏幕上绘制出圆弧的图形,用动画的方式表演图形的生成。

三、关键算法及实现原理1、有关直线生成算法有:DDA(数值微分)直线算法、逐点比较法、直线Bresenham 生成算法。

直线Bresenham生成算法思想如下(第一象限,且斜率k<1的情况图2-1 a 中的1a):1)画点(x1,y1),dx=x2-x1,dy=y2-y1,计算误差初值P1=2dy-dx,i=1;2)求直线下一点位置x i+1=x i+1 如果P i>0,则y i+1=y i+1,否则y i+1=y i;3)画点(x i+1,y i+1);4)求下一个误差P i+1点,如果P i>0,则P i+1=P i+2dy-2dx,否则P i+1=P i+2dy;5)i=i+1,如果i<dx+1则转步骤2,否则结束操作。

Bresenham生成算法的优点如下;1)不必计算直线的斜率,因此不做除法。

2)不用浮点数,只用整数。

3)只做整数加减运算和乘2运算,而乘2运算可以用移位操作实现。

Bresenham算法的速度很快,并适于用硬件实现。

对于图2-1 a中的2a,只需将x i+1=x i+1改为x i+1=x i-1。

对于图2-1 a中的1b,斜率k>1的情况,可交换变量x和y,y每次长1个单位。

对P i进行判断,x i+1=x i或x i+1=x i+1。

2、有关圆弧生成算法有:逐点比较法、DDA(数值微分)直线算法、圆的Bresenham生成算法。

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

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

《计算机图形学》实验2实验报告《计算机图形学》实验2实验报告实验题目:多视图绘图程序实验内容:掌握多视图绘图的概念,掌握二维统计图的绘制方法。

调用实验1中自己编写的基本包,绘制自己所设计的统计图形(饼图、直方图以及折线)。

编写程序调用验证之。

基本概念:(详细叙述自己对实验内容的理解)多视图:就是将多个绘制好的图形按照一定的规则组成一个具有特定意义的图形,在同一个视图中显示出来,如下面绘制的几种统计图形(饼图、直方图以及折线)。

饼图:可以清楚的表示出各个部分所占的比例;直方图:可以清楚地的显示各部分的数量的多少;折线:可以清楚地反应各个部分的变化趋势。

算法设计:(详细叙述自己设计的多视图统计图以及程序的功能、算法及实现)public abstract void drawLine(int x1, int y1, int x2, int y2)使用当前颜色,在点(x1, y1) 和(x2, y2) 之间画线。

public abstract void drawOval(int x, int y, int width, int height) 画椭圆。

public abstract void fillOval(int x, int y, int width, int height)画实心椭圆。

public abstract void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)画x和y坐标定义的多边形。

public void drawRect(int x, int y, int width, int height)画矩形。

public void drawRect(int x, int y, int width, int height)画实心矩形。

public abstract void drawRoundRect(int x, int y, int width, intheight, int arcWidth, int arcHeight) 使用当前颜色画圆角矩形。

计算机图形学实习(实验二)

计算机图形学实习(实验二)

西北农林科技大学实习报告课程 计算机图形学 学院 理学院 专业年级 信计061 姓名袁金龙学号15206012报告日期2009-5-6实验二 圆的扫描转换算法1.实验目的:了解和掌握中点算法Bresenham 算法。

2.实验步骤:1)对直线、圆弧的几何形状及相对位置进行分析,选定比较合适的算法模型。

2)画出程序流程图; 3)编写程序的源程序; 4)编辑源程序并进行调试;5)进行特殊模式的运行测试,并结合情况进行调整。

6)打印源程序或把源程序以文件的形式提交。

3.实验原理:首先画出的是第一象限内(R R [0,x R 的1/8圆弧,此时中点Bresenham 花圆酸法要从(0,R )到(R R 顺时针地确定最佳逼近于该圆弧的像素序列。

然后根据对称法来画出另七个部分。

(1)输入圆的半径R(2)计算初始值d=1-R,x=0,y=R(3) 绘制点(x,y )及其在八分圆中的另外7个对称点(4)判断d 的符号。

若d<0,则先将d 更新为d+2x+3,再将(x,y )更新为(x+1,y );否则先将d 更新为d+2(x-y)+5,再将(x,y )更新为(x+1,y-1) (5)当x<y 时,重复步骤(3)和(4);否则结束4.流程图:5.实验内容:1)问题:请用中点Bresenhan画圆算法画出圆心在(-10,10),半径为10的圆 2)正确的图形和交点坐标:图1:圆心在(-10,10),半径为10的圆-150-100-50050100图2:圆心在(-10,10),半径为100的圆3)程序代码:function []=circle(a,b,r)%(a,b)为圆心,r为半径x=0;y=r;d=1-r;while x<=yplot(x+a,y+b,'r+');plot(-x+a,y+b,'r+');plot(-x+a,-y+b,'r+');plot(x+a,-y+b,'r+');m=[x+a,y+b;-x+a,y+b;-x+a,-y+b;x+a,-y+b]plot(y+a,x+b,'r+');plot(-y+a,x+b,'r+');plot(-y+a,-x+b,'r+');plot(y+a,-x+b,'r+');plo t(a,b,'b*')n=[y+a,x+b;-y+a,x+b;-y+a,-x+b;y+a,-x+b]hold on;grid on;if(d<0)d=d+2*x+3;elsed=d+2*(x-y)+5;y=y-1;endx=x+1;end。

图形学绘制任意斜率的直线段

图形学绘制任意斜率的直线段

《计算机图形学》实验设计报告实验二 绘制任意斜率的直线段一、 实验目的1、掌握任意斜率直线段的中点Bresenham 的扫描转换算法。

2、掌握Cline 直线类的设计方法。

3、掌握状态栏编辑方法。

二、实验要求1、设计CLine 直线类,其数据成员为直线段的起点坐标(00,y x )与直线段的斜率k ,其对应的成员函数为 MoveTo ()与LineTo ()函数。

2、在Cline 类中绘制直线段斜率为 [-1,0]区间类的直线。

3、在MoveTo ()函数中对应的参数为起始点的坐标,在LineTo ()函数中对应的参数为CDC 与直线段的斜率。

三、 设计Cline 直线类在CDC 类的成员函数中有MoveTo ()与LineTo ()函数用于绘制任意斜率的直线段,直线的颜色由所选用的画笔指定。

利用任意斜率直线段的中点Bresenham 算法,可以分析得出,当直线段的斜率01-<≤k 时,对应的初始值为 k d -5.0-=,对应的误差项为b x k y d i i -)1(-5.0-+= ,判别条件为:⎩⎨⎧≤>=+0,0,1-1d y d y y i i i ,递推公式为 ⎩⎨⎧≤>=+0,-0,-1-1d k d d k d d i i i 以此条件,即可在 Line.cpp 中用循环语句绘制直线。

四、程序运行的核心代码1、首先建立一个Cline类,并且在Line.h中写出如下代码:class CLinepublic:CLine();virtual ~CLine();void MoveTo(double x,double y);void LineTo(CDC *,double k);private:double x;double y;double k;2、在Line.cpp中书写如下代码,并要加头文件#include "Line.h"CLine::CLine()CLine::~CLine()void CLine::MoveTo(double x0,double y0)this->x=x0;this->y=y0;void CLine::LineTo(CDC *pDC,double k){double d;double x0=0.0,y0=0.0;d=-0.5-k;for(int i=0;i<100;i++){if(d>0){ y0--;d-=1+k;elsed-=k;x0++;pDC->SetPixel(x0,y0,RGB(255,0,0));3、在sourcefile中"TestView.h"下的OnDraw 函数中输入如下代码void CMFCView::OnDraw(CDC* pDC)CMFCDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CRect rc;GetClientRect(&rc);// 对坐标原点的映射pDC->SetMapMode(MM_ANISOTROPIC);pDC->SetWindowExt(rc.Width(),rc.Height());pDC->SetViewportExt(rc.right,-rc.bottom);pDC->SetViewportOrg(rc.right/2,rc.bottom/2);CLine s;s.MoveTo(1.0,1.0);s.LineTo(pDC,-0.6);五、程序运行结果及图形界面六、心得体会这次实验是通过Cline 类来绘制直线,利用直线段的起点、斜率与两成员函数MoveTo()、LineTo()对直线在斜率为-0.6时,作出了直线的图形。

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

计算机科学系实验报告课程名称计算机图形学班级12网络2实验名称VC存取BMP图像及其几何变换教导教师吴志攀姓名李文森学号1214080613213 日期2014 .11.21一、实验目的1. 掌握VC中BMP图像的存取方法;2. 掌握BMP图像平移、旋转、变比等几何变换。

二、实验设备与环境TC2.0,Windows XP三、实验内容、程序清单及运行结果1.打开VC++ 6.0,选择File|New进入界面。

在Projects中选择MFC AppWinzard(exe),在Project name中输入项目名称,本例为ReadBMP,在Location中输入项目要保存的文件夹。

点击“OK”进入下一步。

如下图2-1所示。

图2-12.选择文档类型。

在本例中使用的是单文档视图结构,所以这里选择Singledocument。

其余部分设置使用VC++ 6.0的默认设置,点击“Finish”完成项目创建。

如下图2-2所示:图2-23.为了将BMP中的数据读入到内存中,在项目中导入专门处理BMP文件头和数据的文件:DIBAPI.H和DIBAPI.CPP,在其中实现对BMP文件的大部分处理。

在工作区“FileView”选项卡的“Header Files”中点右键,在“添加文件到目录”添加“DIBAPI.H”文件。

如下图2-3所示:图2-3在工作区“FileView”选项卡的“Source Files”中点右键,在“添加文件到目录”添加“DIBAPI.CPP”文件。

并在“ReadBMPDoc.h”添加头文件"dibapi.h",如下所示:#include "dibapi.h"4.在CReadBMPDoc类中添加保护成员变量CPalette* m_palDIB,HDIB m_hDIB和CSize m_sizeDoc。

m_hDIB用于保存当前BMP图像句柄,m_palDIB用于指向BMP图像对应的调色板。

protected:HDIB m_hDIB;CPalette* m_palDIB;CSize m_sizeDoc;5.为了取得保存在当前文档中的HDIB和Palette数据,在“ReadBMPDoc.h”的CReadBMPDoc类中添加方法:GetHDIB,GetDocPalette和GDocSize。

如下所示:// Attributespublic:HDIB GetHDIB() const{ return m_hDIB; }CPalette* GetDocPalette() const{ return m_palDIB; }CSize GetDocSize() const{ return m_sizeDoc; }在CReadBMPDoc.cpp的构造函数中初始化:// 初始化变量m_hDIB = NULL;m_palDIB = NULL;m_sizeDoc = CSize(1,1);6.响应类CReadBMPDoc OnOpenDocument事件,以实现打开文件的操作。

从View|ClassWizard进入MFC ClassWizard界面,在Message Maps选项中完成消息映射。

下图2-4所示:图2-4在BOOL CReadBMPDoc::OnOpenDocument(LPCTSTR lpszPathName)函数中添加如下代码://if (!CDocument::OnOpenDocument(lpszPathName))//return FALSE;// TODO: Add your specialized creation code here//return TRUE;CFile file;CFileException fe;// 打开文件if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &fe)){// 失败ReportSaveLoadException(lpszPathName, &fe,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);// 返回FALSEreturn FALSE;}DeleteContents();// 更改光标形状BeginWaitCursor();// 尝试调用ReadDIBFile()读取图像TRY{m_hDIB = ::ReadDIBFile(file);}CA TCH (CFileException, eLoad){// 读取失败file.Abort();// 恢复光标形状EndWaitCursor();// 报告失败ReportSaveLoadException(lpszPathName, eLoad,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);// 设置DIB为空m_hDIB = NULL;// 返回FALSEreturn FALSE;}END_CATCH// 初始化DIBInitDIBData();// 恢复光标形状EndWaitCursor();// 判断读取文件是否成功if (m_hDIB == NULL){// 失败,可能非BMP格式CString strMsg;strMsg = "读取图像时出错!可能是不支持该类型的图像文件!";// 提示出错MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMA TION | MB_OK);// 返回FALSEreturn FALSE;}// 设置文件名称SetPathName(lpszPathName);// 初始化胀标记为FALSESetModifiedFlag(FALSE);// 返回TRUEreturn TRUE;并在ReadBMPDoc.cpp添加Public成员函数InitDIBData,并添加如下程序:void CReadBMPDoc::InitDIBData(){// 初始化DIB对象// 判断调色板是否为空if (m_palDIB != NULL){// 删除调色板对象delete m_palDIB;// 重置调色板为空m_palDIB = NULL;}// 如果DIB对象为空,直接返回if (m_hDIB == NULL){// 返回return;}LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);// 判断图像是否过大if (::DIBWidth(lpDIB) > INT_MAX ||::DIBHeight(lpDIB) > INT_MAX){::GlobalUnlock((HGLOBAL) m_hDIB);// 释放DIB对象::GlobalFree((HGLOBAL) m_hDIB);// 设置DIB为空m_hDIB = NULL;CString strMsg;strMsg = "BMP图像太大!";// 提示用户MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMA TION | MB_OK);// 返回return;}// 设置文档大小m_sizeDoc = CSize((int) ::DIBWidth(lpDIB), (int) ::DIBHeight(lpDIB));::GlobalUnlock((HGLOBAL) m_hDIB);// 创建新调色板m_palDIB = new CPalette;// 判断是否创建成功if (m_palDIB == NULL){// 失败,可能是内存不足::GlobalFree((HGLOBAL) m_hDIB);// 设置DIB对象为空m_hDIB = NULL;// 返回return;}// 调用CreateDIBPalette来创建调色板if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL){// 返回空,可能该DIB对象没有调色板// 删除delete m_palDIB;// 设置为空m_palDIB = NULL;// 返回return;}}// 调用CreateDIBPalette来创建调色板if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL){// 返回空,可能该DIB对象没有调色板// 删除delete m_palDIB;// 设置为空m_palDIB = NULL;// 返回return;}7.完成图片的打开操作之后,图片的数据就已经被保存在程序中,为了将图片显示出来还需要响应类CReadBMPView的OnDraw事件,在其中完成图像显示。

void CReadBMPView::OnDraw(CDC* pDC){//CReadBMPDoc* pDoc = GetDocument();//ASSERT_V ALID(pDoc);// TODO: add draw code for native data here// 显示等待光标BeginWaitCursor();// 获取文档CReadBMPDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// 获取DIBHDIB hDIB = pDoc->GetHDIB();// 判断DIB是否为空if (hDIB != NULL){LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);// 获取DIB宽度int cxDIB = (int) ::DIBWidth(lpDIB);// 获取DIB高度int cyDIB = (int) ::DIBHeight(lpDIB);::GlobalUnlock((HGLOBAL) hDIB);CRect rcDIB;rcDIB.top = rcDIB.left = 0;rcDIB.right = cxDIB;rcDIB.bottom = cyDIB;CRect rcDest;// 判断是否是打印if (pDC->IsPrinting()){// 是打印,计算输出图像的位置和大小,以便符合页面// 获取打印页面的水平宽度(象素)int cxPage = pDC->GetDeviceCaps(HORZRES);// 获取打印页面的垂直高度(象素)int cyPage = pDC->GetDeviceCaps(VERTRES);// 获取打印机每英寸象素数int cxInch = pDC->GetDeviceCaps(LOGPIXELSX);int cyInch = pDC->GetDeviceCaps(LOGPIXELSY);// 计算打印图像大小(缩放,根据页面宽度调整图像大小)rcDest.top = rcDest.left = 0;rcDest.bottom = (int)(((double)cyDIB * cxPage * cyInch)/ ((double)cxDIB * cxInch));rcDest.right = cxPage;// 计算打印图像位置(垂直居中)int temp = cyPage - (rcDest.bottom - rcDest.top);rcDest.bottom += temp/2;rcDest.top += temp/2;}else// 非打印{// 不必缩放图像rcDest = rcDIB;}// 输出DIB::PaintDIB(pDC->m_hDC, &rcDest, pDoc->GetHDIB(),&rcDIB, pDoc->GetDocPalette());}// 恢复正常光标EndWaitCursor();}8.编译、调试并运行程序,自此一个用于打开BMP图像的单文档视图结构的程序就完成了。

相关文档
最新文档