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<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
137impl<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