基於集合的種子填充演算法
阿新 • • 發佈:2019-01-08
通過實踐,我們不難發現,基礎的種子填充演算法根本沒法使用。常常遇到的問題是: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; } };
下面的執行結果,效果還是不錯的。只是在填充較大面積區域時仍然十分緩慢。