autofoam 0.3.1

autofoam and related tools
Documentation
use super::reader::{get_poly_data, get_poly_data_mut};
use std::error::Error;
use vtkio::model::{Attribute, DataArray, ElementType, IOBuffer};
use vtkio::Vtk;

pub struct FieldManager;

impl FieldManager {
    pub fn get_field(vtk: &Vtk, field_name: &str) -> Result<Vec<f64>, Box<dyn Error>> {
        let poly_data = get_poly_data(vtk)?;

        let field_data = poly_data
            .data
            .cell
            .iter()
            .find_map(|attr| match attr {
                Attribute::DataArray(arr) if arr.name == field_name => Some(&arr.data),
                _ => None,
            })
            .ok_or_else(|| format!("Field '{}' not found", field_name))?;

        Self::convert_to_f64(field_data, field_name)
    }

    pub fn list_fields(vtk: &Vtk) -> Result<Vec<String>, Box<dyn Error>> {
        let poly_data = get_poly_data(vtk)?;
        Ok(poly_data
            .data
            .cell
            .iter()
            .filter_map(|attr| match attr {
                Attribute::DataArray(arr) => Some(arr.name.clone()),
                _ => None,
            })
            .collect())
    }

    pub fn field_exists(vtk: &Vtk, field_name: &str) -> Result<bool, Box<dyn Error>> {
        let poly_data = get_poly_data(vtk)?;
        Ok(poly_data
            .data
            .cell
            .iter()
            .any(|attr| matches!(attr, Attribute::DataArray(arr) if arr.name == field_name)))
    }

    pub fn remove_field(vtk: &mut Vtk, field_name: &str) -> Result<(), Box<dyn Error>> {
        let poly_data = get_poly_data_mut(vtk)?;
        if let Some(pos) =
            poly_data.data.cell.iter().position(
                |attr| matches!(attr, Attribute::DataArray(arr) if arr.name == field_name),
            )
        {
            poly_data.data.cell.remove(pos);
        }
        Ok(())
    }

    pub fn add_field(vtk: &mut Vtk, field_name: &str, data: &[f64]) -> Result<(), Box<dyn Error>> {
        if Self::field_exists(vtk, field_name)? {
            return Err(format!("Field '{}' already exists", field_name).into());
        }

        let poly_data = get_poly_data_mut(vtk)?;
        let data_array = DataArray {
            name: field_name.to_string(),
            elem: ElementType::Scalars {
                num_comp: 1,
                lookup_table: None,
            },
            data: IOBuffer::F64(data.to_vec()),
        };

        poly_data.data.cell.push(Attribute::DataArray(data_array));
        Ok(())
    }

    fn convert_to_f64(buffer: &IOBuffer, field_name: &str) -> Result<Vec<f64>, Box<dyn Error>> {
        match buffer {
            IOBuffer::F64(data) => Ok(data.clone()),
            IOBuffer::F32(data) => Ok(data.iter().map(|&x| x as f64).collect()),
            _ => Err(format!("Unsupported data type for field '{}'", field_name).into()),
        }
    }
}