rstmt_nrt/motion/
planner.rs

1/*
2    Appellation: motion <planner>
3    Contrib: @FL03
4*/
5use crate::motion::config::MotionPlannerConfig;
6use crate::motion::types::PathCache;
7use crate::tonnetz::StdHyperTonnetz;
8use core::hash::Hash;
9
10/// The [`MotionPlanner`] is a pathfinding algorithm implementation for finding the chain of
11/// transformations between two triads along the surface of the hyper-tonnetz.
12pub struct MotionPlanner<'a, T = usize>
13where
14    T: Eq + Hash,
15{
16    /// Cache for storing computed paths
17    pub(crate) cache: PathCache<T>,
18    /// Reference to the tonnetz graph
19    pub(crate) tonnetz: &'a StdHyperTonnetz<T>,
20    pub(crate) config: MotionPlannerConfig,
21}
22
23#[cfg(test)]
24mod tests {
25    use super::MotionPlanner;
26    use crate::tonnetz::HyperTonnetz;
27    use crate::triad::Triad;
28    use rstmt_core::Octave;
29
30    #[test]
31    fn test_motion_planner() -> crate::Result<()> {
32        // initialize an empty tonnetz
33        let mut tonnetz = HyperTonnetz::new();
34        // scaffold a layer for the 4th octave
35        let _ = tonnetz.scaffold_layer(Octave(4))?;
36
37        let c_major = Triad::major(0).dynamic(); // C Major (0,4,7)
38        // Add some common triads to the Tonnetz
39        let c_major_idx = tonnetz.add_triad(c_major)?; // C Major (0,4,7)
40
41        // Create a motion planner
42        let mut planner = MotionPlanner::new(&tonnetz).with_max_depth(4);
43
44        // Find paths from C Major to triads containing C# (1)
45        let target_note = 1; // C#
46        let paths = planner.find_paths_to_pitch(c_major_idx, target_note);
47
48        assert!(!paths.is_empty());
49        for path in paths {
50            assert!(path.triads().last().unwrap().contains(&target_note));
51        }
52
53        Ok(())
54    }
55}