use crate::data::{AnyDataArray, DataArray, ImageData};
pub fn compute_magnitude(input: &ImageData, array_name: &str) -> ImageData {
let arr = match input.point_data().get_array(array_name) {
Some(a) => a,
None => return input.clone(),
};
let nc: usize = arr.num_components();
let nt: usize = arr.num_tuples();
let mut magnitudes: Vec<f64> = Vec::with_capacity(nt);
let mut buf: Vec<f64> = vec![0.0; nc];
for i in 0..nt {
arr.tuple_as_f64(i, &mut buf);
let mut sum_sq: f64 = 0.0;
for c in 0..nc {
sum_sq += buf[c] * buf[c];
}
magnitudes.push(sum_sq.sqrt());
}
let mut img = input.clone();
img.point_data_mut().add_array(AnyDataArray::F64(
DataArray::from_vec("Magnitude", magnitudes, 1),
));
img
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn three_four_five() {
let mut img = ImageData::with_dimensions(2, 1, 1);
img.point_data_mut().add_array(AnyDataArray::F64(
DataArray::from_vec("Vectors", vec![3.0, 4.0, 0.0, 0.0, 0.0, 5.0], 3),
));
let result = compute_magnitude(&img, "Vectors");
let mag = result.point_data().get_array("Magnitude").unwrap();
assert_eq!(mag.num_components(), 1);
assert_eq!(mag.num_tuples(), 2);
let mut val = [0.0f64];
mag.tuple_as_f64(0, &mut val);
assert!((val[0] - 5.0).abs() < 1e-10, "expected 5, got {}", val[0]);
mag.tuple_as_f64(1, &mut val);
assert!((val[0] - 5.0).abs() < 1e-10, "expected 5, got {}", val[0]);
}
#[test]
fn single_component_is_abs() {
let mut img = ImageData::with_dimensions(3, 1, 1);
img.point_data_mut().add_array(AnyDataArray::F64(
DataArray::from_vec("Scalars", vec![-2.0, 0.0, 3.0], 1),
));
let result = compute_magnitude(&img, "Scalars");
let mag = result.point_data().get_array("Magnitude").unwrap();
let mut val = [0.0f64];
mag.tuple_as_f64(0, &mut val);
assert!((val[0] - 2.0).abs() < 1e-10);
mag.tuple_as_f64(1, &mut val);
assert!((val[0]).abs() < 1e-10);
mag.tuple_as_f64(2, &mut val);
assert!((val[0] - 3.0).abs() < 1e-10);
}
#[test]
fn missing_array_returns_clone() {
let img = ImageData::with_dimensions(2, 2, 2);
let result = compute_magnitude(&img, "nonexistent");
assert!(result.point_data().get_array("Magnitude").is_none());
}
}