1use maplike::Get;
6
7use crate::{
8 Dcel, EdgeId, Face, FaceId, HalfEdge, HalfEdgeId, Vertex, VertexId,
9 walkers::{
10 CirculateEdgesWithExcludesIter, CirculateEdgesWithExcludesReverseIter,
11 CirculateEdgesWithExcludesReverseWalker, CirculateEdgesWithExcludesWalker,
12 CirculateHalfEdgesWithExcludesIter, CirculateHalfEdgesWithExcludesReverseIter,
13 CirculateHalfEdgesWithExcludesReverseWalker, CirculateHalfEdgesWithExcludesWalker,
14 CirculateVertexesWithExcludesIter, CirculateVertexesWithExcludesReverseIter,
15 CirculateVertexesWithExcludesReverseWalker, CirculateVertexesWithExcludesWalker,
16 FaceEdgesIter, FaceEdgesReverseIter, FaceEdgesReverseWalker, FaceEdgesWalker,
17 FaceHalfEdgesIter, FaceHalfEdgesReverseIter, FaceHalfEdgesReverseWalker,
18 FaceHalfEdgesWalker, FaceVertexesIter, FaceVertexesReverseIter, FaceVertexesReverseWalker,
19 FaceVertexesWalker, HalfSpokesIter, HalfSpokesReverseIter, HalfSpokesReverseWalker,
20 HalfSpokesWalker, InterspokesIter, InterspokesReverseIter, InterspokesReverseWalker,
21 InterspokesWalker, SpokesIter, SpokesReverseIter, SpokesReverseWalker, SpokesWalker,
22 },
23};
24
25impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
26 Dcel<VW, HEW, FW, VC, HEC, FC>
27{
28 #[inline]
29 pub fn vertex_rim_vertexes(
30 &self,
31 vertex: VertexId,
32 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
33 CirculateVertexesWithExcludesWalker {
34 circulator: self.vertex_rim_half_edges(vertex).walker(),
35 }
36 .iter(self)
37 }
38
39 #[inline]
40 pub fn vertex_rim_vertexes_reverse(
41 &self,
42 vertex: VertexId,
43 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
44 CirculateVertexesWithExcludesReverseWalker {
45 circulator: self.vertex_rim_half_edges_reverse(vertex).walker(),
46 }
47 .iter(self)
48 }
49}
50
51impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
52 #[inline]
53 pub fn vertex_half_spokes(
54 &self,
55 vertex: VertexId,
56 ) -> HalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
57 self.half_spokes(self.outgoing_next_half_edge(vertex))
58 }
59
60 #[inline]
61 pub fn vertex_half_spokes_reverse(
62 &self,
63 vertex: VertexId,
64 ) -> HalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
65 self.half_spokes_reverse(self.outgoing_next_half_edge(vertex))
66 }
67}
68
69impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
70 Dcel<VW, HEW, FW, VC, HEC, FC>
71{
72 #[inline]
73 pub fn vertex_rim_half_edges(
74 &self,
75 vertex: VertexId,
76 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
77 let initial_half_edge = self.next_half_edge(self.outgoing_next_half_edge(vertex));
78 let excluded_half_edges = self
79 .vertex_spokes(vertex)
80 .flat_map(|edge| [edge.forward(), edge.backward()])
81 .collect::<Vec<HalfEdgeId>>();
82
83 if self.is_boundary_vertex(vertex) {
86 return CirculateHalfEdgesWithExcludesWalker {
87 initial_half_edge,
88 curr_half_edge: None,
89 excluded_half_edges,
90 }
91 .iter(self);
92 }
93
94 self.circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
95 }
96
97 #[inline]
98 pub fn vertex_rim_half_edges_reverse(
99 &self,
100 vertex: VertexId,
101 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
102 let initial_half_edge = self.prev_half_edge(self.incoming_next_half_edge(vertex));
103 let excluded_half_edges = self
104 .vertex_spokes(vertex)
105 .flat_map(|edge| [edge.forward(), edge.backward()])
106 .collect::<Vec<HalfEdgeId>>();
107
108 if self.is_boundary_vertex(vertex) {
111 return CirculateHalfEdgesWithExcludesReverseWalker {
112 initial_half_edge,
113 curr_half_edge: None,
114 excluded_half_edges,
115 }
116 .iter(self);
117 }
118
119 self.circulate_half_edges_with_excludes_reverse(initial_half_edge, excluded_half_edges)
120 }
121}
122
123impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
124 #[inline]
125 pub fn half_spokes(
126 &self,
127 initial_half_edge: HalfEdgeId,
128 ) -> HalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
129 HalfSpokesWalker {
130 initial_half_edge,
131 curr_half_edge: Some(initial_half_edge),
132 }
133 .iter(self)
134 }
135
136 #[inline]
137 pub fn half_spokes_reverse(
138 &self,
139 initial_half_edge: HalfEdgeId,
140 ) -> HalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
141 HalfSpokesReverseWalker {
142 initial_half_edge,
143 curr_half_edge: Some(initial_half_edge),
144 }
145 .iter(self)
146 }
147}
148
149impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
150 Dcel<VW, HEW, FW, VC, HEC, FC>
151{
152 #[inline]
153 pub fn vertex_spokes(&self, vertex: VertexId) -> SpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
154 self.spokes(self.vertex_next_edge(vertex))
155 }
156
157 #[inline]
158 pub fn vertex_spokes_reverse(
159 &self,
160 vertex: VertexId,
161 ) -> SpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
162 self.spokes_reverse(self.vertex_next_edge(vertex))
163 }
164}
165
166impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
167 Dcel<VW, HEW, FW, VC, HEC, FC>
168{
169 #[inline]
170 pub fn vertex_rim_edges(
171 &self,
172 vertex: VertexId,
173 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
174 CirculateEdgesWithExcludesWalker {
175 circulator: self.vertex_rim_half_edges(vertex).walker(),
176 }
177 .iter(self)
178 }
179
180 #[inline]
181 pub fn vertex_rim_edges_reverse(
182 &self,
183 vertex: VertexId,
184 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
185 CirculateEdgesWithExcludesReverseWalker {
186 circulator: self.vertex_rim_half_edges_reverse(vertex).walker(),
187 }
188 .iter(self)
189 }
190}
191
192impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
193 Dcel<VW, HEW, FW, VC, HEC, FC>
194{
195 #[inline]
196 pub fn vertex_interspokes(
197 &self,
198 vertex: VertexId,
199 ) -> InterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
200 self.interspokes(self.outgoing_next_half_edge(vertex))
201 }
202
203 #[inline]
204 pub fn vertex_interspokes_reverse(
205 &self,
206 vertex: VertexId,
207 ) -> InterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
208 self.interspokes_reverse(self.outgoing_next_half_edge(vertex))
209 }
210}
211
212impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
213 #[inline]
214 pub fn spokes(&self, initial_edge: EdgeId) -> SpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
215 SpokesWalker {
216 initial_edge,
217 curr_edge: Some(initial_edge),
218 }
219 .iter(self)
220 }
221
222 #[inline]
223 pub fn spokes_reverse(
224 &self,
225 initial_edge: EdgeId,
226 ) -> SpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
227 SpokesReverseWalker {
228 initial_edge,
229 curr_edge: Some(initial_edge),
230 }
231 .iter(self)
232 }
233
234 #[inline]
235 pub fn interspokes(
236 &self,
237 initial_half_edge: HalfEdgeId,
238 ) -> InterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
239 InterspokesWalker {
240 initial_half_edge,
241 curr_half_edge: Some(initial_half_edge),
242 }
243 .iter(self)
244 }
245
246 #[inline]
247 pub fn interspokes_reverse(
248 &self,
249 initial_half_edge: HalfEdgeId,
250 ) -> InterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
251 InterspokesReverseWalker {
252 initial_half_edge,
253 curr_half_edge: Some(initial_half_edge),
254 }
255 .iter(self)
256 }
257}
258
259impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
260 #[inline]
261 pub fn circulate_vertexes_with_excludes(
262 &self,
263 initial_edge: EdgeId,
264 excluded_edges: impl IntoIterator<Item = EdgeId>,
265 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
266 CirculateVertexesWithExcludesWalker {
267 circulator: self
268 .circulate_half_edges_with_excludes(
269 initial_edge.forward(),
270 excluded_edges
271 .into_iter()
272 .flat_map(|edge| [edge.forward(), edge.backward()]),
273 )
274 .walker(),
275 }
276 .iter(self)
277 }
278
279 #[inline]
280 pub fn circulate_vertexes_with_excludes_reverse(
281 &self,
282 initial_edge: EdgeId,
283 excluded_edges: impl IntoIterator<Item = EdgeId>,
284 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
285 CirculateVertexesWithExcludesReverseWalker {
286 circulator: self
287 .circulate_half_edges_with_excludes_reverse(
288 initial_edge.forward(),
289 excluded_edges
290 .into_iter()
291 .flat_map(|edge| [edge.forward(), edge.backward()]),
292 )
293 .walker(),
294 }
295 .iter(self)
296 }
297
298 #[inline]
299 pub fn circulate_half_edges_with_excludes(
300 &self,
301 initial_half_edge: HalfEdgeId,
302 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
303 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
304 CirculateHalfEdgesWithExcludesWalker {
305 initial_half_edge,
306 curr_half_edge: Some(initial_half_edge),
307 excluded_half_edges: excluded_half_edges.into_iter().collect(),
308 }
309 .iter(self)
310 }
311
312 #[inline]
313 pub fn circulate_half_edges_with_excludes_reverse(
314 &self,
315 initial_half_edge: HalfEdgeId,
316 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
317 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
318 CirculateHalfEdgesWithExcludesReverseWalker {
319 initial_half_edge,
320 curr_half_edge: Some(initial_half_edge),
321 excluded_half_edges: excluded_half_edges.into_iter().collect(),
322 }
323 .iter(self)
324 }
325
326 #[inline]
327 pub fn circulate_edges_with_excludes(
328 &self,
329 initial_edge: EdgeId,
330 excluded_edges: impl IntoIterator<Item = EdgeId>,
331 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
332 CirculateEdgesWithExcludesWalker {
333 circulator: self
334 .circulate_half_edges_with_excludes(
335 initial_edge.forward(),
336 excluded_edges
337 .into_iter()
338 .flat_map(|edge| [edge.forward(), edge.backward()]),
339 )
340 .walker(),
341 }
342 .iter(self)
343 }
344
345 #[inline]
346 pub fn circulate_edges_with_excludes_reverse(
347 &self,
348 initial_edge: EdgeId,
349 excluded_edges: impl IntoIterator<Item = EdgeId>,
350 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
351 CirculateEdgesWithExcludesReverseWalker {
352 circulator: self
353 .circulate_half_edges_with_excludes_reverse(
354 initial_edge.forward(),
355 excluded_edges
356 .into_iter()
357 .flat_map(|edge| [edge.forward(), edge.backward()]),
358 )
359 .walker(),
360 }
361 .iter(self)
362 }
363}
364
365impl<
366 VW,
367 HEW,
368 FW,
369 VC: Get<usize, Value = Vertex<VW>>,
370 HEC: Get<usize, Value = HalfEdge<HEW>>,
371 FC: Get<usize, Value = Face<FW>>,
372> Dcel<VW, HEW, FW, VC, HEC, FC>
373{
374 #[inline]
375 pub fn face_vertexes(&self, face: FaceId) -> FaceVertexesIter<'_, VW, HEW, FW, VC, HEC, FC> {
376 FaceVertexesWalker {
377 circulator: self.face_half_edges(face).walker(),
378 }
379 .iter(self)
380 }
381
382 #[inline]
383 pub fn face_vertexes_reverse(
384 &self,
385 face: FaceId,
386 ) -> FaceVertexesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
387 FaceVertexesReverseWalker {
388 circulator: self.face_half_edges_reverse(face).walker(),
389 }
390 .iter(self)
391 }
392}
393
394impl<VW, HEW, FW, VC, HEC, FC: Get<usize, Value = Face<FW>>> Dcel<VW, HEW, FW, VC, HEC, FC> {
395 #[inline]
396 pub fn face_half_edges(&self, face: FaceId) -> FaceHalfEdgesIter<'_, VW, HEW, FW, VC, HEC, FC> {
397 if face == self.unbounded_face() {
401 return FaceHalfEdgesWalker {
402 initial_half_edge: HalfEdgeId::new(0),
404 curr_half_edge: None,
407 }
408 .iter(self);
409 }
410
411 let initial_half_edge = self
412 .faces
413 .get(&face.id())
414 .unwrap()
415 .incident_half_edge
416 .unwrap();
417
418 FaceHalfEdgesWalker {
419 initial_half_edge,
420 curr_half_edge: Some(initial_half_edge),
421 }
422 .iter(self)
423 }
424
425 #[inline]
426 pub fn face_half_edges_reverse(
427 &self,
428 face: FaceId,
429 ) -> FaceHalfEdgesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
430 if face == self.unbounded_face() {
434 return FaceHalfEdgesReverseWalker {
435 initial_half_edge: HalfEdgeId::new(0),
437 curr_half_edge: None,
440 }
441 .iter(self);
442 }
443
444 let initial_half_edge = self
445 .faces
446 .get(&face.id())
447 .unwrap()
448 .incident_half_edge
449 .unwrap();
450
451 FaceHalfEdgesReverseWalker {
452 initial_half_edge,
453 curr_half_edge: Some(initial_half_edge),
454 }
455 .iter(self)
456 }
457}
458
459impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC: Get<usize, Value = Face<FW>>>
460 Dcel<VW, HEW, FW, VC, HEC, FC>
461{
462 #[inline]
463 pub fn face_edges(&self, face: FaceId) -> FaceEdgesIter<'_, VW, HEW, FW, VC, HEC, FC> {
464 FaceEdgesWalker {
465 circulator: self.face_half_edges(face).walker(),
466 }
467 .iter(self)
468 }
469
470 #[inline]
471 pub fn face_edges_reverse(
472 &self,
473 face: FaceId,
474 ) -> FaceEdgesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
475 FaceEdgesReverseWalker {
476 circulator: self.face_half_edges_reverse(face).walker(),
477 }
478 .iter(self)
479 }
480}
481
482#[cfg(test)]
483mod test {
484 use crate::{
485 Dcel, assert_face_boundary, assert_vertex_rim, assert_vertex_spokes_interspokes,
486 init_dcel_with_3x3_hex_mesh,
487 };
488
489 #[test]
490 fn test_vertex_rim() {
491 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
492
493 assert_vertex_rim!(&dcel, 0, 0);
494 assert_vertex_rim!(&dcel, 1, 0);
495 assert_vertex_rim!(&dcel, 2, 0);
496 assert_vertex_rim!(&dcel, 3, 0);
497 assert_vertex_rim!(&dcel, 4, 0);
498 assert_vertex_rim!(&dcel, 5, 12);
499 assert_vertex_rim!(&dcel, 6, 0);
500 assert_vertex_rim!(&dcel, 7, 0);
501 assert_vertex_rim!(&dcel, 8, 12);
502 assert_vertex_rim!(&dcel, 9, 12);
503 assert_vertex_rim!(&dcel, 10, 0);
504 assert_vertex_rim!(&dcel, 11, 0);
505 assert_vertex_rim!(&dcel, 12, 12);
506 assert_vertex_rim!(&dcel, 13, 0);
507 assert_vertex_rim!(&dcel, 14, 0);
508 assert_vertex_rim!(&dcel, 15, 12);
509 assert_vertex_rim!(&dcel, 16, 12);
510 assert_vertex_rim!(&dcel, 17, 12);
511 assert_vertex_rim!(&dcel, 18, 12);
512 assert_vertex_rim!(&dcel, 19, 0);
513 assert_vertex_rim!(&dcel, 20, 0);
514 assert_vertex_rim!(&dcel, 21, 0);
515 assert_vertex_rim!(&dcel, 22, 0);
516 assert_vertex_rim!(&dcel, 23, 0);
517 assert_vertex_rim!(&dcel, 24, 0);
518 assert_vertex_rim!(&dcel, 25, 0);
519 assert_vertex_rim!(&dcel, 26, 0);
520 assert_vertex_rim!(&dcel, 27, 0);
521 assert_vertex_rim!(&dcel, 28, 0);
522 assert_vertex_rim!(&dcel, 29, 0);
523 }
524
525 #[test]
526 fn test_vertex_spokes_interspokes() {
527 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
528
529 assert_vertex_spokes_interspokes!(&dcel, 0, 3);
530 assert_vertex_spokes_interspokes!(&dcel, 1, 2);
531 assert_vertex_spokes_interspokes!(&dcel, 2, 2);
532 assert_vertex_spokes_interspokes!(&dcel, 3, 2);
533 assert_vertex_spokes_interspokes!(&dcel, 4, 3);
534 assert_vertex_spokes_interspokes!(&dcel, 5, 3);
535 assert_vertex_spokes_interspokes!(&dcel, 6, 3);
536 assert_vertex_spokes_interspokes!(&dcel, 7, 2);
537 assert_vertex_spokes_interspokes!(&dcel, 8, 3);
538 assert_vertex_spokes_interspokes!(&dcel, 9, 3);
539 assert_vertex_spokes_interspokes!(&dcel, 10, 2);
540 assert_vertex_spokes_interspokes!(&dcel, 11, 2);
541 assert_vertex_spokes_interspokes!(&dcel, 12, 3);
542 assert_vertex_spokes_interspokes!(&dcel, 13, 3);
543 assert_vertex_spokes_interspokes!(&dcel, 14, 3);
544 assert_vertex_spokes_interspokes!(&dcel, 15, 3);
545 assert_vertex_spokes_interspokes!(&dcel, 16, 3);
546 assert_vertex_spokes_interspokes!(&dcel, 17, 3);
547 assert_vertex_spokes_interspokes!(&dcel, 18, 3);
548 assert_vertex_spokes_interspokes!(&dcel, 19, 2);
549 assert_vertex_spokes_interspokes!(&dcel, 20, 3);
550 assert_vertex_spokes_interspokes!(&dcel, 21, 2);
551 assert_vertex_spokes_interspokes!(&dcel, 22, 2);
552 assert_vertex_spokes_interspokes!(&dcel, 23, 2);
553 assert_vertex_spokes_interspokes!(&dcel, 24, 2);
554 assert_vertex_spokes_interspokes!(&dcel, 25, 3);
555 assert_vertex_spokes_interspokes!(&dcel, 26, 2);
556 assert_vertex_spokes_interspokes!(&dcel, 27, 3);
557 assert_vertex_spokes_interspokes!(&dcel, 28, 2);
558 assert_vertex_spokes_interspokes!(&dcel, 29, 2);
559 }
560
561 #[test]
562 fn test_face_boundary() {
563 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
564
565 assert_face_boundary!(&dcel, 0, 0);
566 assert_face_boundary!(&dcel, 1, 6);
567 assert_face_boundary!(&dcel, 2, 6);
568 assert_face_boundary!(&dcel, 3, 6);
569 assert_face_boundary!(&dcel, 4, 6);
570 assert_face_boundary!(&dcel, 5, 6);
571 assert_face_boundary!(&dcel, 6, 6);
572 assert_face_boundary!(&dcel, 7, 6);
573 assert_face_boundary!(&dcel, 8, 6);
574 assert_face_boundary!(&dcel, 9, 6);
575 }
576}