Skip to main content

terrain_forge/effects/
morphology.rs

1//! Morphological operations
2
3use crate::{Grid, Tile};
4
5pub fn erode(grid: &mut Grid<Tile>, iterations: usize) {
6    let (w, h) = (grid.width(), grid.height());
7    for _ in 0..iterations {
8        let snapshot: Vec<bool> = (0..w * h)
9            .map(|i| grid[(i % w, i / w)].is_floor())
10            .collect();
11        for y in 1..h - 1 {
12            for x in 1..w - 1 {
13                let idx = y * w + x;
14                if snapshot[idx] {
15                    let has_wall = !snapshot[idx - 1]
16                        || !snapshot[idx + 1]
17                        || !snapshot[idx - w]
18                        || !snapshot[idx + w];
19                    if has_wall {
20                        grid.set(x as i32, y as i32, Tile::Wall);
21                    }
22                }
23            }
24        }
25    }
26}
27
28pub fn dilate(grid: &mut Grid<Tile>, iterations: usize) {
29    let (w, h) = (grid.width(), grid.height());
30    for _ in 0..iterations {
31        let snapshot: Vec<bool> = (0..w * h)
32            .map(|i| grid[(i % w, i / w)].is_floor())
33            .collect();
34        for y in 1..h - 1 {
35            for x in 1..w - 1 {
36                let idx = y * w + x;
37                if !snapshot[idx] {
38                    let has_floor = snapshot[idx - 1]
39                        || snapshot[idx + 1]
40                        || snapshot[idx - w]
41                        || snapshot[idx + w];
42                    if has_floor {
43                        grid.set(x as i32, y as i32, Tile::Floor);
44                    }
45                }
46            }
47        }
48    }
49}
50
51pub fn open(grid: &mut Grid<Tile>, iterations: usize) {
52    erode(grid, iterations);
53    dilate(grid, iterations);
54}
55
56pub fn close(grid: &mut Grid<Tile>, iterations: usize) {
57    dilate(grid, iterations);
58    erode(grid, iterations);
59}