多边形填充算法之扫描线填充算法
多边形填充可以是凸多边形、凹多边形、或者是可以是带孔的多边形。扫描线填充算法是一种常用的填充算法。
1. 多边形填充过程一般可以分为四个步骤
(1)求交:计算扫描线与多边形各边的交点;
(2)排序:把所有交点按照递增的顺序进行排序;
(3)交点配对:1与2, 3与4等配对处理,每对代表扫描线与多边形的一个相交的区间;
(4)区间填充:把这些相交的区间内的像素设置成多边形颜色,填充区间之外的像素设置背景色。
2. 需要解决的问题
(1)扫描线与多边形相交时,交点的取舍问题;
(2)多边形边界的像素取舍问题。
3. 问题解决
(1) 扫描线交于多变型的顶点时,根据顶点的对应的两条边的另一个顶点的位置来判断取舍。
① 如果另外两个顶点都高于扫描线,则取这个顶点算取2次,即此顶点可以填充,已经作为填充区间;
② 如果另外两个顶点都低于扫描线,则这个交点算取0个,即此顶点不进行填充;
③ 如果另外两个顶点一个在扫描线之上,另一个在扫描线之下,则这个交点算取1次,需要与另一个交点进行配对组成填充区间。
(2) 多边形填充区间的边界取舍问题:遵循“左下闭,右上开”的原则,来避免填充区域扩大的问题。
即落在左下边界的像素进行填充,而落在右上的像素不进行填充,简单解释就是,如果扫描线交点是1和9,则实际填充的区间是[1,9),即不包括x坐标是9的那个点。
具体实现时,对扫描线取左闭右开。
由以上两个策略,综合效果是实现“左下闭,右上开”。
4. 填充算法的4个中的问题
了解几个“连贯性”的概念:
“边的连贯性”:多边形与扫描线相交的边,在一定的范围内,相交的边保持一定的不变性,也可以理解为,当一条便于当前扫描新相交时,其也可能与下一条扫描线相交;
“扫描线的连贯性”:扫描线与多边形相交的交点,由于其连贯性,新的交点序列与之前的交点序列(交点的排序)基本保持一致,最多有几个个别的交点的位置需要调整,整体上都是按照交点X值得递增的顺序排列,在程序实现上,可以借助这个特定实现排序效率的提高;
“扫描区间的连贯性”:对确定好的扫描线的填充区间,即区间内的开始点X值到区间结束X值,同一区间上的像素填充颜色相同。可以直接绘制一条区间内的填充色的线段,提高渲染效率。
(1)求扫描线与多边形的求交运算问题,如果扫描线分别对所有的边进行求交判定,这样处理效率非常低,其中大量的判定计算都是徒劳的;
为了提高求交运算的效率,设定“AET活性边界表”。
“AET活性边表”:把于扫描线相交的边称为活性边,并把他们按照与扫描线交点的X坐标递增的顺序放在一个链表中,这样的链表称为“AET(Active Edge Table)活性边表”。
活性编标的
(2)
5. 算法步骤
1 算法过程: 2 void polyfill (polygon, color) 3 int color;多边形 polygon; 4 { 5 for (各条扫描线i ) 6 { 初始化新边表头指针NET [i]; 7 把y min = i 的边放进边表NET [i]; 8 } 9 y = 最低扫描线号; 10 初始化活性边表AET为空; 11 for (各条扫描线i ) 12 { 把新边表NET[i]中的边结点用插入排序法插入AET表,使之按x坐标递增顺序排列; 13 遍历AET表,把配对交点区间(左闭右开)上的象素(x, y), 14 用drawpixel (x, y, color) 改写象素颜色值; 15 遍历AET表,把ymax= i 的结点从AET表中删除,并把ymax > i结点的x值递增Dx; 16 若允许多边形的边自相交,则用冒泡排序法对AET表重新排序; 17 } 18 } /* polyfill */
注意问题
(1)初始化新边表数组时,各个数据项中的节点按照X递增的顺序排列;
()
()把判定如有新的表插入时,则将新的列表中的节点,通过“插入排序”进行插入操作;
()
由以上