学习计算机图形学,老师留给我的一个作业:实现种子填充算法。
之前按书上讲的的种子填充(先填充一个点,再扫描这个种子点的4个方向的点,判断填充,然后递归),这种
在数学上是可行的方法,在实现中却有了问题,就是填充区过大的话,回使程序停止,问了CSDN上的朋友,说是递归过深。
书上还有一种方法是线性扫描的方法来实现填充,我看了下,蛮复杂的(不要砸我)。于是想了半天,就用两种方法结合起来试试。
方法如下:
用户在窗口客户区点击鼠标,将些时获得鼠标的坐标做为种子点,调用填充算法,实现填充。
种子填充算法:
(1)得到种子点后,如果种子点为旧色,则将这一点设为新色,并向右填充至边界(xmax)。些时效果如下:
(2) 然后从种子点向左填充,至边界(xmin)。效果如下:
(3)扫描这条线的上面和下面的点,如果有旧色,则将旧色做为新的种子点,递归调用自己,重复(1)、(2),直至填充完成。
实现如下:
void CGraphfillView::floodefill(int x, int y, int oldcolor, int
newcolor)
... { CDC* pDC=GetDC();
int xmax,xmin,yy1,yy2;
xmax=x;xmin=x;yy1=y;yy2=y;
//CDC* pDC;
if(pDC->GetPixel(x,y)==oldcolor)
...{
while(pDC->GetPixel(x,y)==oldcolor)
...{
pDC->SetPixel(x,y,newcolor);
x++;
}
xmax=x;
x=xmin-1;
while(pDC->GetPixel(x,y)==oldcolor)
...{
pDC->SetPixel(x,y,newcolor);
x--;
};
xmin=x+1;
for(int i=xmin;i<xmax;i++)
...{
if(pDC->GetPixel(i,y+1)==oldcolor)
floodefill(i,y+1,oldcolor,newcolor);
if(pDC->GetPixel(i,y-1)==oldcolor)
floodefill(i,y-1,oldcolor,newcolor);
}
}
}
... { CDC* pDC=GetDC();
int xmax,xmin,yy1,yy2;
xmax=x;xmin=x;yy1=y;yy2=y;
//CDC* pDC;
if(pDC->GetPixel(x,y)==oldcolor)
...{
while(pDC->GetPixel(x,y)==oldcolor)
...{
pDC->SetPixel(x,y,newcolor);
x++;
}
xmax=x;
x=xmin-1;
while(pDC->GetPixel(x,y)==oldcolor)
...{
pDC->SetPixel(x,y,newcolor);
x--;
};
xmin=x+1;
for(int i=xmin;i<xmax;i++)
...{
if(pDC->GetPixel(i,y+1)==oldcolor)
floodefill(i,y+1,oldcolor,newcolor);
if(pDC->GetPixel(i,y-1)==oldcolor)
floodefill(i,y-1,oldcolor,newcolor);
}
}
}
效果如下: