通过实践,我们不难发现,基础的种子填充算法根本没法使用。常常遇到的问题是:Stack Overflow (栈溢出)。
一种可行的解决办法是通过自己构建数据结构栈来将递归算法改非递归算法,但是实践的运行结果还是极其缓慢。
现在通过使用集合来优化这个算法,虽然效率仍然不理想,但还是有一定现实意义:给学习图形学的学生们一个练习的机会。
下面,我将使用四连通区域的种子填充算法进行展现。核心代码如下:
void fillArea(int x, int y)
{
COLORREF color = getpixel(x, y); //获取替换颜色
COLORREF paintColor = getfillcolor(); //获取填充颜色
set<Point> mySet;
mySet.insert(Point(x, y));
while (!mySet.empty())
{
Point node = *(mySet.begin());
if (node.x < 0 || node.x >= 640 || node.y < 0 || node.y >= 480)
{
mySet.erase(node);
continue; //限制边界
}
//后继
COLORREF colorT = getpixel(node.x, node.y - 1);
COLORREF colorB = getpixel(node.x, node.y + 1);
COLORREF colorL = getpixel(node.x - 1, node.y);
COLORREF colorR = getpixel(node.x + 1, node.y);
Point T = Point(node.x, node.y - 1);
Point B = Point(node.x, node.y + 1);
Point L = Point(node.x - 1, node.y);
Point R = Point(node.x + 1, node.y);
if (colorT !=paintColor && colorT == color && mySet.find(T) == mySet.end())
{
mySet.insert(T);
}
if (colorB != paintColor && colorB == color && mySet.find(B) == mySet.end())
{
mySet.insert(B);
}
if (colorL != paintColor && colorL == color && mySet.find(L) == mySet.end())
{
mySet.insert(L);
}
if (colorR != paintColor && colorR == color && mySet.find(R) == mySet.end())
{
mySet.insert(R);
}
//消已
putpixel(node.x, node.y, getfillcolor());
mySet.erase(node);
}
}
其中,点类(Point)是我自己写的一个类。由于集合的内容不能重复,因素必须重载 <
运算符才能使用。
struct Point
{
int x;
int y;
Point(int x = 0, int y = 0)
{
this->x = x;
this->y = y;
}
bool operator < (const Point& point) const
{
//x值小的点我们认为是较小的点,如果x值相同,则比较y值。
bool flag;
if (x < point.x)
{
flag = true;
}
else if(x > point.x)
{
flag = false;
}
else
{
if (y < point.y)
{
flag = true;
}
else
{
flag = false;
}
}
return flag;
}
};
下面的运行结果,效果还是不错的。只是在填充较大面积区域时仍然十分缓慢。