多边形的扫描转换和区域填充这个问题是怎么样在离散的像素集上表示一个连续的二维图形?
多边形有两种重要的表示方法:顶点表示和点阵表示。
顶点表示
顶点表示是用多边形的顶点序列来表示多边形。
优点:这种表示直观、几何意义强。占内存少、易于进行几何变化
缺点:但由于它没有明确指出哪些像素在多边形内,故不能直接用于面着色
点阵表示
点阵表示是用位于多边形内的像素几何来刻画多边形。
这种表示丢失了许多几何信息(如边界、顶点等),但它却是光栅显示系统时所需的表示形式。
这涉及到两个问题:1)如果知道边界,能否求出哪些像素在多边形内?(可以)
2)知道多边形内部的像素,反过来如何求出边界?(不行)
计算机图形学解决的是第一个问题,也就是光栅图形学的一个基本问题:把多边形的顶点表示转化为点阵表示。这种转换称为多边形的扫描转换。
现在的问题是,知道多边形的边界,如何找到多边形内部的点,即把多边形内部填上颜色。
多边形分为凸多边形(任意两顶点间的连线均在多边形内)、凹多边形(任意两顶点间的连线有不在多边形内的)和含内环的多边形等。多边形的扫描转换和区域填充是研究怎么样在离散的像素集上表示一个连续的二维图形。
X—扫描线算法
X—扫描线算法的基本思想是按扫描线的顺序,计算扫描线与多边形的相交区间,再用要求的颜色显示这些区间的像素,即完成填充工作。算法步骤如下:
1)确定多边形所占有的最大扫描线数,得到多边形顶点的最小和最大y值(ymin和ymax);
2)从 y = ymin 到 y = ymax,每次用一条扫描线进行填充;
3)对每一条扫描线填充的过程可分为四个步骤:
当扫描线与多边形顶点相交时,要考虑交点的取舍问题。
解决方案:若共享顶点的两条边分别落在扫描线的两边,交点只能算一个;若共享顶点的两条边在扫描线的同一边,这时交点作为零或两个,检查共享顶点的两条边的两外两个端点的y值,按这两个y值中大于交点y值的个数来决定交点数。如上图:点(1,7)交点算一个;点(3,1)和点(8,1)算两个;点(6,5)算零个。
以上的算法效率非常低,因为需要大量的求交运算,而求交运算是非常可怕的。
因此需要对以上算法进行改进,想办法不进行求交运算。可以从以下三个方面考虑加以改进:
1)在处理一条扫描线时,仅对与它相交的多边形的边(有效边)进行求交运算。下图中有效边为:P1P4和P2P3
2)考虑扫描线的连贯性,即当前扫描线与各边的交点顺序与下一条扫描线与各边的交点顺序可能相同或非常相似。
3)最后考虑多边形的连贯性,即当某条边y与当前扫描线相交时,它很可能也与下一条扫描线相交。为了避免求交运算,我们需要引进一套数据结构。
该数据结构包括以下几个部分:
1)活性边表(AET):把当前与扫描线相交的边称为活性边,并把他们按照与扫描线交点x坐标递增的顺序存放在一个链表中。
2)结点内容:x(当前扫描线与边交点的横坐标),▲x(从当前扫描线到下一条扫描线间x的增量),ymax(该条边上最大的y值,通过它判断该条线还是不是活性边)。容易知道▲x的值为1/k,其中k为直线斜率。
为了方便活性边表的建立与更新,还需要构造一个新边表(NET),用来存放多边形的边的信息,分为2个步骤:
1)首先构造一个纵向链表,链表的长度为多边形所占有的最大扫描线数,链表的每个结点,称为一个吊桶,对应多边形覆盖的每一条扫描线。
2)NET挂在与该边低端y值相同的扫描线桶中。结点中包含的信息有:该边的ymax、该边较低点的x坐标值xmin、1/k以及指向下个结点的指针。
这里只叙述原理,具体算法不再详述。
基于X扫描的思想,还有改进的边标记算法和Y向连贯性算法。这里不再详述。
区域是指已经表示成点阵形式的填充图形,是像素的集合。
区域填充是指将区域内的一点(常称种子点)赋予给定的颜色,然后将这种颜色扩展到整个区域的过程。
区域填充算法要求区域是联通的,因为只有在联通的区域中,才能将种子点的颜色扩展到区域内的其他点,区域可以分为4向联通区域和8向联通区域。
下图显示了,同一区域使用4连通和8连通算法填充的差别:
下面介绍4连通边界填充算法:
算法输入:种子点坐标(x,y),填充色和边界颜色。
数据结构:栈结构
算法输出:最佳逼近的像素点集
算法步骤:
种子象素入栈,栈非空时重复执行三步操作:
(1)栈顶象素出栈;
(2)将出栈象素置成填充色;
(3)检查出栈象素的4-邻接点,若其中某个象素点 丌是边界色且未置成多边形色,则把该象素入栈。