1 / 28

计算机图形学

计算机图形学. 制作人 : 李彦. 目录介绍. 1、课程简介. 2 、 实验内 容. 返回主 目录?. 课程概述.

shima
Download Presentation

计算机图形学

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 计算机图形学 制作人:李彦

  2. 目录介绍 1、课程简介 2、实验内容

  3. 返回主 目录? 课程概述 本书介绍了计算机图形学的基础知识及应用实例,主要内容包括:计算机图形软、硬件系统基本知识,基本图形生成与多边形填充,字符生成,二维裁剪,二维变换,三维变换,典型曲线曲面,消隐,真实感图形表现,图形学基本应用等。针对主要知识点,每章提供若干图形界面的应用实例的实现过程与执行结果,帮助读者分析计算机图形学原理,并通过大量生动的图片与实例,将枯燥的理论转变为可视化的实践操作,书中所有程序均在Visual C¨6.0环境中验证通过。同时,还特别提供了两个阶段性的应用程序:二维图形综合设计实例与真实感综合设计实例。本书是学习计算机图形学的入门书籍,既能使读者全面了解计算机图形学的基础理论,又能通过大量应用实例提高其编程能力。本书适合作为普通高校计算机、信息处理、艺术设计等专业的计算机图形学课程及其实验教材或教师参考用书,也可作为工程技术人员或图形学爱好者的自学用书,还可作为相关课程设计的参考教材。 • 课程简介

  4. 返回主 目录? 实验内容 实验一:基本图形生成算法 实验二:多边形的填充 实验三:二维图形剪裁和变换 实验四:平面图形综合设计

  5. 实验一 实验一:基本图形生成算法 实验内容:1、熟悉VC ++6.0和常用的绘图函数 2、直线、圆和椭圆的生成 实验类型:设计型 实验类别:学科基础 每组人数: 1人 实验目的: 1、熟悉VC++ 6.0环境,并掌握常用的绘图函数 2、熟悉并掌握直线、圆和椭圆等基本图形的生成算法和实现方法

  6. 实验步骤 已知待扫描转换的直线为(x0,y0),,又,则设k=1/m=(即k∈(0,1])。直线方程为,即。 以一个像素为单位分割区间[y0,y1],由x0<x1,故y0<y1,得到[y0,y1]上的一个划分:,,…. ,其中=+1,得到点列,由公式 故从直接得到。可能为浮点数,要对它取整,实际得到像素集。初值为:()=(x0,y0)。

  7. 实验步骤 void CMy1View::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; } } 编写自定义的成员函数ddaline()程序:

  8. void CMy1View::OnDraw(CDC* pDC) { CMy1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here ddaline(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)); } 实验步骤 编写OnDraw()函数

  9. 实验结果

  10. 实验二 实验二:多边形的填充 实验内容:1、多边形的扫描转换 2、多边形的区域填充 实验类型:设计型 实验类别:学科基础 每组人数: 1人 实验目的: 1、熟悉区域的表示和类型,掌握并实现多边形的扫描转换方法。 2、熟悉并掌握多边形的区域填充方法。

  11. 实验内容 1.图元填充 利用多种图元填充的方法绘制一面五星红旗。 方法有: 扫描转换多边形的逐点判断法(编码算法),扫描线算法, 区域填充的扫描线算法。 2.扫描转换多边形 2.1把多边形的顶点表示转换为点阵表示,也就是从多边形的给定边界出发,求出位于其内部的各个象素,并给帧缓冲器内的各个对应元素设置相应的灰度和颜色,通常称这种转换为多边形的扫描转换。 几种方法:逐点判断法;扫描线算法;边缘填充法; 2.2逐点判断法 逐个判断绘图窗口内的像素。如何判断点在多边形的内外关系?有1)射线法:2)累计角度法3)编码法;这里用的是编码算法。://exam2.timber.com

  12. int Edge_code(point node,point start,point end) {int w,v,s=0; point p; float x0,y0; if(start.x>node.x&&start.y>node.y) v=0; if(start.x<=node.x&&start.y>node.y) v=1; if(start.x<=node.x&&start.y<=node.y) v=2; if(start.x>node.x&&start.y<=node.y) v=3; if(end.x>node.x&&end.y>node.y) w=0; if(end.x<=node.x&&end.y>node.y) w=1; if(end.x<=node.x&&end.y<=node.y) w=2; if(end.x>node.x&&end.y<=node.y) w=3; s=w-v; if(s==2||s==-2) { x0=(end.x+start.x)/2; y0=(end.y+start.y)/2; p.x=x0;p.y=y0; s=Edge_code(node,start,p)+Edge_code(node,p,end); } if(s==3) s=-1; if(s==-3) s=1; return s; } point Getmax(point points[10]) { int i; float maxx,maxy; point p; maxx=points[0].x;maxy=points[0].y; for(i=1;i<10;i++) {if(points[i].x>maxx) maxx=points[i].x; if(points[i].y>maxy) maxy=points[i].y;} p.x=maxx;p.y=maxy; return p; } 实验步骤

  13. point Getmin(point points[10]) {int i; float minx,miny; point p; minx=points[0].x;miny=points[0].y; for(i=1;i<10;i++) {if(points[i].x<minx) minx=points[i].x; if(points[i].y<miny) miny=points[i].y;} p.x=minx;p.y=miny; return p; } for(i=0;i<10;i++) {if(i%2==0) {points[i].x=x[i/2];points[i].y=y[i/2]; } else {points[i].x=a[i/2];points[i].y=b[i/2]; } } p1=Getmax(points);p2=Getmin(points); for(n=p2.y;n<p1.y;n++) for(m=p2.x;m<p1.x;m++) if(getpixel(m,n)!=YELLOW) {node.x=m;node.y=n; j=Edge_code(node,points[0],points[1]); for(i=1;i<9;i++) j+=Edge_code(node,points[i],points[i+1]); j+=Edge_code(node,points[9],points[0]); if(j==4||j==-4) putpixel(m,n,YELLOW);} 实验步骤

  14. 实验结果

  15. 实验三 实验三:二维图形剪裁与变换 实验内容:1、点、线段和多边形的剪裁 2、二维基本几何变换的实现 3、二维复合变换的实现 实验类型:设计型 实验类别:学科基础 每组人数: 1人 实验目的: 1、掌握二维图形的各种裁剪算法,包括点、线段及多边形的裁剪 2、熟悉并掌握二维图形的基本几何变换算法,及其实现方法 。

  16. 实验内容 • 裁剪算法的实现思路 • 这个裁剪算法适用于任何凸多边形,它是从Sutherland-Hodgman算法推广来的。Sutherland-Hodgman算法着重于用竖直线裁剪,在这里首先把它推广到任意直线。 • 两点确定一条直线,在这里我们规定这两点有先后顺序,这就使直线具有了方向。在这个基础上,设直线方程为F(x,y)=0,当直线方向从左至右时,保存使F>=0的顶点,从右至左时,保存使F<=0的顶点。这样就把它推广到了任意直线。 • 对于任意凸多边形,我们把它看成是由逆时针方向的直线组成的。依次用它们来裁剪,最终得到的多边形就是所求图形。 • 注:同学们也可以直接用Sutherland-Hodgma算法实现,也可以用编码算法,或者NICHOLL-LEE-NICHOLL等算法实现对二维图形的裁剪。 能综合利用前面所学的知识进行二维图形综合设计与实现

  17. 实验步骤 • 在主程序的程序头部定义符号常量 • #define LEFT 1 • #define RIGHT 2 • #define BOTTOM 4 • #define TOP 8 • 定义成员变量和成员函数 • int WT; • int WB; • int WR; • int WL; • int C_S_Line(CDC* pDC,int x1,int y1,int x2,int y2); • void encode(int x,int y,int *code); • 在构造函数中为窗口边界变量赋初值: • WL=100;WR=400;WB=100;WT=300;

  18. 实验步骤 • int CMy1_1View::C_S_Line(CDC *pDC, int x1, int y1, int x2, int y2) • { • int code1,code2,code,x,y; • encode(x1,y1,&code1); //(x1,y1)处的编码 • encode(x2,y2,&code2); //(x2,y2)处的编码 • while (code1!=0||code2!=0) //当 code1 不等于 0 或 code2 不等于 0 • { • if ((code1&code2)!=0) return 0; //当 code1 与 code2 不等于 0,在同侧; • code=code1; • if (code1==0) code=code2; • if ((LEFT&code)!=0) //求交点 • { • x=WL; • y=y1+(y2-y1)*(WL-x1)/(x2-x1); • }else if ((RIGHT&code)!=0) • { x=WR; • y=y1+(y2-y1)*(WR-x1)/(x2-x1); • } • else if ((BOTTOM&code)!=0) • { y=WB; • x=x1+(x2-x1)*(WB-y1)/(y2-y1); • } • else if ((TOP&code)!=0) • { y=WT; • x=x1+(x2-x1)*(WT-y1)/(y2-y1); • } • if (code==code1) • { • x1=x;y1=y; • encode(x,y,&code1); • } • else • { • x2=x;y2=y; • encode(x,y,&code2); • } • }

  19. 实验步骤 • int CMy1_1View::C_S_Line(CDC *pDC, int x1, int y1, int x2, int y2) • { • int code1,code2,code,x,y; • encode(x1,y1,&code1); //(x1,y1)处的编码 • encode(x2,y2,&code2); //(x2,y2)处的编码 • while (code1!=0||code2!=0) //当 code1 不等于 0 或 code2 不等于 0 • { • if ((code1&code2)!=0) return 0; //当 code1 与 code2 不等于 0,在同侧; • code=code1; • if (code1==0) code=code2; • if ((LEFT&code)!=0) //求交点 • { • x=WL; • y=y1+(y2-y1)*(WL-x1)/(x2-x1); • }else if ((RIGHT&code)!=0) • { x=WR; • y=y1+(y2-y1)*(WR-x1)/(x2-x1); • } • else if ((BOTTOM&code)!=0) • { y=WB; • x=x1+(x2-x1)*(WB-y1)/(y2-y1); • } • else if ((TOP&code)!=0) • { y=WT; • x=x1+(x2-x1)*(WT-y1)/(y2-y1); • } • if (code==code1) • { • x1=x;y1=y; • encode(x,y,&code1); • } • else • { • x2=x;y2=y; • encode(x,y,&code2); • } • }

  20. 实验步骤 • //end while,表示 code1,code2 都为 0,其中的线段为可视部分 • pDC->MoveTo(x1+350,y1); • pDC->LineTo(x2+350,y2); • } • void CMy1_1View::encode(int x, int y, int *code) • { • int c=0; • if (x<WL) c=c|LEFT; • else if (x>WR) c=c|RIGHT; • if (y<WB) c=c|BOTTOM; • else if (y>WT) c=c|TOP; • *code=c; • } • 编写OnDraw()程序: • void CMy1_1View::OnDraw(CDC* pDC) • { • CMy1_1Doc* pDoc = GetDocument(); • ASSERT_VALID(pDoc); • // TODO: add draw code for native data here • //定义三条直线的坐标 • int x11,y11,x21,y21,x12,y12,x22,y22,x13,y13,x23,y23; • x11=50;y11=150;x21=450;y21=250; • x12=150;y12=150;x22=350;y22=240; • x13=50;y13=400;x23=500;y23=350; • //定义画笔 • CPen PenRed(PS_SOLID,1,RGB(255,0,0));//定义红色笔 • CPen PenBlue(PS_SOLID,1,RGB(0,0,255));//定义蓝色笔 • CPen Penwhite(PS_SOLID,1,RGB(255,255,255));//定义白色笔 • //先画出窗口,用蓝色

  21. 实验步骤 • pDC->SelectObject(&PenBlue); • pDC->Rectangle(WL,WB,WR,WT); • //先画出三条直线,用红线 • pDC->SelectObject(&PenRed); • pDC->MoveTo(x11,y11);pDC->LineTo(x21,y21); • pDC->MoveTo(x12,y12);pDC->LineTo(x22,y22); • pDC->MoveTo(x13,y13);pDC->LineTo(x23,y23); • //画出剪裁后的窗口,用蓝色 • pDC->SelectObject(&PenBlue); • pDC->Rectangle(WL+350,WB,WR+350,WT); • //用蓝线,画出裁剪三条线 • pDC->SelectObject(&PenBlue); • C_S_Line(pDC,x11,y11,x21,y21); • C_S_Line(pDC,x12,y12,x22,y22); • C_S_Line(pDC,x13,y13,x23,y23); • }

  22. 实验结果

  23. 实验四 实验三:平面图形综合设计 实验内容:1、实现交互,完成鼠标绘图 2、平面曲线图案综合设计 实验类型:设计型 实验类别:学科基础 每组人数: 1人 实验目的: 1、了解并熟悉计算机图形的交互技术,并能实现简单的交互,如鼠标绘图 2、能综合利用前面所学的知识进行二维图形综合设计与实现

  24. 实验内容 • Bezier曲线是一种广泛应用于外形设计的参数曲线,它通过对一些特定点的控制来控制曲线的形状,我们称这些点为控制顶点。现在我们来给出Bezier曲线的数学表达式。 • 在空间给定个点,称下列参数曲线为次Bezier曲线: • 其中是Bernstein基函数,其表达式为: • ,接着我们讨论3次Bezier曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:

  25. 实验步骤 • #include<math.h> • double CMy4_1View::b03(double t) • { • return(pow(1-t,3)); • } • double CMy4_1View::b13(double t) • { • return(3*t*pow(1-t,2)); • } • double CMy4_1View::b23(double t) • { • return(3*(1-t)*t*t); • } • double CMy4_1View::b33(double t) • { • return(t*t*t); • }

  26. 实验步骤 • 编写OnDraw函数: • void CMy4_1View::OnDraw(CDC* pDC) • { • CMy4_1Doc* pDoc = GetDocument(); • ASSERT_VALID(pDoc); • // TODO: add draw code for native data here • int i; • int x0,y0,x1,y1,x2,y2,x3,y3,curx,cury; • double t,dt; • // 创建两个不同颜色的画笔 • CPen PenRed(PS_SOLID,1,RGB(255,0,0)); • CPen PenBlue(PS_SOLID,1,RGB(0,0,255)); • // 设置控制点,绘出特征多边形 • x0=220;y0=10;x1=410;y1=10;x2=225;y2=150;x3=410;y3=100; • pDC->SelectObject(PenBlue); //使用蓝色画笔 • pDC->MoveTo(x0,y0); • pDC->LineTo(x1,y1); • pDC->LineTo(x2,y2); • pDC->LineTo(x3,y3); • //绘制 Bezier 曲线 • pDC->MoveTo(x0,y0); • t=0; dt=0.01; //t 从 0 到 1,每步增加 0.01,取 100 个点 • pDC->SelectObject(PenRed); //使用红色画笔 • for (i=0;i<=100;i++) • { curx=(int)(b03(t)*x0+b13(t)*x1+b23(t)*x2+b33(t)*x3); • cury=(int)(b03(t)*y0+b13(t)*y1+b23(t)*y2+b33(t)*y3); • pDC->LineTo(curx,cury); • t=t+dt; • } • }

  27. 实验结果

  28. Thank You

More Related