图形学算法——图形的颜色填充算法


一、有序边表填充算法(扫描线)

1、算法思想

简单的来说,就是计算出屏幕上有哪些像素点是在多边形内部的,重复利用多变形内部区域的连续性。算出每一条水平线上有哪些点是在该多边形内的,然后改变这些点的像素值。如图所示:

2、算法步骤

a、确定多边形顶点的最小和最大y值(ymin和ymax)。

b、从y=ymin到y=ymax,每次用一条扫描线进行填充。

c、对一条扫描线填充的过程可分为三个步骤:

(1)求交(能否只对有效边求交?)

有效边(ActiveEdge):与当前扫描线相交的多边形边。

(2)按交点的x坐标排序(有序链表)

有效边表->有序的有效边表

(3)交点配对,区间填色

二、边填充算法

1、算法思想

利用异或运算,反复填充水平线:

对于多变形边上的每一个点,都以改点为初始点,向右画水平线,水平线的颜色就是所要填充的颜色。根据上一篇博文《点与多边形的关系》中的原理,我们知道处于多边形内部的区域会被水平线画到奇数次,而处于多边形外部的区域会被画到偶数次,由于采用的是异或画法,所以奇数部分的颜色会被保存下来,而偶数部分的颜色会被清除。即多边形内部会被填充颜色。

2、算法步骤

a、选择多边形的一条边,计算出其处于上方的点up和处于下方的点down,并且计算该条边的斜率K

b、根据斜率K,遍历直线上的所有点,对于直线上的每一个点,向右画出水平线,用指定的颜色填充。

c、重复以上步骤直到所有的边都已经被处理过了。

3、评价

该算法实现起来非常的简单,而且适用范围广,凸、凹多边形,甚至可以带孔的多边形都可以用来填色。

同时,确定很明显,它需要大量的重复运算,效率不高。

三、种子填充算法

1、算法思想

在多边形内部指定一个种子点,从这个点开始,向四周蔓延填色,直到碰到边界。

多边形内部的每一个像素点看成图中一个节点,每个节点只与自己上下左右的四个像素点有边相连,这样,多边形的填色问题就演变成了一个图的遍历问题。自然而然地我们就想到了图论中的深度遍历和广度遍历。

2、算法步骤

这个算法有多种实现方法,其中最常见的就是深度遍历和广度遍历。分别对应着栈和堆的特性。这里我就再多说了。直接给出代码:

void CTestView::Fill(CDC*pDC, POINT Seed,
                                  COLORREF BoundaryColor,
                                  COLORREF FillColor)
{
     queue Q;
     int maxsize=0;    // 队列的最大长度
     Q.push(Seed);
     while(Q.size()>0)
  {
    POINT p=Q.front();    Q.pop();
    COLORREF pColor=pDC->GetPixel(p); // 当前点像素色
   if(pColor==FillColor||pColor==BoundaryColor)  continue;
    pDC->SetPixel(p,FillColor); // 填色
    POINT ps[4]={{p.x-1,p.y},{p.x+1,p.y},   // 左右邻接点
                          {p.x,p.y+1},{p.x,p.y-1}};  // 上下邻接点
    for(int i=0; i<4; i++)
     { pColor=pDC->GetPixel(ps[i]);
      if(pColor!=BoundaryColor &&pColor!=FillColor)
             Q.push(ps[i]);
     }
  }
}
作者博客: 点击打开链接


你可能感兴趣的:(算法,图形学)