trk_io/
tractogram.rs

1use nalgebra::Point3;
2
3use crate::ArraySequence;
4
5pub type Point = Point3<f32>;
6pub type Points = Vec<Point>;
7pub type Streamlines = ArraySequence<Point>;
8
9pub type TractogramItem = (Points, ArraySequence<f32>, Vec<f32>);
10pub type RefTractogramItem<'data> = (&'data [Point], &'data [f32], &'data [f32]);
11
12#[derive(Clone, PartialEq)]
13pub struct Tractogram {
14    pub streamlines: Streamlines,
15    pub scalars: ArraySequence<f32>,
16    pub properties: ArraySequence<f32>,
17}
18
19impl Tractogram {
20    pub fn new(
21        streamlines: Streamlines,
22        scalars: ArraySequence<f32>,
23        properties: ArraySequence<f32>,
24    ) -> Tractogram {
25        Tractogram { streamlines, scalars, properties }
26    }
27
28    pub fn item(&self, idx: usize) -> RefTractogramItem {
29        // Do not use .get(idx).unwrap_or(). The empty slice is valid only if the ArraySequence are
30        // empty. It should crash if the index is invalid.
31        let scalars = if self.scalars.is_empty() { &[] } else { &self.scalars[idx] };
32        let properties = if self.properties.is_empty() { &[] } else { &self.properties[idx] };
33        (&self.streamlines[idx], scalars, properties)
34    }
35}
36
37impl<'data> IntoIterator for &'data Tractogram {
38    type Item = RefTractogramItem<'data>;
39    type IntoIter = TractogramIterator<'data>;
40
41    fn into_iter(self) -> Self::IntoIter {
42        TractogramIterator { tractogram: self, index: 0..self.streamlines.len() }
43    }
44}
45
46pub struct TractogramIterator<'data> {
47    tractogram: &'data Tractogram,
48    index: std::ops::Range<usize>,
49}
50
51impl<'data> Iterator for TractogramIterator<'data> {
52    type Item = RefTractogramItem<'data>;
53
54    fn next(&mut self) -> Option<Self::Item> {
55        let idx = self.index.next()?;
56        Some(self.tractogram.item(idx))
57    }
58
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        (0, Some(self.tractogram.streamlines.len()))
61    }
62}
63
64impl<'data> ExactSizeIterator for TractogramIterator<'data> {}
65
66impl<'data> DoubleEndedIterator for TractogramIterator<'data> {
67    fn next_back(&mut self) -> Option<Self::Item> {
68        let idx = self.index.next_back()?;
69        Some(self.tractogram.item(idx))
70    }
71}