conspire 0.7.0

The Rust interface to conspire.
Documentation
#[cfg(test)]
mod test;

use crate::{
    geometry::{
        Coordinate, Coordinates,
        grid::Voxels,
        mesh::{Connectivities, Connectivity, Mesh},
    },
    math::{Set, Tensor, TensorVec},
};
use std::collections::BTreeMap;

impl Mesh<3> {
    pub fn from_voxels<T>(voxels: Voxels<T>, remove: Option<&[T]>) -> Self
    where
        T: Copy + PartialEq + Into<usize>,
    {
        Self::from_voxels_embedded(
            voxels,
            remove,
            &Coordinate::from([1.0; 3]),
            &Coordinate::from([0.0; 3]),
        )
    }
    pub(super) fn from_voxels_embedded<T>(
        voxels: Voxels<T>,
        remove: Option<&[T]>,
        scale: &Coordinate<3>,
        translate: &Coordinate<3>,
    ) -> Self
    where
        T: Copy + PartialEq + Into<usize>,
    {
        let [nx, ny, nz] = *voxels.nel();
        let (nxp, nyp, nzp) = (nx + 1, ny + 1, nz + 1);
        let layer = nxp * nyp;
        let nodes_unfiltered = layer * nzp;
        let mut connectivity = Vec::with_capacity(voxels.len());
        let mut materials = Vec::with_capacity(voxels.len());
        let (mut i, mut j, mut k) = (0, 0, 0);
        for &block in voxels.data() {
            if remove.is_none_or(|ids| !ids.contains(&block)) {
                let base = i + nxp * j + layer * k;
                let top = base + layer;
                connectivity.push([
                    base,
                    base + 1,
                    base + nxp + 1,
                    base + nxp,
                    top,
                    top + 1,
                    top + nxp + 1,
                    top + nxp,
                ]);
                materials.push(block.into());
            }
            i += 1;
            if i == nx {
                i = 0;
                j += 1;
                if j == ny {
                    j = 0;
                    k += 1;
                }
            }
        }
        let mut used = vec![false; nodes_unfiltered];
        connectivity
            .iter()
            .for_each(|nodes| nodes.iter().for_each(|&node| used[node] = true));
        let mut mapping = vec![0usize; nodes_unfiltered];
        let mut coordinates = Coordinates::new();
        for (old, &is_used) in used.iter().enumerate() {
            if is_used {
                mapping[old] = coordinates.len();
                let x = old % nxp;
                let y = old / nxp % nyp;
                let z = old / layer;
                coordinates.push(Coordinate::const_from([
                    x as f64 * scale[0] + translate[0],
                    y as f64 * scale[1] + translate[1],
                    z as f64 * scale[2] + translate[2],
                ]));
            }
        }
        connectivity
            .iter_mut()
            .for_each(|nodes| nodes.iter_mut().for_each(|node| *node = mapping[*node]));
        let mut blocks = BTreeMap::<usize, Vec<_>>::new();
        connectivity
            .into_iter()
            .zip(materials)
            .for_each(|(nodes, material)| blocks.entry(material).or_default().push(nodes));
        let mut connectivities = Vec::with_capacity(blocks.len());
        let mut numbers = Vec::with_capacity(blocks.len());
        for (material, hexes) in blocks {
            numbers.push(material);
            connectivities.push(Connectivity::Hexahedral(hexes.into()));
        }
        (
            Connectivities::from((connectivities, numbers)),
            Set::from(coordinates),
        )
            .into()
    }
}