Skip to main content

vtk_pure_rs/data/
attributes.rs

1use crate::data::{AnyDataArray, FieldData};
2
3/// Field data with "active" attribute designations for scalars, vectors, normals, etc.
4///
5/// Analogous to VTK's `vtkDataSetAttributes`.
6#[derive(Debug, Clone, Default, PartialEq)]
7pub struct DataSetAttributes {
8    field_data: FieldData,
9    active_scalars: Option<usize>,
10    active_vectors: Option<usize>,
11    active_normals: Option<usize>,
12    active_tcoords: Option<usize>,
13    active_tensors: Option<usize>,
14}
15
16impl DataSetAttributes {
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    pub fn field_data(&self) -> &FieldData {
22        &self.field_data
23    }
24
25    pub fn field_data_mut(&mut self) -> &mut FieldData {
26        &mut self.field_data
27    }
28
29    pub fn add_array(&mut self, array: AnyDataArray) {
30        self.field_data.add_array(array);
31    }
32
33    pub fn num_arrays(&self) -> usize {
34        self.field_data.num_arrays()
35    }
36
37    pub fn get_array(&self, name: &str) -> Option<&AnyDataArray> {
38        self.field_data.get_array(name)
39    }
40
41    pub fn get_array_by_index(&self, idx: usize) -> Option<&AnyDataArray> {
42        self.field_data.get_array_by_index(idx)
43    }
44
45    // Active attribute setters/getters
46
47    pub fn set_active_scalars(&mut self, name: &str) -> bool {
48        if let Some(idx) = self.find_index(name) {
49            self.active_scalars = Some(idx);
50            true
51        } else {
52            false
53        }
54    }
55
56    pub fn set_active_vectors(&mut self, name: &str) -> bool {
57        if let Some(idx) = self.find_index(name) {
58            self.active_vectors = Some(idx);
59            true
60        } else {
61            false
62        }
63    }
64
65    pub fn set_active_normals(&mut self, name: &str) -> bool {
66        if let Some(idx) = self.find_index(name) {
67            self.active_normals = Some(idx);
68            true
69        } else {
70            false
71        }
72    }
73
74    pub fn set_active_tcoords(&mut self, name: &str) -> bool {
75        if let Some(idx) = self.find_index(name) {
76            self.active_tcoords = Some(idx);
77            true
78        } else {
79            false
80        }
81    }
82
83    pub fn set_active_tensors(&mut self, name: &str) -> bool {
84        if let Some(idx) = self.find_index(name) {
85            self.active_tensors = Some(idx);
86            true
87        } else {
88            false
89        }
90    }
91
92    pub fn scalars(&self) -> Option<&AnyDataArray> {
93        self.active_scalars.and_then(|i| self.field_data.get_array_by_index(i))
94    }
95
96    pub fn vectors(&self) -> Option<&AnyDataArray> {
97        self.active_vectors.and_then(|i| self.field_data.get_array_by_index(i))
98    }
99
100    pub fn normals(&self) -> Option<&AnyDataArray> {
101        self.active_normals.and_then(|i| self.field_data.get_array_by_index(i))
102    }
103
104    pub fn tcoords(&self) -> Option<&AnyDataArray> {
105        self.active_tcoords.and_then(|i| self.field_data.get_array_by_index(i))
106    }
107
108    pub fn tensors(&self) -> Option<&AnyDataArray> {
109        self.active_tensors.and_then(|i| self.field_data.get_array_by_index(i))
110    }
111
112    /// Check if an array with the given name exists.
113    pub fn has_array(&self, name: &str) -> bool {
114        self.field_data.has_array(name)
115    }
116
117    /// Get all array names.
118    pub fn array_names(&self) -> Vec<&str> {
119        self.field_data.names()
120    }
121
122    /// Remove an array by name. Adjusts active attribute indices.
123    pub fn remove_array(&mut self, name: &str) -> Option<AnyDataArray> {
124        let idx = self.find_index(name);
125        let result = self.field_data.remove_array(name);
126        if let Some(removed_idx) = idx {
127            self.adjust_active_after_remove(removed_idx);
128        }
129        result
130    }
131
132    /// Remove all arrays and clear active attributes.
133    pub fn clear(&mut self) {
134        self.field_data.clear();
135        self.active_scalars = None;
136        self.active_vectors = None;
137        self.active_normals = None;
138        self.active_tcoords = None;
139        self.active_tensors = None;
140    }
141
142    /// Check if any active attributes are set.
143    pub fn has_active_attributes(&self) -> bool {
144        self.active_scalars.is_some()
145            || self.active_vectors.is_some()
146            || self.active_normals.is_some()
147            || self.active_tcoords.is_some()
148            || self.active_tensors.is_some()
149    }
150
151    /// Iterate over all arrays.
152    pub fn iter(&self) -> impl Iterator<Item = &AnyDataArray> {
153        self.field_data.iter()
154    }
155
156    fn find_index(&self, name: &str) -> Option<usize> {
157        (0..self.field_data.num_arrays())
158            .find(|&i| self.field_data.get_array_by_index(i).map(|a| a.name()) == Some(name))
159    }
160
161    fn adjust_active_after_remove(&mut self, removed: usize) {
162        fn adjust(active: &mut Option<usize>, removed: usize) {
163            *active = match *active {
164                Some(i) if i == removed => None,
165                Some(i) if i > removed => Some(i - 1),
166                other => other,
167            };
168        }
169        adjust(&mut self.active_scalars, removed);
170        adjust(&mut self.active_vectors, removed);
171        adjust(&mut self.active_normals, removed);
172        adjust(&mut self.active_tcoords, removed);
173        adjust(&mut self.active_tensors, removed);
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::data::DataArray;
181
182    #[test]
183    fn add_and_get() {
184        let mut attrs = DataSetAttributes::new();
185        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("temp", vec![1.0, 2.0, 3.0], 1)));
186        assert_eq!(attrs.num_arrays(), 1);
187        assert!(attrs.has_array("temp"));
188    }
189
190    #[test]
191    fn active_scalars() {
192        let mut attrs = DataSetAttributes::new();
193        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("temp", vec![1.0], 1)));
194        attrs.set_active_scalars("temp");
195        assert!(attrs.scalars().is_some());
196        assert_eq!(attrs.scalars().unwrap().name(), "temp");
197    }
198
199    #[test]
200    fn active_normals() {
201        let mut attrs = DataSetAttributes::new();
202        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("N", vec![0.0, 0.0, 1.0], 3)));
203        attrs.set_active_normals("N");
204        assert!(attrs.normals().is_some());
205    }
206
207    #[test]
208    fn remove_adjusts_active() {
209        let mut attrs = DataSetAttributes::new();
210        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("a", vec![1.0], 1)));
211        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("b", vec![2.0], 1)));
212        attrs.set_active_scalars("b");
213        attrs.remove_array("a");
214        assert!(attrs.scalars().is_some());
215        assert_eq!(attrs.scalars().unwrap().name(), "b");
216    }
217
218    #[test]
219    fn remove_active_clears() {
220        let mut attrs = DataSetAttributes::new();
221        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("x", vec![1.0], 1)));
222        attrs.set_active_scalars("x");
223        attrs.remove_array("x");
224        assert!(attrs.scalars().is_none());
225    }
226
227    #[test]
228    fn array_names() {
229        let mut attrs = DataSetAttributes::new();
230        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("a", vec![1.0], 1)));
231        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("b", vec![2.0], 1)));
232        assert_eq!(attrs.array_names(), vec!["a", "b"]);
233    }
234
235    #[test]
236    fn has_active() {
237        let mut attrs = DataSetAttributes::new();
238        assert!(!attrs.has_active_attributes());
239        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("s", vec![1.0], 1)));
240        attrs.set_active_scalars("s");
241        assert!(attrs.has_active_attributes());
242    }
243
244    #[test]
245    fn iterate() {
246        let mut attrs = DataSetAttributes::new();
247        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("x", vec![1.0], 1)));
248        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("y", vec![2.0], 1)));
249        let names: Vec<&str> = attrs.iter().map(|a| a.name()).collect();
250        assert_eq!(names, vec!["x", "y"]);
251    }
252
253    #[test]
254    fn clear() {
255        let mut attrs = DataSetAttributes::new();
256        attrs.add_array(AnyDataArray::F64(DataArray::from_vec("a", vec![1.0], 1)));
257        attrs.set_active_scalars("a");
258        assert_eq!(attrs.num_arrays(), 1);
259        assert!(attrs.has_active_attributes());
260
261        attrs.clear();
262        assert_eq!(attrs.num_arrays(), 0);
263        assert!(!attrs.has_active_attributes());
264        assert!(attrs.scalars().is_none());
265    }
266}