fast_sweeping/
fast_sweeping.rs1use crate::{min3, DistanceField, DistanceFieldAlgorithm, Grid, Obstacles};
2
3pub struct NaiveFastSweepingMethod {
4 step_size: f32,
5 num_iter: usize,
6}
7
8impl DistanceFieldAlgorithm for NaiveFastSweepingMethod {
9 fn calculate_distance_field(&self, distance_field: &mut DistanceField, obstacles: &Obstacles) {
10 self.fast_sweeping(distance_field, obstacles)
11 }
12}
13
14impl NaiveFastSweepingMethod {
15 pub fn new(step_size: f32, num_iter: usize) -> Self {
16 Self {
17 step_size,
18 num_iter,
19 }
20 }
21
22 fn fast_sweeping(&self, distance_field: &mut DistanceField, obstacles: &Obstacles) {
23 self.initialize(distance_field, obstacles);
24 self.perform_sweeps(distance_field);
25 }
26
27 fn initialize(&self, distance_field: &mut DistanceField, obstacles: &Obstacles) {
28 distance_field
29 .iter_mut()
30 .zip(obstacles.iter())
31 .for_each(|(dist, &is_obstacle)| {
32 *dist = if is_obstacle {
33 0_f32
34 } else {
35 DistanceField::MAX_DISTANCE
36 };
37 });
38 }
39
40 fn perform_sweeps(&self, distance_field: &mut DistanceField) {
41 let num_iter = self.num_iter;
42 for _i in 0..num_iter {
43 self.sweep_topleft_bottomright(distance_field);
44 self.sweep_bottomright_topleft(distance_field);
45 self.sweep_topright_borromleft(distance_field);
46 self.sweep_bottomleft_topright(distance_field);
47 }
48 }
49
50 fn sweep_topleft_bottomright(&self, distance_field: &mut DistanceField) {
52 let step_size = self.step_size;
53 let height = distance_field.height();
54 let width = distance_field.width();
55
56 for y in 1..height {
57 let mut left_neighbor = *distance_field.get_at(0, y);
59 for x in 1..width {
60 let center = *distance_field.get_at(x, y);
61 let up_neighbor = *distance_field.get_at(x, y - 1);
62
63 let new_value = min3(center, up_neighbor + step_size, left_neighbor + step_size);
64 distance_field.set_at(x, y, new_value);
65
66 left_neighbor = new_value;
69 }
70 }
71 }
72
73 fn sweep_bottomright_topleft(&self, distance_field: &mut DistanceField) {
75 let step_size = self.step_size;
76 let height = distance_field.height();
77 let width = distance_field.width();
78
79 for y in (0..(height - 1)).rev() {
80 let mut right_neighbor = *distance_field.get_at(width - 1, y);
82 for x in (0..(width - 1)).rev() {
83 let center = *distance_field.get_at(x, y);
84 let down_neighbor = *distance_field.get_at(x, y + 1);
85
86 let new_value = min3(
87 center,
88 down_neighbor + step_size,
89 right_neighbor + step_size,
90 );
91 distance_field.set_at(x, y, new_value);
92
93 right_neighbor = new_value;
96 }
97 }
98 }
99
100 fn sweep_topright_borromleft(&self, distance_field: &mut DistanceField) {
102 let step_size = self.step_size;
103 let height = distance_field.height();
104 let width = distance_field.width();
105
106 for y in 1..height {
107 let mut right_neighbor = *distance_field.get_at(width - 1, y);
109 for x in (0..(width - 1)).rev() {
110 let center = *distance_field.get_at(x, y);
111 let up_neighbor = *distance_field.get_at(x, y - 1);
112
113 let new_value = min3(center, up_neighbor + step_size, right_neighbor + step_size);
114 distance_field.set_at(x, y, new_value);
115
116 right_neighbor = new_value;
119 }
120 }
121 }
122
123 fn sweep_bottomleft_topright(&self, distance_field: &mut DistanceField) {
125 let step_size = self.step_size;
126 let height = distance_field.height();
127 let width = distance_field.width();
128
129 for y in (0..(height - 1)).rev() {
130 let mut left_neighbor = *distance_field.get_at(0, y);
132 for x in 1..width {
133 let center = *distance_field.get_at(x, y);
134 let down_neighbor = *distance_field.get_at(x, y + 1);
135
136 let new_value = min3(center, down_neighbor + step_size, left_neighbor + step_size);
137 distance_field.set_at(x, y, new_value);
138
139 left_neighbor = new_value;
142 }
143 }
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn it_works() {
153 let mut obstacles = Obstacles::new(640, 480);
154
155 for y in 100..200 {
156 obstacles.set_at(100, y, true);
157 }
158
159 for x in 100..400 {
160 obstacles.set_at(x, 200, true);
161 }
162
163 for x in 100..200 {
164 obstacles.set_at(400 + x, 200 + x, true);
165 }
166
167 let mut distance_field = DistanceField::from(&obstacles);
168
169 let naive = NaiveFastSweepingMethod::new(0.1, 5);
170 naive.calculate_distance_field(&mut distance_field, &obstacles);
171 }
172}