1use maplike::Get;
6
7use crate::{
8 Dcel, Face, FaceId, HalfEdge, HalfEdgeId, Vertex, VertexId,
9 walkers::{
10 CirculateEdgesWithExcludesIter, CirculateEdgesWithExcludesReverseIter,
11 CirculateEdgesWithExcludesReverseWalker, CirculateEdgesWithExcludesWalker,
12 CirculateHalfEdgesWithExcludesIter, CirculateHalfEdgesWithExcludesReverseIter,
13 CirculateHalfEdgesWithExcludesReverseWalker, CirculateHalfEdgesWithExcludesWalker,
14 CirculateHalfSpokesIter, CirculateHalfSpokesReverseIter, CirculateVertexesWithExcludesIter,
15 CirculateVertexesWithExcludesReverseIter, CirculateVertexesWithExcludesReverseWalker,
16 CirculateVertexesWithExcludesWalker, CirculationHalfSpokesReverseWalker,
17 CirculationHalfSpokesWalker, CirculationInterspokesIter, CirculationInterspokesReverseIter,
18 CirculationInterspokesReverseWalker, CirculationInterspokesWalker, CirculationSpokesIter,
19 CirculationSpokesReverseIter, CirculationSpokesReverseWalker, CirculationSpokesWalker,
20 HalfSpokesIter, HalfSpokesReverseIter, HalfSpokesReverseWalker, HalfSpokesWalker,
21 InterspokesIter, InterspokesReverseIter, InterspokesReverseWalker, InterspokesWalker,
22 SpokesIter, SpokesReverseIter, SpokesReverseWalker, SpokesWalker,
23 },
24};
25
26impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
27 #[inline]
28 pub fn vertex_half_spokes(
29 &self,
30 vertex: VertexId,
31 ) -> HalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
32 self.half_spokes(self.vertex_representative(vertex))
33 }
34
35 #[inline]
36 pub fn vertex_half_spokes_reverse(
37 &self,
38 vertex: VertexId,
39 ) -> HalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
40 self.half_spokes_reverse(self.vertex_representative(vertex))
41 }
42}
43
44impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
45 Dcel<VW, HEW, FW, VC, HEC, FC>
46{
47 #[inline]
48 pub fn vertex_rim_vertices(
49 &self,
50 vertex: VertexId,
51 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
52 CirculateVertexesWithExcludesWalker {
53 circulator: self.vertex_rim_half_edges(vertex).walker(),
54 }
55 .iter(self)
56 }
57
58 #[inline]
59 pub fn vertex_rim_vertices_reverse(
60 &self,
61 vertex: VertexId,
62 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
63 CirculateVertexesWithExcludesReverseWalker {
64 circulator: self.vertex_rim_half_edges_reverse(vertex).walker(),
65 }
66 .iter(self)
67 }
68}
69
70impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
71 Dcel<VW, HEW, FW, VC, HEC, FC>
72{
73 #[inline]
74 pub fn vertex_rim_half_edges(
75 &self,
76 vertex: VertexId,
77 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
78 let initial_half_edge = self.next(self.vertex_representative(vertex));
79 let excluded_half_edges = self
80 .vertex_spokes(vertex)
81 .flat_map(|edge| [edge.lesser(), edge.greater()])
82 .collect::<Vec<HalfEdgeId>>();
83
84 if self.check_if_boundary_vertex(vertex) {
87 return CirculateHalfEdgesWithExcludesWalker {
88 initial_half_edge,
89 curr_half_edge: None,
90 excluded_half_edges,
91 }
92 .iter(self);
93 }
94
95 self.circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
96 }
97
98 #[inline]
99 pub fn vertex_rim_half_edges_reverse(
100 &self,
101 vertex: VertexId,
102 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
103 let initial_half_edge = self.prev(self.twin(self.vertex_representative(vertex)));
104 let excluded_half_edges = self
105 .vertex_spokes(vertex)
106 .flat_map(|edge| [edge.lesser(), edge.greater()])
107 .collect::<Vec<HalfEdgeId>>();
108
109 if self.check_if_boundary_vertex(vertex) {
112 return CirculateHalfEdgesWithExcludesReverseWalker {
113 initial_half_edge,
114 curr_half_edge: None,
115 excluded_half_edges,
116 }
117 .iter(self);
118 }
119
120 self.circulate_half_edges_with_excludes_reverse(initial_half_edge, excluded_half_edges)
121 }
122}
123
124impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
125 #[inline]
126 pub fn half_spokes(
127 &self,
128 initial_half_edge: HalfEdgeId,
129 ) -> HalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
130 HalfSpokesWalker {
131 initial_half_edge,
132 curr_half_edge: Some(initial_half_edge),
133 }
134 .iter(self)
135 }
136
137 #[inline]
138 pub fn half_spokes_reverse(
139 &self,
140 initial_half_edge: HalfEdgeId,
141 ) -> HalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
142 HalfSpokesReverseWalker {
143 initial_half_edge,
144 curr_half_edge: Some(initial_half_edge),
145 }
146 .iter(self)
147 }
148}
149
150impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
151 Dcel<VW, HEW, FW, VC, HEC, FC>
152{
153 #[inline]
154 pub fn vertex_spokes(&self, vertex: VertexId) -> SpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
155 self.spokes(self.vertex_representative(vertex))
156 }
157
158 #[inline]
159 pub fn vertex_spokes_reverse(
160 &self,
161 vertex: VertexId,
162 ) -> SpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
163 self.spokes_reverse(self.vertex_representative(vertex))
164 }
165}
166
167impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
168 Dcel<VW, HEW, FW, VC, HEC, FC>
169{
170 #[inline]
171 pub fn vertex_rim_edges(
172 &self,
173 vertex: VertexId,
174 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
175 CirculateEdgesWithExcludesWalker {
176 circulator: self.vertex_rim_half_edges(vertex).walker(),
177 }
178 .iter(self)
179 }
180
181 #[inline]
182 pub fn vertex_rim_edges_reverse(
183 &self,
184 vertex: VertexId,
185 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
186 CirculateEdgesWithExcludesReverseWalker {
187 circulator: self.vertex_rim_half_edges_reverse(vertex).walker(),
188 }
189 .iter(self)
190 }
191}
192
193impl<VW, HEW, FW, VC: Get<usize, Value = Vertex<VW>>, HEC: Get<usize, Value = HalfEdge<HEW>>, FC>
194 Dcel<VW, HEW, FW, VC, HEC, FC>
195{
196 #[inline]
197 pub fn vertex_interspokes(
198 &self,
199 vertex: VertexId,
200 ) -> InterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
201 self.interspokes(self.vertex_representative(vertex))
202 }
203
204 #[inline]
205 pub fn vertex_interspokes_reverse(
206 &self,
207 vertex: VertexId,
208 ) -> InterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
209 self.interspokes_reverse(self.vertex_representative(vertex))
210 }
211}
212
213impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
214 #[inline]
215 pub fn spokes(
216 &self,
217 initial_half_edge: HalfEdgeId,
218 ) -> SpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
219 SpokesWalker {
220 circulator: HalfSpokesWalker {
221 initial_half_edge,
222 curr_half_edge: Some(initial_half_edge),
223 },
224 }
225 .iter(self)
226 }
227
228 #[inline]
229 pub fn spokes_reverse(
230 &self,
231 initial_half_edge: HalfEdgeId,
232 ) -> SpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
233 SpokesReverseWalker {
234 circulator: HalfSpokesReverseWalker {
235 initial_half_edge,
236 curr_half_edge: Some(initial_half_edge),
237 },
238 }
239 .iter(self)
240 }
241
242 #[inline]
243 pub fn interspokes(
244 &self,
245 initial_half_edge: HalfEdgeId,
246 ) -> InterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
247 InterspokesWalker {
248 initial_half_edge,
249 curr_half_edge: Some(initial_half_edge),
250 }
251 .iter(self)
252 }
253
254 #[inline]
255 pub fn interspokes_reverse(
256 &self,
257 initial_half_edge: HalfEdgeId,
258 ) -> InterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
259 InterspokesReverseWalker {
260 initial_half_edge,
261 curr_half_edge: Some(initial_half_edge),
262 }
263 .iter(self)
264 }
265}
266
267impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
268 #[inline]
269 pub fn circulate_vertices(
270 &self,
271 initial_half_edge: HalfEdgeId,
272 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
273 self.circulate_vertices_with_excludes(initial_half_edge, std::iter::empty())
274 }
275
276 #[inline]
277 pub fn circulate_vertices_reverse(
278 &self,
279 initial_half_edge: HalfEdgeId,
280 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
281 self.circulate_vertices_with_excludes_reverse(initial_half_edge, std::iter::empty())
282 }
283
284 #[inline]
285 pub fn circulate_vertices_with_excludes(
286 &self,
287 initial_half_edge: HalfEdgeId,
288 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
289 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
290 CirculateVertexesWithExcludesWalker {
291 circulator: self
292 .circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
293 .walker(),
294 }
295 .iter(self)
296 }
297
298 #[inline]
299 pub fn circulate_vertices_with_excludes_reverse(
300 &self,
301 initial_half_edge: HalfEdgeId,
302 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
303 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
304 CirculateVertexesWithExcludesReverseWalker {
305 circulator: self
306 .circulate_half_edges_with_excludes_reverse(initial_half_edge, excluded_half_edges)
307 .walker(),
308 }
309 .iter(self)
310 }
311
312 #[inline]
313 pub fn circulate_half_edges(
314 &self,
315 initial_half_edge: HalfEdgeId,
316 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
317 self.circulate_half_edges_with_excludes(initial_half_edge, std::iter::empty())
318 }
319
320 #[inline]
321 pub fn circulate_half_edges_reverse(
322 &self,
323 initial_half_edge: HalfEdgeId,
324 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
325 self.circulate_half_edges_with_excludes_reverse(initial_half_edge, std::iter::empty())
326 }
327
328 #[inline]
329 pub fn circulate_half_edges_with_excludes(
330 &self,
331 initial_half_edge: HalfEdgeId,
332 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
333 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
334 CirculateHalfEdgesWithExcludesWalker {
335 initial_half_edge,
336 curr_half_edge: Some(initial_half_edge),
337 excluded_half_edges: excluded_half_edges.into_iter().collect(),
338 }
339 .iter(self)
340 }
341
342 #[inline]
343 pub fn circulate_half_edges_with_excludes_reverse(
344 &self,
345 initial_half_edge: HalfEdgeId,
346 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
347 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
348 CirculateHalfEdgesWithExcludesReverseWalker {
349 initial_half_edge,
350 curr_half_edge: Some(initial_half_edge),
351 excluded_half_edges: excluded_half_edges.into_iter().collect(),
352 }
353 .iter(self)
354 }
355
356 #[inline]
357 pub fn circulate_edges(
358 &self,
359 initial_half_edge: HalfEdgeId,
360 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
361 self.circulate_edges_with_excludes(initial_half_edge, std::iter::empty())
362 }
363
364 #[inline]
365 pub fn circulate_edges_reverse(
366 &self,
367 initial_half_edge: HalfEdgeId,
368 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
369 self.circulate_edges_with_excludes_reverse(initial_half_edge, std::iter::empty())
370 }
371
372 #[inline]
373 pub fn circulate_edges_with_excludes(
374 &self,
375 initial_half_edge: HalfEdgeId,
376 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
377 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
378 CirculateEdgesWithExcludesWalker {
379 circulator: self
380 .circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
381 .walker(),
382 }
383 .iter(self)
384 }
385
386 #[inline]
387 pub fn circulate_edges_with_excludes_reverse(
388 &self,
389 initial_half_edge: HalfEdgeId,
390 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
391 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
392 CirculateEdgesWithExcludesReverseWalker {
393 circulator: self
394 .circulate_half_edges_with_excludes_reverse(initial_half_edge, excluded_half_edges)
395 .walker(),
396 }
397 .iter(self)
398 }
399
400 #[inline]
401 pub fn circulation_half_spokes(
402 &self,
403 initial_half_edge: HalfEdgeId,
404 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
405 ) -> CirculateHalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
406 CirculationHalfSpokesWalker {
407 circulator: self
408 .circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
409 .walker(),
410 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
411 prev_half_edge: self.prev(initial_half_edge),
412 }
413 .iter(self)
414 }
415
416 #[inline]
417 pub fn circulation_half_spokes_reverse(
418 &self,
419 initial_half_edge: HalfEdgeId,
420 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
421 ) -> CirculateHalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
422 CirculationHalfSpokesReverseWalker {
423 circulator: self
424 .circulate_half_edges_with_excludes_reverse(initial_half_edge, excluded_half_edges)
425 .walker(),
426 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
427 prev_half_edge: self.next(initial_half_edge),
428 }
429 .iter(self)
430 }
431
432 #[inline]
433 pub fn circulation_spokes(
434 &self,
435 initial_half_edge: HalfEdgeId,
436 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
437 ) -> CirculationSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
438 CirculationSpokesWalker {
439 circulator: CirculationHalfSpokesWalker {
440 circulator: self
441 .circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
442 .walker(),
443 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
444 prev_half_edge: self.prev(initial_half_edge),
445 },
446 }
447 .iter(self)
448 }
449
450 #[inline]
451 pub fn circulation_spokes_reverse(
452 &self,
453 initial_half_edge: HalfEdgeId,
454 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
455 ) -> CirculationSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
456 CirculationSpokesReverseWalker {
457 circulator: CirculationHalfSpokesReverseWalker {
458 circulator: self
459 .circulate_half_edges_with_excludes_reverse(
460 initial_half_edge,
461 excluded_half_edges,
462 )
463 .walker(),
464 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
465 prev_half_edge: self.next(initial_half_edge),
466 },
467 }
468 .iter(self)
469 }
470
471 #[inline]
472 pub fn circulation_interspokes(
473 &self,
474 initial_half_edge: HalfEdgeId,
475 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
476 ) -> CirculationInterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
477 CirculationInterspokesWalker {
478 circulator: CirculationHalfSpokesWalker {
479 circulator: self
480 .circulate_half_edges_with_excludes(initial_half_edge, excluded_half_edges)
481 .walker(),
482 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
483 prev_half_edge: self.prev(initial_half_edge),
484 },
485 }
486 .iter(self)
487 }
488
489 #[inline]
490 pub fn circulation_interspokes_reverse(
491 &self,
492 initial_half_edge: HalfEdgeId,
493 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
494 ) -> CirculationInterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
495 CirculationInterspokesReverseWalker {
496 circulator: CirculationHalfSpokesReverseWalker {
497 circulator: self
498 .circulate_half_edges_with_excludes_reverse(
499 initial_half_edge,
500 excluded_half_edges,
501 )
502 .walker(),
503 half_spokes_walker: self.half_spokes(initial_half_edge).walker(),
504 prev_half_edge: self.prev(initial_half_edge),
505 },
506 }
507 .iter(self)
508 }
509
510 #[inline]
511 pub fn circulation_rim_half_edges(
512 &self,
513 initial_half_edge: HalfEdgeId,
514 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
515 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
516 let excluded_half_edges = excluded_half_edges.into_iter().collect::<Vec<HalfEdgeId>>();
517
518 let mut rim_excluded_half_edges: Vec<HalfEdgeId> = self
519 .circulate_edges(initial_half_edge)
520 .flat_map(|edge| [edge.lesser(), edge.greater()])
521 .collect();
522 rim_excluded_half_edges.extend(
523 self.circulation_spokes(initial_half_edge, excluded_half_edges.iter().copied())
524 .flat_map(|edge| [edge.lesser(), edge.greater()]),
525 );
526 rim_excluded_half_edges.extend(excluded_half_edges.iter().copied());
527
528 let Some(initial_half_spoke) = self
529 .circulation_half_spokes(initial_half_edge, excluded_half_edges.iter().copied())
530 .next()
531 else {
532 return CirculateHalfEdgesWithExcludesWalker {
533 initial_half_edge,
534 curr_half_edge: None,
535 excluded_half_edges: rim_excluded_half_edges,
536 }
537 .iter(self);
538 };
539
540 let initial_half_edge = self
541 .half_spokes(self.twin(initial_half_spoke))
542 .find(|half_spoke| !rim_excluded_half_edges.contains(half_spoke))
543 .unwrap();
544
545 self.circulate_half_edges_with_excludes(initial_half_edge, rim_excluded_half_edges)
546 }
547
548 #[inline]
549 pub fn circulation_rim_half_edges_reverse(
550 &self,
551 initial_half_edge: HalfEdgeId,
552 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
553 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
554 let excluded_half_edges = excluded_half_edges.into_iter().collect::<Vec<HalfEdgeId>>();
555
556 let mut rim_excluded_half_edges: Vec<HalfEdgeId> = self
557 .circulate_edges_reverse(initial_half_edge)
558 .flat_map(|edge| [edge.lesser(), edge.greater()])
559 .collect();
560 rim_excluded_half_edges.extend(
561 self.circulation_spokes_reverse(initial_half_edge, excluded_half_edges.iter().copied())
562 .flat_map(|edge| [edge.lesser(), edge.greater()]),
563 );
564 rim_excluded_half_edges.extend(excluded_half_edges.iter().copied());
565
566 let Some(initial_half_spoke) = self
567 .circulation_half_spokes_reverse(initial_half_edge, excluded_half_edges.iter().copied())
568 .next()
569 else {
570 return CirculateHalfEdgesWithExcludesReverseWalker {
571 initial_half_edge,
572 curr_half_edge: None,
573 excluded_half_edges: rim_excluded_half_edges,
574 }
575 .iter(self);
576 };
577
578 let initial_half_edge = self
579 .half_spokes(self.twin(initial_half_spoke))
582 .find(|half_spoke| !rim_excluded_half_edges.contains(half_spoke))
583 .unwrap();
584
585 self.circulate_half_edges_with_excludes_reverse(initial_half_edge, rim_excluded_half_edges)
586 }
587
588 #[inline]
589 pub fn circulation_rim_edges(
590 &self,
591 initial_half_edge: HalfEdgeId,
592 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
593 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
594 CirculateEdgesWithExcludesWalker {
595 circulator: self
596 .circulation_rim_half_edges(initial_half_edge, excluded_half_edges)
597 .walker(),
598 }
599 .iter(self)
600 }
601
602 #[inline]
603 pub fn circulation_rim_edges_reverse(
604 &self,
605 initial_half_edge: HalfEdgeId,
606 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
607 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
608 CirculateEdgesWithExcludesReverseWalker {
609 circulator: self
610 .circulation_rim_half_edges_reverse(initial_half_edge, excluded_half_edges)
611 .walker(),
612 }
613 .iter(self)
614 }
615
616 #[inline]
617 pub fn circulation_rim_vertices(
618 &self,
619 initial_half_edge: HalfEdgeId,
620 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
621 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
622 CirculateVertexesWithExcludesWalker {
623 circulator: self
624 .circulation_rim_half_edges(initial_half_edge, excluded_half_edges)
625 .walker(),
626 }
627 .iter(self)
628 }
629
630 #[inline]
631 pub fn circulation_rim_vertices_reverse(
632 &self,
633 initial_half_edge: HalfEdgeId,
634 excluded_half_edges: impl IntoIterator<Item = HalfEdgeId>,
635 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
636 CirculateVertexesWithExcludesReverseWalker {
637 circulator: self
638 .circulation_rim_half_edges_reverse(initial_half_edge, excluded_half_edges)
639 .walker(),
640 }
641 .iter(self)
642 }
643}
644
645impl<
646 VW,
647 HEW,
648 FW,
649 VC: Get<usize, Value = Vertex<VW>>,
650 HEC: Get<usize, Value = HalfEdge<HEW>>,
651 FC: Get<usize, Value = Face<FW>>,
652> Dcel<VW, HEW, FW, VC, HEC, FC>
653{
654 #[inline]
655 pub fn face_vertices(
656 &self,
657 face: FaceId,
658 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
659 CirculateVertexesWithExcludesWalker {
660 circulator: self.face_half_edges(face).walker(),
661 }
662 .iter(self)
663 }
664
665 #[inline]
666 pub fn face_vertices_reverse(
667 &self,
668 face: FaceId,
669 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
670 CirculateVertexesWithExcludesReverseWalker {
671 circulator: self.face_half_edges_reverse(face).walker(),
672 }
673 .iter(self)
674 }
675}
676
677impl<VW, HEW, FW, VC, HEC, FC: Get<usize, Value = Face<FW>>> Dcel<VW, HEW, FW, VC, HEC, FC> {
678 #[inline]
679 pub fn face_half_edges(
680 &self,
681 face: FaceId,
682 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
683 let Some(initial_half_edge) = self.face_representative(face) else {
687 return CirculateHalfEdgesWithExcludesWalker {
688 initial_half_edge: HalfEdgeId::new(0),
690 curr_half_edge: None,
693 excluded_half_edges: vec![],
694 }
695 .iter(self);
696 };
697
698 CirculateHalfEdgesWithExcludesWalker {
699 initial_half_edge,
700 curr_half_edge: Some(initial_half_edge),
701 excluded_half_edges: vec![],
702 }
703 .iter(self)
704 }
705
706 #[inline]
707 pub fn face_half_edges_reverse(
708 &self,
709 face: FaceId,
710 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
711 let Some(initial_half_edge) = self.face_representative(face) else {
715 return CirculateHalfEdgesWithExcludesReverseWalker {
716 initial_half_edge: HalfEdgeId::new(0),
718 curr_half_edge: None,
721 excluded_half_edges: vec![],
722 }
723 .iter(self);
724 };
725
726 CirculateHalfEdgesWithExcludesReverseWalker {
727 initial_half_edge,
728 curr_half_edge: Some(initial_half_edge),
729 excluded_half_edges: vec![],
730 }
731 .iter(self)
732 }
733
734 #[inline]
735 pub fn face_edges(
736 &self,
737 face: FaceId,
738 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
739 CirculateEdgesWithExcludesWalker {
740 circulator: self.face_half_edges(face).walker(),
741 }
742 .iter(self)
743 }
744
745 #[inline]
746 pub fn face_edges_reverse(
747 &self,
748 face: FaceId,
749 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
750 CirculateEdgesWithExcludesReverseWalker {
751 circulator: self.face_half_edges_reverse(face).walker(),
752 }
753 .iter(self)
754 }
755}
756
757impl<VW, HEW, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>>, FC: Get<usize, Value = Face<FW>>>
758 Dcel<VW, HEW, FW, VC, HEC, FC>
759{
760 #[inline]
761 pub fn face_half_spokes(
762 &self,
763 face: FaceId,
764 ) -> CirculateHalfSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
765 let Some(initial_half_edge) = self.face_representative(face) else {
769 return CirculationHalfSpokesWalker {
770 circulator: CirculateHalfEdgesWithExcludesWalker {
771 initial_half_edge: HalfEdgeId::new(0),
773 curr_half_edge: None,
776 excluded_half_edges: vec![],
777 },
778 half_spokes_walker: HalfSpokesWalker {
779 initial_half_edge: HalfEdgeId::new(0),
780 curr_half_edge: None,
781 },
782 prev_half_edge: HalfEdgeId::new(0),
783 }
784 .iter(self);
785 };
786
787 self.circulation_half_spokes(initial_half_edge, std::iter::empty())
788 }
789
790 #[inline]
791 pub fn face_half_spokes_reverse(
792 &self,
793 face: FaceId,
794 ) -> CirculateHalfSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
795 let Some(initial_half_edge) = self.face_representative(face) else {
799 return CirculationHalfSpokesReverseWalker {
800 circulator: CirculateHalfEdgesWithExcludesReverseWalker {
801 initial_half_edge: HalfEdgeId::new(0),
803 curr_half_edge: None,
806 excluded_half_edges: vec![],
807 },
808 half_spokes_walker: HalfSpokesWalker {
809 initial_half_edge: HalfEdgeId::new(0),
810 curr_half_edge: None,
811 },
812 prev_half_edge: HalfEdgeId::new(0),
813 }
814 .iter(self);
815 };
816
817 self.circulation_half_spokes_reverse(initial_half_edge, std::iter::empty())
818 }
819
820 #[inline]
821 pub fn face_spokes(&self, face: FaceId) -> CirculationSpokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
822 let Some(initial_half_edge) = self.face_representative(face) else {
826 return CirculationSpokesWalker {
827 circulator: CirculationHalfSpokesWalker {
828 circulator: CirculateHalfEdgesWithExcludesWalker {
829 initial_half_edge: HalfEdgeId::new(0),
831 curr_half_edge: None,
834 excluded_half_edges: vec![],
835 },
836 half_spokes_walker: HalfSpokesWalker {
837 initial_half_edge: HalfEdgeId::new(0),
838 curr_half_edge: None,
839 },
840 prev_half_edge: HalfEdgeId::new(0),
841 },
842 }
843 .iter(self);
844 };
845
846 self.circulation_spokes(initial_half_edge, std::iter::empty())
847 }
848
849 #[inline]
850 pub fn face_spokes_reverse(
851 &self,
852 face: FaceId,
853 ) -> CirculationSpokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
854 let Some(initial_half_edge) = self.face_representative(face) else {
858 return CirculationSpokesReverseWalker {
859 circulator: CirculationHalfSpokesReverseWalker {
860 circulator: CirculateHalfEdgesWithExcludesReverseWalker {
861 initial_half_edge: HalfEdgeId::new(0),
863 curr_half_edge: None,
866 excluded_half_edges: vec![],
867 },
868 half_spokes_walker: HalfSpokesWalker {
869 initial_half_edge: HalfEdgeId::new(0),
870 curr_half_edge: None,
871 },
872 prev_half_edge: HalfEdgeId::new(0),
873 },
874 }
875 .iter(self);
876 };
877
878 self.circulation_spokes_reverse(initial_half_edge, std::iter::empty())
879 }
880
881 #[inline]
882 pub fn face_interspokes(
883 &self,
884 face: FaceId,
885 ) -> CirculationInterspokesIter<'_, VW, HEW, FW, VC, HEC, FC> {
886 let Some(initial_half_edge) = self.face_representative(face) else {
890 return CirculationInterspokesWalker {
891 circulator: CirculationHalfSpokesWalker {
892 circulator: CirculateHalfEdgesWithExcludesWalker {
893 initial_half_edge: HalfEdgeId::new(0),
895 curr_half_edge: None,
898 excluded_half_edges: vec![],
899 },
900 half_spokes_walker: HalfSpokesWalker {
901 initial_half_edge: HalfEdgeId::new(0),
902 curr_half_edge: None,
903 },
904 prev_half_edge: HalfEdgeId::new(0),
905 },
906 }
907 .iter(self);
908 };
909
910 self.circulation_interspokes(initial_half_edge, std::iter::empty())
911 }
912
913 #[inline]
914 pub fn face_interspokes_reverse(
915 &self,
916 face: FaceId,
917 ) -> CirculationInterspokesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
918 let Some(initial_half_edge) = self.face_representative(face) else {
922 return CirculationInterspokesReverseWalker {
923 circulator: CirculationHalfSpokesReverseWalker {
924 circulator: CirculateHalfEdgesWithExcludesReverseWalker {
925 initial_half_edge: HalfEdgeId::new(0),
927 curr_half_edge: None,
930 excluded_half_edges: vec![],
931 },
932 half_spokes_walker: HalfSpokesWalker {
933 initial_half_edge: HalfEdgeId::new(0),
934 curr_half_edge: None,
935 },
936 prev_half_edge: HalfEdgeId::new(0),
937 },
938 }
939 .iter(self);
940 };
941
942 self.circulation_interspokes_reverse(initial_half_edge, std::iter::empty())
943 }
944
945 #[inline]
946 pub fn face_rim_half_edges(
947 &self,
948 face: FaceId,
949 ) -> CirculateHalfEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
950 let Some(initial_half_edge) = self.face_representative(face) else {
954 return CirculateHalfEdgesWithExcludesWalker {
955 initial_half_edge: HalfEdgeId::new(0),
957 curr_half_edge: None,
960 excluded_half_edges: vec![],
961 }
962 .iter(self);
963 };
964
965 self.circulation_rim_half_edges(initial_half_edge, std::iter::empty())
966 }
967
968 #[inline]
969 pub fn face_rim_half_edges_reverse(
970 &self,
971 face: FaceId,
972 ) -> CirculateHalfEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
973 let Some(initial_half_edge) = self.face_representative(face) else {
977 return CirculateHalfEdgesWithExcludesReverseWalker {
978 initial_half_edge: HalfEdgeId::new(0),
980 curr_half_edge: None,
983 excluded_half_edges: vec![],
984 }
985 .iter(self);
986 };
987
988 self.circulation_rim_half_edges_reverse(initial_half_edge, std::iter::empty())
989 }
990
991 #[inline]
992 pub fn face_rim_vertices(
993 &self,
994 face: FaceId,
995 ) -> CirculateVertexesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
996 let Some(initial_half_edge) = self.face_representative(face) else {
1000 return CirculateVertexesWithExcludesWalker {
1001 circulator: CirculateHalfEdgesWithExcludesWalker {
1002 initial_half_edge: HalfEdgeId::new(0),
1004 curr_half_edge: None,
1007 excluded_half_edges: vec![],
1008 },
1009 }
1010 .iter(self);
1011 };
1012
1013 self.circulation_rim_vertices(initial_half_edge, std::iter::empty())
1014 }
1015
1016 #[inline]
1017 pub fn face_rim_vertices_reverse(
1018 &self,
1019 face: FaceId,
1020 ) -> CirculateVertexesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
1021 let Some(initial_half_edge) = self.face_representative(face) else {
1025 return CirculateVertexesWithExcludesReverseWalker {
1026 circulator: CirculateHalfEdgesWithExcludesReverseWalker {
1027 initial_half_edge: HalfEdgeId::new(0),
1029 curr_half_edge: None,
1032 excluded_half_edges: vec![],
1033 },
1034 }
1035 .iter(self);
1036 };
1037
1038 self.circulation_rim_vertices_reverse(initial_half_edge, std::iter::empty())
1039 }
1040
1041 #[inline]
1042 pub fn face_rim_edges(
1043 &self,
1044 face: FaceId,
1045 ) -> CirculateEdgesWithExcludesIter<'_, VW, HEW, FW, VC, HEC, FC> {
1046 let Some(initial_half_edge) = self.face_representative(face) else {
1050 return CirculateEdgesWithExcludesWalker {
1051 circulator: CirculateHalfEdgesWithExcludesWalker {
1052 initial_half_edge: HalfEdgeId::new(0),
1054 curr_half_edge: None,
1057 excluded_half_edges: vec![],
1058 },
1059 }
1060 .iter(self);
1061 };
1062
1063 self.circulation_rim_edges(initial_half_edge, std::iter::empty())
1064 }
1065
1066 #[inline]
1067 pub fn face_rim_edges_reverse(
1068 &self,
1069 face: FaceId,
1070 ) -> CirculateEdgesWithExcludesReverseIter<'_, VW, HEW, FW, VC, HEC, FC> {
1071 let Some(initial_half_edge) = self.face_representative(face) else {
1075 return CirculateEdgesWithExcludesReverseWalker {
1076 circulator: CirculateHalfEdgesWithExcludesReverseWalker {
1077 initial_half_edge: HalfEdgeId::new(0),
1079 curr_half_edge: None,
1082 excluded_half_edges: vec![],
1083 },
1084 }
1085 .iter(self);
1086 };
1087
1088 self.circulation_rim_edges_reverse(initial_half_edge, std::iter::empty())
1089 }
1090}
1091
1092#[cfg(test)]
1093mod test {
1094 use crate::{
1095 Dcel, assert_face_boundary, assert_face_rim, assert_face_spokes_interspokes,
1096 assert_vertex_rim, assert_vertex_spokes_interspokes, init_dcel_with_3x3_hex_mesh,
1097 };
1098
1099 #[test]
1100 fn test_vertex_rims() {
1101 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
1102
1103 assert_vertex_rim!(&dcel, 0, 0);
1104 assert_vertex_rim!(&dcel, 1, 0);
1105 assert_vertex_rim!(&dcel, 2, 0);
1106 assert_vertex_rim!(&dcel, 3, 0);
1107 assert_vertex_rim!(&dcel, 4, 0);
1108 assert_vertex_rim!(&dcel, 5, 12);
1109 assert_vertex_rim!(&dcel, 6, 0);
1110 assert_vertex_rim!(&dcel, 7, 0);
1111 assert_vertex_rim!(&dcel, 8, 12);
1112 assert_vertex_rim!(&dcel, 9, 12);
1113 assert_vertex_rim!(&dcel, 10, 0);
1114 assert_vertex_rim!(&dcel, 11, 0);
1115 assert_vertex_rim!(&dcel, 12, 12);
1116 assert_vertex_rim!(&dcel, 13, 0);
1117 assert_vertex_rim!(&dcel, 14, 0);
1118 assert_vertex_rim!(&dcel, 15, 12);
1119 assert_vertex_rim!(&dcel, 16, 12);
1120 assert_vertex_rim!(&dcel, 17, 12);
1121 assert_vertex_rim!(&dcel, 18, 12);
1122 assert_vertex_rim!(&dcel, 19, 0);
1123 assert_vertex_rim!(&dcel, 20, 0);
1124 assert_vertex_rim!(&dcel, 21, 0);
1125 assert_vertex_rim!(&dcel, 22, 0);
1126 assert_vertex_rim!(&dcel, 23, 0);
1127 assert_vertex_rim!(&dcel, 24, 0);
1128 assert_vertex_rim!(&dcel, 25, 0);
1129 assert_vertex_rim!(&dcel, 26, 0);
1130 assert_vertex_rim!(&dcel, 27, 0);
1131 assert_vertex_rim!(&dcel, 28, 0);
1132 assert_vertex_rim!(&dcel, 29, 0);
1133 }
1134
1135 #[test]
1136 fn test_vertex_spokes_interspokes() {
1137 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
1138
1139 assert_vertex_spokes_interspokes!(&dcel, 0, 3);
1140 assert_vertex_spokes_interspokes!(&dcel, 1, 2);
1141 assert_vertex_spokes_interspokes!(&dcel, 2, 2);
1142 assert_vertex_spokes_interspokes!(&dcel, 3, 2);
1143 assert_vertex_spokes_interspokes!(&dcel, 4, 3);
1144 assert_vertex_spokes_interspokes!(&dcel, 5, 3);
1145 assert_vertex_spokes_interspokes!(&dcel, 6, 3);
1146 assert_vertex_spokes_interspokes!(&dcel, 7, 2);
1147 assert_vertex_spokes_interspokes!(&dcel, 8, 3);
1148 assert_vertex_spokes_interspokes!(&dcel, 9, 3);
1149 assert_vertex_spokes_interspokes!(&dcel, 10, 2);
1150 assert_vertex_spokes_interspokes!(&dcel, 11, 2);
1151 assert_vertex_spokes_interspokes!(&dcel, 12, 3);
1152 assert_vertex_spokes_interspokes!(&dcel, 13, 3);
1153 assert_vertex_spokes_interspokes!(&dcel, 14, 3);
1154 assert_vertex_spokes_interspokes!(&dcel, 15, 3);
1155 assert_vertex_spokes_interspokes!(&dcel, 16, 3);
1156 assert_vertex_spokes_interspokes!(&dcel, 17, 3);
1157 assert_vertex_spokes_interspokes!(&dcel, 18, 3);
1158 assert_vertex_spokes_interspokes!(&dcel, 19, 2);
1159 assert_vertex_spokes_interspokes!(&dcel, 20, 3);
1160 assert_vertex_spokes_interspokes!(&dcel, 21, 2);
1161 assert_vertex_spokes_interspokes!(&dcel, 22, 2);
1162 assert_vertex_spokes_interspokes!(&dcel, 23, 2);
1163 assert_vertex_spokes_interspokes!(&dcel, 24, 2);
1164 assert_vertex_spokes_interspokes!(&dcel, 25, 3);
1165 assert_vertex_spokes_interspokes!(&dcel, 26, 2);
1166 assert_vertex_spokes_interspokes!(&dcel, 27, 3);
1167 assert_vertex_spokes_interspokes!(&dcel, 28, 2);
1168 assert_vertex_spokes_interspokes!(&dcel, 29, 2);
1169 }
1170
1171 #[test]
1172 fn test_face_boundaries() {
1173 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
1174
1175 assert_face_boundary!(&dcel, 0, 0);
1176 assert_face_boundary!(&dcel, 1, 6);
1177 assert_face_boundary!(&dcel, 2, 6);
1178 assert_face_boundary!(&dcel, 3, 6);
1179 assert_face_boundary!(&dcel, 4, 6);
1180 assert_face_boundary!(&dcel, 5, 6);
1181 assert_face_boundary!(&dcel, 6, 6);
1182 assert_face_boundary!(&dcel, 7, 6);
1183 assert_face_boundary!(&dcel, 8, 6);
1184 assert_face_boundary!(&dcel, 9, 6);
1185 }
1186
1187 #[test]
1188 fn test_face_spokes_interspokes() {
1189 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
1190
1191 assert_face_spokes_interspokes!(&dcel, 0, 0);
1192 assert_face_spokes_interspokes!(&dcel, 1, 3);
1193 assert_face_spokes_interspokes!(&dcel, 2, 5);
1194 assert_face_spokes_interspokes!(&dcel, 3, 4);
1195 assert_face_spokes_interspokes!(&dcel, 4, 6);
1196 assert_face_spokes_interspokes!(&dcel, 5, 6);
1197 assert_face_spokes_interspokes!(&dcel, 6, 4);
1198 assert_face_spokes_interspokes!(&dcel, 7, 3);
1199 assert_face_spokes_interspokes!(&dcel, 8, 5);
1200 assert_face_spokes_interspokes!(&dcel, 9, 4);
1201 }
1202
1203 #[test]
1204 fn test_face_rims() {
1205 let dcel = init_dcel_with_3x3_hex_mesh!(Dcel<(i32, i32)>);
1206
1207 assert_face_rim!(&dcel, 0, 0);
1208
1209 assert_face_rim!(&dcel, 5, 18);
1218
1219 }
1226}