1use std::hash::Hash;
6
7use maplike::{Get, Insert, Push};
8
9use crate::{
10 Dcel, EdgeId, Face, FaceId, HalfEdge, Vertex, VertexId,
11 track::{EdgesTracker, VertexTracker},
12};
13
14impl<
15 VW: Clone + Eq + Hash,
16 HEW: Clone + Default,
17 FW: Clone + Default,
18 VC: Get<usize, Value = Vertex<VW>> + Insert<usize> + Push<usize>,
19 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
20 FC: Get<usize, Value = Face<FW>> + Insert<usize> + Push<usize>,
21> Dcel<VW, HEW, FW, VC, HEC, FC>
22{
23 pub fn insert_mesh(
24 &mut self,
25 face_polygons: impl IntoIterator<Item = impl IntoIterator<Item = VW>>,
26 ) -> Vec<FaceId> {
27 self.insert_mesh_in_face(face_polygons)
28 }
29
30 pub fn insert_mesh_in_face(
31 &mut self,
32 face_polygons: impl IntoIterator<Item = impl IntoIterator<Item = VW>>,
33 ) -> Vec<FaceId> {
34 let mut vertex_weights_counter = VertexTracker::new();
35 let mut edges_tracker = EdgesTracker::new();
36 let mut faces = vec![];
37
38 for face_polygon in face_polygons {
39 faces.push(self.insert_adjoined_polygon(
40 &mut vertex_weights_counter,
41 &mut edges_tracker,
42 face_polygon,
43 ));
44 }
45
46 faces
47 }
48
49 fn insert_adjoined_polygon(
50 &mut self,
51 vertex_weights_counter: &mut VertexTracker<VW>,
52 edges_tracker: &mut EdgesTracker,
53 vertex_weights: impl IntoIterator<Item = VW>,
54 ) -> FaceId {
55 self.insert_adjoined_polygon_in_face(
56 vertex_weights_counter,
57 edges_tracker,
58 self.unbounded_face(),
59 vertex_weights,
60 )
61 }
62
63 fn insert_adjoined_polygon_in_face(
64 &mut self,
65 vertex_weights_counter: &mut VertexTracker<VW>,
66 edges_tracker: &mut EdgesTracker,
67 outer_face: FaceId,
68 vertex_weights: impl IntoIterator<Item = VW>,
69 ) -> FaceId {
70 self.insert_adjoined_polygon_in_face_with_all_weights(
71 vertex_weights_counter,
72 edges_tracker,
73 outer_face,
74 vertex_weights,
75 std::iter::repeat((HEW::default(), HEW::default())),
76 FW::default(),
77 )
78 }
79}
80
81impl<
82 VW: Clone,
83 HEW: Clone + Default,
84 FW: Clone + Default,
85 VC: Get<usize, Value = Vertex<VW>> + Insert<usize> + Push<usize>,
86 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
87 FC: Get<usize, Value = Face<FW>> + Insert<usize> + Push<usize>,
88> Dcel<VW, HEW, FW, VC, HEC, FC>
89{
90 pub fn insert_polygon(&mut self, vertex_weights: impl IntoIterator<Item = VW>) -> FaceId {
91 self.insert_polygon_in_face(self.unbounded_face(), vertex_weights)
92 }
93
94 pub fn insert_polygon_in_face(
95 &mut self,
96 outer_face: FaceId,
97 vertex_weights: impl IntoIterator<Item = VW>,
98 ) -> FaceId {
99 self.insert_polygon_in_face_with_all_weights(
100 outer_face,
101 vertex_weights,
102 std::iter::repeat((HEW::default(), HEW::default())),
103 FW::default(),
104 )
105 }
106}
107
108impl<
109 VW: Clone + Eq + Hash,
110 HEW: Clone,
111 FW: Clone,
112 VC: Get<usize, Value = Vertex<VW>> + Insert<usize> + Push<usize>,
113 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
114 FC: Get<usize, Value = Face<FW>> + Insert<usize> + Push<usize>,
115> Dcel<VW, HEW, FW, VC, HEC, FC>
116{
117 fn insert_adjoined_polygon_with_all_weights(
118 &mut self,
119 vertex_weights_counter: &mut VertexTracker<VW>,
120 edges_tracker: &mut EdgesTracker,
121 vertex_weights: impl IntoIterator<Item = VW>,
122 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
123 face_weight: FW,
124 ) -> FaceId {
125 self.insert_adjoined_polygon_in_face_with_all_weights(
126 vertex_weights_counter,
127 edges_tracker,
128 self.unbounded_face(),
129 vertex_weights,
130 edge_weights,
131 face_weight,
132 )
133 }
134
135 fn insert_adjoined_polygon_in_face_with_all_weights(
136 &mut self,
137 vertex_weights_tracker: &mut VertexTracker<VW>,
138 edges_tracker: &mut EdgesTracker,
139 outer_face: FaceId,
140 vertex_weights: impl IntoIterator<Item = VW>,
141 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
142 face_weight: FW,
143 ) -> FaceId {
144 let new_face = self.add_unwired_face(face_weight);
145 let vertexes =
146 self.add_deduplicated_unwired_polygon_vertexes(vertex_weights_tracker, vertex_weights);
147 let edges = self.add_adjoined_unwired_polygon_edges(
148 edges_tracker,
149 &vertexes,
150 new_face,
151 outer_face,
152 edge_weights,
153 );
154
155 self.wire_outer_half_edge_chain_adjoiningly(outer_face, &edges);
156 self.wire_inner_half_edge_chain(new_face, &edges);
157
158 new_face
159 }
160
161 fn add_deduplicated_unwired_polygon_vertexes(
162 &mut self,
163 vertex_weights_counter: &mut VertexTracker<VW>,
164 vertex_weights: impl IntoIterator<Item = VW>,
165 ) -> Vec<VertexId> {
166 vertex_weights
167 .into_iter()
168 .map(|weight| {
169 vertex_weights_counter
170 .vertex(weight.clone())
171 .unwrap_or_else(|| {
172 let vertex = self.add_unwired_vertex(weight.clone());
173 vertex_weights_counter.visit_vertex(weight, vertex);
174 vertex
175 })
176 })
177 .collect()
178 }
179
180 fn add_adjoined_unwired_polygon_edges(
181 &mut self,
182 edges_tracker: &mut EdgesTracker,
183 vertexes: &[VertexId],
184 new_face: FaceId,
185 outer_face: FaceId,
186 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
187 ) -> Vec<EdgeId> {
188 let vertexes_circular_tuple_windows = vertexes
189 .iter()
190 .zip(vertexes.iter().skip(1).chain(vertexes.iter().take(1)));
191
192 let mut edges = vec![];
193
194 for ((&from_vertex, &to_vertex), (forward_half_edge_weight, backward_half_edge_weight)) in
195 vertexes_circular_tuple_windows.zip(edge_weights)
196 {
197 let edge = if let Some(existing_half_edge) =
198 edges_tracker.vertexes_half_edge(to_vertex, from_vertex)
199 {
200 let reused_edge = self.full_edge(self.twin(existing_half_edge));
202
203 self.half_edges.insert(
205 reused_edge.forward().id(),
206 HalfEdge {
207 face: new_face,
208 ..self
209 .half_edges
210 .get(&reused_edge.forward().id())
211 .unwrap()
212 .clone()
213 },
214 );
215
216 reused_edge
217 } else {
218 self.add_unwired_edge(
220 from_vertex,
221 to_vertex,
222 new_face,
223 outer_face,
224 forward_half_edge_weight,
225 backward_half_edge_weight,
226 )
227 };
228
229 edges_tracker.visit_vertexes_edge(from_vertex, to_vertex, edge.forward());
230 edges.push(edge);
231 }
232
233 edges
234 }
235}
236
237impl<
238 VW: Clone,
239 HEW: Clone,
240 FW: Clone,
241 VC: Get<usize, Value = Vertex<VW>> + Insert<usize> + Push<usize>,
242 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
243 FC: Get<usize, Value = Face<FW>> + Insert<usize> + Push<usize>,
244> Dcel<VW, HEW, FW, VC, HEC, FC>
245{
246 pub fn insert_polygon_with_all_weights(
247 &mut self,
248 vertex_weights: impl IntoIterator<Item = VW>,
249 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
250 face_weight: FW,
251 ) -> FaceId {
252 self.insert_polygon_in_face_with_all_weights(
253 self.unbounded_face(),
254 vertex_weights,
255 edge_weights,
256 face_weight,
257 )
258 }
259
260 pub fn insert_polygon_in_face_with_all_weights(
261 &mut self,
262 outer_face: FaceId,
263 vertex_weights: impl IntoIterator<Item = VW>,
264 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
265 face_weight: FW,
266 ) -> FaceId {
267 let new_face = self.add_unwired_face(face_weight);
268 let vertexes = self.add_unwired_polygon_vertexes(vertex_weights);
269 let edges = self.add_unwired_polygon_edges(&vertexes, new_face, outer_face, edge_weights);
270
271 self.wire_outer_half_edge_chain_circularly(&edges);
272 self.wire_inner_half_edge_chain(new_face, &edges);
273
274 new_face
275 }
276
277 fn add_unwired_polygon_vertexes(
278 &mut self,
279 vertex_weights: impl IntoIterator<Item = VW>,
280 ) -> Vec<VertexId> {
281 vertex_weights
282 .into_iter()
283 .map(|vertex_weight| self.add_unwired_vertex(vertex_weight))
284 .collect()
285 }
286
287 fn add_unwired_polygon_edges(
288 &mut self,
289 vertexes: &[VertexId],
290 new_face: FaceId,
291 outer_face: FaceId,
292 edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
293 ) -> Vec<EdgeId> {
294 let vertexes_circular_tuple_windows = vertexes
295 .iter()
296 .zip(vertexes.iter().skip(1).chain(vertexes.iter().take(1)));
297
298 let mut edges = vec![];
299
300 for ((from_vertex, to_vertex), (forward_half_edge_weight, backward_half_edge_weight)) in
301 vertexes_circular_tuple_windows.zip(edge_weights)
302 {
303 let edge = self.add_unwired_edge(
304 *from_vertex,
305 *to_vertex,
306 new_face,
307 outer_face,
308 forward_half_edge_weight,
309 backward_half_edge_weight,
310 );
311 edges.push(edge);
312 }
313
314 edges
315 }
316}
317
318#[cfg(test)]
319mod test {
320 use crate::HalfEdgeId;
321
322 use super::*;
323
324 #[test]
325 fn test_insert_adjoined_squares() {
326 let two_adjoined_squares: Vec<Vec<(i64, i64)>> = vec![
327 vec![(0, 0), (0, 1), (-1, 1), (-1, 0)],
329 vec![(0, 0), (1, 0), (1, 1), (0, 1)],
331 ];
332
333 let mut dcel: Dcel<(i64, i64)> = Dcel::new();
334 dcel.insert_mesh(two_adjoined_squares);
335
336 assert_eq!(dcel.vertexes().len(), 6);
337 assert_eq!(dcel.half_edges().len(), 14);
338 assert_eq!(dcel.faces().len(), 3);
339
340 assert_eq!(
341 dcel.face_vertexes(FaceId::new(0))
342 .collect::<Vec<VertexId>>()
343 .len(),
344 0
345 );
346 assert_eq!(
347 dcel.face_half_edges(FaceId::new(0))
348 .collect::<Vec<HalfEdgeId>>()
349 .len(),
350 0
351 );
352 assert_eq!(
353 dcel.face_edges(FaceId::new(0))
354 .collect::<Vec<EdgeId>>()
355 .len(),
356 0
357 );
358 assert_eq!(
359 dcel.face_half_edges(FaceId::new(1))
360 .collect::<Vec<HalfEdgeId>>()
361 .len(),
362 4
363 );
364 assert_eq!(
365 dcel.face_edges(FaceId::new(1))
366 .collect::<Vec<EdgeId>>()
367 .len(),
368 4
369 );
370 assert_eq!(
371 dcel.face_half_edges(FaceId::new(1))
372 .collect::<Vec<HalfEdgeId>>()
373 .len(),
374 4
375 );
376 assert_eq!(
377 dcel.face_edges(FaceId::new(2))
378 .collect::<Vec<EdgeId>>()
379 .len(),
380 4
381 );
382 }
383
384 #[test]
385 fn test_insert_noisy_4x4_grid_mesh() {
386 let mesh: Vec<Vec<(i64, i64)>> = vec![
389 vec![(2, 3), (48, -2), (53, 54), (-4, 48)],
391 vec![(48, -2), (102, 4), (98, 51), (53, 54)],
392 vec![(102, 4), (155, -3), (147, 55), (98, 51)],
393 vec![(155, -3), (201, 2), (197, 49), (147, 55)],
394 vec![(-4, 48), (53, 54), (47, 103), (3, 98)],
396 vec![(53, 54), (98, 51), (104, 97), (47, 103)],
397 vec![(98, 51), (147, 55), (149, 102), (104, 97)],
398 vec![(147, 55), (197, 49), (203, 99), (149, 102)],
399 vec![(3, 98), (47, 103), (51, 155), (-2, 147)],
401 vec![(47, 103), (104, 97), (97, 149), (51, 155)],
402 vec![(104, 97), (149, 102), (155, 148), (97, 149)],
403 vec![(149, 102), (203, 99), (198, 152), (155, 148)],
404 vec![(-2, 147), (51, 155), (49, 204), (5, 197)],
406 vec![(51, 155), (97, 149), (102, 198), (49, 204)],
407 vec![(97, 149), (155, 148), (146, 201), (102, 198)],
408 vec![(155, 148), (198, 152), (204, 199), (146, 201)],
409 ];
410
411 let mut dcel: Dcel<(i64, i64)> = Dcel::new();
412 dcel.insert_mesh(mesh);
413
414 for (i, _face) in dcel.faces().iter().enumerate() {
415 if FaceId::new(i) == dcel.unbounded_face() {
416 assert_eq!(
417 dcel.face_vertexes(FaceId::new(i))
418 .collect::<Vec<VertexId>>()
419 .len(),
420 0
421 );
422 assert_eq!(
423 dcel.face_half_edges(FaceId::new(i))
424 .collect::<Vec<HalfEdgeId>>()
425 .len(),
426 0
427 );
428 assert_eq!(
429 dcel.face_edges(FaceId::new(i))
430 .collect::<Vec<EdgeId>>()
431 .len(),
432 0
433 );
434 continue;
435 }
436
437 assert_eq!(
438 dcel.face_vertexes(FaceId::new(i))
439 .collect::<Vec<VertexId>>()
440 .len(),
441 4
442 );
443 assert_eq!(
444 dcel.face_half_edges(FaceId::new(i))
445 .collect::<Vec<HalfEdgeId>>()
446 .len(),
447 4
448 );
449 assert_eq!(
450 dcel.face_edges(FaceId::new(i))
451 .collect::<Vec<EdgeId>>()
452 .len(),
453 4
454 );
455 }
456
457 assert_eq!(dcel.vertexes().len(), 25);
458 assert_eq!(dcel.half_edges().len(), 80);
459 assert_eq!(dcel.faces().len(), 17);
460 }
461}