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<
64        FS: OrderedRingStructure + FieldStructure,
65        SP: Borrow<AffineSpace<FS>> + Clone,
66        T: Eq + Clone,
67    > LabelledSimplicialDisjointUnion<FS, SP, T>
68where
69    FS::Set: Hash,
70{
71    pub fn subtract_raw<S: Eq + Clone>(
72        &self,
73        other: &LabelledSimplicialDisjointUnion<FS, SP, S>,
74    ) -> LabelledSimplicialDisjointUnion<FS, SP, T> {
75        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
76
77        Self::new_labelled_unchecked(ambient_space.clone(), {
78            let mut simplexes = HashMap::new();
79            for (self_spx, self_spx_label) in self.labelled_simplexes() {
80                let mut self_leftover = HashSet::from([self_spx.clone()]);
81                for other_spx in other.simplexes() {
82                    self_leftover = self_leftover
83                        .into_iter()
84                        .map(|self_leftover_spx| {
85                            Simplex::venn(&self_leftover_spx, other_spx)
86                                .subset_by_label(&VennLabel::Left)
87                                .into_simplexes()
88                        })
89                        .flatten()
90                        .collect();
91                }
92                for spx in self_leftover {
93                    simplexes.insert(spx, self_spx_label.clone());
94                }
95            }
96            simplexes
97        })
98    }
99
100    pub fn intersection_raw<S: Eq + Clone>(
101        &self,
102        other: &LabelledSimplicialDisjointUnion<FS, SP, S>,
103    ) -> LabelledSimplicialDisjointUnion<FS, SP, (T, S)> {
104        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
105        LabelledSimplicialDisjointUnion::new_labelled_unchecked(ambient_space.clone(), {
106            let mut simplexes = HashMap::new();
107            for (self_spx, self_spx_label) in self.labelled_simplexes() {
108                for (other_spx, other_spx_label) in other.labelled_simplexes() {
109                    for spx in Simplex::venn(self_spx, other_spx)
110                        .subset_by_label(&VennLabel::Middle)
111                        .into_simplexes()
112                    {
113                        simplexes.insert(spx, (self_spx_label.clone(), other_spx_label.clone()));
114                    }
115                }
116            }
117            simplexes
118        })
119    }
120}
121
122impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
123    SimplicialDisjointUnion<FS, SP>
124where
125    FS::Set: Hash,
126{
127    pub fn union_raw(&self, other: &Self) -> SimplicialDisjointUnion<FS, SP> {
128        let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
129        let mut simplexes = HashSet::new();
130        for spx in Self::subtract_raw(other, self).into_simplexes() {
131            simplexes.insert(spx);
132        }
133        for spx in self.simplexes() {
134            simplexes.insert(spx.clone());
135        }
136        return Self::new_unchecked(ambient_space, simplexes);
137    }
138}
139
140// impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
141//     PartialSimplicialComplex<FS, SP>
142// where
143//     FS::Set: Hash,
144// {
145//     pub fn union(&self, other: &Self) -> Self {
146//         self.union_raw(other).simplify()
147//     }
148
149//     pub fn union_raw(&self, other: &Self) -> Self {
150//         SimplicialComplex::union_raw(&self, other)
151//     }
152
153//     pub fn intersection_raw(&self, other: &Self) -> Self {
154//         SimplicialDisjointUnion::intersection_raw(&self.into(), &other.into())
155//             .refine_to_partial_simplicial_complex()
156//             .closure()
157//             .forget_labels()
158//             .into()
159//     }
160
161//     pub fn intersection(&self, other: &Self) -> Self {
162//         self.intersection_raw(other).simplify()
163//     }
164// }
165
166impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone>
167    SimplicialComplex<FS, SP>
168where
169    FS::Set: Hash,
170{
171    pub fn union_raw(&self, other: &Self) -> Self {
172        LabelledSimplicialDisjointUnion::union_raw(&self.into(), &other.into())
173            .refine_to_partial_simplicial_complex()
174            .try_as_simplicial_complex()
175            .unwrap()
176    }
177
178    pub fn union(&self, other: &Self) -> Self {
179        self.union_raw(other).simplify()
180    }
181
182    pub fn intersection_raw(&self, other: &Self) -> Self {
183        LabelledSimplicialDisjointUnion::intersection_raw(&self.into(), &other.into())
184            .refine_to_partial_simplicial_complex()
185            .apply_label_function(|_| ())
186            .try_as_simplicial_complex()
187            .unwrap()
188    }
189
190    pub fn intersection(&self, other: &Self) -> Self {
191        self.intersection_raw(other).simplify()
192    }
193}
194
195/*
196 - Venn dju <T1> and dju <T2> to produce dju <(Option<T1>, Option<T2>)>
197 - Replace partial simplicial complex (psc) with labelled simplicial complex <bool>
198 - Intersect psc, psc -> psc
199 - Union psc, psc -> psc
200 - Subtract psc, psc -> psc
201 - Have a trait for a collection of labelled simplexes
202   - Labelled subset
203   - Filtered labelled subset
204   - Union -> PartialSimplicialComplex
205   - Intersection -> PartialSimplicialComplex
206   - Difference -> PartialSimplicialComplex
207 - Implement it for:
208   - SimplexUnion
209   - SimplexDisjointUnion
210   - SemiSimplicialComplex
211   - SimplicialComplex
212*/