morphological_operations/
morphological_operations.rs1use terrain_forge::{
6 algorithms,
7 spatial::{morphological_transform, MorphologyOp, StructuringElement},
8 Grid, Tile,
9};
10
11fn main() {
12 println!("=== Morphological Operations Demo ===\n");
13
14 let mut grid = Grid::new(30, 20);
16 let algo = algorithms::get("cellular").unwrap();
17 algo.generate(&mut grid, 98765);
18
19 println!("1. Original Cave System (30x20):");
20 print_grid(&grid);
21
22 println!("\n2. Erosion (3x3 rectangle):");
24 let rect_element = StructuringElement::rectangle(3, 3);
25 let eroded = morphological_transform(&grid, MorphologyOp::Erosion, &rect_element);
26 print_grid(&eroded);
27
28 println!("\n3. Dilation (3x3 rectangle):");
30 let dilated = morphological_transform(&grid, MorphologyOp::Dilation, &rect_element);
31 print_grid(&dilated);
32
33 println!("\n4. Opening (removes small features):");
35 let opened = morphological_transform(&grid, MorphologyOp::Opening, &rect_element);
36 print_grid(&opened);
37
38 println!("\n5. Closing (fills small gaps):");
40 let closed = morphological_transform(&grid, MorphologyOp::Closing, &rect_element);
41 print_grid(&closed);
42
43 println!("\n6. Circular Structuring Element (radius 2):");
45 let circle_element = StructuringElement::circle(2);
46 let circle_eroded = morphological_transform(&grid, MorphologyOp::Erosion, &circle_element);
47 print_grid(&circle_eroded);
48
49 println!("\n7. Cross Structuring Element (size 5):");
50 let cross_element = StructuringElement::cross(5);
51 let cross_dilated = morphological_transform(&grid, MorphologyOp::Dilation, &cross_element);
52 print_grid(&cross_dilated);
53
54 println!("\n8. Multiple Iterations (3x erosion):");
56 let mut iterative = grid.clone();
57 for i in 1..=3 {
58 iterative = morphological_transform(&iterative, MorphologyOp::Erosion, &rect_element);
59 println!(" Iteration {}:", i);
60 print_grid_compact(&iterative);
61 }
62
63 println!("\n9. Performance Analysis:");
65 let elements = [
66 ("Rectangle 3x3", StructuringElement::rectangle(3, 3)),
67 ("Circle r=2", StructuringElement::circle(2)),
68 ("Cross 5x5", StructuringElement::cross(5)),
69 ];
70
71 for (name, element) in &elements {
72 let start = std::time::Instant::now();
73 let _ = morphological_transform(&grid, MorphologyOp::Erosion, element);
74 println!(" {} erosion: {:?}", name, start.elapsed());
75 }
76
77 println!("\n10. Shape Analysis:");
79 let original_floors = grid.count(|t| t.is_floor());
80 let eroded_floors = eroded.count(|t| t.is_floor());
81 let dilated_floors = dilated.count(|t| t.is_floor());
82
83 println!(" Original floors: {}", original_floors);
84 println!(
85 " After erosion: {} ({:.1}% reduction)",
86 eroded_floors,
87 100.0 * (original_floors - eroded_floors) as f32 / original_floors as f32
88 );
89 println!(
90 " After dilation: {} ({:.1}% increase)",
91 dilated_floors,
92 100.0 * (dilated_floors - original_floors) as f32 / original_floors as f32
93 );
94}
95
96fn print_grid(grid: &Grid<Tile>) {
97 for y in 0..grid.height() {
98 for x in 0..grid.width() {
99 let tile = grid.get(x as i32, y as i32).unwrap();
100 print!("{}", if tile.is_floor() { "." } else { "#" });
101 }
102 println!();
103 }
104}
105
106fn print_grid_compact(grid: &Grid<Tile>) {
107 for y in 0..grid.height().min(8) {
108 print!(" ");
109 for x in 0..grid.width() {
110 let tile = grid.get(x as i32, y as i32).unwrap();
111 print!("{}", if tile.is_floor() { "." } else { "#" });
112 }
113 println!();
114 }
115 if grid.height() > 8 {
116 println!(" ... ({} more rows)", grid.height() - 8);
117 }
118}