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