use crate::data::{CellArray, DataArray, DataSet, Points, PolyData};
pub fn threshold(input: &PolyData, lower: f64, upper: f64) -> PolyData {
let scalars = match input.point_data().scalars() {
Some(s) => s,
None => return input.clone(),
};
let n = input.num_points();
let mut values = vec![0.0f64; n];
let mut buf = [0.0f64];
for (i, val) in values.iter_mut().enumerate() {
scalars.tuple_as_f64(i, &mut buf);
*val = buf[0];
}
let mut point_used = vec![false; n];
let mut kept_cells: Vec<Vec<i64>> = Vec::new();
for cell in input.polys.iter() {
let all_in_range = cell.iter().all(|&id| {
let v = values[id as usize];
v >= lower && v <= upper
});
if all_in_range {
for &id in cell {
point_used[id as usize] = true;
}
kept_cells.push(cell.to_vec());
}
}
let mut point_map = vec![0i64; n];
let mut new_points = Points::<f64>::new();
let mut new_scalars = DataArray::<f64>::new(scalars.name(), 1);
for (old_id, &used) in point_used.iter().enumerate() {
if used {
point_map[old_id] = new_points.len() as i64;
new_points.push(input.points.get(old_id));
new_scalars.push_tuple(&[values[old_id]]);
}
}
let mut polys = CellArray::new();
for cell in &kept_cells {
let remapped: Vec<i64> = cell.iter().map(|&id| point_map[id as usize]).collect();
polys.push_cell(&remapped);
}
let mut output = PolyData::new();
output.points = new_points;
output.polys = polys;
output.point_data_mut().add_array(new_scalars.into());
output
.point_data_mut()
.set_active_scalars(scalars.name());
output
}
pub fn threshold_above(input: &PolyData, value: f64) -> PolyData {
threshold(input, value, f64::INFINITY)
}
pub fn threshold_below(input: &PolyData, value: f64) -> PolyData {
threshold(input, f64::NEG_INFINITY, value)
}
#[cfg(test)]
mod tests {
use super::*;
fn make_test_data() -> PolyData {
let mut pd = PolyData::from_triangles(
vec![
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[2.0, 0.0, 0.0],
],
vec![[0, 1, 2], [1, 3, 2]],
);
let scalars = DataArray::from_vec("temp", vec![0.0, 5.0, 10.0, 15.0], 1);
pd.point_data_mut().add_array(scalars.into());
pd.point_data_mut().set_active_scalars("temp");
pd
}
#[test]
fn threshold_range() {
let pd = make_test_data();
let result = threshold(&pd, 0.0, 10.0);
assert_eq!(result.polys.num_cells(), 1);
}
#[test]
fn threshold_keeps_all() {
let pd = make_test_data();
let result = threshold(&pd, -100.0, 100.0);
assert_eq!(result.polys.num_cells(), 2);
}
#[test]
fn threshold_removes_all() {
let pd = make_test_data();
let result = threshold(&pd, 100.0, 200.0);
assert_eq!(result.polys.num_cells(), 0);
}
}