带孔多边形填充算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
带孔多边形填充算法
带孔多边形填充算法一( 基本原理
用自上而下的每一条水平的扫描线扫描多边形,每一条扫描线被多边形分成几段,每一段要么在多边形内,要么在多边形外。在内的填充,在外的舍弃。见图1 图1
二( 基本算法
1. 水平扫描线与线段求交点
假定当前扫描线y与多边形的某一条边的交点x坐标为x,那么下一条扫描线
y-1与该边的交点不必从头算起,只要加上一个增量即可。设增量为dx,显然dx= -(x1-x0)/(y1-y0)
结果是:若y=y ,x=x,则当y=y-1时,x=x-(x1-x0)/(y1-y0) iiii
(x0,y0)
y 11 y-1 dx (x1,y1)
图2
2. 活性边与活性边表
为了提高效率,在处理一条扫描线时,仅对与它相交的多边形的边进行求交运算。我们把与当前扫描线相交的边称为活性边,并把它们按与扫描线交点x坐标递增的顺序存放在一个链表中,称此链表为活性边表。
由于边的连贯性(即当某条边与当前扫描线相交时,它很可能也与下一条扫描
线相交),以及扫描线的连贯性(当前扫描线与各边的交点顺序与下一条扫描线与各边的交点顺序很可能相同或非常类似),在当前扫描线处理完毕之后,我们不必为
下一条扫描线从头开始构造活性边表,而只要对当前扫描线的活性边表稍作修改,即可更新得到下一条扫描线的活性边表。
例如,(见图3)
扫描线6的活性边表如下:PP,PP, PP,PP61 6554 43
扫描线4的活性边表如下:PP,PP 6143
扫描线3的活性边表如下:PP,PP (满足上闭下开的原则)。 6132
扫描线2的活性边表如下:PP,PP (满足上闭下开的原则)。 1223
y
(11,8) 9 P4
(2,7) 8 P6
7
6
5 P(5,5) 5 4
(11,3) 3 P3 P(5,1) 2 2 P(2,2) 11
4 56 78 910 11 1 2 3 0 x
图3
3(Y桶表
为了方便活性边表的建立与更新,我们为每一条扫描线建立一个新边表,存放在
该扫描线第一次出现的边。也就是说,若某边的较高端点为Y,则该边就放在扫描线maxY的新边表中。这样,当我们按扫描线从大到小顺序处理扫描线时,该边在该扫描max
线第一次出现。我们把这样的表称为Y桶表。
例如,图3的多边形可以产生以下的Y桶表。
Ymax
8 PP PP 4543
7 PPP P 6165
3 PP 32
2 PP 12
图4 : Y桶表
三(数据结构
/*多边形边表*/
typedef struct LINE{
int y; /*边所交的最高扫描线号(顶点的最大y值)*/ double x; /*当前扫描线与边的交点x值*/
double dx; /*从当前扫描线到下一扫描线之间的x增量*/ int dy; /*边的两个顶点的y差值>=0*/
struct LINE *next; /*下一条边*/
}LINE;
/*Y桶表*/
typedef struct Y_TUB{
int y; /*该桶最大值*/
struct Y_TUB *next; /*下一桶*/
struct LINE *line; /*该桶的边表*/
}Y_TUB;
/*活性边表*/
typedef struct EXP_LINE{
int y; /*当前扫描线*/
struct LINE *line; /*活性边*/
}EXP_LINE;
四(算法步骤
1( 首先生成如图4的多边形Y桶表
2( 取Y桶的Y值最大的一桶(或第一桶)的边表作为活性边表。取该桶的Y为maxmax
第一条扫描线。
3( 清除活性边表中的水平线(水平边出链)及dy=0的边。 4( 计算出交点序列,并按点列x坐标递增重排点列,由点列中奇数点依次连线到偶数点(如1-2,3-4,5-6 …),即可填充该扫描线所在行。注意在连线填充时,最右边
一点不要填充,以达到左闭右开的结果。
5( 扫描线下移,即y=y-1;
6( 修改当前活性边表,如果下一桶存在并且y值等于下一桶的Y,则在活性边表后加max
入下一桶的边表(下一桶边表入链)。
7( 重复3-6步,直到当前活性边表为空。
(注:该算法由于最后一条扫描线使活性边的dy=0而不处理,这就产生了上闭下开的结果)