计算机图形学实验报告.docx

上传人:jian****018 文档编号:9213015 上传时间:2020-04-03 格式:DOCX 页数:23 大小:229.19KB
返回 下载 相关 举报
计算机图形学实验报告.docx_第1页
第1页 / 共23页
计算机图形学实验报告.docx_第2页
第2页 / 共23页
计算机图形学实验报告.docx_第3页
第3页 / 共23页
点击查看更多>>
资源描述
实验报告实验课程: 计算机图形学 学生姓名: XXXX 学 号: XXXX 专业班级: 软件 2014年12月25日目 录i. 实验一 矩阵变换ii. 实验二 图形绘制iii. 实验三 曲线的生成算法实现iv. 实验四 二维基本图形生成的算法v. 实验五 二维填充图的生成算法实验一 矩阵变换实验题目:求绕平面中任一点P(x,y)旋转角的变换矩阵,并编程检验。实验目的:掌握图形变换的几何化表示的基本原理和方法;采用几何化方法实现二维图形的组合变换;算法思想:1、根据题意构建新的坐标系; 构成新坐标系的两条直线方程分别为: L2:过点P,且与x轴的夹角为的逆向直线; L1:过点P,且与x轴的夹角为/2+的正向直线。2、写出新旧坐标系的坐标变换矩阵Txy_xy 该矩阵就完成了新坐标系下绕原点(原坐标系下P点)的旋转3、输出原坐标系下的线性变换矩阵: R=Txy_xyTtr程序代码:void CZhouView:pingyi()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x+100,m_nPoint1.y+100);dc.LineTo(m_nPoint2.x+100,m_nPoint2.y+100);void CZhouView:xuanzhuan()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x*cos(0.5)-(m_nPoint1.y*sin(0.5),(m_nPoint1.x*sin(0.5)+(m_nPoint1.y*cos(0.5);dc.LineTo(m_nPoint2.x*cos(0.5)-(m_nPoint2.y*sin(0.5),(m_nPoint2.x*sin(0.5)+(m_nPoint2.y*cos(0.5);void CZhouView:bili()CClientDC dc(this); dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x*2,m_nPoint1.y*2);dc.LineTo(m_nPoint2.x*2,m_nPoint2.y*2);void CZhouView:XCQ()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x+100,m_nPoint2.y);void CZhouView:DC()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.y,m_nPoint1.x);dc.LineTo(m_nPoint2.y,m_nPoint2.x);void CZhouView:YCQ()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y+100);/OnLButtonUp(UINT nFlags, CPoint point) case 8:pingyi();break;case 9:xuanzhuan();break;case 10:bili();break;case 11:XCQ();break;case 12:YCQ();break;case 13:DC();break;dc.MoveTo(m_nPoint1.y,m_nPoint1.x);dc.LineTo(m_nPoint2.y,m_nPoint2.x);void CZhouView:YCQ()CClientDC dc(this);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y);dc.MoveTo(m_nPoint1.x,m_nPoint1.y);dc.LineTo(m_nPoint2.x,m_nPoint2.y+100);/OnLButtonUp(UINT nFlags, CPoint point) case 8:pingyi();break;case 9:xuanzhuan();break;case 10:bili();break;case 11:XCQ();break;case 12:YCQ();break;case 13:DC();break;代码实现:实验结论:二维图形齐次坐标变换矩阵一般表达式:这33 矩阵中各元素功能一共可分成四块,即:实验二 图形绘制实验名称:1. 图形系统初始化;2. 综合应用Turbo C 中图形库函数,进行图形设计与绘制;3. 绘制金刚石图案,学有余力的同学可以尝试完成一笔绘制出金刚石图案。实验目的:1. 掌握图形驱动程序及图形模式的基本概念,掌握图形初始化的方法;2. 掌握Turbo C 进行图形程序设计的基本方法;3. 了解Turbo C 的图形功能,了解常见的图形库函数;4. 能设计较复杂的静态图形。实验设计:算法分析:本实验的核心是在圆的基础上绘制金刚石图案。金刚石图案是一个二维图案,仅使用二维坐标(x,y)就可以绘制,本实验使用CP2数组实现。金刚石图案是有依次连接位于圆上的不同等分点的直线段构成。等分点个数越多,金刚石图案越复杂。当圆的等分点个数n=5时,线段连接情况如图1-1所示,线段连接点见表1-2。算法设计的难点是避免直线段的重复连接。为此,设计一个二重循环,代表起点索引号的外层整型变量i从i=0循环到i=n-2,代表终点所以你好的内层整型变量j从j=j+1循环到j=n-1。以(pi.x,pi.y)为起点,以(pj.x,pj.y)为终点依次连接各线段形成金刚石图案。起点终点(x0,y0)(x1, y1),( x2, y2),( x3, y3),( x4, y4)(x1, y1)( x2, y2),( x3, y3),( x4, y4)( x2, y2)( x3, y3),( x4, y4)( x3, y3)( x4, y4)表1-2 线段连接方式 x2, y2 x1, y1 x3, y3 x0,y0 x4, y4 图1-1 n=5时的线段连接实验步骤:/ testView.cpp : implementation of the CTestView class#include stdafx.h#include test.h#include testDoc.h#include testView.h#include #define PI 3.1415926#define ROUND(a) int(a+0.5)#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif/ CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)ON_COMMAND(ID_FILE_PRINT, CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView:OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView:OnFilePrintPreview)END_MESSAGE_MAP()/ CTestView construction/destructionCTestView:CTestView()CTestView:CTestView()BOOL CTestView:PreCreateWindow(CREATESTRUCT& cs)return CView:PreCreateWindow(cs);/ CTestView drawingvoid CTestView:OnDraw(CDC* pDC)CTestDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);CRect rect;GetClientRect(&rect);pDC-SetMapMode(MM_ANISOTROPIC);pDC-SetWindowExt(rect.Width(),rect.Height();pDC-SetViewportExt(rect.Width(),-rect.Height();pDC-SetViewportOrg(rect.Width()/2,rect.Height()/2);CPen NewPen,*pOldPen;NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255);pOldPen=pDC-SelectObject(&NewPen);double thta;int n=20,r=150; CPoint p20;thta=2*PI/n;for(int i=0;in;i+)pi.x=(long)(r*cos(i*thta);pi.y=(long)(r*sin(i*thta);for(i=0;i=n-2;i+)for(int j=i+1;jMoveTo(ROUND(pi.x),ROUND(pi.y);pDC-LineTo(ROUND(pj.x),ROUND(pj.y);pDC-SelectObject(pOldPen);NewPen.DeleteObject();ReleaseDC(pDC);/ CTestView printingBOOL CTestView:OnPreparePrinting(CPrintInfo* pInfo)/ default preparationreturn DoPreparePrinting(pInfo);void CTestView:OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)void CTestView:OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)/ CTestView diagnostics#ifdef _DEBUGvoid CTestView:AssertValid() constCView:AssertValid();void CTestView:Dump(CDumpContext& dc) constCView:Dump(dc);CTestDoc* CTestView:GetDocument() / non-debug version is inlineASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CTestDoc);return (CTestDoc*)m_pDocument;#endif /_DEBUG/ CTestView message handlers结果截图该图为n=20,r=150时绘制出的金刚石图案。实验结论:二维图形齐次坐标变换矩阵一般表达式:这33 矩阵中各元素功能一共可分成四块,即:实验三 曲线的生成算法实现实验名称:二次Bezier曲线的绘制实验目的:1.掌握B样条曲线、Bezier曲线的定义;2.能编程实现N 次B样条曲线、Bezier曲线的绘制与显示。3.编程实现Bezier曲线生成算法实验设计:算法设计:绘制三次Bezier曲线,可以采用公式法或德卡斯特里奥(De Casteliau)算法绘制当n3时,Bezier曲线的控制多边形有四个控制点P0、P1、P2和P3,Bezier曲线是三次多项式。 其中:B0,3(t),B1,3(t),B2,3(t),B3,3(t) 称为基函数。实验内容:程序代码:1)/TestView.hclass CTestView : public CView.protected:bool Flag;/标志CPoint *pt;/顶点int CtrlPoint;/控制多边形顶点.2) /TestView.cpp#include math.h/数学头文件#define N_MAX_POINT 10/控制多边形的最大顶点数#define ROUND(a) int(a+0.5) /四舍五入。CTestView:CTestView()Flag=false;void CTestView:OnMENUBezierCurve() / TODO: Add your command handler code hereRedrawWindow();AfxGetMainWnd()-SetWindowText(三次Bezier曲线);/显示标题MessageBox(单击左键绘制控制多边形,单击右键绘制曲线,提示,MB_OK);pt=new CPointN_MAX_POINT;Flag=true;CtrlPoint=0;void CTestView:DrawBezier()/绘制Bezier曲线CClientDC dc(this);double x,y;int rate=800,n;n=CtrlPoint-1;for(double t=0;t=1;t+=1.0/rate)x=0;y=0;for(int i=0;i=n;i+)x+=pti.x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);y+=pti.y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255);/曲线颜色double CTestView:Cnk(const int &n, const int &i)/Bernstein第一项return double(Factorial(n)/(Factorial(i)*Factorial(n-i);int CTestView:Factorial(int m)/阶乘函数int f=1;for(int i=1;i=m;i+)f*=i;return f;void CTestView:DrawCharPolygon()/绘制控制多边形CClientDC dc(this);CPen MyPen,*pOldPen;MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0);/控制多边形pOldPen=dc.SelectObject(&MyPen);for(int i=0;iCtrlPoint;i+)if(i=0)dc.MoveTo(pti);dc.Ellipse(pti.x-2,pti.y-2,pti.x+2,pti.y+2);elsedc.LineTo(pti);dc.Ellipse(pti.x-2,pti.y-2,pti.x+2,pti.y+2);dc.SelectObject(pOldPen);MyPen.DeleteObject();void CTestView:OnLButtonDown(UINT nFlags, CPoint point)/获得屏幕控制点坐标 / TODO: Add your message handler code here and/or call defaultCView:OnLButtonDown(nFlags, point);if(Flag)ptCtrlPoint.x=point.x;ptCtrlPoint.y=point.y;if(CtrlPointN_MAX_POINT)CtrlPoint+;elseFlag=false;DrawCharPolygon();void CTestView:OnRButtonDown(UINT nFlags, CPoint point)/调用绘制函数 / TODO: Add your message handler code here and/or call defaultFlag=false;DrawBezier();CView:OnRButtonDown(nFlags, point);代码实现:(屏幕截图)实验结论:贝塞尔曲线的参数向量表达式:通常,n+1个顶点定义一个n次多项式。其中: 称为“伯恩斯坦(Bernstain)基函数”。实验四 二维基本图形生成的算法实现实验名称:DDA画线算法的实现实验目的:1学习C语言的基本绘图方法;2掌握二维图形显示原理。3掌握直线的两种生成算法; 实验设计:理论基础:DDA算法:实现的关键是如何步进和步进的方向:步进的正或负,决定能否正确的到达终点。步进的大小:它控制了变化最大的步进,令其为单位步进,而另一个方向的步进必小于1 ,这样不论斜率|m|1否,都会使直线的亮度均匀。 依公式: 则下一点坐标为: 算法设计与分析:DDA算法:(1)已知过端点P0 (x0, y0), P1(x1, y1)的直线段L :y=kx+b(2)直线斜率为 :k=(y1-y0)/(x1-x0)(3)Xi+1=Xi+*X Yi+1=Yi+*Y 其中, =1/max(|X|,|Y|) max(|X|,|Y|)= |X| (|k|1)(4)|k|1时:Xi+1=Xi+(或-)1/k Yi+1=Yi+(或-)1这种方法直观,但效率太低,因为每一步需要一次浮点乘法和一次舍入运算。 实验步骤:程序代码:int x0=sp0,x1=ep0,y0=sp1,y1=ep1;double x, dx,dy,k,y;if(x0=x1)if(y0=y1)for(y=y0;ySetPixel(x,y,color) ; y+;elsefor(y=y0;ySetPixel(x,y,color) ; y-;dx=x1-x0;dy=y1-y0;k=dy/dx;if(fabs(k)=1)if(x0x1)y=y0;for(x=x0;xSetPixel(x,y,color) ; y=y+k;if(x0x1)y=y0;for(x=x0;x=x1;x-) pDC-SetPixel(x,y,color) ;y=y-k;elseif(y0y1)x=x0;for(y=y0;ySetPixel(x,y,color) ;x=x+1/k;elsex=x0;for(y=y0;y=y1;y-) pDC-SetPixel(x,y,color) ;x=x-1/k;运行结果:实验结论:画线算法的实现有:数值微分法(Digital Differential Analyzer,DDA)生成直线和Bresenham算法生成直线两种实现方法。本次图形学实验,可以很好的了解和掌握DDA画线算法的原理以及实现方法。实验五 二维填充图的生成算法实验名称:扫描线填充算法的实现实验目的:掌握区域填充的扫描线算法思想。 实验设计:设计思想:扫描线种子填充算法:先将种子像素入栈,种子像素为栈底像素,如果栈不为空,执行如下4步操作。(1)栈顶像素出栈。(2)沿扫描线对出栈像素的左右像素进行填充,直至遇到边界像素为止。即每出栈一个像素,就对区域内包含该像素的整个连续区间进行填充。(3)同时记录该区间,将区间最左端像素记为xleft,最右端像素记为xright。(4)在区间xleft,xright中检查与当前扫描线相邻的上下两条扫描线的有关像素是否全为边界像素或已填充像素,若存在非边界且未填充的像素,则把未填充区间的最右端像素取作种子像素入栈。实验步骤:源代码:void CTestView:OnLButtonDown(UINT nFlags, CPoint point)/左键按下函数 / TODO: Add your message handler code here and/or call defaultSeed=point;/选择种子位置CharFill();/进行填充CView:OnLButtonDown(nFlags, point);void CTestView:CharFill()/文字填充函数CRect Rect;GetClientRect(&Rect);CClientDC dc(this);COLORREF BoundColor;/边界色int Width=Rect.right-Rect.left;int Hight=Rect.bottom-Rect.top ;int Flag;int x0,y0,x,y;CPoint Point;std:vector FillBuffle;/定义CPoint类型的数组序列对象FillBuffle.reserve(10);/定义数组序列的大小FillBuffle.push_back(CPoint(Seed); /把种子结点压入数组序列BoundColor=RGB(0,0,0);/定义边界色为黑色while(!FillBuffle.empty()/如果数组序列非空 Point=FillBuffle.front();/弹出数组序列头元素x=Point.x;y=Point.y;FillBuffle.erase(FillBuffle.begin();/清除数组序列内的元素dc.SetPixel(Point,Fillcolor);/绘制像素/判断像素的位置是否在图形内部x0=x+1;/右方判断while(dc.GetPixel(x0,y)!=BoundColor&dc.GetPixel(x0,y)!=Fillcolor)x0=x0+1;if(x0=Width)/到达屏幕最右端MessageBox(种子超出范围,警告); RedrawWindow();return;y0=y+1;/下方判断 while(dc.GetPixel(x,y0)!=BoundColor&dc.GetPixel(x,y0)!=Fillcolor)y0=y0+1;if(y0=Hight)/到达屏幕最下端MessageBox(种子超出范围,警告);RedrawWindow();return;RightPoint.x=x0;/右边界内的左邻点x0=x-1;while(dc.GetPixel(x0,y)!=Fillcolor&dc.GetPixel(x0,y)!=BoundColor)dc.SetPixel(x0,y,Fillcolor);x0=x0-1;if(x0=0)/到达屏幕最左端MessageBox(种子超出范围,警告);RedrawWindow();return;y0=y-1; while(dc.GetPixel(x,y0)!=BoundColor&dc.GetPixel(x,y0)!=Fillcolor)y0=y0-1;if(y0=0)/到达屏幕最上端MessageBox(种子超出范围,警告);RedrawWindow();return;LeftPoint.x=x0+1;/左边界内的右邻点x0=LeftPoint.x;y=y+1;/下一条扫描线while(x0RightPoint.x)Flag=0;while(dc.GetPixel(x0,y)!=Fillcolor)&(dc.GetPixel(x0,y)!=BoundColor)if(Flag=0)Flag=1;x0+ ;if(Flag=1)if(x0=RightPoint.x)&(dc.GetPixel(x0,y)!=Fillcolor)&(dc.GetPixel(x0,y)!=BoundColor)FillBuffle.push_back(CPoint(x0,y);/进入数组序列elseFillBuffle.push_back(CPoint(x0-1,y);Flag=0;PointNext.x=x0;while(dc.GetPixel(x0,y)=Fillcolor)&(x0RightPoint.x)|(dc.GetPixel(x0,y)=BoundColor)&(x0RightPoint.x)x0 +; x0=LeftPoint.x;y=y-2;while(x0RightPoint.x)Flag=0;while(dc.GetPixel(x0,y)!=Fillcolor)&(dc.GetPixel(x0,y)!=BoundColor)&(x0RightPoint.x)if(Flag=0)Flag=1;x0+ ;if(Flag=1)if(x0=RightPoint.x)&(dc.GetPixel(x0,y)!=Fillcolor)&(dc.GetPixel(x0,y)!=BoundColor)FillBuffle.push_back(CPoint(x0,y);elseFillBuffle.push_back(CPoint(x0-1,y);Flag=0;PointNext.x=x0;while(dc.GetPixel(x0,y)=Fillcolor&x0RightPoint.x)|(dc.GetPixel(x0,y)=BoundColor&x0RightPoint.x)x0+;FillBuffle.clear();return;void CTestView:OnMENUFill() / TODO: Add your command handler code hereRedrawWindow();MessageBox(请在空心字体内部单击鼠标左键!,提示);代码实现: (实验前) ( 试验后) 实验结论:用水平扫描线从上到下扫描由点线段构成的多段构成的多边形。每根扫描线与多边形各边产生一系列交点,将这些交点按横坐标从小到大排序,将交点两两配对,并填充每一区段。多边形被扫描完毕后,填充也就完成。其步骤为: 为每一条扫描线建立新边表NET; 将扫描线纵坐标y的初值置为NET中非空元素的最小序号; 置活性边表AET为空; 执行下列步骤直至NET和AET都为空;如果NET中的第y类非空,则将其中的所有边取出并插入AET中,在插入过程中进行排序;对AET中的边两两配对,将每对边中x坐标按规则取整,获得有效的填充区段,再填充;将当前扫描线纵坐标y值递增1,即y=1;将AET中满足y=ymax边删去;对AET中剩下的每一条边的x递增deltax,即x=x+deltax。
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 工作总结


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!