In this semester, we learned the basic content of computational geometry, in-depth learning after class I found that computational geometry is only an important branch of the algorithm world-computer graphics, one of the fundamental part of computer graphics there are many other very interesting algorithms, such as line generation, circle generation, ellipse generation. In the course of implementing Java project in this semester, I also encountered a problem which is closely related to computer graphics, that is, how to implement the tool paint bucket of Windows own drawing software? The open source drawing code on the Web basically only implements other simple drawing tools. To this end, after consulting a large number of relevant data, I learned that the seed filling algorithm can be a good way to achieve the polygon area fill, and the best effect of the stack-based scan line seed filling algorithm to achieve the paint bucket tool in the artboard. Find a specific algorithm, understand the principle and write out the program code of the algorithm, in this process, I deeply understand the algorithm everywhere, also deeply feel the fun of the algorithm, feel the sense of accomplishment after solving the problem with the algorithm.
In this paper, the principle of the algorithm is introduced, and the common seed filling algorithm for non-vector graphics area filling is divided into several types, such as filling algorithm (Flood fill algorithm) and boundary filling algorithm according to the definition of image region boundary and the method of color modification of the point (boundary fill Algorithm). The core of both is recursive plus search, that is, starting from the specified seed point, up, down, left, right, top left, left, right, and bottom right all eight directions to the search, pixel-by-bit processing, until the boundary encountered. The difference between the two is that flood fill algorithm does not emphasize the boundary of the region, it just starts at the specified position, replacing the point of a specified color in all the unicom areas with another color, that is, the function of color substitution, and the boundary filling algorithm is not the same as the end condition of recursion of the injection filling algorithm. Boundary Fill algorithm emphasizes the existence of boundaries, as long as the points within the boundary, regardless of the color, are replaced by the specified color. The tool "Paint bucket" in paint software should belong to the latter case.
But in the actual project, the use of recursive algorithm is too inefficient, in order to eliminate recursion, there is a more commonly used improved algorithm, that is, the scanning line seed filling algorithm. It fills the pixel segment along the vertical scan line and handles the neighboring points of 8-unicom over a period of time, so that only the starting point position of each vertical pixel segment is pressed into a special stack in the process of the algorithm, instead of pressing all adjacent points that have not been processed around the current position to the stack like a recursive algorithm. Thus, the stack space is saved, and the algorithm of the seed filling of the scan line with the boundary filling algorithm is used in this example. The specific steps of the algorithm are:
(1) Initialize an empty stack to hold the seed point, and the seed point (x, y) into the stack;
(2) Determine whether the stack is empty, if the stack is empty to end the algorithm, otherwise remove the top element of the stack as the current scan line seed point (x, y), X is the current scan line;
(3) from the seed point (x, y), fill the current scan line up and down two directions, until the boundary. The upper and lower point coordinates of the marked section are yup and Ydown respectively.
(4) respectively check the x-1 and X + 12 scan lines adjacent to the current scan line (that is, the left and right two scan lines connected to this section) in the interval [yUp, ydown] pixels, starting from yUp to Ydown direction search, if there are non-boundary and unfilled pixels, Then find the bottom one of these adjacent pixels and press it into the stack as a seed point and return to step (2).
One of the more difficult questions to understand in step (4) is why only the pixels in the interval [YUp, Ydown] are checked when the left and right two scan lines connected to the current section are checked? What if the actual range of the new scan line is larger or even discontinuous than this interval? I did not find a rigorous proof-of-process, but it can be understood by a relevant example:
Note that this example is a horizontal scan of pixel points, and after the current scan is over, scan with its adjacent top and bottom two scan lines, the rest of the principle is exactly the same. Assuming that the current algorithm has finished processing the 5th line of the yellow dot in the 3rd step, the interval [7, 9] is determined.
The adjacent 4th row, although the actual range is larger than the interval [7, 9], but because of the (4, 6) boundary point obstruction, after determining the seed point (4, 9) (note that the above algorithm step is to take the rightmost point), the left padding can only fill the right of the 7th column to the area between column 10th, The area between the 3rd and 5th columns on the left is not populated. However, if the 3rd line is finished, the left part of Line 4th is the next row in line 3rd, and the opportunity to scan again is obtained. The 3rd line of the interval is [3, 9], to the left across the 6th column of this barrier point, the 2nd scan of the 4th line starts from the 3rd column, to the right to determine the seed point (4, 5). So the 4th line has two seed points that can be filled in completely. Thus, for the row with a barrier point, through the adjacent edge of the relationship, you can cross the barrier point, through multiple scans to get a complete fill.
Most classes of the program are code that implements the artboard user interface and other basic tools, and the scan line seed algorithm that implements the area fill has only one Seedfillalgorithm class:
Public voidSeedfillscanlinewithstack (intXintYintNewcolor,intOldcolor) { if(Oldcolor = =Newcolor) { return; } emptystack (); intY1; BooleanSpanleft, Spanright; Push (x, y);//seed point into the stack while(true) { //take the current seed pointx =popx (); if(x = =-1)return; Y=Popy (); Y1=y; while(y1 >= 0 && getColor (x, y1) = = Oldcolor) y1--;//find the top of the area to filly1++;//populate from starting pixel pointSpanleft = Spanright =false; while(Y1 < height && getColor (x, y1) = =Oldcolor) {setcolor (x, y1, newcolor);//check adjacent left scan lines if(!spanleft && x > 0 && getColor (x-1, y1) = =Oldcolor) {Push (x-1, y1); Spanleft=true; } Else if(spanleft && x > 0 && getColor (x-1, y1)! =Oldcolor) {Spanleft=false; } //check adjacent right scan lines if(!spanright && x < width-1 && GetColor (x + 1, y1) = =Oldcolor) {Push (x+ 1, y1); Spanright=true; } Else if(Spanright && x < width-1 && GetColor (x + 1, y1)! =Oldcolor) {Spanright=false; } y1++; } } }
// The Paint Bucket tool can be implemented by invoking the seed fill algorithm in the drawing class if (painter.drawmethod==11) { seedfillalgorithm FFA; New Seedfillalgorithm (bufimg); Ffa.seedfillscanlinewithstack (x1,y1,new Color (COLORPANEL.IIR,COLORPANEL.IIG,COLORPANEL.IIB). getRGB (), Ffa.getcolor (x1, y1)); Ffa.updateresult (); Repaint ();}
Realization of polygon area filling based on scanning seed line algorithm