use super::*;
use crate::{
ambient_space::AffineSpace,
convex_hull::ConvexHull,
partial_simplicial_complex::LabelledPartialSimplicialComplex,
simplex::Simplex,
simplex_collection::{InteriorOrBoundarySimplexCollection, LabelledSimplexCollection},
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use std::collections::{HashMap, HashSet};
#[derive(Clone)]
pub struct LabelledSimplicialDisjointUnion<
'f,
FS: OrderedRingSignature + FieldSignature,
T: Eq + Clone + Send + Sync,
> where
FS::Set: Hash,
{
ambient_space: AffineSpace<'f, FS>,
simplexes: HashMap<Simplex<'f, FS>, T>,
}
pub type SimplicialDisjointUnion<'f, FS> = LabelledSimplicialDisjointUnion<'f, FS, ()>;
impl<'f, FS: OrderedRingSignature + FieldSignature, T: Eq + Clone + Send + Sync>
LabelledSimplexCollection<'f, FS, T> for LabelledSimplicialDisjointUnion<'f, FS, T>
where
FS::Set: Hash,
{
type WithLabel<S: Eq + Clone + Send + Sync> = LabelledSimplicialDisjointUnion<'f, FS, S>;
type SubsetType = LabelledSimplicialDisjointUnion<'f, FS, T>;
fn try_new_labelled(
ambient_space: AffineSpace<'f, FS>,
simplexes: HashMap<Simplex<'f, FS>, T>,
) -> Result<Self, &'static str> {
Ok(Self {
ambient_space,
simplexes,
})
}
fn new_labelled_unchecked(
ambient_space: AffineSpace<'f, FS>,
simplexes: HashMap<Simplex<'f, FS>, T>,
) -> Self {
let s = Self {
ambient_space,
simplexes,
};
#[cfg(debug_assertions)]
s.check();
s
}
fn ambient_space(&self) -> AffineSpace<'f, FS> {
self.ambient_space
}
fn labelled_simplexes(&self) -> HashMap<&Simplex<'f, FS>, &T> {
self.simplexes.iter().collect()
}
fn into_labelled_simplexes(self) -> HashMap<Simplex<'f, FS>, T> {
self.simplexes
}
fn into_partial_simplicial_complex(self) -> LabelledPartialSimplicialComplex<'f, FS, T> {
self.refine_into_partial_simplicial_complex()
}
fn to_partial_simplicial_complex(&self) -> LabelledPartialSimplicialComplex<'f, FS, T> {
self.clone().refine_into_partial_simplicial_complex()
}
fn into_simplicial_disjoint_union(self) -> LabelledSimplicialDisjointUnion<'f, FS, T> {
self
}
fn to_simplicial_disjoint_union(&self) -> LabelledSimplicialDisjointUnion<'f, FS, T> {
self.clone()
}
}
impl<'f, FS: OrderedRingSignature + FieldSignature, T: Eq + Clone + Send + Sync>
LabelledSimplicialDisjointUnion<'f, FS, T>
where
FS::Set: Hash,
{
#[allow(unused)]
pub(crate) fn check(&self) {
for spx_a in self.simplexes.keys() {
for spx_b in self.simplexes.keys() {
let bdry_a = spx_a
.sub_simplices_not_null()
.into_iter()
.collect::<HashSet<_>>();
let bdry_b = spx_b
.sub_simplices_not_null()
.into_iter()
.collect::<HashSet<_>>();
if !bdry_a.contains(spx_b) && !bdry_b.contains(spx_a) {
let overlap = ConvexHull::intersect(
&ConvexHull::from_simplex(spx_a.clone()),
&ConvexHull::from_simplex(spx_b.clone()),
);
if !(overlap.affine_span_dimension() < spx_a.n()
&& overlap.affine_span_dimension() < spx_b.n())
{
println!("spx_a = {spx_a:?}");
println!("spx_b = {spx_b:?}");
panic!("simplicial complex simplex overlap");
}
}
}
}
}
pub fn into_partial_simplicial_complex(self) -> LabelledPartialSimplicialComplex<'f, FS, T> {
self.refine_into_partial_simplicial_complex().simplify()
}
pub fn refine_into_partial_simplicial_complex(
mut self,
) -> LabelledPartialSimplicialComplex<'f, FS, T> {
let ambient_space = self.ambient_space();
let mut pairs_todo: HashMap<Simplex<'f, FS>, HashSet<Simplex<'f, FS>>> = HashMap::new();
let simplexes = self.simplexes().into_iter().collect::<Vec<_>>();
for (spx_i, spx_j) in (0..simplexes.len())
.flat_map(|i| ((i + 1)..simplexes.len()).map(move |j| (i, j)))
.collect::<Vec<_>>()
.into_par_iter()
.filter_map(|(i, j)| {
let spx_i = simplexes[i];
let spx_j = simplexes[j];
if simplex_overlap::simplex_closure_overlap(spx_i, spx_j) {
Some((spx_i, spx_j))
} else {
None
}
})
.collect::<Vec<_>>()
{
pairs_todo
.entry(spx_i.clone())
.or_default()
.insert(spx_j.clone());
pairs_todo
.entry(spx_j.clone())
.or_default()
.insert(spx_i.clone());
}
while !pairs_todo.is_empty() {
let spx1 = pairs_todo.keys().next().unwrap().clone();
match pairs_todo.get(&spx1).unwrap().iter().next().cloned() {
None => {
pairs_todo.remove(&spx1);
}
Some(spx2) => {
pairs_todo.get_mut(&spx1).unwrap().remove(&spx2);
pairs_todo.get_mut(&spx2).unwrap().remove(&spx1);
debug_assert_ne!(spx1, spx2);
debug_assert!(self.simplexes.contains_key(&spx1));
debug_assert!(self.simplexes.contains_key(&spx2));
let overlap = ConvexHull::intersect(
&ConvexHull::from_simplex(spx1.clone()),
&ConvexHull::from_simplex(spx2.clone()),
);
if !overlap.is_empty()
&& match ambient_space
.simplex(overlap.defining_points().into_iter().collect())
{
Ok(overlap_spx) => {
let spx1_points = spx1.points().iter().collect::<HashSet<_>>();
let spx2_points = spx2.points().iter().collect::<HashSet<_>>();
!overlap_spx
.points()
.iter()
.all(|pt| spx1_points.contains(pt) && spx2_points.contains(pt))
}
Err(_) => true,
}
{
let mut spx1_replacement = overlap.clone();
for pt in spx1.points() {
spx1_replacement.extend_by_point(pt.clone());
}
let mut spx2_replacement = overlap.clone();
for pt in spx2.points() {
spx2_replacement.extend_by_point(pt.clone());
}
let mut spx1_paired = vec![];
for spx in pairs_todo.get(&spx1).unwrap_or(&HashSet::new()).clone() {
debug_assert_ne!(spx, spx1);
debug_assert_ne!(spx, spx2);
debug_assert!(self.simplexes.contains_key(&spx));
pairs_todo
.get_mut(&spx)
.unwrap_or(&mut HashSet::new())
.remove(&spx1);
spx1_paired.push(spx);
}
pairs_todo.remove(&spx1);
let mut spx2_paired = vec![];
for spx in pairs_todo.get(&spx2).unwrap_or(&HashSet::new()).clone() {
debug_assert_ne!(spx, spx1);
debug_assert_ne!(spx, spx2);
debug_assert!(self.simplexes.contains_key(&spx));
pairs_todo
.get_mut(&spx)
.unwrap_or(&mut HashSet::new())
.remove(&spx2);
spx2_paired.push(spx);
}
pairs_todo.remove(&spx2);
let spx1_label = self.simplexes.get(&spx1).unwrap().clone();
let spx2_label = self.simplexes.get(&spx2).unwrap().clone();
self.simplexes.remove(&spx1);
self.simplexes.remove(&spx2);
for spx1_repl in spx1_replacement
.to_simplicial_complex()
.interior()
.into_simplexes()
{
for spx in &spx1_paired {
pairs_todo
.entry(spx1_repl.clone())
.or_default()
.insert(spx.clone());
pairs_todo
.entry(spx.clone())
.or_default()
.insert(spx1_repl.clone());
}
self.simplexes.insert(spx1_repl, spx1_label.clone());
}
for spx2_repl in spx2_replacement
.to_simplicial_complex()
.interior()
.into_simplexes()
{
for spx in &spx2_paired {
pairs_todo
.entry(spx2_repl.clone())
.or_default()
.insert(spx.clone());
pairs_todo
.entry(spx.clone())
.or_default()
.insert(spx2_repl.clone());
}
self.simplexes.insert(spx2_repl, spx2_label.clone());
}
}
}
}
}
LabelledPartialSimplicialComplex::new_labelled_unchecked(ambient_space, self.simplexes)
}
}