algebraeon_geometry/simplexes/
boolean_opperations.rs

1use std::collections::{HashMap, HashSet};
2
3use super::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum VennLabel {
7    Left,
8    Middle,
9    Right,
10}
11
12impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone> Simplex<FS, SP>
13where
14    FS::Set: Hash,
15{
16    pub fn venn(&self, other: &Self) -> LabelledPartialSimplicialComplex<FS, SP, VennLabel> {
17        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
18
19        let overlap = ConvexHull::intersect(
20            &ConvexHull::from_simplex(self.clone()),
21            &ConvexHull::from_simplex(other.clone()),
22        );
23
24        let mut self_ext = overlap.clone();
25        for pt in self.points() {
26            self_ext.extend_by_point(pt.clone());
27        }
28        let self_parts = self_ext
29            .as_simplicial_complex()
30            .subset_by_label(&InteriorBoundaryLabel::Interior)
31            .into_simplexes();
32
33        let mut other_ext = overlap.clone();
34        for pt in other.points() {
35            other_ext.extend_by_point(pt.clone());
36        }
37        let other_parts = other_ext
38            .as_simplicial_complex()
39            .subset_by_label(&InteriorBoundaryLabel::Interior)
40            .into_simplexes();
41
42        let all_parts = self_parts.union(&other_parts);
43        LabelledPartialSimplicialComplex::<FS, SP, VennLabel>::new_labelled_unchecked(
44            ambient_space.clone(),
45            all_parts
46                .into_iter()
47                .map(|spx| {
48                    let label = match (self_parts.contains(spx), other_parts.contains(spx)) {
49                        (true, false) => VennLabel::Left,
50                        (true, true) => VennLabel::Middle,
51                        (false, true) => VennLabel::Right,
52                        (false, false) => {
53                            unreachable!()
54                        }
55                    };
56                    (spx.clone(), label)
57                })
58                .collect(),
59        )
60    }
61}
62
63impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone, T: Eq + Clone>
64    LabelledSimplicialDisjointUnion<FS, SP, T>
65where
66    FS::Set: Hash,
67{
68    pub fn subtract_raw<S: Eq + Clone>(
69        &self,
70        other: &LabelledSimplicialDisjointUnion<FS, SP, S>,
71    ) -> LabelledSimplicialDisjointUnion<FS, SP, T> {
72        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
73
74        Self::new_labelled_unchecked(ambient_space.clone(), {
75            let mut simplexes = HashMap::new();
76            for (self_spx, self_spx_label) in self.labelled_simplexes() {
77                let mut self_leftover = HashSet::from([self_spx.clone()]);
78                for other_spx in other.simplexes() {
79                    self_leftover = self_leftover
80                        .into_iter()
81                        .map(|self_leftover_spx| {
82                            Simplex::venn(&self_leftover_spx, other_spx)
83                                .subset_by_label(&VennLabel::Left)
84                                .into_simplexes()
85                        })
86                        .flatten()
87                        .collect();
88                }
89                for spx in self_leftover {
90                    simplexes.insert(spx, self_spx_label.clone());
91                }
92            }
93            simplexes
94        })
95    }
96
97    pub fn intersection_raw<S: Eq + Clone>(
98        &self,
99        other: &LabelledSimplicialDisjointUnion<FS, SP, S>,
100    ) -> LabelledSimplicialDisjointUnion<FS, SP, (T, S)> {
101        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
102        LabelledSimplicialDisjointUnion::new_labelled_unchecked(ambient_space.clone(), {
103            let mut simplexes = HashMap::new();
104            for (self_spx, self_spx_label) in self.labelled_simplexes() {
105                for (other_spx, other_spx_label) in other.labelled_simplexes() {
106                    for spx in Simplex::venn(self_spx, other_spx)
107                        .subset_by_label(&VennLabel::Middle)
108                        .into_simplexes()
109                    {
110                        simplexes.insert(spx, (self_spx_label.clone(), other_spx_label.clone()));
111                    }
112                }
113            }
114            simplexes
115        })
116    }
117}
118
119impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
120    SimplicialDisjointUnion<FS, SP>
121where
122    FS::Set: Hash,
123{
124    pub fn union_raw(&self, other: &Self) -> SimplicialDisjointUnion<FS, SP> {
125        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
126        let mut simplexes = HashSet::new();
127        for spx in Self::subtract_raw(other, self).into_simplexes() {
128            simplexes.insert(spx);
129        }
130        for spx in self.simplexes() {
131            simplexes.insert(spx.clone());
132        }
133        return Self::new_unchecked(ambient_space, simplexes);
134    }
135}
136
137// impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
138//     PartialSimplicialComplex<FS, SP>
139// where
140//     FS::Set: Hash,
141// {
142//     pub fn union(&self, other: &Self) -> Self {
143//         self.union_raw(other).simplify()
144//     }
145
146//     pub fn union_raw(&self, other: &Self) -> Self {
147//         SimplicialComplex::union_raw(&self, other)
148//     }
149
150//     pub fn intersection_raw(&self, other: &Self) -> Self {
151//         SimplicialDisjointUnion::intersection_raw(&self.into(), &other.into())
152//             .refine_to_partial_simplicial_complex()
153//             .closure()
154//             .forget_labels()
155//             .into()
156//     }
157
158//     pub fn intersection(&self, other: &Self) -> Self {
159//         self.intersection_raw(other).simplify()
160//     }
161// }
162
163impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
164    SimplicialComplex<FS, SP>
165where
166    FS::Set: Hash,
167{
168    pub fn union_raw(&self, other: &Self) -> Self {
169        LabelledSimplicialDisjointUnion::union_raw(&self.into(), &other.into())
170            .refine_to_partial_simplicial_complex()
171            .try_as_simplicial_complex()
172            .unwrap()
173    }
174
175    pub fn union(&self, other: &Self) -> Self {
176        self.union_raw(other).simplify()
177    }
178
179    pub fn intersection_raw(&self, other: &Self) -> Self {
180        LabelledSimplicialDisjointUnion::intersection_raw(&self.into(), &other.into())
181            .refine_to_partial_simplicial_complex()
182            .apply_label_function(|_| ())
183            .try_as_simplicial_complex()
184            .unwrap()
185    }
186
187    pub fn intersection(&self, other: &Self) -> Self {
188        self.intersection_raw(other).simplify()
189    }
190}
191
192/*
193 - Venn dju <T1> and dju <T2> to produce dju <(Option<T1>, Option<T2>)>
194 - Replace partial simplicial complex (psc) with labelled simplicial complex <bool>
195 - Intersect psc, psc -> psc
196 - Union psc, psc -> psc
197 - Subtract psc, psc -> psc
198 - Have a trait for a collection of labelled simplexes
199   - Labelled subset
200   - Filtered labelled subset
201   - Union -> PartialSimplicialComplex
202   - Intersection -> PartialSimplicialComplex
203   - Difference -> PartialSimplicialComplex
204 - Implement it for:
205   - SimplexUnion
206   - SimplexDisjointUnion
207   - SemiSimplicialComplex
208   - SimplicialComplex
209*/