矢量数据栅格化
李泉 陈玉进(南京跬步科技有限公司http://www.creable.cn )
在计算机绘制图形过程中,除了需要绘制出多边形的轮廓线之外,有时还希望用某种色彩来填充图形的内部,以使得图形具有明暗自然、色彩丰富以及形象逼真,从而生动直观。这里需要采用多边形栅格化的理论对多边形进行填充。
所谓多边形填充,就是在绘制多边形边界线之后,要对多边形内部象素点进行色彩赋值。实现多边形内部填充的最简单方法是在一个区域内对所有点进行判别,即逐个象素点判别其是否在多边形内部,这样来确定位于多边形内部的象素点的集合。逐点判别方法虽然简单,但不可取,主要原因是速度太慢。常用算法是扫描线算法。
扫描线算法
扫描线算法充分利用了扫描线连贯性原理,避免了针对象素点的逐点判别,有效地选择象素点来进行多边形的填充。
算法的基本思想是:对于一个给定的多边形,用一组水平或者垂直的扫描线进行扫描,对没一条扫描线均可求出与多边形的交点,这些交点将扫描线分割成落在多边形内部的线段和落在多边形外部的线段,并且二者相间排列。于是,将落在多边形内部的线段上的所有象素点赋予给定的色彩值。可见,算法中不需要检验每一个象素点,而只考虑与多边形边相交的交点分割后的扫描线段。
图1左图所示多边形,在经过扫描线扫描之后即可完成栅格化,并借此可以填充该多边形的内部。下面介绍这种算法如何实现(采用活化边表和横向扫描的方式)。
数据结构设计:
public class Node
{
int Ymin;
float Xs;
float xx;
Node next;
}
Node类用来描述活化边表中的节点(此节点一般是扫描线与多边形的交点),其中Ymin表示该节点的y坐标,Xs表示该节点的x坐标,xx表示一个用于推算x坐标的系数,next表示该节点的下一个节点的引用,用于形成一个单向链表结构。
class NodeY // Y 桶表
{
Node link;
}
NodeY类表示一个Y桶,用来存放扫描线Y上的节点链表。
public class Table
{
int Ys,Ye;
NodeY[] nodeY;
Table(int Ys,int Ye)
{
nodeY=new NodeY[Ye-Ys+1];
for (int i=Ys;i<=Ye;i++) nodeY[i-Ys]=new NodeY();
this.Ys=Ys;
this.Ye=Ye;
}
}
Table类表示活化边表,其中Ys和Ye分别表示经过该多边形的扫描线的最小y值和最大y值,nodeY数组表示若干个Y桶,每个Y桶中按照x坐标存放节点的引用。
算法实施步骤:
① 根据多边形的节点坐标数据生成一个边表。
② 利用步骤1生成的边表来生成具有交点信息的交点表。计算每条穿过多边形的扫描线与多边形交点的x坐标(y坐标就是扫描线y值)。这个过程中需要根据x坐标升序排序。本文实现方法采用链表形式,每次插入一个节点到链表中时都保持链表的按照x坐标升序这一原则,故不用再排序。
③ 按照扫描线顺序,一条一条的得到栅格结果(此时也可以画线,以达到填充多边形内部的目的)。连接节点的原则是:1号点连上2号点、3号点连上4号点,依此类推。