fast_sweeping/
distance_field.rs

1use crate::obstacles::Obstacles;
2use crate::{Grid, SavePgm};
3use std::fs::File;
4use std::io::Write;
5use std::path::PathBuf;
6use std::slice::{from_raw_parts_mut, Iter, IterMut};
7
8/// The distance field.
9pub struct DistanceField {
10    distances: Vec<f32>,
11    width: usize,
12    height: usize,
13}
14
15impl DistanceField {
16    pub const MAX_DISTANCE: f32 = f32::INFINITY;
17
18    #[inline(always)]
19    pub const fn width(&self) -> usize {
20        self.width
21    }
22
23    #[inline(always)]
24    pub const fn height(&self) -> usize {
25        self.height
26    }
27
28    #[inline(always)]
29    pub fn iter(&self) -> Iter<'_, f32> {
30        self.distances.iter()
31    }
32
33    #[inline(always)]
34    pub fn iter_mut(&mut self) -> IterMut<'_, f32> {
35        self.distances.iter_mut()
36    }
37}
38
39impl From<&Obstacles> for DistanceField {
40    fn from(value: &Obstacles) -> Self {
41        Self {
42            distances: vec![0_f32; value.obstacles.len()],
43            width: value.width,
44            height: value.height,
45        }
46    }
47}
48
49impl Grid for DistanceField {
50    type Item = f32;
51
52    #[inline(always)]
53    fn get_at(&self, x: usize, y: usize) -> &Self::Item {
54        &self.distances[y * self.width + x]
55    }
56
57    #[inline(always)]
58    fn set_at(&mut self, x: usize, y: usize, value: Self::Item) {
59        self.distances[y * self.width + x] = value
60    }
61
62    #[inline(always)]
63    fn get_rows_mut(&mut self, y: usize) -> (&mut [Self::Item], &mut [Self::Item]) {
64        let top = y * self.width;
65        let bottom = (y + 1) * self.width;
66        let ptr = self.distances.as_mut_ptr();
67        unsafe {
68            (
69                from_raw_parts_mut(ptr.add(top), self.width),
70                from_raw_parts_mut(ptr.add(bottom), self.width),
71            )
72        }
73    }
74
75    #[inline(always)]
76    fn iter(&self) -> Iter<'_, Self::Item> {
77        self.iter()
78    }
79
80    #[inline(always)]
81    fn iter_mut(&mut self) -> IterMut<'_, Self::Item> {
82        self.iter_mut()
83    }
84}
85
86impl SavePgm for DistanceField {
87    fn save_pgm(&self, file_name: &PathBuf) -> std::io::Result<()> {
88        let mut file = File::create(file_name)?;
89
90        let max_value: u8 = 255;
91        let scaler = (max_value as f32) / self.iter().fold(0_f32, |acc, &d| acc.max(d));
92
93        // Write the header
94        let header = format!("P5\n{} {}\n{}\n", self.width, self.height, max_value);
95        file.write_all(header.as_bytes())?;
96
97        // Convert and write the pixel data as binary
98        for distance in self.iter() {
99            let value = (distance * scaler) as u8;
100            file.write_all(&[value])?;
101        }
102
103        Ok(())
104    }
105}