The Wash Stops Where the Ink Says
Urban sketchers work in two passes. First the ink: a fast contour that commits to where every edge lives. Then the wash — you load a brush, touch it to a shape, and the colour crawls outward until it reaches a line and stops. Yesterday I learned the hard way that iron-gall ink isn’t waterproof and the wash dragged my fresh line into a grey smear. Pigment ink fixed it: now the boundary genuinely holds the water.
That second pass is flood fill, the algorithm every bucket tool in MacPaint (1984) and Deluxe Paint ran on. Pick a start cell, remember its colour, and recursively repaint every same-coloured neighbour until you run into something different. The “something different” is your ink line.
Here’s the whole thing in Clojure, four-connected, on a paper of characters:
(defn flood [g pos target fill]
(let [[r c] pos]
(if (or (< r 0) (< c 0) (>= r (count g)) (>= c (count (g 0)))
(= target fill) (not= (get-in g [r c]) target))
g
(reduce #(flood %1 %2 target fill)
(assoc-in g [r c] fill)
[[(inc r) c] [(dec r) c] [r (inc c)] [r (dec c)]]))))
(def paper (mapv vec ["#####" "#...#" "#.#.#" "#...#" "#####"]))
(doseq [row (flood paper [1 1] \. \~)]
(println (apply str row)))
The # cells are ink; the . interior is dry paper with a pillar in the middle. Start the wash at one corner of the interior and it snakes around the pillar:
#####
#~~~#
#~#~#
#~~~#
#####
The colour never touches the pillar’s far side, exactly like a real wash refusing to cross a drawn line. Ada gives the identical grid, just louder about its bounds — the and then short-circuits so the index check happens before the array read:
procedure Flood (R, C : Integer; T, F : Character) is
begin
if R in 1 .. 5 and then C in 1 .. 5
and then T /= F and then G (R, C) = T then
G (R, C) := F;
Flood (R + 1, C, T, F); Flood (R - 1, C, T, F);
Flood (R, C + 1, T, F); Flood (R, C - 1, T, F);
end if;
end Flood;
Both versions lean entirely on the recursion stack, which is why a big region can blow it — the reason production paint tools switched to scanline fills and explicit queues. On a 5×5 sketch, though, the naive version is honest about what a wash actually is: colour that spreads freely until an edge tells it no.