当前位置:文档之家› 计算机图形学实验四 区域填充的实现

计算机图形学实验四 区域填充的实现

计算机图形学实验四 区域填充的实现
计算机图形学实验四 区域填充的实现

实验四区域填充的实现

组号1班级 08信计2学号71姓名李永分数

一、实验目的与要求

理解区域的表示和类型,能正确区分四连通和八连通的区域,了解区域填充的实现原理,利用TurboC实现区域填充的归算法。

二、实验内容

(1)利用画线函数,在屏幕上定义一个封闭区域。

(2)利用种子填充算法,填充第(1)题中定义的区域。

三、实验结果分析

种子填充算法假设在多边形内有一像素已知,由此出发利用连通性找到区域内的所有像素。设:(x,y)为内点表示的四连通区域内的一点,oldcolor为区域的原色,现取(x,y)为种子点,要将整个区域填充为新的颜色newcolor,递归填充过程如下:先判别像素(x,y)的颜色,若它的值不等于oldcolor,说明该像素位于区域之外,或者已经被置为newcolor,不需填充,算法结束;否则置该像素的颜色为newcolor,再对与其相邻的上下左右4个像素分别做递归填充。四连通与八连通的区别:四连通只包含四个方向,八连通包含八个方向,八连通更细致,对算法的要求也更高。

四连通实现代码:

#include

#include

#include

void floodfill4(int x,int y,int oldcolor,int newcolor)

{

if(getpixel(x,y)==oldcolor)

{

putpixel(x,y,newcolor);

Sleep(1);

floodfill4(x,y+1,oldcolor,newcolor);

floodfill4(x,y-1,oldcolor,newcolor);

floodfill4(x-1,y,oldcolor,newcolor);

floodfill4(x+1,y,oldcolor,newcolor);

}

}

main()

{

int a,b,c,d,i,j;

int graphdriver=DETECT;

int graphmode=0;

initgraph(&graphdriver,&graphmode,"");

cleardevice();

setcolor(RED);

rectangle(50,50,70,100);

for(i=51;i<70;i++)

for(j=51;j<100;j++)

{

putpixel(i,j,4);

}

a=57;

b=70;

c=4;

d=RGB(0,255,0);

floodfill4(a,b,c,d);

getch();

closegraph();

}

八连通区域填充程序代码:

#define pi 3.141592

#define MAX(a,b) (a>b)? a:b

#define MIN(a,b) (a

#include "graphics.h"

#include "math.h"

struct edge {

int ymax;

float x;

float delat;

struct edge * pedge; }; struct point{

int x;

int y;} ;

struct et { struct edge * pedge;

int n;};

struct edge g_aet[10];

struct edge dge[10];

struct et g_et[10];

struct point point1,point2;

int ZUO(float x)

{ if((int)x==x)

return (int)x;

return (int)x+1;

}

int YOU(float x)

{ if((int)x==x)

return (int)x-1;

return (int)x;

}

int k=400,l=0;

void draw1()

{

int i,t,j,a,c,p,z; float b;

struct edge temp;

for(i=k;i<=l;i++)

{

a=0;

for(t=0;t<=9;t++)

{ if(g_et[t].n==i) break;}

for(j=0;j<=9;j++)

{ if(g_aet[j].ymax==0) break;}

if(t!=10){ g_aet[j].ymax=g_et[t].pedge->ymax;

g_aet[j].x=g_et[t].pedge->x;

g_aet[j].delat=g_et[t].pedge->delat;

if(g_et[t].pedge->pedge!=0)

{

g_aet[j+1].ymax=g_et[t].pedge->pedge->ymax;

g_aet[j+1].x=g_et[t].pedge->pedge->x;

g_aet[j+1].delat=g_et[t].pedge->pedge->delat; }

}

for(j=0;j<=9;j++)

{ if(g_aet[j].ymax==0) break; }

j--;

for(t=0;t<=j;t++)

{ for(z=0;z<=j-1;z++)

{

if(g_aet[z].x>g_aet[z+1].x)

{ temp.ymax=g_aet[z].ymax;

temp.x=g_aet[z].x;

temp.delat=g_aet[z].delat;

g_aet[z].ymax=g_aet[z+1].ymax;

g_aet[z].x=g_aet[z+1].x;

g_aet[z].delat=g_aet[z+1].delat;

g_aet[z+1].ymax=temp.ymax;

g_aet[z+1].x=temp.x;

g_aet[z+1].delat=temp.delat;

}

}

}

for(j=0;j<=9;j++)

{ if(g_aet[j].ymax==0) break; }

j--;

for(p=0;p<=j;p++)

{ a++;

if(a%2!=0)b=g_aet[p].x;

else

{

for(c=ZUO(b);c<=YOU(g_aet[p].x);c++)

putpixel(c,i,2);}

}

for(t=0;t<=j;t++)

{ if(g_aet[t].ymax==(i+1))

{ g_aet[t].ymax=0;

g_aet[t].x=0;

g_aet[t].delat=0;

}

g_aet[t].x+=g_aet[t].delat;

}

for(t=0;t<=j;t++)

{ for(z=0;z<=j-1;z++)

{

if(g_aet[z].x

{ temp.ymax=g_aet[z].ymax;

temp.x=g_aet[z].x;

temp.delat=g_aet[z].delat;

g_aet[z].ymax=g_aet[z+1].ymax;

g_aet[z].x=g_aet[z+1].x;

g_aet[z].delat=g_aet[z+1].delat;

g_aet[z+1].ymax=temp.ymax;

g_aet[z+1].x=temp.x;

g_aet[z+1].delat=temp.delat;

}

}

}

}

}

void generate()

{

int i,y,n=1,m,q,p;float x;

for(i=0;i<=9;i++)

{

if(n==1)

{ point2.x=point1.x=300;

point2.y=point1.y=200;

n++;

}

else

{ if(n%2==0)

{ x=40*cos(i*pi/5)+200;

y=40*sin(i*pi/5)+200;

}

else

{ x=100*cos(i*pi/5)+200;

y=100*sin(i*pi/5)+200;

}

if(point1.y==y) { n++; continue;}

m=MIN(point1.y,y);

if(x==point1.x)

{ dge[i-1].delat=0;

dge[i-1].ymax=MAX(point1.y,y);

dge[i-1].x=x;

dge[i-1].pedge=0;

for(q=0;q<=9;q++)

{ if(g_et[q].n==m) break;}

if(q==10)

{

g_et[i-1].pedge=&dge[i-1];

g_et[i-1].n=m;

}

else

{

g_et[q].pedge->pedge=&dge[i-1];

g_et[i-1].n=0;

}

}

else

{

dge[i-1].delat=(float)(x-point1.x)/(y-point1.y);

dge[i-1].ymax=MAX(point1.y,y);

if(point1.y>y) dge[i-1].x=x;

else {dge[i-1].x=point1.x; }

dge[i-1].pedge=0;

for(q=0;q<=9;q++)

{ if(g_et[q].n==m) break;}

if(q==10)

{ g_et[i-1].pedge=&dge[i-1];

g_et[i-1].n=m;

}

else

{

g_et[q].pedge->pedge=&dge[i-1];

g_et[i-1].n=0;

}

}

p=MAX(point1.y,y);

k=MIN(k,m);l=MAX(l,p);

point1.x=x;

point1.y=y;

n++;}

}

if(point1.y==point2.y) return;

else

{if(point2.x==point1.x){

dge[i-1].delat=0;

dge[i-1].ymax=MAX(point1.y,point2.y);

dge[i-1].x=point2.x;}

else

{ dge[i-1].ymax=MAX(point1.y,point2.y);

if(point1.y>point2.y) dge[i-1].x=point2.x;

else {dge[i-1].x=point1.x;}

dge[i-1].delat=(float)(point2.x-point1.x)/(point2.y-point1.y);

}

}

m=MIN(point1.y,point2.y);

k=MIN(k,m);l=MAX(l,dge[i-1].ymax);

g_et[i-1].n=m;

g_et[i-1].pedge=&dge[i-1];

}

void main()

{ int driver=DETECT,mode; int i;

registerbgidriver(EGA VGA_driver);

initgraph(&driver,&mode,"\\tc");

initgraph(&driver,&mode,"\\tc");

for(i=0;i<=9;i++)

{ g_aet[i].ymax=0; g_aet[i].x=0; g_aet[i].delat=0;

g_et[i].pedge=0;

}

generate();

draw1();

circle(200,200,100); circle(200,200,40);

getch();

closegraph();

}

四、实验结果分析:

通过这个实验,多边形域可以多种形状的,一种常用的填充方法是按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作。区间的端点可以通过计算扫描线与多边形边界线的交点获得。所谓区域填充,指的是在输出平面的闭合区域内完整地填充某种颜色或图案。以上所述及的区域填充算法或相关程序,主要针对显示平面内的区域而言。

八连通区域填充法实现了区域的填充,都是应用递归的算法来实现的,更加细密,

填充效果更加真切,在对要求较高的填充有好处,多边形填充有一定难度,种子填充在

掌握了“栈”这一抽象数据类型的实现方法的前提下,比较容易完成。而边标志填充算

法却是介于这两类之间,部分地具有它们的痕迹,算法思想巧妙,实现起来更容易。区域填

充算法的递归算法原理很简单,关键是选择扫描线算法来减少递归次数,提高效率。

计算机图形学 区域填充算法的实现

实验四区域填充算法的实现 班级 08信计2班学号 20080502088 姓名许延恒分数 一、实验目的和要求: 1、理解区域的表示和类型。 2、能正确区分四连通和八连通的区域 3、了解区域填充的实验原理。 4、利用C++实现区域填充的递归算法。 二、实验内容: 1假设在多边形内有一像素已知,由此出发利用连通性找到区域内所有像素。 2 取(x,y)为种子点将整个区域填充为新的颜色。 3 进行递归填充。 三、实验结果分析 区域填充属性包括填充样式,填充颜色和填充图案的类型。C语言中定义了某种图形后,即可调用-floodfill函数,对指定区域进行填充 . 程序代码 #include #include #include void floodfill4(int x,int y,int oldcolor,int newcolor) { if(getpixel(x,y)==oldcolor) { putpixel(x,y,newcolor); Sleep(1); floodfill4(x,y+1,oldcolor,newcolor); floodfill4(x,y-1,oldcolor,newcolor); floodfill4(x-1,y,oldcolor,newcolor); floodfill4(x+1,y,oldcolor,newcolor); } } main() { int a,b,c,d,i,j; int graphdriver=DETECT; int graphmode=0; initgraph(&graphdriver,&graphmode,"");

计算机图形学实验一

实验一二维基本图元的生成与填充 实验目的 1.了解并掌握二维基本图元的生成算法与填充算法。 2.实现直线生成的DDA算法、中点算法和Bresenham算法。 3.实现圆和椭圆生成的DDA和中点算法, 对几种算法的优缺点有感性认识。 二.实验内容和要求 1.选择自己熟悉的任何编程语言, 建议使用VC++。 2.创建良好的用户界面,包括菜单,参数输入区域和图形显示区域。 3.实现生成直线的DDA算法、中点算法和Bresenham算法。 4.实现圆弧生成的中点算法。 5.实现多边形生成的常用算法, 如扫描线算法,边缘填充算法。 6.实现一般连通区域的基于扫描线的种子填充算法。 7.将生成算法以菜单或按钮形式集成到用户界面上。 8.直线与圆的坐标参数可以用鼠标或键盘输入。 6. 可以实现任何情形的直线和圆的生成。 实验报告 1.用户界面的设计思想和框图。 2.各种实现算法的算法思想。 3.算法验证例子。 4.上交源程序。 直线生成程序设计的步骤如下: 为编程实现上述算法,本程序利用最基本的绘制元素(如点、直线等),绘制图形。如图1-1所示,为程序运行主界面,通过选择菜单及下拉菜单的各功能项分别完成各种对应算法的图形绘制。 图1-1 基本图形生成的程序运行界面 2.创建工程名称为“基本图形的生成”单文档应用程序框架 (1)启动VC,选择“文件”|“新建”菜单命令,并在弹出的新建对话框中单击“工程”标签。 (2)选择MFC AppWizard(exe),在“工程名称”编辑框中输入“基本图形的生成”作为工程名称,单击“确定”按钮,出现Step 1对话框。 (3)选择“单个文档”选项,单击“下一个”按钮,出现Step 2对话框。 (4)接受默认选项,单击“下一个”按钮,在出现的Step 3~Step 5对话框中,接受默认选项,单击“下一个”按钮。

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

中南大学信息科学与工程学院 实验报告实验名称 实验地点科技楼四楼 实验日期2014年6月 指导教师 学生班级 学生姓名 学生学号 提交日期2014年6月

实验一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))

《计算机图形学》有序边表填充算法

实验报告 一、实验目的 1、掌握有序边表算法填充多边形区域; 2、理解多边形填充算法的意义; 3、增强C语言编程能力。 二、算法原理介绍 根据多边形内部点的连续性知:一条扫描线与多边形的交点中,入点和出点之间所有点都是多边形的内部点。所以,对所有的扫描线填充入点到出点之间所有的点就可填充多边形。 判断扫描线上的点是否在多边形之内,对于一条扫描线,多边形的扫描转换过程可以分为四个步骤: (1)求交:计算扫描线与多边形各边的交点; (2)排序:把所有交点按x值递增顺序排序; (3)配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边形的一个相交区间; (4)着色:把相交区间内的象素置成多边形颜色,把相交区间外的象素置成背景色。 p1,p3,p4,p5属于局部极值点,要把他们两次存入交点表中。如扫描线y=7上的交点中,有交点(2,7,13),按常规方法填充不正确,而要把顶点(7,7)两次存入交点表中(2,7,7,13)。p2,p6为非极值点,则不用如上处理。

为了提高效率,在处理一条扫描线时,仅对与它相交的多边形的边进行求交运算。把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。 对每一条扫描线都建立一个与它相交的多边形的活性边表(AET)。每个AET的一个节点代表一条活性边,它包含三项内容 1.x -当前扫描线与这条边交点的x坐标; 2.Δx -该边与当前扫描线交点到下一条扫描线交点的x增量; 3.ymax -该边最高顶点相交的扫描线号。 每条扫描线的活性边表中的活性边节点按照各活性边与扫描线交点的x值递增排序连接在一起。 当扫描线y移动到下一条扫描线y = y+1时,活性边表需要更新,即删去不与新扫描线相交的多边形边,同时增加与新扫描线相交的多边形边,并根据增量法重新计算扫描线与各边的交点x。 当多边形新边表ET构成后,按下列步骤进行: ①对每一条扫描线i,初始化ET表的表头指针ET[i]; ②将ymax = i的边放入ET[i]中; ③使y =多边形最低的扫描线号; ④初始化活性边表AET为空; ⑤循环,直到AET和ET为空。 ●将新边表ET中对应y值的新边节点插入到AET表。 ●遍历AET表,将两两配对的交点之间填充给定颜色值。 ●遍历AET表,将 ymax= y的边节点从AET表中删除,并将ymax> y的各边节点 的x值递增Δx;并重新排序。 ●y增加1。 三、程序源代码 #include "graphics.h" #define WINDOW_HEIGHT 480 #define NULL 0 #include "alloc.h" #include "stdio.h" #include "dos.h" #include "conio.h" typedef struct tEdge /*typedef是将结构定义成数据类型*/ { int ymax; /* 边所交的最高扫描线号 */

计算机图形学实验内容汇总

计算机图形学实验 肖加清

实验一图形学实验基础 一、实验目的 (1)掌握VC++绘图的一般步骤; (2)掌握OpenGL软件包的安装方法; (3)掌握OpenGL绘图的一般步骤; (4)掌握OpenGL的主要功能与基本语法。 二、实验内容 1、VC++绘图实验 (1)实验内容:以下是绘制金刚石图案。已给出VC++参考程序,但里面有部分错误,请改正,实现以下图案。 N=3 N=4

N=5 N=10 N=30

N=50 (2)参考程序 //自定义的一个类 //此代码可以放在视图类的实现文件(.cpp) 里class CP2 { public: CP2(); virtual ~CP2(); CP2(double,double); double x; double y; }; CP2::CP2() { this->x=0.0; this->y=0.0; } CP2::~CP2() { } CP2::CP2(double x0,double y0) { this->x=x0; this->y=y0; }

//视图类的一个成员函数,这个成员函数可以放在OnDraw函数里调用。 //在视图类的头文件(.h)里定义此函数 void Diamond(); //在视图类的实现文件(.cpp)里实现此函数 void CTestView::Diamond() { CP2 *P; int N; double R; R=300; N=10; P=new CP2[N]; CClientDC dc(this); CRect Rect; GetClientRect(&Rect); double theta; theta=2*PI/N; for(int i=0;i #include #include #include //定义输出窗口的大小 #define WINDOW_HEIGHT 300

计算机图形学实验报告,DOC

欢迎共阅

目录

实验一直线的DDA算法 一、【实验目的】 1.掌握DDA算法的基本原理。 2.掌握 3. 1.利用 2.加强对 四 { glClearColor(1.0f,1.0f,1.0f,1.0f); glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0,200.0,0.0,150.0); } voidDDALine(intx0,inty0,intx1,inty1) { glColor3f(1.0,0.0,0.0); intdx,dy,epsl,k; floatx,y,xIncre,yIncre; dx=x1-x0;dy=y1-y0;

x=x0;y=y0; if(abs(dx)>abs(dy))epsl=abs(dx); elseepsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { glPointSize(3); glBegin(GL_POINTS); glEnd(); } } { } { } { glutInitWindowSize(400,300); glutInitWindowPosition(100,120); glutCreateWindow("line"); Initial(); glutDisplayFunc(Display); glutReshapeFunc(winReshapeFcn); glutMainLoop(); return0; }

计算机图形学必考知识点

Phong Lighting 该模型计算效率高、与物理事实足够接近。Phong模型利用4个向量计算表面任一点的颜色值,考虑了光线和材质之间的三种相互作用:环境光反射、漫反射和镜面反射。Phong模型使用公式:I s=K s L s cosαΦα:高光系数。计算方面的优势:把r和v归一化为单位向量,利用点积计算镜面反射分量:I s=K s L s max((r,v)α,0),还可增加距离衰减因子。 在Gouraud着色这种明暗绘制方法中,对公用一个顶点的多边形的法向量取平均值,把归一化的平均值定义为该顶点的法向量,Gouraud着色对顶点的明暗值进行插值。Phong着色是在多边形内对法向量进行插值。Phong着色要求把光照模型应用到每个片元上,也被称为片元的着色。 颜色模型RGB XYZ HSV RGB:RGB颜色模式已经成为现代图形系统的标准,使用RGB加色模型的RGB三原色系统中,红绿蓝图像在概念上有各自的缓存,每个像素都分别有三个分量。任意色光F都可表示为F=r [ R ] + g [ G ] + b [ B ]。RGB颜色立方体中沿着一个坐标轴方向的距离代表了颜色中相应原色的分量,原点(黑)到体对角线顶点(白)为不同亮度的灰色 XYZ:在RGB 系统基础上,改用三个假想的原色X、Y、Z建立了一个新的色度系统, 将它匹配等能光谱的三刺激值,该系统称为视场XYZ色度系统,在XYZ空间中不能直观地评价颜色。 HSV是一种将RGB中的点在圆柱坐标系中的表示法,H色相S饱和度V明度,中心轴为灰色底黑顶白,绕轴角度为H,到该轴距离为S,沿轴高度为S。 RGB优点:笛卡尔坐标系,线性,基于硬件(易转换),基于三刺激值,缺点:难以指定命名颜色,不能覆盖所有颜色范围,不一致。 HSV优点:易于转换成RGB,直观指定颜色,’缺点:非线性,不能覆盖所有颜色范围,不一致 XYZ:覆盖所有颜色范围,基于人眼的三刺激值,线性,包含所有空间,缺点:不一致 交互式计算机程序员模型 (应用模型<->应用程序<->图形库)->(图形系统<->显示屏).应用程序和图形系统之间的接口可以通过图形库的一组函数来指定,这和接口的规范称为应用程序编程人员接口(API),软件驱动程序负责解释API的输出并把这些数据转换为能被特定硬件识别的形式。API提供的功能应该同程序员用来确定图像的概念模型相匹配。建立复杂的交互式模型,首先要从基本对象开始。良好的交互式程序需包含下述特性:平滑的显示效果。使用交互设备控制屏幕上图像的显示。能使用各种方法输入信息和显示信息。界面友好易于使用和学习。对用户的操作具有反馈功能。对用户的误操作具有容忍性。Opengl并不直接支持交互,窗口和输入函数并没有包含在API中。 简单光线跟踪、迭代光线跟踪 光线跟踪是一种真实感地显示物体的方法,该方法由Appel在1968年提出。光线跟踪方法沿着到达视点的光线的相反方向跟踪,经过屏幕上每一象素,找出与视线所交的物体表面点P0,并继续跟踪,找出影响P0点光强的所有的光源,从而算出P0点上精确的光照强度。光线跟踪器最适合于绘制具有高反射属性表面的场景。优缺点:原理简单,便于实现,能生成各种逼真的视觉效果,但计算量开销大,终止条件:光线与光源相交光线超出视线范围,达到最大递归层次。一般有三种:1)相交表面为理想漫射面,跟踪结束。2)相交表面为理想镜面,光线沿镜面反射方向继续跟踪。3)相交表面为规则透射面,光线沿规则透射方向继续跟踪。 描述光线跟踪简单方法是递归,即通过一个递归函数跟踪一条光线,其反射光想和折射光线再调用此函数本身,递归函数用来跟踪一条光线,该光线由一个点和一个方向确定,函数返回与光线相交的第一个对象表面的明暗值。递归函数会调用函数计算指定的光线与最近对象表面的交点位置。 图形学算法加速技术BVH, GRID, BSP, OCTree 加速技术:判定光线与场景中景物表面的相对位置关系,避免光线与实际不相交的景物表面的求交运算。加速器技术分为以下两种:Bounding Volume Hierarchy 简写BVH,即包围盒层次技术,是一种基于“物体”的场景管理技术,广泛应用于碰撞检测、射线相交测试之类的场合。BVH的数据结构其实就是一棵二叉树(Binary Tree)。它有两种节点(Node)类型:Interior Node 和Leaf Node。前者也是非叶子节点,即如果一个Node不是Leaf Node,它必定是Interior Node。Leaf Node 是最终存放物体/们的地方,而Interior Node存放着代表该划分(Partition)的包围盒信息,下面还有两个子树有待遍历。使用BVH需要考虑两个阶段的工作:构建(Build)和遍历(Traversal)。另一种是景物空间分割技术,包括BSP tree,KD tree Octree Grid BSP:二叉空间区分树 OCTree:划分二维平面空间无限四等分 Z-buffer算法 算法描述:1、帧缓冲器中的颜色设置为背景颜色2、z缓冲器中的z值设置成最小值(离视点最远)3、以任意顺序扫描各多边形a) 对于多边形中的每一个采样点,计算其深度值z(x,y) b) 比较z(x, y)与z缓冲器中已有的值zbuffer(x,y)如果z(x, y) >zbuffer(x, y),那么计算该像素(x, y)的光亮值属性并写入帧缓冲器更新z缓冲器zbuffer(x, y)=z(x, y) Z-buffer算法是使用广泛的隐藏面消除算法思想为保留每条投影线从COP到已绘制最近点距离,在投影后绘制多边形时更新这个信息。存储必要的深度信息放在Z缓存中,深度大于Z缓存中已有的深度值,对应投影线上已绘制的多边形距离观察者更近,故忽略该当前多边形颜色,深度小于Z缓存中的已有深度值,用这个多边形的颜色替换缓存中的颜色,并更新Z缓存的深度值。 void zBuffer() {int x, y; for (y = 0; y < YMAX; y++) for (x = 0; x < XMAX; x++) { WritePixel (x, y, BACKGROUND_VALUE); WriteZ (x, y, 1);} for each polygon { for each pixel in polygon’s projection { //plane equation doubl pz = Z-value at pixel (x, y); if (pz < ReadZ (x, y)) { // New point is closer to front of view WritePixel (x, y, color at pixel (x, y)) WriteZ (x, y, pz);}}}} 优点:算法复杂度只会随着场景的复杂度线性增加、无须排序、适合于并行实现 缺点:z缓冲器需要占用大量存储单元、深度采样与量化带来走样现象、难以处理透明物体 着色器编程方法vert. frag 着色器初始化:1、将着色器读入内存2、创建一个程序对象3、创建着色器对象4、把着色器对象绑定到程序对象5、编译着色器6、将所有的程序连接起来7、选择当前的程序对象8、把应用程序和着色器之间的uniform变量及attribute变量关联起来。 Vertex Shader:实现了一种通用的可编程方法操作顶点,输入主要有:1、属性、2、使用的常量数据3、被Uniforms使用的特殊类型4、顶点着色器编程源码。输入叫做varying变量。被使用在传统的基于顶点的操作,例如位移矩阵、计算光照方程、产生贴图坐标等。Fragment shader:计算每个像素的颜色和其他属性,实现了一种作用于片段的通用可编程方法,对光栅化阶段产生的每个片段进行操作。输入:Varying 变量、Uniforms-用于片元着色器的常量,Samples-用于呈现纹理、编程代码。输出:内建变量。 观察变换 建模变换是把对象从对象标架变换到世界标架 观察变换把世界坐标变换成照相机坐标。VC是与物理设备无关的,用于设置观察窗口观察和描述用户感兴趣的区域内部分对象,观察坐标系采用左手直角坐标系,可在用户坐标系中的任何位置、任何方向定义。其中有一坐标轴与观察方向重合同向并与观察平面垂直。观察变换是指将对象描述从世界坐标系变换到观察坐标系的过程。(1):平移观察坐标系的坐标原点,与世界坐标系的原点重合,(2):将x e,y e轴分别旋转(-θ)角与x w、y w轴重合。 规范化设备坐标系 规范化设备坐标系是与具体的物理设备无关的一种坐标系,用于定义视区,描述来自世界坐标系窗口内对象的图形。 光线与隐式表面求交 将一个对象表面定义为f(x,y,z)=f(p)=0,来自P0,方向为d的光线用参数的形式表示为P(t)=P0+td. 交点位置处参数t的值满足:f(P0+td)=0,若f是一个代数曲面,则f是形式为X i Y j Z k的多项式之和,求交就转化为寻求多项式所有根的问题,满足的情况一:二次曲面,情况二:品面求交,将光线方程带入平面方程:p*n+c=0可得到一个只需做一次除法的标量方程p=p0+td。可通过计算得到交点的参数t的值:t=(p0*n+c)/(n*d). 几何变换T R S矩阵表示 三维平移T 三维缩放S旋转绕z轴Rz( ) 100dx 010dy 001dz 0001 Sx000 0Sy00 00Sz0 0001 cos-sin00 sin cos00 0010 0001 θθ θθ 旋转绕x轴Rx(θ) 旋转绕y轴Ry(θ) 1000 0cos-sin0 0sin cos0 0001 θθ θθ cos0sin0 0100 -sin0cos0 0001 θθ θθ 曲线曲面 Bezier曲线性质:Bezier曲线的起点和终点分别是特征多边形的第一个顶点和最后一个顶点。曲线在起点和终点处的切线分别是特征多边形的第一条边和最后一条边,且切矢的模长分别为相应边长的n倍;(2)凸包性;(3)几何不变性(4)变差缩减性。端点插值。 均匀B样条曲线的性质包括:凸包性、局部性、B样条混合函数的权性、连续性、B样条多项式的次数不取决于控制函数。 G连续C连续 C0连续满足:C1连续满足: (1)(0) p(1)=(1)(0)(0) (1)(0) px qx py q qy pz qz == ???? ???? ???? ???? (1)(0) p'(1)=(1)'(0)(0) (1)(0) p x q x p y q q y p z q z == ???? ???? ???? ???? C0(G0)连续:曲线的三个分量在连接点必须对应相等 C1连续:参数方程和一阶导数都对应相等 G1连续:两曲线的切线向量成比例 三维空间中,曲线上某点的导数即是该点的切线,只要求两个曲线段连接点的导数成比例,不需要导 数相等,即p’(1)=aq’(0) 称为G1几何连续性。将该思想推广到高阶导数,就可得到C n和G n连续性。

计算机图形学实验指导书1

佛山科学技术学院计算机图形学实验指导书 李晓东编 电信学院计算机系 2011年11月

实验1 直线段的扫描转换 实验类型:设计性 实验类别:专业实验 实验目的 1.通过实验,进一步理解直线段扫描转换的DDA算法、中点bresenham算法及 bresenham算法的基本原理; 2.掌握以上算法生成直线段的基本过程; 3.通过编程,会在C/C++环境下完成用DDA算法、中点bresenham算法及 bresenham算法对任意直线段的扫描转换。 实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用DDA算法中点bresenham算法及bresenham算法实现任意给定两点的直线段的绘制(直线宽度和线型可自定)。 实验步骤: 1、复习有关算法的基本原理,明确实验目的和要求; 2、依据算法思想,绘制程序流程图; 3、设计程序界面,要求操作方便; 4、用C/C++语言编写源程序并调试、执行; 5、分析实验结果 6、对程序设计过程中出现的问题进行分析与总结; 7、打印源程序或把源程序以文件的形式提交; 8、按格式要求完成实验报告。 实验报告要求: 1、各种算法的基本原理; 2、各算法的流程图 3、实验结果及分析(比较三种算法的特点,界面插图并注明实验条件) 4、实验总结(含问题分析及解决方法)

实验2 圆的扫描转换 实验类型:设计性 实验类别:专业实验 实验目的 1、通过实验,进一步理解和掌握中点bresenham画圆算法的基本原理; 2、掌握以上算法生成圆和圆弧的基本过程; 3、掌握在C/C++环境下完成用中点bresenham算法圆或圆弧的绘制方法。实验设备及实验环境 计算机(每人一台) VC++6.0或其他C/C++语言程序设计环境 实验学时:2学时 实验内容 用中点(Besenham)算法实现圆或圆弧的绘制。 实验步骤 1.复习有关圆的生成算法,明确实验目的和要求; 2.依据算法思想,绘制程序流程图(注意圆弧生成时的输入条件); 3.设计程序界面,要求操作方便; 4.用C/C++语言编写源程序并调试、执行; 5.分析实验结果 6.对程序设计过程中出现的问题进行分析与总结; 7.打印源程序或把源程序以文件的形式提交; 8.按格式要求完成实验报告。 实验报告要求: 1.分析算法的工作原理; 2.画出算法的流程图 3.实验结果及分析(比较圆与圆弧生成算法的不同) 4.实验总结(含问题分析及解决方法)

计算机图形学实验三报告

计算机科学与通信工程学院 实验报告 课程计算机图形学 实验题目二维图形变换 学生姓名 学号 专业班级 指导教师 日期

成绩评定表

二维图形变换 1. 实验内容 完成对北极星图案的缩放、平移、旋转、对称等二维变换。 提示:首先要建好图示的北极星图案的数据模型(顶点表、边表)。另外,可重复调用“清屏”和“暂停”等函数,使整个变换过程具有动态效果。 2. 实验环境 软硬件运行环境:Windows XP 开发工具:visual studio 2008 3. 问题分析

4. 算法设计 程序框架: //DiamondView.h class CDiamondView : public CView { …… public: //参数输入和提示对话框 void Polaris();//北极星 …… }; //DiamondView.cpp void CDiamondView::OnMenuDiamond() { IsCutting = FALSE; if(dlgDiamond.DoModal()==IDOK) DrawDiamond(dlgDiamond.m_nVertex,dlgDiamond.

m_nRadius,100);//调用绘制金刚石的函数 } //北极星 void CDiamondView::Polaris() {......} 5. 源代码 //北极星 void hzbjx(CDC* pDC,long x[18],long y[18]) { CPen newPen1,*oldPen; newPen1.CreatePen(PS_SOLID,2,RGB(255,0,0)); oldPen = pDC->SelectObject(&newPen1); POINT vertex1[11]={{x[1],y[1]},{x[2],y[2]},{x[3],y[3]},{x[4],y[4]},{x[5],y[5]},{x[3],y[3]},{x[1],y[1]}, {x[6],y[6]},{x[3],y[3]},{x[7],y[7]},{x[5],y[5]}}; pDC->Polyline(vertex1, 11); newPen1.DeleteObject(); newPen1.CreatePen(PS_SOLID, 2, RGB(0,255,0)); oldPen = pDC->SelectObject(&newPen1); POINT vertex2[5]={{x[6],y[6]},{x[8],y[8]},{x[9],y[9]},{x[3],y[3]},{x[8],y[8]}}; pDC->Polyline(vertex2, 5); POINT vertex3[5]={{x[4],y[4]},{x[10],y[10]},{x[11],y[11]},{x[3],y[3]},{x[10],y[10]}}; pDC->Polyline(vertex3, 5);

计算机图形学实验二

实验报告 课程名称:计算机图形学 实验项目:区域填充算法 实验仪器:计算机 系别:计算机学院 专业:计算机科学与技术 班级姓名:计科1602/ 学号:2016011 日期:2018-12-8 成绩: 指导教师:

一.实验目的(Objects) 1.实现多边形的扫描线填充算法。 二.实验内容 (Contents) 实现多边形的扫描线填充算法,通过鼠标,交互的画出一个多边形,然后利用种子填充算法,填充指定的区域。不能使用任何自带的填充区域函数,只能使用画点、画线函数或是直接对图像的某个像素进行赋值操作;

三.实验内容 (Your steps or codes, Results) //widget.cpp //2016CYY Cprogramming #include"widget.h" #include #include #include using namespace std; #define H 1080 #define W 1920 int click = 0; //端点数量 QPoint temp; QPoint first; int result = 1; //判断有没有结束 int sign = 1; //2为画线 int length = 5; struct edge { int ymax; float x; float dx; edge *next; }; edge edge_; QVector edges[H]; QVector points;//填充用 bool fin = false; QPoint *Queue = (QPoint *)malloc(length * sizeof(QPoint)); //存放端点的数组 Widget::Widget(QWidget *parent) : QWidget(parent) { } Widget::~Widget() { } void Widget::mouseMoveEvent(QMouseEvent *event) { setMouseTracking(true); if (click > 0 && result != 0) { startPt = temp; endPt =event->pos(); sign = 2; update(); } } void Widget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { } else if (event->button() == Qt::RightButton) { sign = 2;

计算机图形学实验

实验1 直线的绘制 实验目的 1、通过实验,进一步理解和掌握DDA和Bresenham算法; 2、掌握以上算法生成直线段的基本过程; 3、通过编程,会在TC环境下完成用DDA或中点算法实现直线段的绘制。实验环境 计算机、Turbo C或其他C语言程序设计环境 实验学时 2学时,必做实验。 实验内容 用DDA算法或Besenham算法实现斜率k在0和1之间的直线段的绘制。 实验步骤 1、算法、原理清晰,有详细的设计步骤; 2、依据算法、步骤或程序流程图,用C语言编写源程序; 3、编辑源程序并进行调试; 4、进行运行测试,并结合情况进行调整; 5、对运行结果进行保存与分析; 6、把源程序以文件的形式提交; 7、按格式书写实验报告。 实验代码:DDA: # include # include

void DDALine(int x0,int y0,int x1,int y1,int color) { int dx,dy,epsl,k; float x,y,xIncre,yIncre; dx=x1-x0; dy=y1-y0; x=x0; y=y0; if(abs(dx)>abs(dy)) epsl=abs(dx); else epsl=abs(dy); xIncre=(float)dx/(float)epsl; yIncre=(float)dy/(float)epsl; for(k=0;k<=epsl;k++) { putpixel((int)(x+0.5),(int)(y+0.5),4); x+=xIncre; y+=yIncre; } } main(){ int gdriver ,gmode ;

计算机图形学上机实验指导

计算机图形学上机实验指导 指导教师:张加万老师 助教:张怡 2009-10-10

目录 1.计算机图形学实验(一) – OPENGL基础 ..................................... - 1 - 1.1综述 (1) 1.2在VC中新建项目 (1) 1.3一个O PEN GL的例子及说明 (1) 2.计算机图形学实验(二) – OPENGL变换 ..................................... - 5 - 2.1变换 (5) 3.计算机图形学实验(三) - 画线、画圆算法的实现....................... - 9 - 3.1MFC简介 (9) 3.2VC6的界面 (10) 3.3示例的说明 (11) 4.计算机图形学实验(四)- 高级OPENGL实验...................... - 14 - 4.1光照效果 (14) 4.2雾化处理 (16) 5.计算机图形学实验(五)- 高级OPENGL实验........................ - 20 - 5.1纹理映射 (20) 5.2反走样 (24) 6.计算机图形学实验(六) – OPENGL IN MS-WINDOWS .......... - 27 - 6.1 实验目标: (27) 6.2分形 (28)

1.计算机图形学实验(一) – OpenGL基础 1.1综述 这次试验的目的主要是使大家初步熟悉OpenGL这一图形系统的用法,编程平台是Visual C++,它对OpenGL提供了完备的支持。 OpenGL提供了一系列的辅助函数,用于简化Windows操作系统的窗口操作,使我们能把注意力集中到图形编程上,这次试验的程序就采用这些辅助函数。 本次实验不涉及面向对象编程,不涉及MFC。 1.2在VC中新建项目 1.2.1新建一个项目 选择菜单File中的New选项,弹出一个分页的对话框,选中页Projects中的Win32 Console Application项,然后填入你自己的Project name,如Test,回车即可。VC为你创建一个工作区(WorkSpace),你的项目Test就放在这个工作区里。 1.2.2为项目添加文件 为了使用OpenGL,我们需要在项目中加入三个相关的Lib文件:glu32.lib、glaux.lib、opengl32.lib,这三个文件位于c:\program files\microsoft visual studio\vc98\lib目录中。 选中菜单Project->Add To Project->Files项(或用鼠标右键),把这三个文件加入项目,在FileView中会有显示。这三个文件请务必加入,否则编译时会出错。或者将这三个文件名添加到Project->Setting->Link->Object/library Modules 即可。 点击工具条中New Text File按钮,新建一个文本文件,存盘为Test.c作为你的源程序文件,再把它加入到项目中,然后就可以开始编程了。 1.3一个OpenGL的例子及说明 1.3.1源程序 请将下面的程序写入源文件Test.c,这个程序很简单,只是在屏幕上画两根线。 #include

计算机图形学实验报告

《计算机图形学》实验报告姓名:郭子玉 学号:2012211632 班级:计算机12-2班 实验地点:逸夫楼507 实验时间:15.04.10 15.04.17

实验一 1 实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析实验数据的能力; 编程实现DDA 算法、Bresenham 中点算法;对于给定起点和终点的直线,分别调用DDA 算法和Bresenham 中点算法进行批量绘制,并记录两种算法的绘制时间;利用excel 等数据分析软件,将试验结果编制成表格,并绘制折线图比较两种算法的性能。 2 实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One (自制平台) 3 实验结果 3.1 程序流程图 (1)DDA 算法 是 否 否 是 是 开始 计算k ,b K<=1 x=x+1;y=y+k; 绘点 x<=X1 y<=Y1 绘点 y=y+1;x=x+1/k; 结束

(2)Mid_Bresenham 算法 是 否 否 是 是 是 否 是 否 开始 计算dx,dy dx>dy D=dx-2*dy 绘点 D<0 y=y+1;D = D + 2*dx - 2*dy; x=x+1; D = D - 2*dy; x=x+1; x

3.2程序代码 //-------------------------算法实现------------------------------// //绘制像素的函数DrawPixel(x, y); (1)DDA算法 void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) { //----------请实现DDA算法------------// float k, b; float d; k = float(Y1 - Y0)/float(X1 - X0); b = float(X1*Y0 - X0*Y1)/float(X1 - X0); if(fabs(k)<= 1) { if(X0 > X1) { int temp = X0; X0 = X1; X1 = temp; }

计算机图形学实验报告

计算机图形学 实验报告 姓名:谢云飞 学号:20112497 班级:计算机科学与技术11-2班实验地点:逸夫楼507 实验时间:2014.03

实验1直线的生成 1实验目的和要求 理解直线生成的原理;掌握典型直线生成算法;掌握步处理、分析 实验数据的能力; 编程实现DDA算法、Bresenham中点算法;对于给定起点和终点的 直线,分别调用DDA算法和Bresenham中点算法进行批量绘制,并记 录两种算法的绘制时间;利用excel等数据分析软件,将试验结果编 制成表格,并绘制折线图比较两种算法的性能。 2实验环境和工具 开发环境:Visual C++ 6.0 实验平台:Experiment_Frame_One(自制平台)。 本实验提供名为 Experiment_Frame_One的平台,该平台提供基本 绘制、设置、输入功能,学生在此基础上实现DDA算法和Mid_Bresenham 算法,并进行分析。 ?平台界面:如错误!未找到引用源。所示 ?设置:通过view->setting菜单进入,如错误!未找到引 用源。所示 ?输入:通过view->input…菜单进入.如错误!未找到引用 源。所示 ?实现算法: ◆DDA算法:void CExperiment_Frame_OneView::DDA(int X0, int Y0, int X1, int Y1) Mid_Bresenham法:void CExperiment_Frame_OneView::Mid_Bresenham(int X0, int Y0, int X1, int Y1)

3实验结果 3.1程序流程图 1)DDA算法流程图:开始 定义两点坐标差dx,dy,以及epsl,计数k=0,描绘点坐标x,y,x增 量xIncre,y增量yIncre ↓ 输入两点坐标x1,y1,x0,y0 ↓ dx=x1-x0,dy=y1-y0; _________↓_________ ↓↓ 若|dx|>|dy| 反之 epsl=|dx| epsl=|dy| ↓________...________↓ ↓ xIncre=dx/epsl; yIncre=dy/epsl ↓ 填充(强制整形)(x+0.5,y+0.5); ↓←←←← 横坐标x+xIncre; 纵坐标y+yIncre; ↓↑ 若k<=epsl →→→k++ ↓ 结束 2)Mid_Bresenham算法流程图开始 ↓ 定义整形dx,dy,判断值d,以及UpIncre,DownIncre,填充点x,y ↓ 输入x0,y0,x1,y1 ______↓______ ↓↓ 若x0>x1 反之 x=x1;x1=x0;x0=x; x=x0;

相关主题
文本预览
相关文档 最新文档