Graphical progressive fill

Siarhei Siamashka siarhei.siamashka at gmail.com
Mon Dec 12 04:49:09 UTC 2022


On Sunday, 11 December 2022 at 06:50:44 UTC, Joel wrote:
> I've been trying to fill in areas with a colour but can't work 
> it out. I want something like the effect where it fills with 
> diamonds. Not all at once but building up in the main program 
> loop.

I'm not sure if I understood the question correctly, but maybe 
https://en.wikipedia.org/wiki/Breadth-first_search approach will 
do the job?

Basically have a queue for point coordinates. Add your starting 
point to it (or multiple starting points). In a loop keep 
extracting points from the front of the queue, paint this point 
with a color and add non-painted neighbors of this point to the 
end of the queue. Keep going until the queue is empty.

Example:
```D
import std;

const width = 78;
const height = 10;
const number_of_starting_points = 5;

struct point { int x, y; }

void show_grid(char[][] grid) {
   foreach (ref row ; grid)
     writeln(row);
   writeln;
}

void animated_fill(char[][] grid, point[] starting_points) {
   auto height = grid.length;
   if (height == 0)
     return;
   auto width = grid[0].length;

   struct xpoint { int x, y, dist_from_start; }

   DList!xpoint queue;
   foreach (p ; starting_points)
     queue.insertBack(xpoint(p.x, p.y, 0));

   int current_dist = 0;
   while (!queue.empty) {
       auto p = queue.front;
       queue.removeFront;

       if (grid[p.y][p.x] != '.')
         continue; // only fill the dots

       if (p.dist_from_start > current_dist) {
         show_grid(grid);
         current_dist = p.dist_from_start;
       }

       grid[p.y][p.x] = '#';

       if (p.y + 1 < height)
         queue.insertBack(xpoint(p.x, p.y + 1, p.dist_from_start + 
1));
       if (p.y - 1 >= 0)
         queue.insertBack(xpoint(p.x, p.y - 1, p.dist_from_start + 
1));
       if (p.x + 1 < width)
         queue.insertBack(xpoint(p.x + 1, p.y, p.dist_from_start + 
1));
       if (p.x - 1 >= 0)
         queue.insertBack(xpoint(p.x - 1, p.y, p.dist_from_start + 
1));
   }
   show_grid(grid);
}

void main() {
   auto grid = new char[][](height, width);
   foreach (ref row ; grid)
     row[] = '.';

   auto random_points = new point[](number_of_starting_points);
   foreach (ref p ; random_points)
     p = point(uniform(0, width), uniform(0, height));

   animated_fill(grid, random_points);
}
```

Instead of a slow DList, it's also possible to just use a regular 
static array and two indexes for the start and the end of the 
queue. With a good implementation of BFS, this array won't need 
to store more than `grid_width * grid_height` elements. My 
implementation isn't a good one, but can be improved to do it.


More information about the Digitalmars-d-learn mailing list