cell_map/
cell_map_file.rs

1//! Provides the [`CellMapFile`] type which allows a cell map to be serialised using serde.
2
3// ------------------------------------------------------------------------------------------------
4// IMPORTS
5// ------------------------------------------------------------------------------------------------
6
7use std::convert::TryFrom;
8
9use nalgebra::{Affine2, Vector2};
10use ndarray::Array2;
11use serde::{de::DeserializeOwned, Deserialize, Serialize};
12
13use crate::{cell_map::Bounds, CellMap, CellMapParams, Error, Layer};
14
15// ------------------------------------------------------------------------------------------------
16// STRUCTS
17// ------------------------------------------------------------------------------------------------
18
19/// Represents a file that can be serialised and deserialised using serde.
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct CellMapFile<L, T>
22where
23    L: Layer,
24{
25    /// Number of layers stored in the map
26    pub num_layers: usize,
27
28    /// The order of layers in the map.
29    ///
30    /// The index of a layer name in this vector matches the index of that layer in the `data`
31    /// member.
32    pub layers: Vec<L>,
33
34    /// The bounds of the map
35    pub cell_bounds: Bounds,
36
37    /// The size of each cell in the map, in parent-frame units.
38    pub cell_size: Vector2<f64>,
39
40    /// The precision used when calculating cell boundaries, relative to `cell_size`.
41    pub cell_boundary_precision: f64,
42
43    /// The angle which rotates the parent frame into the map frame, in radians.
44    pub from_parent_angle_rad: f64,
45
46    /// The translation that goes from the parent frame to the map frame, in parent frame units.
47    pub from_parent_translation: Vector2<f64>,
48
49    /// The affine transformation matrix that converts from points in the parent frame to the map frame.
50    pub from_parent_matrix: Affine2<f64>,
51
52    /// Stores each layer of the map as an [`ndarray::Array2<T>`].
53    pub data: Vec<Array2<T>>,
54}
55
56// ------------------------------------------------------------------------------------------------
57// IMPLS
58// ------------------------------------------------------------------------------------------------
59
60impl<L, T> CellMapFile<L, T>
61where
62    L: Layer,
63{
64    /// Converts this file into a [`CellMap`].
65    pub fn into_cell_map(self) -> Result<CellMap<L, T>, Error> {
66        let params = CellMapParams {
67            cell_size: self.cell_size,
68            cell_bounds: self.cell_bounds,
69            rotation_in_parent_rad: self.from_parent_angle_rad,
70            position_in_parent: self.from_parent_translation,
71            cell_boundary_precision: self.cell_boundary_precision,
72        };
73
74        CellMap::new_from_data(params, self.data)
75    }
76}
77
78impl<L, T> CellMapFile<L, T>
79where
80    L: Layer + Serialize,
81    T: Clone + Serialize,
82{
83    pub(crate) fn new(map: &CellMap<L, T>) -> Self {
84        Self {
85            num_layers: L::NUM_LAYERS,
86            layers: L::all(),
87            cell_bounds: map.metadata.cell_bounds,
88            cell_size: map.metadata.cell_size,
89            cell_boundary_precision: map.metadata.cell_boundary_precision,
90            from_parent_angle_rad: map.params.rotation_in_parent_rad,
91            from_parent_translation: map.params.position_in_parent,
92            from_parent_matrix: map.metadata.to_parent.inverse(),
93            data: map.data.clone(),
94        }
95    }
96}
97
98impl<L, T> CellMapFile<L, T>
99where
100    L: Layer + Serialize,
101    T: Serialize,
102{
103    /// Writes the [`CellMapFile`] to the given path, overwriting any existing file. The format of
104    /// the written file is JSON.
105    #[cfg(feature = "json")]
106    pub fn write_json<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), Error> {
107        let file = std::fs::OpenOptions::new()
108            .create(true)
109            .append(false)
110            .truncate(true)
111            .write(true)
112            .open(path)
113            .map_err(Error::IoError)?;
114
115        serde_json::to_writer_pretty(file, &self).map_err(Error::JsonError)?;
116
117        Ok(())
118    }
119}
120
121impl<L, T> CellMapFile<L, T>
122where
123    L: Layer + DeserializeOwned,
124    T: DeserializeOwned,
125{
126    /// Loads a [`CellMapFile`] from the given path, which points to a JSON file.
127    #[cfg(feature = "json")]
128    pub fn from_json<P: AsRef<std::path::Path>>(path: P) -> Result<Self, Error> {
129        // Open the file
130        let file = std::fs::File::open(path).map_err(Error::IoError)?;
131        let map_file: CellMapFile<L, T> =
132            serde_json::from_reader(&file).map_err(Error::JsonError)?;
133        Ok(map_file)
134    }
135}
136
137impl<L, T> From<CellMap<L, T>> for CellMapFile<L, T>
138where
139    L: Layer + Serialize,
140    T: Clone + Serialize,
141{
142    fn from(map: CellMap<L, T>) -> Self {
143        Self::new(&map)
144    }
145}
146
147impl<L, T> TryFrom<CellMapFile<L, T>> for CellMap<L, T>
148where
149    L: Layer,
150{
151    type Error = Error;
152
153    fn try_from(value: CellMapFile<L, T>) -> Result<Self, Self::Error> {
154        value.into_cell_map()
155    }
156}