algebraeon_geometry/simplexes/
simplicial_disjoint_union.rs1use std::collections::{HashMap, HashSet};
2
3use super::*;
4
5#[derive(Clone)]
6pub struct LabelledSimplicialDisjointUnion<
7 FS: OrderedRingStructure + FieldStructure,
8 SP: Borrow<AffineSpace<FS>> + Clone,
9 T: Eq + Clone,
10> where
11 FS::Set: Hash,
12{
13 ambient_space: SP,
14 simplexes: HashMap<Simplex<FS, SP>, T>,
15}
16
17pub type SimplicialDisjointUnion<FS, SP> = LabelledSimplicialDisjointUnion<FS, SP, ()>;
18
19impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone, T: Eq + Clone>
20 From<&LabelledSimplicialComplex<FS, SP, T>> for LabelledSimplicialDisjointUnion<FS, SP, T>
21where
22 FS::Set: Hash,
23{
24 fn from(sc: &LabelledSimplicialComplex<FS, SP, T>) -> Self {
25 Self {
26 ambient_space: sc.ambient_space(),
27 simplexes: sc
28 .labelled_simplexes()
29 .into_iter()
30 .map(|(spx, label)| (spx.clone(), label.clone()))
31 .collect(),
32 }
33 }
34}
35
36impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone, T: Eq + Clone>
37 From<&LabelledPartialSimplicialComplex<FS, SP, T>>
38 for LabelledSimplicialDisjointUnion<FS, SP, T>
39where
40 FS::Set: Hash,
41{
42 fn from(sc: &LabelledPartialSimplicialComplex<FS, SP, T>) -> Self {
43 Self {
44 ambient_space: sc.ambient_space(),
45 simplexes: sc
46 .labelled_simplexes()
47 .into_iter()
48 .map(|(s, label)| (s.clone(), label.clone()))
49 .collect(),
50 }
51 }
52}
53
54impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone, T: Eq + Clone>
55 LabelledSimplexCollection<FS, SP, T> for LabelledSimplicialDisjointUnion<FS, SP, T>
56where
57 FS::Set: Hash,
58{
59 type WithLabel<S: Eq + Clone> = LabelledSimplicialDisjointUnion<FS, SP, S>;
60 type SubsetType = LabelledSimplicialDisjointUnion<FS, SP, T>;
61
62 fn new_labelled(
63 ambient_space: SP,
64 simplexes: HashMap<Simplex<FS, SP>, T>,
65 ) -> Result<Self, &'static str> {
66 Ok(Self {
68 ambient_space,
69 simplexes,
70 })
71 }
72
73 fn new_labelled_unchecked(ambient_space: SP, simplexes: HashMap<Simplex<FS, SP>, T>) -> Self {
74 Self {
75 ambient_space,
76 simplexes,
77 }
78 }
79
80 fn ambient_space(&self) -> SP {
81 self.ambient_space.clone()
82 }
83
84 fn labelled_simplexes(&self) -> HashMap<&Simplex<FS, SP>, &T> {
85 self.simplexes.iter().collect()
86 }
87
88 fn into_labelled_simplexes(self) -> HashMap<Simplex<FS, SP>, T> {
89 self.simplexes
90 }
91
92 fn into_partial_simplicial_complex(self) -> LabelledPartialSimplicialComplex<FS, SP, T> {
93 self.refine_to_partial_simplicial_complex()
94 }
95}
96
97impl<FS: OrderedRingStructure + FieldStructure, SP: Borrow<AffineSpace<FS>> + Clone, T: Eq + Clone>
98 LabelledSimplicialDisjointUnion<FS, SP, T>
99where
100 FS::Set: Hash,
101{
102 pub(super) fn check(&self) {
103 for (spx_a, _label_a) in &self.simplexes {
104 for (spx_b, _label_b) in &self.simplexes {
105 let bdry_a = spx_a
106 .sub_simplices_not_null()
107 .into_iter()
108 .collect::<HashSet<_>>();
109 let bdry_b = spx_b
110 .sub_simplices_not_null()
111 .into_iter()
112 .collect::<HashSet<_>>();
113 if !bdry_a.contains(spx_b) && !bdry_b.contains(spx_a) {
114 let overlap = ConvexHull::intersect(
115 &ConvexHull::from_simplex(spx_a.clone()),
116 &ConvexHull::from_simplex(spx_b.clone()),
117 );
118
119 if !(overlap.affine_span_dimension() < spx_a.n()
120 && overlap.affine_span_dimension() < spx_b.n())
121 {
122 println!("spx_a = {:?}", spx_a);
123 println!("spx_b = {:?}", spx_b);
124 panic!("simplicial complex simplex overlap");
125 }
126 }
127 }
128 }
129 }
130
131 pub fn refine_to_partial_simplicial_complex(
132 mut self,
133 ) -> LabelledPartialSimplicialComplex<FS, SP, T> {
134 let ambient_space = self.ambient_space();
135
136 let mut pairs_todo: HashMap<Simplex<FS, SP>, HashSet<Simplex<FS, SP>>> = HashMap::new();
138 let simplexes = self.simplexes().into_iter().collect::<Vec<_>>();
139 for i in 0..simplexes.len() {
140 for j in 0..simplexes.len() {
141 if i != j {
142 let spx_i = simplexes[i];
143 let spx_j = simplexes[j];
144 pairs_todo
145 .entry(spx_i.clone())
146 .or_insert(HashSet::new())
147 .insert(spx_j.clone());
148 }
149 }
150 }
151
152 while !pairs_todo.is_empty() {
153 let spx1 = pairs_todo.keys().into_iter().next().unwrap().clone();
154 match pairs_todo.get(&spx1).unwrap().iter().next().cloned() {
155 None => {
156 pairs_todo.remove(&spx1);
157 }
158 Some(spx2) => {
159 pairs_todo.get_mut(&spx1).unwrap().remove(&spx2);
161 pairs_todo.get_mut(&spx2).unwrap().remove(&spx1);
162
163 debug_assert_ne!(spx1, spx2);
164 debug_assert!(self.simplexes.contains_key(&spx1));
165 debug_assert!(self.simplexes.contains_key(&spx2));
166
167 let overlap = ConvexHull::intersect(
168 &ConvexHull::from_simplex(spx1.clone()),
169 &ConvexHull::from_simplex(spx2.clone()),
170 );
171
172 if !overlap.is_empty() {
173 if match Simplex::new(
174 ambient_space.clone(),
175 overlap.defining_points().into_iter().collect(),
176 ) {
177 Ok(overlap_spx) => {
178 let spx1_points = spx1.points().into_iter().collect::<HashSet<_>>();
179 let spx2_points = spx2.points().into_iter().collect::<HashSet<_>>();
180 !overlap_spx
181 .points()
182 .into_iter()
183 .all(|pt| spx1_points.contains(pt) && spx2_points.contains(pt))
184 }
185 Err(_) => true,
186 } {
187 let mut spx1_replacement = overlap.clone();
189 for pt in spx1.points() {
190 spx1_replacement.extend_by_point(pt.clone());
191 }
192 let mut spx2_replacement = overlap.clone();
193 for pt in spx2.points() {
194 spx2_replacement.extend_by_point(pt.clone());
195 }
196
197 let mut spx1_paired = vec![];
199 for spx in pairs_todo.get(&spx1).unwrap_or(&HashSet::new()).clone() {
200 debug_assert_ne!(spx, spx1);
201 debug_assert_ne!(spx, spx2);
202 debug_assert!(self.simplexes.contains_key(&spx));
203 pairs_todo
204 .get_mut(&spx)
205 .unwrap_or(&mut HashSet::new())
206 .remove(&spx1);
207 spx1_paired.push(spx);
208 }
209 pairs_todo.remove(&spx1);
210
211 let mut spx2_paired = vec![];
212 for spx in pairs_todo.get(&spx2).unwrap_or(&HashSet::new()).clone() {
213 debug_assert_ne!(spx, spx1);
214 debug_assert_ne!(spx, spx2);
215 debug_assert!(self.simplexes.contains_key(&spx));
216 pairs_todo
217 .get_mut(&spx)
218 .unwrap_or(&mut HashSet::new())
219 .remove(&spx2);
220 spx2_paired.push(spx);
221 }
222 pairs_todo.remove(&spx2);
223
224 let spx1_label = self.simplexes.get(&spx1).unwrap().clone();
233 let spx2_label = self.simplexes.get(&spx2).unwrap().clone();
234
235 self.simplexes.remove(&spx1);
237 self.simplexes.remove(&spx2);
238
239 for spx1_repl in spx1_replacement
241 .as_simplicial_complex()
242 .subset_by_label(&InteriorBoundaryLabel::Interior)
243 .into_simplexes()
244 {
245 for spx in &spx1_paired {
246 pairs_todo
247 .entry(spx1_repl.clone())
248 .or_insert(HashSet::new())
249 .insert(spx.clone());
250 pairs_todo
251 .entry(spx.clone())
252 .or_insert(HashSet::new())
253 .insert(spx1_repl.clone());
254 }
255 self.simplexes.insert(spx1_repl, spx1_label.clone());
256 }
257
258 for spx2_repl in spx2_replacement
259 .as_simplicial_complex()
260 .subset_by_label(&InteriorBoundaryLabel::Interior)
261 .into_simplexes()
262 {
263 for spx in &spx2_paired {
264 pairs_todo
265 .entry(spx2_repl.clone())
266 .or_insert(HashSet::new())
267 .insert(spx.clone());
268 pairs_todo
269 .entry(spx.clone())
270 .or_insert(HashSet::new())
271 .insert(spx2_repl.clone());
272 }
273 self.simplexes.insert(spx2_repl, spx2_label.clone());
274 }
275 }
276 }
277 }
278 }
279 }
280
281 LabelledPartialSimplicialComplex::new_labelled_unchecked(ambient_space, self.simplexes)
282 }
283}