algebraeon-geometry 0.0.17

Algorithms for working with geometric shapes
Documentation
use super::*;
use crate::{
    ambient_space::AffineSpace,
    simplex::Simplex,
    simplex_collection::LabelledSimplexCollection,
    simplicial_complex::{LabelledSimplicialComplex, SimplicialComplex},
    simplicial_disjoint_union::LabelledSimplicialDisjointUnion,
};
use std::collections::{HashMap, HashSet};

#[derive(Clone)]
pub struct LabelledPartialSimplicialComplex<
    'f,
    FS: OrderedRingSignature + FieldSignature,
    T: Eq + Clone + Send + Sync,
> {
    ambient_space: AffineSpace<'f, FS>,
    simplexes: HashMap<Simplex<'f, FS>, T>,
}

pub type PartialSimplicialComplex<'f, FS> = LabelledPartialSimplicialComplex<'f, FS, ()>;

impl<'f, FS: OrderedRingSignature + FieldSignature> std::fmt::Debug
    for PartialSimplicialComplex<'f, FS>
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("PartialSimplicialComplex")
            .field("simplexes", &self.simplexes)
            .finish()
    }
}

impl<'f, FS: OrderedRingSignature + FieldSignature, T: Eq + Clone + Send + Sync>
    LabelledSimplexCollection<'f, FS, T> for LabelledPartialSimplicialComplex<'f, FS, T>
where
    FS::Set: Hash,
{
    type WithLabel<S: Eq + Clone + Send + Sync> = LabelledPartialSimplicialComplex<'f, FS, S>;
    type SubsetType = LabelledPartialSimplicialComplex<'f, FS, T>;

    fn try_new_labelled(
        ambient_space: AffineSpace<'f, FS>,
        simplexes: std::collections::HashMap<Simplex<'f, FS>, T>,
    ) -> Result<Self, &'static str> {
        Ok(Self {
            ambient_space,
            simplexes,
        })
    }

    fn new_labelled_unchecked(
        ambient_space: AffineSpace<'f, FS>,
        simplexes: std::collections::HashMap<Simplex<'f, FS>, T>,
    ) -> Self {
        Self::try_new_labelled(ambient_space, simplexes).unwrap()
    }

    fn ambient_space(&self) -> AffineSpace<'f, FS> {
        self.ambient_space
    }

    fn labelled_simplexes(&self) -> std::collections::HashMap<&Simplex<'f, FS>, &T> {
        self.simplexes.iter().collect()
    }

    fn into_labelled_simplexes(self) -> std::collections::HashMap<Simplex<'f, FS>, T> {
        self.simplexes
    }

    fn into_partial_simplicial_complex(self) -> LabelledPartialSimplicialComplex<'f, FS, T> {
        self
    }

    fn to_partial_simplicial_complex(&self) -> LabelledPartialSimplicialComplex<'f, FS, T> {
        self.clone()
    }

    fn into_simplicial_disjoint_union(self) -> LabelledSimplicialDisjointUnion<'f, FS, T> {
        LabelledSimplicialDisjointUnion::new_labelled_unchecked(self.ambient_space, self.simplexes)
    }

    fn to_simplicial_disjoint_union(&self) -> LabelledSimplicialDisjointUnion<'f, FS, T> {
        self.clone().into_simplicial_disjoint_union()
    }
}

impl<'f, FS: OrderedRingSignature + FieldSignature, T: Eq + Clone + Send + Sync>
    LabelledPartialSimplicialComplex<'f, FS, T>
where
    FS::Set: Hash,
{
    pub fn try_into_simplicial_complex(
        self,
    ) -> Result<LabelledSimplicialComplex<'f, FS, T>, &'static str> {
        LabelledSimplicialComplex::try_new_labelled(self.ambient_space, self.simplexes)
    }

    pub fn into_labelled_simplicial_complex(&self) -> LabelledSimplicialComplex<'f, FS, Option<T>> {
        let mut simplexes = HashSet::new();
        for spx in self.simplexes.keys() {
            for bdry in spx.sub_simplices_not_null() {
                simplexes.insert(bdry);
            }
        }
        LabelledSimplicialComplex::try_new_labelled(
            self.ambient_space(),
            simplexes
                .into_iter()
                .map(|spx| {
                    let label = self.simplexes.get(&spx).cloned();
                    (spx, label)
                })
                .collect(),
        )
        .unwrap()
    }

    pub fn simplify(&self) -> Self {
        self.into_labelled_simplicial_complex()
            .simplify()
            .subset_by_filter(|label| label.is_some())
            .apply_label_function(|label| label.clone().unwrap())
    }
}

impl<'f, FS: OrderedRingSignature + FieldSignature> PartialSimplicialComplex<'f, FS>
where
    FS::Set: Hash,
{
    pub fn closure(&self) -> SimplicialComplex<'f, FS> {
        self.into_labelled_simplicial_complex().forget_labels()
    }
}