pub struct DistanceTransform { /* private fields */ }Expand description
Distance transform result
Implementations§
Source§impl DistanceTransform
impl DistanceTransform
pub fn new(width: usize, height: usize) -> Self
Sourcepub fn get(&self, x: usize, y: usize) -> f32
pub fn get(&self, x: usize, y: usize) -> f32
Examples found in repository?
examples/distance_transforms.rs (line 63)
60fn print_distance_field(transform: &terrain_forge::spatial::DistanceTransform) {
61 for y in 0..transform.height() {
62 for x in 0..transform.width() {
63 let dist = transform.get(x, y);
64 if dist == f32::INFINITY {
65 print!("## ");
66 } else if dist < 10.0 {
67 print!("{:2.0} ", dist);
68 } else {
69 print!("++ ");
70 }
71 }
72 println!();
73 }
74}More examples
examples/spatial_workflow.rs (line 52)
14fn main() {
15 println!("=== Complete Spatial Analysis Workflow ===\n");
16
17 // Step 1: Generate base dungeon
18 println!("1. Generating Base Dungeon:");
19 let mut grid = Grid::new(40, 30);
20 let algo = algorithms::get("bsp").unwrap();
21 algo.generate(&mut grid, 42424);
22
23 let original_floors = grid.count(|t| t.is_floor());
24 println!(
25 " Generated {}x{} dungeon with {} floor tiles",
26 grid.width(),
27 grid.height(),
28 original_floors
29 );
30
31 // Step 2: Clean up with morphological operations
32 println!("\n2. Cleaning Up Small Features:");
33 let cleanup_element = StructuringElement::rectangle(3, 3);
34 let cleaned = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
35
36 let cleaned_floors = cleaned.count(|t| t.is_floor());
37 println!(
38 " Removed {} small features ({} floors remaining)",
39 original_floors - cleaned_floors,
40 cleaned_floors
41 );
42
43 // Step 3: Analyze distances from walls
44 println!("\n3. Analyzing Distance from Walls:");
45 let distance_map = distance_field(&cleaned, DistanceMetric::Euclidean);
46
47 let mut max_distance = 0.0;
48 let mut center_points = Vec::new();
49
50 for y in 0..distance_map.height() {
51 for x in 0..distance_map.width() {
52 let dist = distance_map.get(x, y);
53 if dist != f32::INFINITY {
54 if dist > max_distance {
55 max_distance = dist;
56 center_points.clear();
57 center_points.push((x, y));
58 } else if (dist - max_distance).abs() < 0.1 {
59 center_points.push((x, y));
60 }
61 }
62 }
63 }
64
65 println!(" Maximum distance from walls: {:.1}", max_distance);
66 println!(" Found {} center points", center_points.len());
67
68 // Step 4: Create strategic pathfinding network
69 println!("\n4. Creating Strategic Pathfinding Network:");
70
71 // Use the most central points as strategic locations
72 let strategic_points: Vec<_> = center_points.into_iter().take(3).collect();
73 println!(" Strategic points: {:?}", strategic_points);
74
75 let constraints = PathfindingConstraints::default();
76 let strategic_dijkstra = dijkstra_map(&cleaned, &strategic_points, &constraints);
77
78 // Step 5: Generate AI movement flow field
79 println!("\n5. Generating AI Movement Flow Field:");
80 let flow_field = flow_field_from_dijkstra(&strategic_dijkstra);
81
82 // Analyze flow field coverage
83 let mut flow_coverage = 0;
84 for y in 0..flow_field.height() {
85 for x in 0..flow_field.width() {
86 let (dx, dy) = flow_field.get_direction(x, y);
87 if dx != 0 || dy != 0 {
88 flow_coverage += 1;
89 }
90 }
91 }
92
93 println!(" Flow field covers {} cells", flow_coverage);
94
95 // Step 6: Identify chokepoints using morphological analysis
96 println!("\n6. Identifying Chokepoints:");
97 let thin_element = StructuringElement::rectangle(2, 2);
98 let thinned = morphological_transform(&cleaned, MorphologyOp::Erosion, &thin_element);
99
100 let mut chokepoints = Vec::new();
101 for y in 1..cleaned.height() - 1 {
102 for x in 1..cleaned.width() - 1 {
103 if let (Some(original), Some(thinned_cell)) = (
104 cleaned.get(x as i32, y as i32),
105 thinned.get(x as i32, y as i32),
106 ) {
107 if original.is_floor() && !thinned_cell.is_floor() {
108 // This was a floor that got eroded - potential chokepoint
109 let neighbors = count_floor_neighbors(&cleaned, x, y);
110 if (2..=4).contains(&neighbors) {
111 chokepoints.push((x, y));
112 }
113 }
114 }
115 }
116 }
117
118 println!(" Found {} potential chokepoints", chokepoints.len());
119
120 // Step 7: Performance summary
121 println!("\n7. Performance Summary:");
122
123 let start = std::time::Instant::now();
124 let _ = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
125 println!(" Morphological cleanup: {:?}", start.elapsed());
126
127 let start = std::time::Instant::now();
128 let _ = distance_field(&cleaned, DistanceMetric::Euclidean);
129 println!(" Distance field calculation: {:?}", start.elapsed());
130
131 let start = std::time::Instant::now();
132 let _ = dijkstra_map(&cleaned, &strategic_points, &constraints);
133 println!(" Dijkstra map generation: {:?}", start.elapsed());
134
135 let start = std::time::Instant::now();
136 let _ = flow_field_from_dijkstra(&strategic_dijkstra);
137 println!(" Flow field generation: {:?}", start.elapsed());
138
139 // Step 8: Spatial analysis results
140 println!("\n8. Spatial Analysis Results:");
141 println!(" Original dungeon: {} floors", original_floors);
142 println!(" After cleanup: {} floors", cleaned_floors);
143 println!(" Strategic locations: {}", strategic_points.len());
144 println!(" Chokepoints identified: {}", chokepoints.len());
145 println!(
146 " Flow field coverage: {:.1}%",
147 100.0 * flow_coverage as f32 / cleaned_floors as f32
148 );
149
150 println!("\n✅ Spatial analysis workflow complete!");
151 println!(" The dungeon is now ready for:");
152 println!(" - AI pathfinding using flow fields");
153 println!(" - Strategic placement at center points");
154 println!(" - Tactical analysis of chokepoints");
155 println!(" - Distance-based gameplay mechanics");
156}pub fn set(&mut self, x: usize, y: usize, distance: f32)
Sourcepub fn width(&self) -> usize
pub fn width(&self) -> usize
Examples found in repository?
examples/distance_transforms.rs (line 62)
60fn print_distance_field(transform: &terrain_forge::spatial::DistanceTransform) {
61 for y in 0..transform.height() {
62 for x in 0..transform.width() {
63 let dist = transform.get(x, y);
64 if dist == f32::INFINITY {
65 print!("## ");
66 } else if dist < 10.0 {
67 print!("{:2.0} ", dist);
68 } else {
69 print!("++ ");
70 }
71 }
72 println!();
73 }
74}More examples
examples/spatial_workflow.rs (line 51)
14fn main() {
15 println!("=== Complete Spatial Analysis Workflow ===\n");
16
17 // Step 1: Generate base dungeon
18 println!("1. Generating Base Dungeon:");
19 let mut grid = Grid::new(40, 30);
20 let algo = algorithms::get("bsp").unwrap();
21 algo.generate(&mut grid, 42424);
22
23 let original_floors = grid.count(|t| t.is_floor());
24 println!(
25 " Generated {}x{} dungeon with {} floor tiles",
26 grid.width(),
27 grid.height(),
28 original_floors
29 );
30
31 // Step 2: Clean up with morphological operations
32 println!("\n2. Cleaning Up Small Features:");
33 let cleanup_element = StructuringElement::rectangle(3, 3);
34 let cleaned = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
35
36 let cleaned_floors = cleaned.count(|t| t.is_floor());
37 println!(
38 " Removed {} small features ({} floors remaining)",
39 original_floors - cleaned_floors,
40 cleaned_floors
41 );
42
43 // Step 3: Analyze distances from walls
44 println!("\n3. Analyzing Distance from Walls:");
45 let distance_map = distance_field(&cleaned, DistanceMetric::Euclidean);
46
47 let mut max_distance = 0.0;
48 let mut center_points = Vec::new();
49
50 for y in 0..distance_map.height() {
51 for x in 0..distance_map.width() {
52 let dist = distance_map.get(x, y);
53 if dist != f32::INFINITY {
54 if dist > max_distance {
55 max_distance = dist;
56 center_points.clear();
57 center_points.push((x, y));
58 } else if (dist - max_distance).abs() < 0.1 {
59 center_points.push((x, y));
60 }
61 }
62 }
63 }
64
65 println!(" Maximum distance from walls: {:.1}", max_distance);
66 println!(" Found {} center points", center_points.len());
67
68 // Step 4: Create strategic pathfinding network
69 println!("\n4. Creating Strategic Pathfinding Network:");
70
71 // Use the most central points as strategic locations
72 let strategic_points: Vec<_> = center_points.into_iter().take(3).collect();
73 println!(" Strategic points: {:?}", strategic_points);
74
75 let constraints = PathfindingConstraints::default();
76 let strategic_dijkstra = dijkstra_map(&cleaned, &strategic_points, &constraints);
77
78 // Step 5: Generate AI movement flow field
79 println!("\n5. Generating AI Movement Flow Field:");
80 let flow_field = flow_field_from_dijkstra(&strategic_dijkstra);
81
82 // Analyze flow field coverage
83 let mut flow_coverage = 0;
84 for y in 0..flow_field.height() {
85 for x in 0..flow_field.width() {
86 let (dx, dy) = flow_field.get_direction(x, y);
87 if dx != 0 || dy != 0 {
88 flow_coverage += 1;
89 }
90 }
91 }
92
93 println!(" Flow field covers {} cells", flow_coverage);
94
95 // Step 6: Identify chokepoints using morphological analysis
96 println!("\n6. Identifying Chokepoints:");
97 let thin_element = StructuringElement::rectangle(2, 2);
98 let thinned = morphological_transform(&cleaned, MorphologyOp::Erosion, &thin_element);
99
100 let mut chokepoints = Vec::new();
101 for y in 1..cleaned.height() - 1 {
102 for x in 1..cleaned.width() - 1 {
103 if let (Some(original), Some(thinned_cell)) = (
104 cleaned.get(x as i32, y as i32),
105 thinned.get(x as i32, y as i32),
106 ) {
107 if original.is_floor() && !thinned_cell.is_floor() {
108 // This was a floor that got eroded - potential chokepoint
109 let neighbors = count_floor_neighbors(&cleaned, x, y);
110 if (2..=4).contains(&neighbors) {
111 chokepoints.push((x, y));
112 }
113 }
114 }
115 }
116 }
117
118 println!(" Found {} potential chokepoints", chokepoints.len());
119
120 // Step 7: Performance summary
121 println!("\n7. Performance Summary:");
122
123 let start = std::time::Instant::now();
124 let _ = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
125 println!(" Morphological cleanup: {:?}", start.elapsed());
126
127 let start = std::time::Instant::now();
128 let _ = distance_field(&cleaned, DistanceMetric::Euclidean);
129 println!(" Distance field calculation: {:?}", start.elapsed());
130
131 let start = std::time::Instant::now();
132 let _ = dijkstra_map(&cleaned, &strategic_points, &constraints);
133 println!(" Dijkstra map generation: {:?}", start.elapsed());
134
135 let start = std::time::Instant::now();
136 let _ = flow_field_from_dijkstra(&strategic_dijkstra);
137 println!(" Flow field generation: {:?}", start.elapsed());
138
139 // Step 8: Spatial analysis results
140 println!("\n8. Spatial Analysis Results:");
141 println!(" Original dungeon: {} floors", original_floors);
142 println!(" After cleanup: {} floors", cleaned_floors);
143 println!(" Strategic locations: {}", strategic_points.len());
144 println!(" Chokepoints identified: {}", chokepoints.len());
145 println!(
146 " Flow field coverage: {:.1}%",
147 100.0 * flow_coverage as f32 / cleaned_floors as f32
148 );
149
150 println!("\n✅ Spatial analysis workflow complete!");
151 println!(" The dungeon is now ready for:");
152 println!(" - AI pathfinding using flow fields");
153 println!(" - Strategic placement at center points");
154 println!(" - Tactical analysis of chokepoints");
155 println!(" - Distance-based gameplay mechanics");
156}Sourcepub fn height(&self) -> usize
pub fn height(&self) -> usize
Examples found in repository?
examples/distance_transforms.rs (line 61)
60fn print_distance_field(transform: &terrain_forge::spatial::DistanceTransform) {
61 for y in 0..transform.height() {
62 for x in 0..transform.width() {
63 let dist = transform.get(x, y);
64 if dist == f32::INFINITY {
65 print!("## ");
66 } else if dist < 10.0 {
67 print!("{:2.0} ", dist);
68 } else {
69 print!("++ ");
70 }
71 }
72 println!();
73 }
74}More examples
examples/spatial_workflow.rs (line 50)
14fn main() {
15 println!("=== Complete Spatial Analysis Workflow ===\n");
16
17 // Step 1: Generate base dungeon
18 println!("1. Generating Base Dungeon:");
19 let mut grid = Grid::new(40, 30);
20 let algo = algorithms::get("bsp").unwrap();
21 algo.generate(&mut grid, 42424);
22
23 let original_floors = grid.count(|t| t.is_floor());
24 println!(
25 " Generated {}x{} dungeon with {} floor tiles",
26 grid.width(),
27 grid.height(),
28 original_floors
29 );
30
31 // Step 2: Clean up with morphological operations
32 println!("\n2. Cleaning Up Small Features:");
33 let cleanup_element = StructuringElement::rectangle(3, 3);
34 let cleaned = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
35
36 let cleaned_floors = cleaned.count(|t| t.is_floor());
37 println!(
38 " Removed {} small features ({} floors remaining)",
39 original_floors - cleaned_floors,
40 cleaned_floors
41 );
42
43 // Step 3: Analyze distances from walls
44 println!("\n3. Analyzing Distance from Walls:");
45 let distance_map = distance_field(&cleaned, DistanceMetric::Euclidean);
46
47 let mut max_distance = 0.0;
48 let mut center_points = Vec::new();
49
50 for y in 0..distance_map.height() {
51 for x in 0..distance_map.width() {
52 let dist = distance_map.get(x, y);
53 if dist != f32::INFINITY {
54 if dist > max_distance {
55 max_distance = dist;
56 center_points.clear();
57 center_points.push((x, y));
58 } else if (dist - max_distance).abs() < 0.1 {
59 center_points.push((x, y));
60 }
61 }
62 }
63 }
64
65 println!(" Maximum distance from walls: {:.1}", max_distance);
66 println!(" Found {} center points", center_points.len());
67
68 // Step 4: Create strategic pathfinding network
69 println!("\n4. Creating Strategic Pathfinding Network:");
70
71 // Use the most central points as strategic locations
72 let strategic_points: Vec<_> = center_points.into_iter().take(3).collect();
73 println!(" Strategic points: {:?}", strategic_points);
74
75 let constraints = PathfindingConstraints::default();
76 let strategic_dijkstra = dijkstra_map(&cleaned, &strategic_points, &constraints);
77
78 // Step 5: Generate AI movement flow field
79 println!("\n5. Generating AI Movement Flow Field:");
80 let flow_field = flow_field_from_dijkstra(&strategic_dijkstra);
81
82 // Analyze flow field coverage
83 let mut flow_coverage = 0;
84 for y in 0..flow_field.height() {
85 for x in 0..flow_field.width() {
86 let (dx, dy) = flow_field.get_direction(x, y);
87 if dx != 0 || dy != 0 {
88 flow_coverage += 1;
89 }
90 }
91 }
92
93 println!(" Flow field covers {} cells", flow_coverage);
94
95 // Step 6: Identify chokepoints using morphological analysis
96 println!("\n6. Identifying Chokepoints:");
97 let thin_element = StructuringElement::rectangle(2, 2);
98 let thinned = morphological_transform(&cleaned, MorphologyOp::Erosion, &thin_element);
99
100 let mut chokepoints = Vec::new();
101 for y in 1..cleaned.height() - 1 {
102 for x in 1..cleaned.width() - 1 {
103 if let (Some(original), Some(thinned_cell)) = (
104 cleaned.get(x as i32, y as i32),
105 thinned.get(x as i32, y as i32),
106 ) {
107 if original.is_floor() && !thinned_cell.is_floor() {
108 // This was a floor that got eroded - potential chokepoint
109 let neighbors = count_floor_neighbors(&cleaned, x, y);
110 if (2..=4).contains(&neighbors) {
111 chokepoints.push((x, y));
112 }
113 }
114 }
115 }
116 }
117
118 println!(" Found {} potential chokepoints", chokepoints.len());
119
120 // Step 7: Performance summary
121 println!("\n7. Performance Summary:");
122
123 let start = std::time::Instant::now();
124 let _ = morphological_transform(&grid, MorphologyOp::Opening, &cleanup_element);
125 println!(" Morphological cleanup: {:?}", start.elapsed());
126
127 let start = std::time::Instant::now();
128 let _ = distance_field(&cleaned, DistanceMetric::Euclidean);
129 println!(" Distance field calculation: {:?}", start.elapsed());
130
131 let start = std::time::Instant::now();
132 let _ = dijkstra_map(&cleaned, &strategic_points, &constraints);
133 println!(" Dijkstra map generation: {:?}", start.elapsed());
134
135 let start = std::time::Instant::now();
136 let _ = flow_field_from_dijkstra(&strategic_dijkstra);
137 println!(" Flow field generation: {:?}", start.elapsed());
138
139 // Step 8: Spatial analysis results
140 println!("\n8. Spatial Analysis Results:");
141 println!(" Original dungeon: {} floors", original_floors);
142 println!(" After cleanup: {} floors", cleaned_floors);
143 println!(" Strategic locations: {}", strategic_points.len());
144 println!(" Chokepoints identified: {}", chokepoints.len());
145 println!(
146 " Flow field coverage: {:.1}%",
147 100.0 * flow_coverage as f32 / cleaned_floors as f32
148 );
149
150 println!("\n✅ Spatial analysis workflow complete!");
151 println!(" The dungeon is now ready for:");
152 println!(" - AI pathfinding using flow fields");
153 println!(" - Strategic placement at center points");
154 println!(" - Tactical analysis of chokepoints");
155 println!(" - Distance-based gameplay mechanics");
156}Trait Implementations§
Source§impl Clone for DistanceTransform
impl Clone for DistanceTransform
Source§fn clone(&self) -> DistanceTransform
fn clone(&self) -> DistanceTransform
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for DistanceTransform
impl RefUnwindSafe for DistanceTransform
impl Send for DistanceTransform
impl Sync for DistanceTransform
impl Unpin for DistanceTransform
impl UnwindSafe for DistanceTransform
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more