algebraeon_geometry/simplexes/
boolean_opperations.rs1use 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
140impl<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