conspire 0.7.1

The Rust interface to conspire.
Documentation
mod laplace;
mod taubin;

use crate::{
    geometry::mesh::{Mesh, differential::laplace::Weighting},
    math::Scalar,
};

pub enum Smoothing {
    Laplace {
        iterations: usize,
        scale: Scalar,
        weighting: Weighting,
        preserve_boundary: bool,
        preserve_interfaces: bool,
    },
    Taubin {
        iterations: usize,
        pass_band: Scalar,
        scale: Scalar,
        weighting: Weighting,
        preserve_boundary: bool,
        preserve_interfaces: bool,
    },
}

impl<const D: usize> Mesh<D> {
    pub fn smooth(&mut self, smoothing: Smoothing) {
        match smoothing {
            Smoothing::Laplace {
                iterations,
                scale,
                weighting,
                preserve_boundary,
                preserve_interfaces,
            } => self.laplace_smooth(
                iterations,
                scale,
                weighting,
                preserve_boundary,
                preserve_interfaces,
            ),
            Smoothing::Taubin {
                iterations,
                pass_band,
                scale,
                weighting,
                preserve_boundary,
                preserve_interfaces,
            } => self.taubin_smooth(
                iterations,
                pass_band,
                scale,
                weighting,
                preserve_boundary,
                preserve_interfaces,
            ),
        }
    }
    fn constrained_adjacency(
        &self,
        preserve_boundary: bool,
        preserve_interfaces: bool,
    ) -> Vec<Vec<usize>> {
        let mut constrained = vec![false; self.number_of_nodes()];
        if preserve_boundary {
            self.exterior_faces()
                .iter()
                .flatten()
                .for_each(|&node| constrained[node] = true);
        }
        if preserve_interfaces {
            self.mark_interface_nodes(&mut constrained);
        }
        let mut adjacency: Vec<Vec<usize>> = self.node_node_connectivity().to_vec();
        adjacency
            .iter_mut()
            .enumerate()
            .filter(|(node, _)| constrained[*node])
            .for_each(|(_, neighbors)| neighbors.retain(|&other| constrained[other]));
        adjacency
    }
    fn mark_interface_nodes(&self, constrained: &mut [bool]) {
        let mut element_block = Vec::with_capacity(self.number_of_elements());
        for (block, connectivity) in self.connectivities().iter().enumerate() {
            element_block.resize(
                element_block.len() + connectivity.number_of_elements(),
                block,
            );
        }
        self.node_element_connectivity()
            .iter()
            .enumerate()
            .for_each(|(node, elements)| {
                let mut blocks = elements.iter().map(|&element| element_block[element]);
                if let Some(first) = blocks.next()
                    && blocks.any(|block| block != first)
                {
                    constrained[node] = true;
                }
            });
    }
}