quantized_density_fields/lod/
mod.rs

1pub mod level;
2mod tests;
3
4pub use self::level::*;
5use error::*;
6use id::*;
7use petgraph::algo::astar;
8use petgraph::graphmap::UnGraphMap;
9use qdf::*;
10use rayon::prelude::*;
11use std::collections::{HashMap, HashSet};
12
13/// Object that represents space level of details.
14/// This gives you the ability to sample space area states at different zoom levels (LOD mechanism).
15#[derive(Debug)]
16pub struct LOD<S>
17where
18    S: State,
19{
20    id: ID,
21    graph: UnGraphMap<ID, ()>,
22    levels: HashMap<ID, Level<S>>,
23    platonic_levels: HashSet<ID>,
24    root: ID,
25    dimensions: usize,
26    count: usize,
27}
28
29impl<S> LOD<S>
30where
31    S: State,
32{
33    /// Creates new LOD information universe.
34    ///
35    /// # Arguments
36    /// * `dimensions` - Number of dimensions which space contains.
37    /// * `count` - Number of levels.
38    /// * `root_state` - State of root level.
39    ///
40    /// # Examples
41    /// ```
42    /// use quantized_density_fields::LOD;
43    ///
44    /// // Create 2D space with 1 level of details and `16` as root space.
45    /// let lod = LOD::new(2, 1, 16);
46    /// assert_eq!(*lod.state(), 16);
47    /// // LOD has 4 children level objects.
48    /// assert_eq!(lod.level(lod.root()).sublevels().len(), 4);
49    /// // sampled state at level 1 equals to `4` (`16 / 4`).
50    /// assert_eq!(*lod.level(lod.level(lod.root()).sublevels()[0]).state(), 4);
51    /// ```
52    pub fn new(dimensions: usize, count: usize, root_state: S) -> Self {
53        let mut graph = UnGraphMap::new();
54        let mut levels = HashMap::new();
55        let mut platonic_levels = HashSet::new();
56        let root = ID::new();
57        let main = Level::new(root, None, 0, 0, root_state);
58        levels.insert(root, main);
59        graph.add_node(root);
60        Self::subdivide_level(root, &mut graph, &mut levels, dimensions + 2, count);
61        Self::connect_clusters(root, &mut graph, &levels);
62        Self::collect_platonic_levels(root, &levels, &mut platonic_levels);
63        Self {
64            id: ID::new(),
65            graph,
66            levels,
67            platonic_levels,
68            root,
69            dimensions,
70            count,
71        }
72    }
73
74    /// Gets LOD id.
75    #[inline]
76    pub fn id(&self) -> ID {
77        self.id
78    }
79
80    /// Gets LOD root level node id.
81    #[inline]
82    pub fn root(&self) -> ID {
83        self.root
84    }
85
86    /// Gets LOD dimensions number.
87    ///
88    /// # Examples
89    /// ```
90    /// use quantized_density_fields::LOD;
91    ///
92    /// let lod = LOD::new(2, 1, 16);
93    /// assert_eq!(lod.dimensions(), 2);
94    /// ```
95    #[inline]
96    pub fn dimensions(&self) -> usize {
97        self.dimensions
98    }
99
100    /// Gets LOD zoom levels number.
101    ///
102    /// # Examples
103    /// ```
104    /// use quantized_density_fields::LOD;
105    ///
106    /// let lod = LOD::new(2, 1, 16);
107    /// assert_eq!(lod.levels_count(), 1);
108    /// ```
109    #[inline]
110    pub fn levels_count(&self) -> usize {
111        self.count
112    }
113
114    /// Gets LOD root level state.
115    /// # Examples
116    /// ```
117    /// use quantized_density_fields::LOD;
118    ///
119    /// let lod = LOD::new(2, 1, 16);
120    /// assert_eq!(*lod.state(), 16);
121    /// ```
122    #[inline]
123    pub fn state(&self) -> &S {
124        self.levels[&self.root].state()
125    }
126
127    /// Tells if space level with given id exists in LOD.
128    ///
129    /// # Arguments
130    /// * `id` - level id.
131    ///
132    /// # Examples
133    /// ```
134    /// use quantized_density_fields::LOD;
135    ///
136    /// let lod = LOD::new(2, 1, 16);
137    /// assert!(lod.level_exists(lod.root()));
138    /// ```
139    #[inline]
140    pub fn level_exists(&self, id: ID) -> bool {
141        self.levels.contains_key(&id)
142    }
143
144    /// Try to get reference to given space level.
145    ///
146    /// # Arguments
147    /// * `id` - level id.
148    ///
149    /// # Examples
150    /// ```
151    /// use quantized_density_fields::LOD;
152    ///
153    /// let lod = LOD::new(2, 1, 16);
154    /// if let Some(level) = lod.try_get_level(lod.root()) {
155    ///     assert_eq!(*level.state(), 16);
156    /// }
157    /// ```
158    #[inline]
159    pub fn try_get_level(&self, id: ID) -> Option<&Level<S>> {
160        self.levels.get(&id)
161    }
162
163    /// Gets reference to given space level and throws error if level does not exists.
164    ///
165    /// # Arguments
166    /// * `id` - level id.
167    ///
168    /// # Examples
169    /// ```
170    /// use quantized_density_fields::LOD;
171    ///
172    /// let lod = LOD::new(2, 1, 16);
173    /// if let Ok(level) = lod.get_level(lod.root()) {
174    ///     assert_eq!(*level.state(), 16);
175    /// }
176    /// ```
177    #[inline]
178    pub fn get_level(&self, id: ID) -> Result<&Level<S>> {
179        if let Some(level) = self.levels.get(&id) {
180            Ok(level)
181        } else {
182            Err(QDFError::LevelDoesNotExists(id))
183        }
184    }
185
186    /// Gets reference to given space level and panics if level does not exists.
187    ///
188    /// # Arguments
189    /// * `id` - level id.
190    ///
191    /// # Examples
192    /// ```
193    /// use quantized_density_fields::LOD;
194    ///
195    /// let lod = LOD::new(2, 1, 16);
196    /// assert_eq!(*lod.level(lod.root()).state(), 16);
197    /// ```
198    #[inline]
199    pub fn level(&self, id: ID) -> &Level<S> {
200        &self.levels[&id]
201    }
202
203    /// Try to set given level state.
204    ///
205    /// # Arguments
206    /// * `id` - level id.
207    /// * `state` - state.
208    ///
209    /// # Examples
210    /// ```
211    /// use quantized_density_fields::LOD;
212    ///
213    /// let mut lod = LOD::new(2, 1, 9);
214    /// let id = lod.root();
215    /// assert!(lod.try_set_level_state(id, 3));
216    /// ```
217    #[inline]
218    pub fn try_set_level_state(&mut self, id: ID, state: S) -> bool {
219        self.set_level_state(id, state).is_ok()
220    }
221
222    /// Set given level state or throw error if level does not exists.
223    ///
224    /// # Arguments
225    /// * `id` - level id.
226    /// * `state` - state.
227    ///
228    /// # Examples
229    /// ```
230    /// use quantized_density_fields::LOD;
231    ///
232    /// let mut lod = LOD::new(2, 1, 9);
233    /// let id = lod.root();
234    /// assert!(lod.set_level_state(id, 3).is_ok());
235    /// ```
236    #[inline]
237    pub fn set_level_state(&mut self, id: ID, state: S) -> Result<()> {
238        if self.level_exists(id) {
239            self.levels.get_mut(&id).unwrap().apply_state(state);
240            self.recalculate_children_states(id);
241            self.recalculate_parent_state(id);
242            Ok(())
243        } else {
244            Err(QDFError::LevelDoesNotExists(id))
245        }
246    }
247
248    /// Gets list of space level neighbors IDs or throws error if level does not exists.
249    ///
250    /// # Arguments
251    /// * `id` - Level id.
252    ///
253    /// # Examples
254    /// ```
255    /// use quantized_density_fields::LOD;
256    ///
257    /// let lod = LOD::new(2, 1, 16);
258    /// let subs = lod.level(lod.root()).sublevels();
259    /// assert_eq!(lod.find_level_neighbors(subs[0]).unwrap(), vec![subs[1], subs[2], subs[3]]);
260    /// ```
261    #[inline]
262    pub fn find_level_neighbors(&self, id: ID) -> Result<Vec<ID>> {
263        if self.graph.contains_node(id) {
264            Ok(self.graph.neighbors(id).collect())
265        } else {
266            Err(QDFError::LevelDoesNotExists(id))
267        }
268    }
269
270    /// Gets list of space level IDs that defines shortest path between two space levels,
271    /// or throws error if level does not exists. Levels must lay on the same zoom level!
272    ///
273    /// # Arguments
274    /// * `from` - source level id.
275    /// * `to` - target level id.
276    ///
277    /// # Examples
278    /// ```
279    /// use quantized_density_fields::LOD;
280    ///
281    /// let lod = LOD::new(2, 1, 16);
282    /// let subs = lod.level(lod.root()).sublevels();
283    /// assert_eq!(lod.find_path(subs[1], subs[3]).unwrap(), vec![subs[1], subs[0], subs[3]]);
284    /// ```
285    pub fn find_path(&self, from: ID, to: ID) -> Result<Vec<ID>> {
286        if !self.level_exists(from) {
287            return Err(QDFError::LevelDoesNotExists(from));
288        }
289        if !self.level_exists(to) {
290            return Err(QDFError::LevelDoesNotExists(to));
291        }
292        if let Some((_, levels)) = astar(&self.graph, from, |f| f == to, |_| 0, |_| 0) {
293            Ok(levels)
294        } else {
295            Ok(vec![])
296        }
297    }
298
299    /// Performs simulation step (go through all platonic spaces and modifies its states based on
300    /// neighbor states). Actual state simulation is performed by your struct that implements
301    /// `Simulation` trait.
302    pub fn simulation_step<M>(&mut self)
303    where
304        M: Simulate<S>,
305    {
306        let states = self.simulate_states::<M>();
307        for (id, state) in states {
308            self.levels.get_mut(&id).unwrap().apply_state(state);
309        }
310        let root = self.root;
311        self.recalculate_states(root);
312    }
313
314    /// Does the same as `simulation_step()` but in parallel manner (it may or may not increase
315    /// simulation performance if simulation is very complex).
316    pub fn simulation_step_parallel<M>(&mut self)
317    where
318        M: Simulate<S>,
319    {
320        let states = self.simulate_states_parallel::<M>();
321        for (id, state) in states {
322            self.levels.get_mut(&id).unwrap().apply_state(state);
323        }
324        let root = self.root;
325        self.recalculate_states(root);
326    }
327
328    /// Performs simulation on LOD like `simulation_step()` but instead of applying results to LOD,
329    /// it returns simulated platonic level states along with their level ID.
330    pub fn simulate_states<M>(&self) -> Vec<(ID, S)>
331    where
332        M: Simulate<S>,
333    {
334        self.platonic_levels
335            .iter()
336            .map(|id| {
337                let neighbor_states = self
338                    .graph
339                    .neighbors(*id)
340                    .map(|i| self.levels[&i].state())
341                    .collect::<Vec<&S>>();
342                (*id, M::simulate(self.levels[id].state(), &neighbor_states))
343            }).collect()
344    }
345
346    /// Performs simulation on LOD like `simulation_step_parallel()` but instead of applying
347    /// results to LOD, it returns simulated platonic level states along with their level ID.
348    pub fn simulate_states_parallel<M>(&self) -> Vec<(ID, S)>
349    where
350        M: Simulate<S>,
351    {
352        self.platonic_levels
353            .par_iter()
354            .map(|id| {
355                let neighbor_states = self
356                    .graph
357                    .neighbors(*id)
358                    .map(|i| self.levels[&i].state())
359                    .collect::<Vec<&S>>();
360                (*id, M::simulate(self.levels[id].state(), &neighbor_states))
361            }).collect()
362    }
363
364    fn subdivide_level(
365        id: ID,
366        graph: &mut UnGraphMap<ID, ()>,
367        levels: &mut HashMap<ID, Level<S>>,
368        subdivisions: usize,
369        count: usize,
370    ) {
371        // TODO: optimize!
372        let mut level = levels[&id].clone();
373        if level.level() < count {
374            let substates = level.state().subdivide(subdivisions);
375            let sublevels = substates
376                .iter()
377                .enumerate()
378                .map(|(idx, substate)| {
379                    let i = ID::new();
380                    graph.add_node(i);
381                    Level::new(i, Some(id), level.level() + 1, idx, substate.clone())
382                }).collect::<Vec<Level<S>>>();
383            let first = sublevels[0].id();
384            for l in sublevels.iter().skip(1) {
385                graph.add_edge(first, l.id(), ());
386            }
387            level.apply_sublevels(sublevels.iter().map(|l| l.id()).collect());
388            for l in sublevels {
389                let i = l.id();
390                levels.insert(i, l);
391                Self::subdivide_level(i, graph, levels, subdivisions, count);
392            }
393            levels.insert(id, level);
394        }
395    }
396
397    fn connect_clusters(id: ID, graph: &mut UnGraphMap<ID, ()>, levels: &HashMap<ID, Level<S>>) {
398        let sublevels = levels[&id].sublevels();
399        if !sublevels.is_empty() {
400            let neighbors = graph
401                .neighbors(id)
402                .map(|i| (i, levels[&i].index()))
403                .collect::<Vec<(ID, usize)>>();
404            for (i, l) in sublevels.iter().enumerate().skip(1) {
405                for (nl, ni) in &neighbors {
406                    if i != *ni {
407                        graph.add_edge(*l, levels[&nl].sublevels()[i], ());
408                    }
409                }
410            }
411            for l in sublevels.iter().skip(1) {
412                Self::connect_clusters(*l, graph, levels);
413            }
414        }
415    }
416
417    fn collect_platonic_levels(
418        id: ID,
419        levels: &HashMap<ID, Level<S>>,
420        platonic_levels: &mut HashSet<ID>,
421    ) {
422        let sublevels = levels[&id].sublevels();
423        if sublevels.is_empty() {
424            platonic_levels.insert(id);
425        } else {
426            for id in sublevels {
427                Self::collect_platonic_levels(*id, levels, platonic_levels);
428            }
429        }
430    }
431
432    fn recalculate_states(&mut self, id: ID) -> S {
433        let level = self.levels[&id].clone();
434        if level.sublevels().is_empty() {
435            level.state().clone()
436        } else {
437            let states = level
438                .sublevels()
439                .iter()
440                .map(|i| self.recalculate_states(*i))
441                .collect::<Vec<S>>();
442            let state = State::merge(&states);
443            self.levels.get_mut(&id).unwrap().apply_state(state.clone());
444            state
445        }
446    }
447
448    fn recalculate_children_states(&mut self, id: ID) {
449        let level = self.levels[&id].clone();
450        let states = level.state().subdivide(self.dimensions + 2);
451        for (id, state) in level.sublevels().iter().zip(states.into_iter()) {
452            self.levels.get_mut(&id).unwrap().apply_state(state);
453            self.recalculate_children_states(*id);
454        }
455    }
456
457    fn recalculate_parent_state(&mut self, id: ID) {
458        if let Some(id) = self.levels[&id].parent() {
459            let level = self.levels[&id].clone();
460            let states = level
461                .sublevels()
462                .iter()
463                .map(|i| self.levels[i].state().clone())
464                .collect::<Vec<S>>();
465            self.levels
466                .get_mut(&id)
467                .unwrap()
468                .apply_state(State::merge(&states));
469            self.recalculate_parent_state(id);
470        }
471    }
472}