当前位置:文档之家› 用扫描线算法实现多边形填充

用扫描线算法实现多边形填充

用扫描线算法实现多边形填充
用扫描线算法实现多边形填充

计算机图形学论文基于扫描线的区域填充算法

姓名:魏艳娜

学号: 2012151115

班级: 201201

基于扫描线的区域填充算法

[摘要] :图形通常由点、线、面、体等几何元素和灰度、色彩、线型、线宽等非几何属性组成。从处理技术上来看,图形主要分为两类,一类是基于线条信息表示的,如工程图、等高线地图、曲面的线框图等,另一类是明暗图,也就是通常所说的真实感图形。为此,必须建立图形所描述的场景的几何表示,再用某种光照模型,计算在假想的光源、纹理、材质属性下的光照明效果。计算机图形学的内容非常广泛,如图形硬件、图形标准、图形交互技术、光栅图形生成算法,以及科学计算可视化、计算机动画、虚拟现实等,这里重点研究区域填充。

[关键词]:计算机图形学;区域填充;扫描线算法

第1章绪论

1.1研究的背景

在计算机中重现真实世界的场景叫做真实感绘制。真实感绘制的主要任务是模拟真实物体的物理属性,简单的说就是物体的形状、光学性质、表面的纹理和粗糙程度,以及物体间的相对位置、遮挡关系等等。实时的真实感绘制已经成为当前真实感绘制的研究热点,而当前真实感图形实时绘制的两个热点问题则是物体网格模型的面片简化和基于图象的绘制。网格模型的面片简化,就是指对网格面片表示的模型,在一定误差的精度范围内,删除点、边、面,从而简化所绘制场景的复杂层度,加快图形绘制速度。IBR完全摒弃传统的先建模,然后确定光源的绘制的方法。它直接从一系列已知的图象中生成未知视角的图象。这种方法省去了建立场景的几何模型和光照模型的过程,也不用进行如光线跟踪等极费时的计算。该方法尤其适用于野外极其复杂场景的生成和漫游。

1.2研究的主要内容及结构

主要任务是实现多边形区域扫描线填充的有序边表算法,设计相关的数据结构,并将实现的算法应用于任意多边形的填充,区域填充,指的是在输出平面的闭合区域内完整地填充某种颜色或图案。以下所述及的区域填充算法或相关程序,主要针对显示平面内的区域而言。

区域填充的问题一般分两大类,一是多边形填充;一是种子填充;种子填充在学生掌握了“栈”这一抽象数据类型的实现方法的前提下,比较容易完成。而边标志填充算法却是介于这两类之间,部分地具有它们的痕迹,算法思想巧妙,实现起来更容易。多边形填充有一定难度,我们主要对多边形的扫描线算法填充做一些探讨,具体将以五角星为实例。

第2章理论综述

2.1 区域填充的理论知识

2.1.1 区域填充的概念

将区域的边界表示转换为区域内部象素表示的过程称为区域填充。区域填充是计算机图形学中的一个基本问题,在计算机辅助设计、真实感图形显示、图像分析等领域有着广泛的应用。区域填充算法是指给出一个区域的边界,要求在边界范围内对所有像素单元赋予指定的颜色代码。目前,区域填充算法中最常用的是多边形填色,常用的多边形填色算法

有两种:一类是种子填充算法,一类是扫描线填充算法。

研究如何用一种颜色或图案来填充一个二维区域。一般来说,区域的封闭轮廓是简单的多边形。若轮廓线由曲线构成,则可将曲线转换成多条直线段顺连而成,此时,区域轮廓线仍然是一种多边形逼近。

在计算机图形学中,多边形区域有两种重要的表示方法:顶点表示和点阵表示。所谓顶点表示,即是用多边形的顶点序列来表示多边形。这种表示直观、几何意义强、占内存少、易于进行几何变换,但由于它没有明确指出哪些像素在多边形内,故不能直接用于区域填充。所谓点阵表示,则是用位于多边形内的像素集合来刻画多边形。这种表示丢失了许多几何信息,但便于进行填充。

根据区域的定义,可以采用不同的填充算法,其中最具代表性的是:适用于顶点表示的扫描线类算法和适应于点阵表示的种子填充算法。

2.1.2 扫描线算法的描述

扫描线填充算法一般包括四个步骤:求交、排序、交点配对、区域填充。正确求得扫描线与区域填内外轮廓线的交点是算法成败的关键问题。另一方面,采用合适的数据结构又可以简化操作、提高算法的效率。本论文由于采用链表结构记录轮廓线和交点,无需焦点排序的过程,因而提高了算法效率。扫描线来源于光栅显示器的显示原理:对于屏幕上所有待显示像素的信息,将这些信息按从上到下、自左至右的方式显示。

扫描线多边形区域填充算法是按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作。区间的端点可以通过计算扫描线与多边形边界线的交点获得。对于一条扫描线,多边形的填充过程可以分为四个步骤:

(1)求交:计算扫描线与多边形各边的交点;

(2)排序:把所有交点按x值递增顺序排序;

(3)配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边形的一个相交区间;

(4)填色:把相交区间内的象素置成多边形颜色;

2.2 数据结构与算法

2.2.1 扫描线多边形填充算法的主要步骤

1.建立NET(NewEdgeList);

2.从最低扫描线开始到最高扫描线循环:

3.建立或调整AET(ActiveEdgeList);

4.按照AET中的接点顺序填充。

扫描线填充算法的目标是减少递归层次。步骤是填充并确定种段;初始化:将种子区段压入堆栈;出栈:如果堆栈为空,则算法结束;否则取栈顶元素(y, xLeft, xRight),以纵坐标为 y 的扫描线为当前扫描线,[xLeft, yLeft]为搜索区间;填充并确定新的区段。

因此,扫描线多边形区域填充算法的基本原理是,待填充区域按y方向(x方向亦可)扫描线顺序扫描生成。具体实现时,首先按扫描线顺序,计算扫描线与多边形的相交区间;再用指定的颜色填充这些区间内的像素,即完成这一条扫描线的填充工作。区间的端点可以通过计算扫描线与多边形边界的交点获得。

为了提高效率,在处理每一条扫描线时,仅对与它相交的多边形的边进行求交运算。我们把当前扫描线相交的边称为活性边(active edge),并把它们按扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。

为了提高速度,假定当前扫描线与多边形某一条边的交点的x坐标为xi,则下一条扫描线与该点的交点不需要重新计算,而是通过增加一个增量△x来获得。对于直线ax+by+c=0,△x=-b/a为常数。

另外使用增量法计算时,还需要知道一条边何时不再与下一条扫描线相交,以便及时把它从活性边表中删除出去。因此,活性边表结点的数据结构应保存如下内容:第1项保存当

前扫描线与边的交点坐标x值;第2项保存从当前扫描线到下一条扫描线间x的增量△x;第3项保存该边所交的最高扫描线好ymax。第4项存指向下一条边的指针。

为了方便活性边表的建立与更新,可为每一条扫描线建立一个边表(ET),存放在该扫描线第一次出现的边。也就是说,若某边的较低端点为ymin,则该边就放在扫描线ymin的边表中。

边的分类表ET按照边的下端点y坐标对非水平边进行分类的指针数组活化边表AEL记录与当前扫描线相交的边(交点)

2.2.2边的算法:

typedef struct{

int ymax;

float x,delta;

struct Edge *nextEdge;

}Edge;

ymax:边的上端点y坐标

x:在AEL中表示当前扫描线与边的交点的x坐标,在ET中的初值为边的下端点的x坐标。deltax:边的斜率的倒数

nextEdge:指向下一条边的指针。

具体步骤如下:

step1:把新边表NET[i]中的边结点,用插入排序法

插入活性边表AET,使之按X坐标递增顺序排序;

step2:遍历AET表,把配对交点之间的区间(左闭右开)上的各象

素(X,Y),用drawpixel(x,y,color)改写象素颜色值;

step3:遍历AET表,把Ymax=i的结点从AET表中删除,并把

Ymax>i的结果点的X值递增△X;

step4:重复各扫描线

2.2.3顶点交点的计数问题 :

扫描线与多边形顶点相交时,必须正确的进行交点个数计算,否则,在进行填充时会出现错误。扫描线与多边形相交的边分处扫描线的两侧,则计一个交点;扫描线与多边形相交的边分处扫描线同侧,且yiy(i-1),yi>y(i+1),则计0个交点;扫描线与多边形边界重合,则计1个交点。

是否正确求取扫描线与多边形的交点是扫描线填充算法成败的关键。研究发现,求取扫描线与多边形的交点,既要利用边界点的局部信息,又要利用一条扫描线上所有交点的全部信息。因此,论文的求交过程包括以下三步:

第一步:遍历多边形的边一次,确定扫描线纵坐标的变化范围ymin 和ymax,建立一个空间的扫描线交点链表;

第二步:遍历多边形区域的边一次,根据每一边界点与前驱、后继之间的空间关系,初步求得各扫描线与边的交点;

第三步:对第二步中求得的交点进行修剪,得到正确的扫描线交点表。

当遍历完区域多边形轮廓线上的所有边界点之后,求交过程的第二步结束,此时的扫描线活动边表所记录得是各条扫描线与区域轮廓线的交点。但是,此时还不能保证各条扫描线上的交点的数目为偶数,因此不能直接用于配对,必须对各个扫描线的交点链表进行修剪。

求交点过程的第三步对每一条扫描线的交点链表进行修剪,其目的是删除那些由于出现“半交半切”的情况而多算的交点,以便实现正确的配对。假设待修剪的扫描线为y=i,修正的过程为:

1)以扫描线y=i的交点链表上的第一个交点Pi,l点作为起点;

2)如果起点为空,转5)结束;否则,按照从左到右的顺序遍历链表上的每一个点,如果遇到一个标号非零的交点Pf(设其标号值为lf),则从Pf的后继开始,寻找第二个标号非零的交点Ps,设其标号值为ls,此时:

如果lf与ls 符号相同,则转3);

如果lf与ls符号相反,则转4);

3)将Pf和Ps从交点链表中删除,并以Ps 的后继作为起点,转2);

4)将Pf从交点链表中删除,令Ps的标号ls=0,并以Ps的后继作为起点,转2);

5)结束。

通过分析不难发现,对于任意多边形区域,经上述算法所求的每一条扫描线与多边形的交点数目为偶数,按照先后次序两两配对时,能确保交点之间的区域位于区域的内部。

描述扫描线与多边形交点的数据结构定义一为:

struct crosspoint{

int x;/*交点的横坐标*/

int y;/*交点的纵坐标*/

int l;/*交点的标记*/

crosspoint* pNextPoint;/*下一个交点*/

}

采用单链表的方式记录多边形上的所有与扫描线的交点坐标,下图所示。图中,E表示多边形的边,E , =1,2,…,n。由于多边形的外轮廓具有封闭性,所以链表的起点E 和终点E 也具有8-连通关系。对于链表中任意一个边界点E ,定义E 为E 的前驱,E 为E 的后继。后面将会看到,前去和后继对于判断交点的属性是必不可少的。

把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表(AET)。

2.3扫描线的算法步骤:

1)分析多边形区域扫描线填充算法的原理,确定算法流程

①初始化:构造边表ET,置AET表为空;

②将第一个不空的ET表中的边插入AET表;

③由AET表取出交点进行配对(奇偶)获得填充区间,依次对这些填充区间着色;

④ y=yi+1时,根据x=xi+1/k修改AET表所有结点中交点的x坐标。同时如果相应的ET 表不空,则将其中的结点插入AET表,形成新的AET表;

⑤AET表不空,则转(3),否则结束。

2)编程

①首先确定多边形顶点和ET/AET表中结点的结构

②编写链表相关操作(如链表结点插入、删除和排序等)

③根据1)中的算法结合上述已有的链表操作函数实现多边形区域扫描线填充的主体功能

④编写主函数,测试该算法

3)算法描述:

void polyfill (多边形polygon,颜色color)

{ for (各条扫描线i )

{ 初始化新边表头指针NET [i];把ymin = i的边放进边表NET [i]; } y = 最低扫描线号;

初始化活性边表AET为空;

for (各条扫描线i )

{ 把新边表NET[i]中的边结点用插入排序法插入AET表,使之按x坐标递增顺序排列;

遍历AET表,把y max= i的结点从AET表中删除,并把y max > i结点的x值递增D x;

若允许多边形的边自相交,则用冒泡排序法对AET表重新排序;

遍历AET表,把配对交点区间(左闭右开)上的象素(x, y),用drawpixel (x, y, color)改写象素颜色值;

}

} /* polyfill */

第3章多边形填充实例

多边形区域填充算法。多边形区域填充主要有以下步骤:第一步是确定哪些像素位于图元内部,第二步是确定用何种颜色显示那些像素。经过上一章的知识,本章将以五角星为实例进行用扫描线算法的填充。

3.1用扫描线算法实现五角星填充

以(50,0),(60,30),(90,30),(70,45),(80,90),(50,60),(20,90),(30,45),(10,30),(40,30)这十个点作为五角星的十个点,利用扫描线算法将这个五角星进行填充。

3.2画五角星图形

(1)五角星图形

(2)五角星的边表

构造ET表算法描述如下:

void CreatET(Edge *et[],struct pointtype p[])

/*根据顶点数组构造ET表*/

{

int i,lasty,lastx,nextx,nexty,ymax,cy,cx;

Edge *pe;

for(i=0;i

cy=p[i].y;

cx=p[i].x;

/*确定上一点的坐标及下一点的坐标,考虑数组的首尾点*/

if(0==i){lasty=p[EDGEMAX-1].y;

lastx=p[EDGEMAX-1].x;

}

else{ lasty=p[i-1].y;

lastx=p[i-1].x;

}

if(EDGEMAX-1==i){

nexty=p[0].y;

nextx=p[0].x;

}

else{ nexty=p[i+1].y;

nextx=p[i+1].x;

}

五角星的边的分类表:

(3)相对应活化边表

(a)y=0对应的活化边表:

(4)描述边算法的数据结构定义为:

typedef struct{

int ymax;

float x,delta;

struct Edge *nextEdge;

}Edge;

void CreatET(Edge *et[],struct pointtype p[]); /*根据顶点数组构造ET表*/

void EdgeInAel(Edge *ael,Edge *edge); /*ET表中某边edge插入至AEL表中,并排序,x相同时用下一点x+delta判断*/

void EdgeOutAel(Edge *ael,int y); /*删除AEL中y=ymax的边,并同时修改每边的delta值*/

(5) 顶点交点的计数问题

(6)对AEL中的边两两配对,(1和2为一对,3和4为一对,……)

(7)如果ET中的第y类非空,则将其中的结点插入AET,形成新的AET表

(8)实现五角星主要算法:

void main()

{

int gd=DETECT,gm;

int i,y,ymax;

struct pointtype p[EDGEMAX]={{50,0},{60,30},{90,30},{70,45},{80,90},{50,60},{20,90},{30,45},{10,30},{40 ,30},{50,0}};

Edge *et[ETMAX]={0};

Edge *ael;

ael->nextEdge=NULL;

initgraph(&gd,&gm,"");

CreatET(et,p);

for(i=0;i

if(et[i]!=NULL){

y=i;

break;

}

}/*确定y的最小序号*/

ymax=p[0].y;

for(i=0;i

if(p[i].y>ymax){

ymax=p[i].y;

}

}/*确定ymax*/

while(y<=ymax){

EtInAel(et,ael,y);

EdgeDraw(ael,y);

y++;

EdgeOutAel(ael,y);

}

填充算法如下:

void EdgeDraw(Edge *ael,int y)

{

int counter=1; /*奇偶计数器*/

int color,maxcolor;

Edge *pmove;

float xlast,xcur;

int ylast,ycur;

maxcolor=getmaxcolor();

pmove=ael->nextEdge;

while(pmove!=NULL){

if(counter%2==1){

xlast=pmove->x;

}

else{ /*每两次边画线一次并重新赋值开始*/

xcur=pmove->x;

color=random(maxcolor);

setcolor(color);

line((int)xlast+1,y,(int)xcur,y);

xlast=0;

xcur=0;

}

counter++;

pmove=pmove->nextEdge;

}

}

[结束语]:这种方法省去了建立场景的几何模型和光照模型的过程,也不用进行如光线跟踪等极费时的计算。该方法尤其适用于野外极其复杂场景的生成和漫游。

参考文献:

[1]李桂清,李淘渊.扫描线种子填充的问题及改进[J].广西大学学报(自然科学版),1998;(9):207~212

[2]余正生,马立庄,彭群生.任意区域的边界扫描线转换[J].工程图学学报,1999;(1):72~77

[3]倪明田,吴良芝. 计算机图形学[M].北京大学出版社,2008.

Area Filling Algorithm Based On Scan Line

[Abstract]: graphics usually consist of non geometric properties, such as point, line, surface, body, etc.. From the point of view of the processing technology, graphics can be divided into two categories, one is based on the line information representation, such as engineering drawing, the surface of the line diagram, another kind is the light and shade chart, is commonly referred to as the realistic graphics. To this , we must establish geometry of the scene described by the graphics, and then use a light model to calculate lighting effect of the light source, texture and material properties. The content of computer graphics is very extensive, such as graphics hardware, graphics, interactive graphics, raster graphics generation algorithm, and scientific computing visualization, computer animation, virtual reality etc., where the focus of the study area filling.

[Keywords]: computer graphics, area filling, scan line algorithm

多边形区域填充算法

13. 设五边形的五个顶点坐标为(10, 10),(15, 5),(12, 5),(8, 2)和(4, 5),利用多边形区域填充算法,编一程序生成一个实心图。 解:假设以上五个顶点依次对应编号A-B-C-D-E,首先计算得到ET表: 6-10 5 4 3 2 1 该多边形的AET指针的内容为: 1 AET为空 2 3 4 1 2 3 4 5 6 7 8 9 10 01234567891011121314 1516

5 6 7 8 9 10 具体编程实现如下: 第1步:(1) 根据输入的五个顶点坐标找到y 值最小的点(例如点D ,此时y=2),并找到与D 有边关系的两个顶点(此时为E 和C),在y=2处建立ET 边表记录(ymax 、xi 和m 值均可通过顶点坐标间的计算得到,例如DE 边的建立,特别注意:当D 点和E 点y 坐标值相同时,也即是DE 与x 轴平行,该边不能计入ET 边表),之后标记D 点被访问过;(2) 排除访问过的点以及和该点相关联的边,重复(1)直至将ET 表建立完善。 [注]边关系的建立可通过邻接矩阵的数据结构实现,权值可以为该矩阵行编号对应点的y 坐标值,ET 边表采用邻接表的数据结构 第2步:根据ET 表构建AET 表,并逐行完成多边形填充,具体的C++代码如下: (1) 建立头文件base_class.h ,主要是边表结点结构体和ET 边表类的实现 enum ResultCode{Success, Failure}; template struct Enode { Enode() {next=NULL;} Enode(T pymax, float pxi, float pm, Enode *pnext) { ymax=pymax; xi=pxi; m=pm; next=pnext; } T ymax, xi; //ymax 表示最大的y 值,xi 表示最底端点的x 坐标值 float m; //m 表示斜率的倒数 Enode *next; }; //定义了ET 表和AET 表中结点的结构体

扫描线填充算法讲解

扫描线算法(S c a n-L i n e F i l l i n g) 扫描线算法适合对矢量图形进行区域填充,只需要直到多边形区域的几何位置,不需要指 定种子点,适合计算机自动进行图形处理的场合使用,比如电脑游戏和三维CAD软件的渲染等等。 对矢量多边形区域填充,算法核心还是求交。《计算几何与图形学有关的几种常用算法》 一文给出了判断点与多边形关系的算法――扫描交点的奇偶数判断算法,利用此算法可以 判断一个点是否在多边形内,也就是是否需要填充,但是实际工程中使用的填充算法都是 只使用求交的思想,并不直接使用这种求交算法。究其原因,除了算法效率问题之外,还 存在一个光栅图形设备和矢量之间的转换问题。比如某个点位于非常靠近边界的临界位置,用矢量算法判断这个点应该是在多边形内,但是光栅化后,这个点在光栅图形设备上看就 有可能是在多边形外边(矢量点没有大小概念,光栅图形设备的点有大小概念),因此, 适用于矢量图形的填充算法必须适应光栅图形设备。 2.1扫描线算法的基本思想 扫描线填充算法的基本思想是:用水平扫描线从上到下(或从下到上)扫描由多条首尾相 连的线段构成的多边形,每根扫描线与多边形的某些边产生一系列交点。将这些交点按照 x坐标排序,将排序后的点两两成对,作为线段的两个端点,以所填的颜色画水平直线。 多边形被扫描完毕后,颜色填充也就完成了。扫描线填充算法也可以归纳为以下4个步骤:(1)求交,计算扫描线与多边形的交点 (2)交点排序,对第2步得到的交点按照x值从小到大进行排序; (3)颜色填充,对排序后的交点两两组成一个水平线段,以画线段的方式进行颜色填充; (4)是否完成多边形扫描?如果是就结束算法,如果不是就改变扫描线,然后转第1步 继续处理; 整个算法的关键是第1步,需要用尽量少的计算量求出交点,还要考虑交点是线段端点的 特殊情况,最后,交点的步进计算最好是整数,便于光栅设备输出显示。 对于每一条扫描线,如果每次都按照正常的线段求交算法进行计算,则计算量大,而且效 率底下,如图(6)所示: 图(6)多边形与扫描线示意图

区域填充算法的实现

实验四区域填充算法的实现 一、实验目的和要求: 1、掌握区域填充算法基本知识 2、理解区域的表示和类型,能正确区分四连通和八连通的区域 3、了解区域填充的实现原理,利用Microsoft Visual C++ 6.0(及EasyX_2011版) 实现区域种子填充的递归算法。 二、实验内容: 1、编程完成区域填色 2、利用画线函数,在屏幕上定义一个封闭区域。 3、利用以下两种种子填充算法,填充上述步骤中定义的区域 (1)边界表示的四连通区域种子填充的实现 (2)内点表示的四连通区域种子填充的实现 4、将上述算法作部分改动应用于八连通区域,构成八连通区域种子填充算法, 并编程实现。 三、实验结果分析 1、以上各种算法相应代码及运行结果如下: 程序代码: #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-1,y,oldcolor,newcolor); FloodFill4(x,y+1,oldcolor,newcolor); FloodFill4(x+1,y,oldcolor,newcolor); FloodFill4(x,y-1,oldcolor,newcolor); } } void main() { int a,b,c,d,i,j; int graphdriver=DETECT; int graphmode=0; initgraph(&graphdriver,&graphmode," "); cleardevice();

计算机图形学课程设计-有效边表填充算法的实现

计算机图形学课程设计设计题目改进的有效边表算法对多边形的填充学院名称信息科学与技术学院 专业名称计算机科学与技术 学生姓名刘柯 学生学号201213030112 任课教师梅占勇 设计(论文)成绩 教务处制 2015年9 月28 日

目录 一、设计内容与要求 (3) 1.1设计题目 (3) 1.2 设计内容 (3) 1.3 设计目标 (3) 二、总体设计 (3) 2.1 多边形的表示 (3) 2.2 x-扫描线算法 (4) 2.3 改进的有效边表算法 (4) 2.3.1 改进的有效边表算法 (4) 2.3.2 有效边表 (5) 2.3.3 边表 (6) 三、详细设计 (8) 3.1 改进的有效边表算法的实现 (8) 3.2 有效边表算法程序流程图 (9) 四、测试结果 (9) 五、总结 (15) 六、源代码 (15) 参考文献 (26)

一、设计内容与要求 1.1设计题目 用改进的有效边表算法实现多边形的填充 1.2 设计内容 使用OpenGL实现用改进的有效边表算法填充多边形 1.3 设计目标 参照课本上改进的有效边表算法的思想,实现该算法的C语言代码,并用该算法搭配OpenGL以像素点的方式绘制出给定顶点坐标的多边形。 二、总体设计 2.1 多边形的表示 在计算机图形学中,多边形有2种重要的表示方法:顶点表示和点阵表示。 顶点表示用多边形的顶点序列来刻画多边形,这种方法直观、几何意义强,占用内存少,应用普遍,但它没有明确指出哪些像素在多边形内,故不能直接用于面着色。 点阵表示用位于多边形内的像素的集合来刻画多边形。这种表示法虽然失去了许多重要的几何信息,但便于运用帧缓存表示图形,是面着色所需要的图形表示形式。 大多数图形应用系统采用顶点序列表示多边形,而顶点表示又不能直接用于显示,那么就必须有从多边形的顶点表示到点阵表示的转换,这种转换称为多边形的扫描转

扫描线填充算法

任意封闭多边形的扫描线填充算法类收藏 这个代码不是我写的,但是我肯定这代码是一个牛人写的,放在这里供大家学习和使用啦!感谢原作者! 我在这里做了些改进: 1 去除了绘制多边形的函数,使其成为了一个纯的填充算法模块 2 改进了其成员变量,使其更容易让大多数人所使用 3 改进了填充,使其“看”(代码上)起来更像用扫描线在填充 改进后的扫描线算法类如下: //扫描线填充算法类 class CPFill { public: CPoint *Point; //指向点坐标的指针 int Count; //多边形点的个数 public: CPFill(int,int[],int[]);//构造函数 bool FillPolygon(CDC*);//填充多边形 bool CrossJudge(CPoint,CPoint,CPoint,CPoint,CPoint&);//判断两条线段是否相交 int GetAi(int);//获取下一个点的索引号 int GetBi(int);//获取前一个点的索引号 bool Sort(int*,int);//冒泡排序 ~CPFill();//析构函数 }; //构造函数(模块入口,koradji 注,合理的设计这个地方,就可以完全不用改动其他的地方就可以使用这个类) CPFill::CPFill(){ } //获取前一个点的索引号 int CPFill::GetBi(int i) { return (i==0)? Count-1:i-1; } //获取下一个点的索引号

int CPFill::GetAi(int i) { return (i==Count-1)?0:i+1; } //在指定的pDC设备中,填充多边形 bool CPFill::FillPolygon(CDC* pDC) { //获取多边形中所有坐标点的最大值和最小值,作为扫描线循环的范围 int minX=Point[0].x , minY=Point[0].y; int maxX=Point[0].x , maxY=Point[0].y; for(int i=1;iPoint[i].x) minX=Point[i].x; if(minY>Point[i].y) minY=Point[i].y; if(maxXPointCross.y)&&(Point[Ai].y>PointCross.y)) { //边顶点的y值大于交点的y值,x坐标取两次 xArray.Add(PointCross.x); xArray.Add(PointCross.x); } else { //边顶点的y值在交点的y值之间,即一个顶点的y值大于交点的y值,而另一个小于,相应的x坐标取一次 if((Point[Bi].y-PointCross.y)*(Point[Ai].y-PointCross.y)<0) xArray.Add(PointCross.x);

画圆与凸多边形填充算法

华北水利水电大学 计算机图形学 实验报告 2017--2018学年 第一学期 2014级 计算机科学与技术 专业 指导老师 曹源昊 班级 2014157 学号 201415717 姓名 李卫朋 实验四、画圆与凸多边形填充算法 1. 实验目的 练习对Bezier 曲线的绘制和Bezier 曲线的de Casteljau 算法。 2. 实验内容和要求 按要求完成以下一个作业。提交纸质实验报告,同时提交实验报告和源代码的电子版。 实现Bezier 曲线的de Casteljau 递推算法,能够对任意介于0和1之间的参数t 计算Bezier 曲线上的点,然后把Bezier 曲线绘制成首尾相连的直线段。 要求: (1). 对[0,1]参数区间进行100等分。 (2). 控制点的数目至少为5个,即Bezier 曲线的次数不低于4次。 (3). 同时绘制控制多边形。 (4). 至少绘制两条Bezier 曲线,具有不同的次数,颜色和曲线宽度。 形如: 3. 算法描述 使用vs2012编译环境,使用OpenGL 进行绘图操作。 4. 源程序代码 // 实验4.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include #include GLfloat ctrlPoints[5][2] = { { -0.8f, 0.1f }, {-0.4f, 0.6f }, { 0.0f, 0.8f }, { 0.5f, 0.2f },{0.9f,0.7f} }; 1P 2P 3P 4 P 5P

计算机图形学 多边形裁剪与填充 计算机图形学课程设计

课程设计报告 课程名称计算机图形学 课题名称多边形裁剪与填充 专业计算机科学与技术 班级计算机0902 学号 姓名 指导教师刘长松曹燚 2012年10 月9 日

湖南工程学院 课程设计任务书 课程名称计算机图形学课题多边形裁剪与填充 专业班级计算机0902 学生姓名 学号 指导老师刘长松曹燚 审批 任务书下达日期2012年9月15 日 任务完成日期2012 年10月9 日

一、设计内容与设计要求 1.设计内容: 交互式地实现多边形的裁剪和填充。。 2.设计要求: 1)窗口功能设计。 2)实现鼠标画多边形与数据存储功能。 3)实现鼠标剪裁窗口选择功能。 4)实现多边形裁剪和填充功能。 3.算法提示: 多边形裁剪算法分析: 基本思想是一次用窗口的一条边裁剪多边形,窗口的一条边以及延长线构成裁剪线,该线把平面分成两个部分:可见一侧,不可见一侧。用一条裁剪边对多边形进行裁剪,得到一个顶点序列,作为下一条裁剪边处理过程的输入点。 对于每一条裁剪边,只是判断点在窗口的哪一测以及求线段与裁剪边的交点算法应随之改变。 多边形填充算法分析: 确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin 和ymax),从y=ymin 到 y=ymax, 每次用一条扫描进行填充。对一条扫描线填充的过程可分为四个步骤: a.求交b.排序c.交点配对d.区间填色。 二、进度安排 第 3 周星期一8:00——12:00 星期二8:00——12:00 星期三8:00——12:00 星期四8:00——12:00 星期五8:00——12:00 第 4 周星期一8:00——12:00 附: 课程设计报告装订顺序:封面、任务书、目录、正文、附件(A4大小的图纸及程序清单)、评分。正文的格式:一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。 正文的内容:一、课题的主要功能;二、课题的功能模块的划分(要求画出模块图);三、主要功能的实现(至少要有一个主要模块的流程图);四、程序调试;五、总结;六、附件(所有程序的原代码,要求对程序写出必要的注释)。 正文总字数要求在5000字以上(不含程序原代码)。

扫描线填充算法讲解

扫描线算法(Scan-Line F illing) 扫描线算法适合对矢量图形进行区域填充,只需要直到多边形区域的几何位置,不需要指定种子点,适合计算机自动进行图形处理的场合使用,比如电脑游戏 和三维CAD软件的渲染等等。 对矢量多边形区域填充,算法核心还是求交。《计算几何与图形学有关的几种 常用算法》一文给出了判断点与多边形关系的算法――扫描交点的奇偶数判断 算法,利用此算法可以判断一个点是否在多边形内,也就是是否需要填充,但 是实际工程中使用的填充算法都是只使用求交的思想,并不直接使用这种求交 算法。究其原因,除了算法效率问题之外,还存在一个光栅图形设备和矢量之 间的转换问题。比如某个点位于非常靠近边界的临界位置,用矢量算法判断这 个点应该是在多边形内,但是光栅化后,这个点在光栅图形设备上看就有可能 是在多边形外边(矢量点没有大小概念,光栅图形设备的点有大小概念),因此,适用于矢量图形的填充算法必须适应光栅图形设备。 2.1扫描线算法的基本思想 扫描线填充算法的基本思想是:用水平扫描线从上到下(或从下到上)扫描由 多条首尾相连的线段构成的多边形,每根扫描线与多边形的某些边产生一系列 交点。将这些交点按照x坐标排序,将排序后的点两两成对,作为线段的两个 端点,以所填的颜色画水平直线。多边形被扫描完毕后,颜色填充也就完成了。扫描线填充算法也可以归纳为以下4个步骤: (1)求交,计算扫描线与多边形的交点 (2)交点排序,对第2步得到的交点按照x值从小到大进行排序; (3)颜色填充,对排序后的交点两两组成一个水平线段,以画线段的方式进 行颜色填充; (4)是否完成多边形扫描?如果是就结束算法,如果不是就改变扫描线,然 后转第1步继续处理; 整个算法的关键是第1步,需要用尽量少的计算量求出交点,还要考虑交点是 线段端点的特殊情况,最后,交点的步进计算最好是整数,便于光栅设备输出 显示。

多边形的有效边表填充算法-

实验三多边形的有效边表填充算法 一、实验目的与要求 1、理解多边形的扫描转换原理、方法; 2、掌握有效边表填充算法; 3、掌握链表的建立、添加结点、删除节点的基本方法; 3、掌握基于链表的排序操作。 二、实验内容 在实验二所实现工程的基础上,实现以下内容并把实现函数封装在类 CMyGL 中。 1、C++实现有效边表算法进行多边形扫描转换 2、利用1进行多边形扫描转换和区域填充的实现; 三、实验原理 请同学们根据教材及上课的PPT独立完成。 四、实验步骤(程序实现)。 1、建立并选择工程项目。打开VC6.0->菜单File 的New 项,在projects 属性页选择MFC AppWizard(exe)项,在Project name 中输入一个工程名,如“Sample”。单文档。 2、新建一个图形类。选择菜单Insert New class,Class type 选择“Generic Class”,Name 输入类名,如“CMyCG。 3、向新建的图形类中添加成员函数(实际就是加入实验要求实现的图形生成算法的实现代码)。在工作区中直接鼠标右键单击,选择“Add Member Function…”项,添加绘制圆的成员函数。 void PolygonFill(int number, CPoint *p, COLORREF color, CDC* pDC) 添加其他成员函数: CreatBucket(); CreatET(); AddEdge(); EdgeOrder(); 4、成员函数的实现。实现有效边表填充算法。这一部分需要同学们去实现。 参考实现: 多边形的有效边表填充算法的基本过程为: 1、定义多边形: 2、初始化桶 3、建立边表 4、多边形填充 1)对每一条扫描线,将该扫描线上的边结点插入到临时AET表中,HeadE. 2)对临时AET表排序,按照x递增的顺序存放。 3)根据AET表中边表结点的ymax抛弃扫描完的边结点,即ymax>=scanline 4)扫描AET表,填充扫描线和多边形相交的区间。

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

实验报告 一、实验目的 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; /* 边所交的最高扫描线号 */

实验六 扫描线填充算法

实验六扫描线填充算法 一、实验目的 编写多边形的扫描线填充算法程序,加深对扫描线算法的理解,验证算法的正确性。 二、实验任务(2学时) 编写多边形的扫描线填充算法程序,利用数组实现AET,考虑与链表实现程序的不同。 三、实验内容 1、算法 对一条扫描线的填充一般分为以下4个步骤: (1)求交:计算扫描线与多边形各边的交点; (2)排序:把扫描线上所有交点按递增顺序进行排序; (3)配对:将第一个交点与第二个交点,第三个交点与第四个交点等等进行配对,每对交点代表扫描线与多边形的一个相交区间。 (4)着色:把区间内的像素置为填充色。 2、成员函数的关系 主程序名为fill_area(count, x, y),其中参数x, y是两个一维数组,存放多边形顶点(共c ount个)的x和y坐标。它调用8个子程序,彼此之间的调用关系图1所示为: 图1 fill_area的程序结构 3、算法的程序设计

步骤1:创建“S_L_Fill”工程文件; 步骤2:创建类class:“EACH_ENTRY”。 在工作区“S_L_Fill classes”单击右键-→“new class”-→选择类型“Generic Class”名称为“EACH_ENTRY”,添加成员变量(添加至“class EACH_ENTRY { public:”之内):int y_top; float x_int; int delta_y; float x_change_per_scan; 步骤3:包含头文件,同时初始化定义多边形顶点数目。在“class CS_L_FillView : public Cview……”之前添加代码“#include EACH_ENTRY.h”及“#define MAX_POINT 9”。 #define MAX_POINT 9 #include "EACH_ENTRY.h" 步骤4:在类“class CS_L_FillView”中添加成员变量(鼠标双击工作区“CS_L_FillView”,代码添加至“class CS_L_FillView : public Cview {protected: ……public:之后”):EACH_ENTRY sides[MAX_POINT]; int x[MAX_POINT],y[MAX_POINT]; int side_count,first_s,last_s,scan,bottomscan,x_int_count; 步骤5:利用构造函数“CS_L_FillView::CS_L_FillView()”初始化顶点坐标(鼠标双击工作区“CS_L_FillView”,代码添加至“CS_L_FillView()之内”): x[0]=200;y[0]=100; x[1]=240;y[1]=160; x[2]=220;y[2]=340; x[3]=330;y[3]=100; x[4]=400;y[4]=180; x[5]=300;y[5]=400; x[6]=170;y[6]=380; x[7]=120;y[7]=440; x[8]=100;y[8]=220; 步骤6:在“class CS_L_FillView”下添加实现不同功能的成员函数。在工作区“CS_L_FillView”上单击鼠标右键,选择“Add Member Function”,分别完成以下成员函数的添加: (1)void put_in_sides_list(int entry,int x1,int y1,int x2,int y2,int next_y) 函数说明:put_in_sides_list子程序的主要功能是将一条边存入活性边表之内。操作步骤是:对该边判别是否左顶点或右顶点,如果将入边之终点删去,按照y_top的大小在活性边表中找到该点的合适位置,y值较大者,排在活性边表的靠前位置。 void put_in_sides_list(int entry,int x1,int y1,int x2,int y2,int next_y)// entry为剔除水平边之后的第entry条边,x1, y1,为起点,x2, y2为终点,next_y为终点相邻的下一个顶点y坐标{ int maxy; float x2_temp,x_change_temp; x_change_temp=(float)(x2-x1)/(float)(y2-y1);//计算1/k x2_temp=float(x2); if((y2>y1)&&(y2

扫描线Z-Buffer算法作业说明-Read

扫描线Z-Buffer算法作业说明 学号20821055 姓名邹松 联系方式zousong@https://www.doczj.com/doc/b73326917.html, 1、SRC目录 src目录为算法源代码,编译环境为microsoft visual c++ 2005 express edition,源码中有主要步骤的注释说明。绘制时用到了OpenGL的glDrawPixels函数,需用到OpenGL库文件和头文件及glut库 2、BIN目录 bin目录为编译好的可执行程序,批处理运行程序,多个测试obj文件。 各个obj文件说明: cube.obj 为立方体模型,8个点,12个面,36条边。 cone.obj为圆台模型,146个点,288个多边形,864条边; sphere.obj为球模型,482个点,960个多边形,2880条边; teapot.obj为茶壶模型,530个点,992个多边形,2976条边; torus.obj为圆环模型,288个点,576个多边形,1728条边; torusknot.obj为环形结模型,1440个点,2880个多边形,8640条边; venusm.obj 为维纳斯像模型,19755个点,43357个多边形,130071个条边。 test.obj为我自己手工建立的obj文件,包含一个五角星和两个三角形,主要测试(凹)多边形(上面几个模型都只有三角形),及多边形互相贯穿的情况。 可执行程序运行方式: SL_Z_buffer [file] 参数分别为obj文件名 默认分别为test.obj 直接运行run.bat文件即可对以上obj文件分别绘制出对应的图像。 使用的可执行程序为每个面片产生随机颜色 运行SL_Z_buffer可绘制test.obj 对应的图像

区域填充的扫描线算法

计算机图形学 ——区域填充的扫描线算法 NORTHWESTUNIVER SITY

一、实验目的 1.通过实验,进一步理解和掌握几种常用多边形填充算法的基本原理 2.掌握多边形区域填充算法的基本过程 3.掌握在C/C++环境下用多边形填充算法编程实现指定多边形的填充。 4.利用TC2.0编写区域填充的扫描线算法。 二、实验内容 算法基本思想:首先填充种子点所在扫描线上位于区域内的区段,然后确定与该区段相邻的上下两条扫描线上位于区域内的区段,并依次将各区段的起始位置保存, 这些区段分别被用区域边界色显示的像素点所包围。随后,逐步取出一开始点并重复上述过程,直到所保存各区段都填充完毕为止。 算法描述:扫描线填充算法一般包括四个步骤:求交、排序、交点配对、区域填充。正确求得扫描线与区域填内外轮廓线的交点是算法成败的关键问题。另一方面,采用合适的数据结构又可以简化操作、提高算法的效率。本论文由于采用链表结构记录轮廓线和交点,无需焦点排序的过程,因而提高了算法效率。扫描线来源于光栅显示器的显示原理:对于屏幕上所有待显示像素的信息,将这些信息按从上到下、自左至右的方式显示。 扫描线多边形区域填充算法是按扫描线顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的象素,即完成填充工作。区间的端点可以通过计算扫描线与多边形边界线的交点获得。对于一条扫描线,多边形的填充过程可以分为四个步骤: (1)求交:计算扫描线与多边形各边的交点; (2)排序:把所有交点按x值递增顺序排序; (3)配对:第一个与第二个,第三个与第四个等等;每对交点代表扫描线与多边形的一个相交区间; (4)填色:把相交区间内的象素置成多边形颜色; 三、实验原理 扫描线填充算法的基本过程如下:当给定种子点(x,y)时,首先填充种子点所在扫描线上的位于给定区域的一个区段,然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。反复这个过程,直到填充结束。 区域填充的扫描线算法可由下列四个步骤实现: (1)初始化:堆栈置空。将种子点(x,y)入栈。 (2)出栈:若栈空则结束。否则取栈顶元素(x,y),以y作为当前扫描线。 (3)填充并确定种子点所在区段:从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xl和xr。 (4)并确定新的种子点:在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条

多边形填充算法运行代码

private void scanLineFillingToolStripMenuItem_Click(object sender, EventArgs e) { slf.ScanLinePolygonFill(P,g,XiangSu); } private void label2_Click(object sender, EventArgs e) { } private void四联通填充ToolStripMenuItem_Click(object sender, EventArgs e) { tempp.X = tempP[3].X + XiangSu;//选取第4个点内侧(随机猜测) tempp.Y = tempP[3].Y + XiangSu; checkBox.Enabled = false;//让绘制过程中不能改变选择 do_check();//也要检查一遍,不然会出现错误 FloodSeedFill(tempp); checkBox.Enabled = true;//恢复 } ///

///下拉框选择像素回调函数 /// /// /// private void PortList_SelectedIndexChanged(object sender, EventArgs e) { XiangSu = 2 * PortList.SelectedIndex + 2;//根据下拉框选择绘制像素 } /// ///洪泛填充[注入填充] ///将所有联通区域内某种指定颜色的点都替换成另一种颜色 ///边界填充:只要是边界内的点无论是什么颜色,都替换成指定的颜色 /// /// /// private void floodFillAlgorithmToolStripMenuItem_Click(object sender, EventArgs e) {

[最新]扫描线算法代码

[最新]扫描线算法代码 #include #include #include "stdlib.h" void init (void) { glClearColor (1.0, 1.0, 1.0, 0.0); // 指定清空颜色(背景色)为白色glMatrixMode (GL_PROJECTION); //指定投影矩阵 gluOrtho2D (0.0, 400.0, 0.0, 400.0); //指定二维坐标系中被显示的区域} typedef struct tEdge { int yUpper; float xIntersect, dxPerScan; struct tEdge * next; } Edge; struct dcPt { //dcPt 实际上是一个点的结构体 int x; int y; }; void setPixel(GLint x, GLint y){ glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); }

/* Inserts edge into list in order of increasing xIntersect field. */ void insertEdge (Edge * list, Edge * edge) { Edge * p, * q = list; p = q->next; while (p != NULL) { if (edge->xIntersect < p->xIntersect) p = NULL; else { q = p; p = p->next; } } edge->next = q->next; q->next = edge; } /* For an index, return y-coordinate of next nonhorizontal line */ int yNext (int k, int cnt, dcPt * pts) { int j; if ((k+1) > (cnt-1)) j = 0; else j = k + 1; while (pts[k].y == pts[j].y)

多边形的偏移填充算法

多边形的偏移填充算法 多边形偏移(polygon offset)算法可能我们印象不深,不过用过autoCAD的同学也印象autoCAD 上面也还是有这个功能的。我们可以用autoCAD上的“正多边形”功能画一个多边形,然后用修改工具中“偏移”按钮,对多边形进行偏移,见图1,从外面的一个大的5边形按照边偏移至里面小的5边形,其中相应边偏移的距离定义为offset值。 图1 AutoCAD中的多边形偏移效果图 当然,这只是简单的情况,复杂的情况可能是有多个多边形,其中1个outer多边形,多个inner 多边形,然后offset的时候应该是outer多边形向内offset,inner多边形向外offset。当一个多边形(特别是凹多边形)初步offset时,可能会发生自交;然后多边形之间也可能会发生相交。大概思路:这里就需要首先将自交的多边形分裂出来,并选择正确的多边形;然后将选择出来的多边形进行求交计算,再一次将有相交的多边形合并分裂出来,并且选择正确的多边形,这个时候得到的全部多边形就是一次offset出来的结果。 1、为了保证outer多边形能向内offset,inner多边形能向外offset,这里需要保证outer多边形是逆时针方向旋转的,inner多边形是顺时针方向旋转的。 1.1 这里就稍稍讲下多边形的顺逆判断。

在多边形是简单多边形的前提下,其实还是挺简单的,只要找出多边形左下角的一个顶点,然后判断与这个顶点相连的两条边的叉积是否大于0就行了;如果多边形不是简单多边形,比如有自相交,有顶点夹角为0的情况等等,这个时候多边形就不应该有顺逆这种属性吧 2、对单个多边形,根据角平分线初步偏移得到角点 对于一个角点,可以设这个顶点为curPoint,相连的前一个点为prePoint,下一个点为nexPoint,于是可以得到两个向量a = prePoint – curPoint,b=nexPoint – curPoint。将向量a和b设置为单位向量之后,相加就能得到角平分线的方向向量c。然后对单位向量a和b做点乘和叉乘,就能得到这个角度的cos和sin值了,我们假设这个角度的一般为Θ,则cos=cos2Θ,sin=sin2Θ。根据三角函数,就能得到sinΘ值,之后将就能得到该顶点的角平分线方向的偏移向量d=c/|c|×offset÷sinΘ。 3、考虑到有些边在偏移的过程中会消失,即一些边有退化的offset值,见图3。如果初步偏移的值大于它的退化offset值,则该边就会反向出现,见图3中的边【4,5】,会给后面的程序带来很大的麻烦。 图2

计算机图形学-区域填充的扫描线算法

计算机图形学——区域填充的扫描线算法 一.实验名称: 区域填充的扫描线算法 二.实验目的: 1、理解区域填充扫描线算法的原理; 2、实现区域填充的扫描线算法并测试; 三.算法原理: 算法基本思想: 首先填充种子点所在扫描线上位于区域内的区段,然后确定与该区段相邻的上下两条扫描线上位于区域内的区段,并依次将各区段的起始位置保存, 这些区段分别被用区域边界色显示的像素点所包围。随后,逐步取出一开始点并重复上述过程,直到所保存各区段都填充完毕为止。 借助于栈结构,区域填充的扫描线算法之步骤如下: Step 1. 初始化种子点栈:置种子点栈为空栈,并将给定的种子点入栈; Step 2. 出栈:若种子点栈为空,算法结束;否则,取栈顶元素(x,y)为种子点; Step 3. 区段填充:从种子点(x, y) 开始沿纵坐标为y 的当前扫描线向左右两个方向逐像素点进行填色,其颜色值置为newcolor 直至到达区域边界。分别以xl 和xr 表示该填充区段两端点的横坐标; Step 4. 新种子点入栈: 分别确定当前扫描线上、下相邻的两条

扫描线上位于区段[xl, xr] 内的区域内的区段。若这些区段内的像素点颜色值为newolor ,则转至Step 2;否则以区段的右端点为种子点入种子点栈,再转至Step 2。 四.原程序代码: /*****************************************/ /*4-ScanLineFill 区域填充的扫描线算法实现*/ /*****************************************/ #include #include #include #include #define Stack_Size 100 //栈的大小常量 //定义结构体,记录种子点 typedef struct{ int x; int y; }Seed; //定义顺序栈(种子点) typedef struct { Seed Point[Stack_Size]; int top;

扫描线填充算法--有效边表填充算法

代码: draw.cpp //using OpenGL #include "opengl.h" #include #include #include #include #define PN 6 int point[N][2]={{40,5},{75,40},{60,70},{35,50},{25,80},{5,30 }}; //AE struct AE{ AE(float _x,float _dx,int _ymax){x=_x;dx=_dx;ymax=_ymax;} float x; float dx; int ymax; void operator++(int){ x+=dx; } }; //AET //which eage is on the right bool fill_comp(const AE& ae1,const AE& ae2){ if(ae1.x

flush(); } void fill(){ //make k=(x2-x1)/(y2-y1) float k[PN]={0.0};for(int i=0;i!=PN;i++){k[i]=((float)(point[(i+1)%PN][0]-point[i][ 0])/(float)(point[(i+1)%PN][1]-point[i][1]));} //find min and max with selection sort. int min=point[0][1],max=min;for(int i=0;i!=PN;i++){if(point[i][1]>max){max=point[i][1];};;if( point[i][1]*ET =new std::vector[max-min+1]; //make ET // for(int i =0; i=point[(i+1)%PN][1]? i : (i+1)%PN; AE *tmp =new AE(point[yminn][0],k[i],point[ymaxn][1]); //insert node ET[point[yminn][1]-min].push_back(*tmp); } //init AET std::vector AET; for(int i=0;i!=max-min+1;i++){ //insert node from ET to AET for(int ii=0;ii!=ET[i].size();ii++){ //sort with selection sort. AET.insert(std::upper_bound(AET.begin(), AET.end(),ET[i][ii],fill_comp),ET[i][ii]); } //delete y=ymax,"下闭上开" for(int ii=0;ii!=AET.size();){if(i+min==AET[ii].ymax) {AET.erase(AET.begin()+ii);}else{ii++;}} //draw { bool flag=false;

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