算法系列之十二:多边形区域填充算法--扫描线填充算法(有序边表法)

本文介绍了扫描线算法在矢量图形区域填充中的应用,特别是针对计算机自动图形处理,如游戏和CAD软件。扫描线算法通过求交、排序、填充和判断扫描线完成来实现,关键在于维护活动边表。算法处理顶点特殊情况,如左顶点和右顶点的修正,以及处理水平边和避免填充越过边界。整个算法的核心是活动边表的管理和更新。
摘要由CSDN通过智能技术生成
 

二、扫描线算法(Scan-Line Filling)

        扫描线算法适合对矢量图形进行区域填充,只需要直到多边形区域的几何位置,不需要指定种子点,适合计算机自动进行图形处理的场合使用,比如电脑游戏和三维CAD软件的渲染等等。

        对矢量多边形区域填充,算法核心还是求交。《计算几何与图形学有关的几种常用算法》一文给出了判断点与多边形关系的算法――扫描交点的奇偶数判断算法,利用此算法可以判断一个点是否在多边形内,也就是是否需要填充,但是实际工程中使用的填充算法都是只使用求交的思想,并不直接使用这种求交算法。究其原因,除了算法效率问题之外,还存在一个光栅图形设备和矢量之间的转换问题。比如某个点位于非常靠近边界的临界位置,用矢量算法判断这个点应该是在多边形内,但是光栅化后,这个点在光栅图形设备上看就有可能是在多边形外边(矢量点没有大小概念,光栅图形设备的点有大小概念),因此,适用于矢量图形的填充算法必须适应光栅图形设备。

 

2.1扫描线算法的基本思想

        扫描线填充算法的基本思想是:用水平扫描线从上到下(或从下到上)扫描由多条首尾相连的线段构成的多边形,每根扫描线与多边形的某些边产生一系列交点。将这些交点按照x坐标排序,将排序后的点两两成对,作为线段的两个端点,以所填的颜色画水平直线。多边形被扫描完毕后,颜色填充也就完成了。扫描线填充算法也可以归纳为以下4个步骤:

 

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

(2)       交点排序,对第2步得到的交点按照x值从小到大进行排序;

(3)       颜色填充,对排序后的交点两两组成一个水平线段,以画线段的方式进行颜色填充;

(4)       是否完成多边形扫描?如果是就结束算法,如果不是就改变扫描线,然后转第1步继续处理;

 

        整个算法的关键是第1步,需要用尽量少的计算量求出交点,还要考虑交点是线段端点的特殊情况,最后,交点的步进计算最好是整数,便于光栅设备输出显示。

        对于每一条扫描线,如果每次都按照正常的线段求交算法进行计算,则计算量大,而且效率底下,如图(6)所示:

图(6) 多边形与扫描线示意图

 

观察多边形与扫描线的交点情况,可以得到以下两个特点:

 

(1)       每次只有相关的几条边可能与扫描线有交点,不必对所有的边进行求交计算;

(2)       相邻的扫描线与同一直线段的交点存在步进关系,这个关系与直线段所在直线的斜率有关;

 

        第一个特点是显而易见的,为了减少计算量,扫描线算法需要维护一张由“活动边”组成的表,称为“活动边表(AET)”。例如扫描线4的“活动边表”由P1P2和P3P4两条边组成,而扫描线7的“活动边表”由P1P2、P6P1、P5P6和P4P5四条边组成。

        第二个特点可以进一步证明,假设当前扫描线与多边形的某一条边的交点已经通过直线段求交算法计算出来,得到交点的坐标为(x, y),则下一条扫描线与这条边的交点不需要再求交计算,通过步进关系可以直接得到新交点坐标为(x + △x, y + 1)。前面提到过,步进关系△x是个常量,与直线的斜率有关,下面就来推导这个△x。

        假设多边形某条边所在的直线方程是:ax + by + c = 0,扫描线yi和下一条扫描线yi+1与该边的两个交点分别是(xi,yi)和(xi+1,yi+1),则可得到以下两个等式:

 

axi + byi + c = 0                        (等式 1)

axi+1 + byi+1 + c = 0                     (等式 2)

 

由等式1可以得到等式3:

 

xi = -(byi + c) / a                           (等式 3)

 

同样,由等式2可以得到等式4:

 

xi+1 = -(byi+1 + c) / a                      (等式 4)

 

由等式 4 – 等式3可得到

 

xi+1 – xi = -b (yi+1 - yi) / a

 

由于扫描线存在yi+1 = yi + 1的关系,将代入上式即可得到:

 

xi+1 – xi = -b / a

 

即△x = -b / a,是个常量(直线斜率的倒数)。

 

        “活动边表”是扫描线填充算法的核心,整个算法都是围绕者这张表进行处理的。要完整的定义“活动边表”,需要先定义边的数据结构。每条边都和扫描线有个交点,扫描线填充算法只关注交点的x坐标。每当处理下一条扫描线时,根据△x直接计算出新扫描线与边的交点x坐标,可以避免复杂的求交计算。一条边不会一直待在“活动边表”中,当扫描线与之没有交点时,要将其从“活动边表”中删除,判断是否有交点的依据就是看扫描线y是否大于这条边两个端点的y坐标值,为此,需要记录边的y坐标的最大值。根据以上分析,边的数据结构可以定义如下:

65 typedef struct tagEDGE

66 {

67     double xi;

68     double dx;

69     int ymax;

74 }EDGE;

 根据EDGE的定义,扫描线4和扫描线7的“活动边表”就分别如图(7)和图(8)所示:

 

  • 58
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 28
    评论
多边形扫描线填充算法是一种基于扫描线算法,主要用于将一个封闭的多边形区域进行填充有序边表法多边形扫描线填充算法的一种实现方式。 有序边表法的基本思路是将多边形区域分割成若干条水平的线段,并将这些线段按照从上到下的顺序排序,形成有序边表。然后,从上到下扫描每条扫描线,将扫描线多边形边界相交的线段加入活动边表。对于每条扫描线,从左到右依次处理活动边表中的线段,根据线段的左右端点的交点来确定需要填充的区域。 具体实现时,我们可以使用一个数组来维护有序边表和活动边表。每个元素存储一条线段的信息,如线段的上端点、下端点、斜率等。在扫描线过程中,我们需要动态地更新有序边表和活动边表,以便能够正确地计算出需要填充的像素区域。 以下是基于有序边表法多边形扫描线填充算法的主要步骤: 1. 将多边形的边按照从上到下的顺序排序,形成有序边表。 2. 初始化活动边表为空。 3. 从上到下扫描每条扫描线。对于每条扫描线,从左到右处理活动边表中的线段,根据线段的左右端点的交点来确定需要填充的区域,并将填充的像素标记为已填充。 4. 对于每个顶点,将其左侧的线段加入活动边表,将其右侧的线段从活动边表中删除。 5. 如果当前扫描线与某条边界线段相交,则根据相交点的位置来判断是否需要将该线段加入或删除活动边表。 6. 重复步骤3~5,直到扫描完整个多边形区域。 总的来说,有序边表法是一种比较简单易懂的多边形扫描线填充算法,但由于需要维护有序边表和活动边表,算法效率较低,不适用于处理大规模的多边形区域。
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吹泡泡的小猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值