alum/iterator.rs
1use crate::{
2 Adaptor, FPropBuf, HasTopology, PolyMeshT, Status,
3 element::{EH, FH, HH, VH},
4 topol::Topology,
5};
6use std::{marker::PhantomData, ptr::NonNull};
7
8/*
9Halfedges are at the core of all iterators, because halfedges have the most
10amount of connectivity information than any other type of mesh element. There
11are two base types of iterators: Radial and Loop. Radial iterators go over the
12halfedges rotated around their tail vertex. Loop iterators traverse the
13next/previous halfedge links, hence traverse loops. Both of these iterator types
14can go either counter-clockwise or clockwise. Further more, they can either
15borrow the mesh immutably or mutably. All other iterators such as face-vertex,
16and vertex-vertex etc. can be expressed in terms of these base iterators using
17`.map()`.
18 */
19
20/// Iterator over halfedges radiating outward from a vertex.
21struct RadialHalfedgeIter<'a, const CCW: bool> {
22 topol: &'a Topology,
23 hstart: Option<HH>,
24 hcurrent: Option<HH>,
25}
26
27impl Iterator for RadialHalfedgeIter<'_, true> {
28 type Item = HH;
29
30 fn next(&mut self) -> Option<Self::Item> {
31 match self.hcurrent {
32 Some(current) => {
33 let next = current.prev(self.topol).opposite();
34 self.hcurrent = match self.hstart {
35 Some(start) if start != next => Some(next),
36 _ => None,
37 };
38 Some(current)
39 }
40 None => None,
41 }
42 }
43}
44
45impl Iterator for RadialHalfedgeIter<'_, false> {
46 type Item = HH;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 match self.hcurrent {
50 Some(current) => {
51 let next = current.opposite().next(self.topol);
52 self.hcurrent = match self.hstart {
53 Some(start) if start != next => Some(next),
54 _ => None,
55 };
56 Some(current)
57 }
58 None => None,
59 }
60 }
61}
62
63/// Iterator for halfedges in a loop.
64struct LoopHalfedgeIter<'a, const CCW: bool> {
65 topol: &'a Topology,
66 hstart: HH,
67 hcurrent: Option<HH>,
68}
69
70impl Iterator for LoopHalfedgeIter<'_, true> {
71 type Item = HH;
72
73 fn next(&mut self) -> Option<Self::Item> {
74 match self.hcurrent {
75 Some(current) => {
76 let next = current.next(self.topol);
77 self.hcurrent = if next == self.hstart {
78 None
79 } else {
80 Some(next)
81 };
82 Some(current)
83 }
84 None => None,
85 }
86 }
87}
88
89impl Iterator for LoopHalfedgeIter<'_, false> {
90 type Item = HH;
91
92 fn next(&mut self) -> Option<Self::Item> {
93 match self.hcurrent {
94 Some(current) => {
95 let next = current.prev(self.topol);
96 self.hcurrent = if next == self.hstart {
97 None
98 } else {
99 Some(next)
100 };
101 Some(current)
102 }
103 None => None,
104 }
105 }
106}
107
108struct RadialHalfedgeIterMut<'a, const CCW: bool, T> {
109 reference: NonNull<T>,
110 topol: &'a mut Topology,
111 hstart: Option<HH>,
112 hcurrent: Option<HH>,
113 _phantom: PhantomData<&'a mut T>,
114}
115
116impl<'a, T> Iterator for RadialHalfedgeIterMut<'a, true, T> {
117 type Item = (&'a mut T, HH);
118
119 fn next(&mut self) -> Option<Self::Item> {
120 match self.hcurrent {
121 Some(current) => {
122 let next = current.prev(self.topol).opposite();
123 self.hcurrent = match self.hstart {
124 Some(start) if start != next => Some(next),
125 _ => None,
126 };
127 /* SAFETY: This is just a to get around the the fact that Rust
128 doesn't allow lending iterators. The output type of the iterator
129 cannot have a lifetime, and cannot borrow from the iterator
130 itself. `self.reference` points to `self.topol` and that
131 reference cannot be modified by anyone else.
132 */
133 Some((unsafe { self.reference.as_mut() }, current))
134 }
135 None => None,
136 }
137 }
138}
139
140impl<'a, T> Iterator for RadialHalfedgeIterMut<'a, false, T> {
141 type Item = (&'a mut T, HH);
142
143 fn next(&mut self) -> Option<Self::Item> {
144 match self.hcurrent {
145 Some(current) => {
146 let next = current.opposite().next(self.topol);
147 self.hcurrent = match self.hstart {
148 Some(start) if start != next => Some(next),
149 _ => None,
150 };
151 /* SAFETY: This is just a to get around the the fact that Rust
152 doesn't allow lending iterators. The output type of the iterator
153 cannot have a lifetime, and cannot borrow from the iterator
154 itself. `self.reference` points to `self.topol` and that
155 reference cannot be modified by anyone else.
156 */
157 Some((unsafe { self.reference.as_mut() }, current))
158 }
159 None => None,
160 }
161 }
162}
163
164struct LoopHalfedgeIterMut<'a, const CCW: bool, T> {
165 reference: NonNull<T>,
166 topol: &'a mut Topology,
167 hstart: HH,
168 hcurrent: Option<HH>,
169 _phantom: PhantomData<&'a mut T>,
170}
171
172impl<'a, T> Iterator for LoopHalfedgeIterMut<'a, true, T> {
173 type Item = (&'a mut T, HH);
174
175 fn next(&mut self) -> Option<Self::Item> {
176 match self.hcurrent {
177 Some(current) => {
178 let next = current.next(self.topol);
179 self.hcurrent = if next == self.hstart {
180 None
181 } else {
182 Some(next)
183 };
184 /* SAFETY: This is just a to get around the the fact that Rust
185 doesn't allow lending iterators. The output type of the iterator
186 cannot have a lifetime, and cannot borrow from the iterator
187 itself. `self.reference` points to `self.topol` and that
188 reference cannot be modified by anyone else.
189 */
190 Some((unsafe { self.reference.as_mut() }, current))
191 }
192 None => None,
193 }
194 }
195}
196
197impl<'a, T> Iterator for LoopHalfedgeIterMut<'a, false, T> {
198 type Item = (&'a mut T, HH);
199
200 fn next(&mut self) -> Option<Self::Item> {
201 match self.hcurrent {
202 Some(current) => {
203 let next = current.prev(self.topol);
204 self.hcurrent = if next == self.hstart {
205 None
206 } else {
207 Some(next)
208 };
209 /* SAFETY: This is just a to get around the the fact that Rust
210 doesn't allow lending iterators. The output type of the iterator
211 cannot have a lifetime, and cannot borrow from the iterator
212 itself. `self.reference` points to `self.topol` and that
213 reference cannot be modified by anyone else.
214 */
215 Some((unsafe { self.reference.as_mut() }, current))
216 }
217 None => None,
218 }
219 }
220}
221
222pub trait HasIterators: HasTopology {
223 /*!
224 This trait defines iterators to traverse the topology of a mesh.
225
226 # Working with mutable iterators
227
228 Iterators such as [`Self::loop_ccw_iter`] and other `*_iter` iterators
229 borrow the mesh immutably. These are useful when iterating over the elements
230 of the mesh without needing to modify the mesh. While the mesh is borrowed
231 by the iterators, the borrow checker will not let you borrow the mesh again
232 mutably, for as long as the iterator is alive. This is a problem if you're
233 trying to modify the mesh while iterating over it's elements. In such
234 scenarios, mutable iterators are useful. These functions end with
235 `*_iter_mut`.
236
237 The `*_iter_mut` functions borrow the mesh mutably. Similar to immutable
238 iterators, while the mutable iterator is alive, the borrow checker won't let
239 you mutably borrow the mesh again. But, unlike the immutable iterators, the
240 mutable iterators don't yield just the elements of the mesh. Instead the
241 mutable iterators yield a tuple containing a mutable reference to the mesh,
242 and the mesh element. You can modify the mesh using the mutable reference
243 yielded by the mutable iterator. So essentially, the borrow checker is happy
244 because the iterator borrows the mesh mutably and to modify the mesh, you
245 borrow the mesh from the iterator. The borrows are chained instead of being
246 simultaenous. This keeps the borrow checker happy, and ensures safety to
247 some extent. Below is some example code that iterates over the vertices of
248 face with index 2, and modifies their positions.
249
250 ```rust
251 use alum::{PolyMeshF32, FH, HasIterators, HasTopology};
252
253 let mut boxmesh = PolyMeshF32::unit_box().expect("Cannot create a box");
254 assert_eq!(1.0, boxmesh.try_calc_volume().expect("Cannot compute volume"));
255 // Modify the mesh while using a mutable iterator - pull points closer to origin.
256 let f: FH = 2.into();
257 for (mesh, v) in boxmesh.fv_ccw_iter_mut(f) {
258 // Inside this loop, while the iterator is alive, we cannot borrow `boxmesh`
259 // because the iterator already borrowed `boxmesh` mutably. Instead we will use
260 // the `mesh` mutable reference yielded by the iterator along with the halfedge.
261 let mut pos = mesh.point(v).expect("Cannot read position");
262 pos *= 0.75;
263 mesh.set_point(v, pos);
264 }
265 // The iterator is not alive anymore, so we can borrow `boxmesh` again.
266 boxmesh.check_topology().expect("Topological errors found");
267 // Volume is smaller than one because we pulled the vertices closer to the origin.
268 assert!(1.0 > boxmesh.try_calc_volume().expect("Cannot compute volume"));
269 ```
270
271 Despite enforcing the borrow checker rules, the mutable iterators can lead
272 to problems when used incorrectly. Modifying the topology of the mesh while
273 using mutable iterators is NOT advised, as this can lead to topological
274 errors. Only do this if you're know what you're doing. This is akin to
275 mutably iterating over a linked list while modifying the links between the
276 elements of the linked list. You can easily create cycles, infinite loops
277 and other problems if you're not careful.
278 */
279
280 /// Iterator over the outgoing halfedges around a vertex, going counter-clockwise.
281 fn voh_ccw_iter(&self, v: VH) -> impl Iterator<Item = HH> {
282 let h = v.halfedge(self.topology());
283 RadialHalfedgeIter::<true> {
284 topol: self.topology(),
285 hstart: h,
286 hcurrent: h,
287 }
288 }
289
290 /// Iterator over the outgoing halfedges around a vertex, going clockwise
291 fn voh_cw_iter(&self, v: VH) -> impl Iterator<Item = HH> {
292 let h = v.halfedge(self.topology());
293 RadialHalfedgeIter::<false> {
294 topol: self.topology(),
295 hstart: h,
296 hcurrent: h,
297 }
298 }
299
300 /// Iterator over the incoming halfedges around a vertex, going
301 /// counter-clockwise
302 fn vih_ccw_iter(&self, v: VH) -> impl Iterator<Item = HH> {
303 self.voh_ccw_iter(v).map(|h| h.opposite())
304 }
305
306 /// Iterator over the incoming halfedges around a vertex, going clockwise
307 fn vih_cw_iter(&self, v: VH) -> impl Iterator<Item = HH> {
308 self.voh_cw_iter(v).map(|h| h.opposite())
309 }
310
311 /// Iterator over the faces incident on a vertex, going counter-clockwise.
312 fn vf_ccw_iter(&self, v: VH) -> impl Iterator<Item = FH> {
313 self.voh_ccw_iter(v).filter_map(|h| h.face(self.topology()))
314 }
315
316 /// Iterator over the faces incident on a vertex, going clockwise.
317 fn vf_cw_iter(&self, v: VH) -> impl Iterator<Item = FH> {
318 self.voh_cw_iter(v).filter_map(|h| h.face(self.topology()))
319 }
320
321 /// Iterator over the neighboring vertices around the given vertex, going
322 /// counter-clockwise.
323 fn vv_ccw_iter(&self, v: VH) -> impl Iterator<Item = VH> {
324 self.voh_ccw_iter(v).map(|h| h.head(self.topology()))
325 }
326
327 /// Iterator over the neighboring vertices around the given vertex, going
328 /// clockwise.
329 fn vv_cw_iter(&self, v: VH) -> impl Iterator<Item = VH> {
330 self.voh_cw_iter(v).map(|h| h.head(self.topology()))
331 }
332
333 /// Iterator over the incident edges around an vertex, going counter-clockwise.
334 fn ve_ccw_iter(&self, v: VH) -> impl Iterator<Item = EH> {
335 self.voh_ccw_iter(v).map(|h| h.edge())
336 }
337
338 /// Iterator over the incident edges around a vertex, going clockwise.
339 fn ve_cw_iter(&self, v: VH) -> impl Iterator<Item = EH> {
340 self.voh_cw_iter(v).map(|h| h.edge())
341 }
342
343 /// Iterator over the two vertices incident on the given edge.
344 fn ev_iter(&self, e: EH) -> impl Iterator<Item = VH> {
345 self.eh_iter(e).map(|h| h.head(self.topology()))
346 }
347
348 /// Iterator over the two halfedges corresponding to an edge.
349 fn eh_iter(&self, e: EH) -> impl Iterator<Item = HH> {
350 [false, true].iter().map(move |flag| e.halfedge(*flag))
351 }
352
353 /// Iterator over the faces incident on an edge.
354 fn ef_iter(&self, e: EH) -> impl Iterator<Item = FH> {
355 self.eh_iter(e).filter_map(|h| h.face(self.topology()))
356 }
357
358 /// Iterator over the halfedges of a face loop, going counter-clockwise.
359 fn fh_ccw_iter(&self, f: FH) -> impl Iterator<Item = HH> {
360 let h = f.halfedge(self.topology());
361 LoopHalfedgeIter::<true> {
362 topol: self.topology(),
363 hstart: h,
364 hcurrent: Some(h),
365 }
366 }
367
368 /// Iterator over the halfedges of a face loop, going clockwise.
369 fn fh_cw_iter(&self, f: FH) -> impl Iterator<Item = HH> {
370 let h = f.halfedge(self.topology());
371 LoopHalfedgeIter::<false> {
372 topol: self.topology(),
373 hstart: h,
374 hcurrent: Some(h),
375 }
376 }
377
378 /// Iterator over the vertices incident on a face, going counter-clockwise.
379 fn fv_ccw_iter(&self, f: FH) -> impl Iterator<Item = VH> {
380 self.fh_ccw_iter(f).map(|h| h.head(self.topology()))
381 }
382
383 /// Iterator over the vertices incident on a face, going clockwise.
384 fn fv_cw_iter(&self, f: FH) -> impl Iterator<Item = VH> {
385 self.fh_cw_iter(f).map(|h| h.head(self.topology()))
386 }
387
388 /// Iterator over the edges incident on a face, going counter-clockwise.
389 fn fe_ccw_iter(&self, f: FH) -> impl Iterator<Item = EH> {
390 self.fh_ccw_iter(f).map(|h| h.edge())
391 }
392
393 /// Iterator over the edges incident on a face, going clockwise.
394 fn fe_cw_iter(&self, f: FH) -> impl Iterator<Item = EH> {
395 self.fh_cw_iter(f).map(|h| h.edge())
396 }
397
398 /// Iterator over the neighboring faces arouund the given face, going
399 /// counter-clockwise.
400 ///
401 /// This includes the faces connected via a shared edge, but not those
402 /// connected via a shared vertex.
403 fn ff_ccw_iter(&self, f: FH) -> impl Iterator<Item = FH> {
404 self.fh_ccw_iter(f)
405 .filter_map(|h| h.opposite().face(self.topology()))
406 }
407
408 /// Iterator over the neighboring faces around the given face, going
409 /// clockwise.
410 ///
411 /// This includes the faces connected via a shared edge, but not those
412 /// connected via a shared vertex.
413 fn ff_cw_iter(&self, f: FH) -> impl Iterator<Item = FH> {
414 self.fh_cw_iter(f)
415 .filter_map(|h| h.opposite().face(self.topology()))
416 }
417
418 /// This is similar to [`Self::voh_ccw_iter`] around the tail of the given
419 /// halfedge, except this iterator starts at the provided halfedge.
420 ///
421 /// This is equivalent to a circular shifted [`Self::voh_ccw_iter`] of the
422 /// vertex at the tail of this halfedge.
423 fn ccw_rotate_iter(&self, h: HH) -> impl Iterator<Item = HH> {
424 RadialHalfedgeIter::<true> {
425 topol: self.topology(),
426 hstart: Some(h),
427 hcurrent: Some(h),
428 }
429 }
430
431 /// This is similar to [`Self::voh_cw_iter`] around the tail of the given
432 /// halfedge, except this iterator starts at the provided halfedge.
433 ///
434 /// This is equivalent to a circular shifted [`Self::voh_cw_iter`] of the
435 /// vertex at the tail of this halfedge.
436 fn cw_rotate_iter(&self, h: HH) -> impl Iterator<Item = HH> {
437 RadialHalfedgeIter::<false> {
438 topol: self.topology(),
439 hstart: Some(h),
440 hcurrent: Some(h),
441 }
442 }
443
444 /// Counter-clockwise iterator over the halfedges in a loop.
445 ///
446 /// The iterator will start at the given halfedge. If the halfedge has an
447 /// incident face, this iterator is equivalent to a circular shifted
448 /// [`Self::fh_ccw_iter`] of the incident face. If the halfedge is on the
449 /// boundary, this iterator goes over the boundary loop counter-clockwise.
450 fn loop_ccw_iter(&self, h: HH) -> impl Iterator<Item = HH> {
451 LoopHalfedgeIter::<true> {
452 topol: self.topology(),
453 hstart: h,
454 hcurrent: Some(h),
455 }
456 }
457
458 /// Counter-clockwise iterator over the halfedges in a loop.
459 ///
460 /// The iterator will start at the given halfedge. If the halfedge has an
461 /// incident face, this iterator is equivalent to a circular shifted
462 /// [`Self::fh_cw_iter`] of the incident face. If the halfedge is on the
463 /// boundary, this iterator goes over the boundary loop clockwise.
464 fn loop_cw_iter(&self, h: HH) -> impl Iterator<Item = HH> {
465 LoopHalfedgeIter::<false> {
466 topol: self.topology(),
467 hstart: h,
468 hcurrent: Some(h),
469 }
470 }
471
472 /// Iterator over the outgoing halfedges around a vertex, going
473 /// counter-clockwise.
474 ///
475 /// A mutable iterator allows modifying the mesh while iterating over its
476 /// elements. See [this section](#working-with-mutable-iterators) for an
477 /// overview on mutable iterators.
478 fn voh_ccw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, HH)> {
479 let h = v.halfedge(self.topology());
480 RadialHalfedgeIterMut::<true, Self> {
481 reference: self.into(),
482 topol: self.topology_mut(),
483 hstart: h,
484 hcurrent: h,
485 _phantom: PhantomData,
486 }
487 }
488
489 /// Iterator over the outgoing halfedges around a vertex, going clockwise.
490 ///
491 /// A mutable iterator allows modifying the mesh while iterating over its
492 /// elements. See [this section](#working-with-mutable-iterators) for an
493 /// overview on mutable iterators.
494 fn voh_cw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, HH)> {
495 let h = v.halfedge(self.topology());
496 RadialHalfedgeIterMut::<false, Self> {
497 reference: self.into(),
498 topol: self.topology_mut(),
499 hstart: h,
500 hcurrent: h,
501 _phantom: PhantomData,
502 }
503 }
504
505 /// Iterator over the incoming halfedges around a vertex, going
506 /// counter-clockwise.
507 ///
508 /// A mutable iterator allows modifying the mesh while iterating over its
509 /// elements. See [this section](#working-with-mutable-iterators) for an
510 /// overview on mutable iterators.
511 fn vih_ccw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, HH)> {
512 self.voh_ccw_iter_mut(v)
513 .map(|(mesh, h)| (mesh, h.opposite()))
514 }
515
516 /// Iterator over the incoming halfedges around a vertex, going clockwise.
517 ///
518 /// A mutable iterator allows modifying the mesh while iterating over its
519 /// elements. See [this section](#working-with-mutable-iterators) for an
520 /// overview on mutable iterators.
521 fn vih_cw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, HH)> {
522 self.voh_cw_iter_mut(v)
523 .map(|(mesh, h)| (mesh, h.opposite()))
524 }
525
526 /// Mutable iterator over the neighboring vertices around the given vertex,
527 /// going counter-clockwise.
528 ///
529 /// A mutable iterator allows modifying the mesh while iterating over its
530 /// elements. See [this section](#working-with-mutable-iterators) for an
531 /// overview on mutable iterators.
532 fn vv_ccw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, VH)> {
533 self.voh_ccw_iter_mut(v).map(|(mesh, h)| {
534 let v = h.head(mesh);
535 (mesh, v)
536 })
537 }
538
539 /// Mutable iterator over the neighboring vertices around the given vertex,
540 /// going clockwise.
541 ///
542 /// A mutable iterator allows modifying the mesh while iterating over its
543 /// elements. See [this section](#working-with-mutable-iterators) for an
544 /// overview on mutable iterators.
545 fn vv_cw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, VH)> {
546 self.voh_cw_iter_mut(v).map(|(mesh, h)| {
547 let v = h.head(mesh);
548 (mesh, v)
549 })
550 }
551
552 /// Iterator over the incident edges around a vertex, going
553 /// counter-clockwise.
554 ///
555 /// A mutable iterator allows modifying the mesh while iterating over its
556 /// elements. See [this section](#working-with-mutable-iterators) for an
557 /// overview on mutable iterators.
558 fn ve_ccw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, EH)> {
559 self.voh_ccw_iter_mut(v).map(|(mesh, h)| (mesh, h.edge()))
560 }
561
562 /// Iterator over the incident edges around a vertex, going clockwise.
563 ///
564 /// A mutable iterator allows modifying the mesh while iterating over its
565 /// elements. See [this section](#working-with-mutable-iterators) for an
566 /// overview on mutable iterators.
567 fn ve_cw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, EH)> {
568 self.voh_cw_iter_mut(v).map(|(mesh, h)| (mesh, h.edge()))
569 }
570
571 /// Iterator over the incident faces around a vertex, going
572 /// counter-clockwise.
573 ///
574 /// A mutable iterator allows modifying the mesh while iterating over its
575 /// elements. See [this section](#working-with-mutable-iterators) for an
576 /// overview on mutable iterators.
577 fn vf_ccw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, FH)> {
578 self.voh_ccw_iter_mut(v)
579 .filter_map(|(mesh, h)| h.face(mesh).map(|f| (mesh, f)))
580 }
581
582 /// Iterator over the incident faces around a vertex, going clockwise.
583 ///
584 /// A mutable iterator allows modifying the mesh while iterating over its
585 /// elements. See [this section](#working-with-mutable-iterators) for an
586 /// overview on mutable iterators.
587 fn vf_cw_iter_mut(&mut self, v: VH) -> impl Iterator<Item = (&mut Self, FH)> {
588 self.voh_cw_iter_mut(v)
589 .filter_map(|(mesh, h)| h.face(mesh).map(|f| (mesh, f)))
590 }
591
592 /// Iterator over the vertices incident on a face, going counter-clockwise.
593 ///
594 /// A mutable iterator allows modifying the mesh while iterating over its
595 /// elements. See [this section](#working-with-mutable-iterators) for an
596 /// overview on mutable iterators.
597 fn fv_ccw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, VH)> {
598 self.fh_ccw_iter_mut(f).map(|(mesh, h)| {
599 let v = h.head(mesh);
600 (mesh, v)
601 })
602 }
603
604 /// Iterator over the vertices incident on a face, going clockwise.
605 ///
606 /// A mutable iterator allows modifying the mesh while iterating over its
607 /// elements. See [this section](#working-with-mutable-iterators) for an
608 /// overview on mutable iterators.
609 fn fv_cw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, VH)> {
610 self.fh_cw_iter_mut(f).map(|(mesh, h)| {
611 let v = h.head(mesh);
612 (mesh, v)
613 })
614 }
615
616 /// Iterator over the halfedges of a face loop, going counter-clockwise.
617 ///
618 /// A mutable iterator allows modifying the mesh while iterating over its
619 /// elements. See [this section](#working-with-mutable-iterators) for an
620 /// overview on mutable iterators.
621 fn fh_ccw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, HH)> {
622 let h = f.halfedge(self);
623 LoopHalfedgeIterMut::<true, Self> {
624 reference: self.into(),
625 topol: self.topology_mut(),
626 hstart: h,
627 hcurrent: Some(h),
628 _phantom: PhantomData,
629 }
630 }
631
632 /// Iterator over the halfedges in a face loop, going clockwise.
633 ///
634 /// A mutable iterator allows modifying the mesh while iterating over its
635 /// elements. See [this section](#working-with-mutable-iterators) for an
636 /// overview on mutable iterators.
637 fn fh_cw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, HH)> {
638 let h = f.halfedge(self);
639 LoopHalfedgeIterMut::<false, Self> {
640 reference: self.into(),
641 topol: self.topology_mut(),
642 hstart: h,
643 hcurrent: Some(h),
644 _phantom: PhantomData,
645 }
646 }
647
648 /// Iterator over the edges incident on a face, going counter-clockwise.
649 ///
650 /// A mutable iterator allows modifying the mesh while iterating over its
651 /// elements. See [this section](#working-with-mutable-iterators) for an
652 /// overview on mutable iterators.
653 fn fe_ccw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, EH)> {
654 self.fh_ccw_iter_mut(f).map(|(mesh, h)| (mesh, h.edge()))
655 }
656
657 /// Iterator over the edges incident on a face, going clockwise.
658 ///
659 /// A mutable iterator allows modifying the mesh while iterating over its
660 /// elements. See [this section](#working-with-mutable-iterators) for an
661 /// overview on mutable iterators.
662 fn fe_cw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, EH)> {
663 self.fh_cw_iter_mut(f).map(|(mesh, h)| (mesh, h.edge()))
664 }
665
666 /// Iterator over the neighboring faces around a given face, going
667 /// counter-clockwise.
668 ///
669 /// This includes the faces connected via a shared edge, but not those
670 /// connected via shared edge.
671 ///
672 /// A mutable iterator allows modifying the mesh while iterating over its
673 /// elements. See [this section](#working-with-mutable-iterators) for an
674 /// overview on mutable iterators.
675 fn ff_ccw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, FH)> {
676 self.fh_ccw_iter_mut(f)
677 .filter_map(|(mesh, h)| h.opposite().face(mesh).map(|f| (mesh, f)))
678 }
679
680 /// Iterator over the neighboring faces around a given face, going
681 /// clockwise.
682 ///
683 /// This includes the faces connected via a shared edge, but not those
684 /// connected via shared edge.
685 ///
686 /// A mutable iterator allows modifying the mesh while iterating over its
687 /// elements. See [this section](#working-with-mutable-iterators) for an
688 /// overview on mutable iterators.
689 fn ff_cw_iter_mut(&mut self, f: FH) -> impl Iterator<Item = (&mut Self, FH)> {
690 self.fh_cw_iter_mut(f)
691 .filter_map(|(mesh, h)| h.opposite().face(mesh).map(|f| (mesh, f)))
692 }
693
694 /// This is similar to [`Self::voh_ccw_iter_mut`] around the tail of the
695 /// given halfedge, except this iterator starts at the provided halfedge.
696 ///
697 /// This is equivalent to a circular shifted [`Self::voh_ccw_iter_mut`] of
698 /// the vertex at the tail of the given halfedge. A mutable iterator allows
699 /// modifying the mesh while iterating over its elements. See [this
700 /// section](#working-with-mutable-iterators) for an overview on
701 /// mutable iterators.
702 fn ccw_rotate_iter_mut(&mut self, h: HH) -> impl Iterator<Item = (&mut Self, HH)> {
703 RadialHalfedgeIterMut::<true, Self> {
704 reference: self.into(),
705 topol: self.topology_mut(),
706 hstart: Some(h),
707 hcurrent: Some(h),
708 _phantom: PhantomData,
709 }
710 }
711
712 /// This is similar to [`Self::voh_cw_iter_mut`] around the tail of the
713 /// given halfedge, except this iterator starts at the provided halfedge.
714 ///
715 /// This is equivalent to a circular shifted [`Self::voh_cw_iter_mut`] of
716 /// the vertex at the tail of the given halfedge. A mutable iterator allows
717 /// modifying the mesh while iterating over its elements. See [this
718 /// section](#working-with-mutable-iterators) for an overview on
719 /// mutable iterators.
720 fn cw_rotate_iter_mut(&mut self, h: HH) -> impl Iterator<Item = (&mut Self, HH)> {
721 RadialHalfedgeIterMut::<false, Self> {
722 reference: self.into(),
723 topol: self.topology_mut(),
724 hstart: Some(h),
725 hcurrent: Some(h),
726 _phantom: PhantomData,
727 }
728 }
729
730 /// Counter-clockwise iterator over the halfedges in a loop.
731 ///
732 /// The iterator will start at the given halfedge. If the halfedge has an
733 /// incident face, this iterator is equivalent to a circular shifted
734 /// [`Self::fh_ccw_iter_mut`] of the incident face. If the halfedge is on
735 /// the boundary, this iterator goes over the boundary loop
736 /// counter-clockwise. A mutable iterator allows modifying the mesh while
737 /// iterating over its elements. See [this
738 /// section](#working-with-mutable-iterators) for an overview on
739 /// mutable iterators.
740 fn loop_ccw_iter_mut(&mut self, h: HH) -> impl Iterator<Item = (&mut Self, HH)> {
741 LoopHalfedgeIterMut::<true, Self> {
742 reference: self.into(),
743 topol: self.topology_mut(),
744 hstart: h,
745 hcurrent: Some(h),
746 _phantom: PhantomData,
747 }
748 }
749
750 /// Counter-clockwise iterator over the halfedges in a loop.
751 ///
752 /// The iterator will start at the given halfedge. If the halfedge has an
753 /// incident face, this iterator is equivalent to a circular shifted
754 /// [`Self::fh_cw_iter_mut`] of the incident face. If the halfedge is on the
755 /// boundary, this iterator goes over the boundary loop clockwise. A mutable
756 /// iterator allows modifying the mesh while iterating over its
757 /// elements. See [this section](#working-with-mutable-iterators) for
758 /// an overview on mutable iterators.
759 fn loop_cw_iter_mut(&mut self, h: HH) -> impl Iterator<Item = (&mut Self, HH)> {
760 LoopHalfedgeIterMut::<false, Self> {
761 reference: self.into(),
762 topol: self.topology_mut(),
763 hstart: h,
764 hcurrent: Some(h),
765 _phantom: PhantomData,
766 }
767 }
768
769 /// Iterator over the vertex triplets that represent a triangulation of the
770 /// given face.
771 ///
772 /// The triangulation does not take the shape of the face into account. It
773 /// only accounts for the topology of the face.
774 /// ```rust
775 /// use alum::{PolyMeshF32, Handle, HasTopology, HasIterators, Vec3};
776 ///
777 /// let mut mesh = PolyMeshF32::new();
778 /// let verts = [Vec3(0.0, 0.0, 0.0), Vec3(1.0, 0.0, 0.0),
779 /// Vec3(1.0, 1.0, 0.0), Vec3(0.0, 1.0, 0.0)];
780 /// mesh.add_vertices(&verts).expect("Cannot add vertices");
781 /// mesh.add_quad_face(0.into(), 1.into(), 2.into(), 3.into());
782 /// assert_eq!(mesh.triangulated_face_vertices(0.into())
783 /// .flatten()
784 /// .map(|v| v.index())
785 /// .collect::<Vec<u32>>(), [3, 0, 1, 3, 1, 2]);
786 /// ```
787 fn triangulated_face_vertices(&self, f: FH) -> impl Iterator<Item = [VH; 3]> {
788 let hstart = f.halfedge(self);
789 let vstart = hstart.tail(self);
790 self.loop_ccw_iter(hstart.next(self))
791 .take_while(move |h| h.head(self) != vstart)
792 .map(move |h| [vstart, h.tail(self), h.head(self)])
793 }
794
795 /// Iterator over the vertex triplets that represent a triangulation of the
796 /// given loop. Unlike [`Self::triangulated_face_vertices`], this can be
797 /// used on face loops as well as boundary loops. For example, this can be
798 /// used to fill a boundary loop with triangles.
799 ///
800 /// The triangulation does not take the shape of the loop into account. It
801 /// only accounts for the topology of the face.
802 fn triangulated_loop_vertices(&self, hstart: HH) -> impl Iterator<Item = [VH; 3]> {
803 let vstart = hstart.tail(self);
804 self.loop_ccw_iter(hstart.next(self))
805 .take_while(move |h| h.head(self) != vstart)
806 .map(move |h| [vstart, h.tail(self), h.head(self)])
807 }
808
809 /// Iterator over the vertex triplets that represent a triangulation of this
810 /// mesh. The triangulation of a face does not take it's shape into
811 /// account. It only accounts for the topology.
812 ///
813 /// ```rust
814 /// use alum::{PolyMeshF32, Handle, HasTopology, HasIterators, Vec3};
815 ///
816 /// let mut mesh = PolyMeshF32::new();
817 /// let verts = [Vec3(0.0, 0.0, 0.0), Vec3(1.0, 0.0, 0.0),
818 /// Vec3(1.0, 1.0, 0.0), Vec3(0.0, 1.0, 0.0)];
819 /// mesh.add_vertices(&verts).expect("Cannot add vertices");
820 /// mesh.add_quad_face(0.into(), 1.into(), 2.into(), 3.into());
821 /// let fstatus = mesh.face_status_prop();
822 /// let fstatus = fstatus.try_borrow().unwrap();
823 /// assert_eq!(mesh.triangulated_vertices(&fstatus)
824 /// .flatten()
825 /// .map(|v| v.index())
826 /// .collect::<Vec<u32>>(), [3, 0, 1, 3, 1, 2]);
827 /// ```
828 fn triangulated_vertices(&self, fstatus: &FPropBuf<Status>) -> impl Iterator<Item = [VH; 3]> {
829 self.faces()
830 .filter(|&f| !fstatus[f].deleted())
831 .flat_map(move |f| self.triangulated_face_vertices(f))
832 }
833
834 /// Find a halfedge spanning the vertices `from` and `to`, if one exists
835 fn find_halfedge(&self, from: VH, to: VH) -> Option<HH> {
836 self.voh_ccw_iter(from)
837 .find(|h| h.head(self.topology()) == to)
838 }
839
840 /// Adjust the outgoing halfedge of a vertex, if necessary.
841 ///
842 /// If a vertex is on the boundary, it's outgoing halfedge MUST be a
843 /// boundary halfedge.
844 fn adjust_outgoing_halfedge(&mut self, v: VH) {
845 let h = self.voh_ccw_iter(v).find(|h| h.is_boundary(self));
846 if let Some(h) = h {
847 self.topology_mut().vertex_mut(v).halfedge = Some(h);
848 }
849 }
850}
851
852impl<const DIM: usize, A> HasIterators for PolyMeshT<DIM, A> where A: Adaptor<DIM> {}
853
854impl HasIterators for Topology {}
855
856#[cfg(test)]
857mod test {
858 use crate::{
859 element::{Handle, VH},
860 iterator::HasIterators,
861 mesh::PolyMeshF32,
862 topol::{HasTopology, TopolCache, Topology},
863 };
864 use arrayvec::ArrayVec;
865
866 /**
867 * Makes a box with the following topology.
868 * ```text
869 *
870 * 7-----------6
871 * /| /|
872 * / | / |
873 * 4-----------5 |
874 * | | | |
875 * | 3--------|--2
876 * | / | /
877 * |/ |/
878 * 0-----------1
879 * ```
880 */
881 fn quad_box() -> Topology {
882 let mut topol = Topology::with_capacity(8, 12, 6);
883 let verts: Vec<_> = (0..8)
884 .map(|_| topol.add_vertex().expect("Unable to add a vertex").index())
885 .collect();
886 assert_eq!(verts, (0u32..8).collect::<Vec<_>>());
887 let mut cache = TopolCache::default();
888 let faces: Vec<_> = [
889 [0u32, 3, 2, 1],
890 [0, 1, 5, 4],
891 [1, 2, 6, 5],
892 [2, 3, 7, 6],
893 [3, 0, 4, 7],
894 [4, 5, 6, 7],
895 ]
896 .iter()
897 .map(|indices| {
898 topol
899 .add_face(
900 &indices.iter().map(|idx| (*idx).into()).collect::<Vec<_>>(),
901 &mut cache,
902 )
903 .expect("Unable to add a face")
904 })
905 .collect();
906 assert_eq!(faces, (0u32..6).map(|i| i.into()).collect::<Vec<_>>());
907 assert_eq!(topol.num_vertices(), 8);
908 assert_eq!(topol.num_halfedges(), 24);
909 assert_eq!(topol.num_edges(), 12);
910 assert_eq!(topol.num_faces(), 6);
911 topol
912 }
913
914 fn loop_mesh() -> Topology {
915 /*
916
917 12---------13---------14---------15
918 / / / /
919 / f5 / f6 / f7 /
920 / / / /
921 / / / /
922 8----------9----------10---------11
923 / / / /
924 / f3 / / f4 /
925 / / / /
926 / / / /
927 4----------5----------6----------7
928 / / / /
929 / f0 / f1 / f2 /
930 / / / /
931 / / / /
932 0----------1----------2----------3
933 */
934 let mut topol = Topology::with_capacity(16, 24, 8);
935 let mut cache = TopolCache::default();
936 for _ in 0u32..16 {
937 topol.add_vertex().expect("Unable to add vertex");
938 }
939 for fvi in [
940 [0u32, 1, 5, 4],
941 [1, 2, 6, 5],
942 [2, 3, 7, 6],
943 [4, 5, 9, 8],
944 [6, 7, 11, 10],
945 [8, 9, 13, 12],
946 [9, 10, 14, 13],
947 [10, 11, 15, 14],
948 ] {
949 let vs = fvi.iter().map(|i| (*i).into()).collect::<ArrayVec<VH, 4>>();
950 topol.add_face(&vs, &mut cache).expect("Unable to add face");
951 }
952 topol
953 }
954
955 #[test]
956 fn t_box_vv_ccw_iter() {
957 let qbox = quad_box();
958 for (vi, vis) in [
959 (0u32, [4u32, 3, 1]),
960 (1u32, [2u32, 5, 0]),
961 (2u32, [3u32, 6, 1]),
962 (3u32, [0u32, 7, 2]),
963 (4u32, [5u32, 7, 0]),
964 (5u32, [6u32, 4, 1]),
965 (6u32, [7u32, 5, 2]),
966 (7u32, [4u32, 6, 3]),
967 ] {
968 assert_eq!(
969 qbox.vv_ccw_iter(vi.into())
970 .map(|v| v.index())
971 .collect::<Vec<_>>(),
972 vis
973 );
974 }
975 }
976
977 #[test]
978 fn t_box_vv_cw_iter() {
979 let qbox = quad_box();
980 for (vi, fis) in [
981 (0u32, [4, 1, 3]),
982 (1u32, [2, 0, 5]),
983 (2u32, [3, 1, 6]),
984 (3u32, [0, 2, 7]),
985 (4u32, [5, 0, 7]),
986 (5u32, [6, 1, 4]),
987 (6u32, [7, 2, 5]),
988 (7u32, [4, 3, 6]),
989 ] {
990 assert_eq!(
991 qbox.vv_cw_iter(vi.into())
992 .map(|x| x.index())
993 .collect::<Vec<_>>(),
994 fis
995 );
996 }
997 }
998
999 #[test]
1000 fn t_box_vih_iter() {
1001 let qbox = quad_box();
1002 for v in qbox.vertices() {
1003 assert!(
1004 qbox.vih_ccw_iter(v)
1005 .all(|h| h.head(&qbox) == v && h.tail(&qbox) != v)
1006 );
1007 assert!(
1008 qbox.vih_cw_iter(v)
1009 .all(|h| h.head(&qbox) == v && h.tail(&qbox) != v)
1010 );
1011 }
1012 }
1013
1014 #[test]
1015 fn t_box_voh_iter() {
1016 let qbox = quad_box();
1017 for v in qbox.vertices() {
1018 assert!(
1019 qbox.voh_ccw_iter(v)
1020 .all(|h| h.tail(&qbox) == v && h.head(&qbox) != v)
1021 );
1022 assert!(
1023 qbox.voh_cw_iter(v)
1024 .all(|h| h.tail(&qbox) == v && h.head(&qbox) != v)
1025 );
1026 }
1027 }
1028
1029 #[test]
1030 fn t_box_vf_ccw_iter() {
1031 let qbox = quad_box();
1032 for (vi, fis) in [
1033 (0u32, [4u32, 0, 1]),
1034 (1u32, [2u32, 1, 0]),
1035 (2u32, [3u32, 2, 0]),
1036 (3u32, [4u32, 3, 0]),
1037 (4u32, [5u32, 4, 1]),
1038 (5u32, [5u32, 1, 2]),
1039 (6u32, [5u32, 2, 3]),
1040 (7u32, [5u32, 3, 4]),
1041 ] {
1042 assert_eq!(
1043 qbox.vf_ccw_iter(vi.into())
1044 .map(|x| x.index())
1045 .collect::<Vec<_>>(),
1046 fis
1047 );
1048 }
1049 }
1050
1051 #[test]
1052 fn t_box_vf_cw_iter() {
1053 let qbox = quad_box();
1054 for (vi, fis) in [
1055 (0u32, [4u32, 1, 0]),
1056 (1, [2, 0, 1]),
1057 (2, [3, 0, 2]),
1058 (3, [4, 0, 3]),
1059 (4, [5, 1, 4]),
1060 (5, [5, 2, 1]),
1061 (6, [5, 3, 2]),
1062 (7, [5, 4, 3]),
1063 ] {
1064 assert_eq!(
1065 qbox.vf_cw_iter(vi.into())
1066 .map(|x| x.index())
1067 .collect::<Vec<_>>(),
1068 fis
1069 );
1070 }
1071 }
1072
1073 #[test]
1074 fn t_box_fv_ccw_iter() {
1075 let qbox = quad_box();
1076 for (fi, vis) in [
1077 (0u32, [0, 3, 2, 1]),
1078 (1u32, [0, 1, 5, 4]),
1079 (2u32, [1, 2, 6, 5]),
1080 (3u32, [2, 3, 7, 6]),
1081 (4u32, [3, 0, 4, 7]),
1082 (5u32, [4, 5, 6, 7]),
1083 ] {
1084 assert_eq!(
1085 qbox.fv_ccw_iter(fi.into())
1086 .map(|x| x.index())
1087 .collect::<Vec<_>>(),
1088 vis
1089 );
1090 }
1091 }
1092
1093 #[test]
1094 fn t_box_fv_cw_iter() {
1095 let qbox = quad_box();
1096 for (fi, vis) in [
1097 (0u32, [0, 1, 2, 3]),
1098 (1u32, [0, 4, 5, 1]),
1099 (2u32, [1, 5, 6, 2]),
1100 (3u32, [2, 6, 7, 3]),
1101 (4u32, [3, 7, 4, 0]),
1102 (5u32, [4, 7, 6, 5]),
1103 ] {
1104 assert_eq!(
1105 qbox.fv_cw_iter(fi.into())
1106 .map(|x| x.index())
1107 .collect::<Vec<_>>(),
1108 vis
1109 );
1110 }
1111 }
1112
1113 #[test]
1114 fn t_box_ff_ccw_iter() {
1115 let qbox = quad_box();
1116 for (fi, fis) in [
1117 (0u32, [1, 4, 3, 2]),
1118 (1u32, [4, 0, 2, 5]),
1119 (2u32, [1, 0, 3, 5]),
1120 (3u32, [2, 0, 4, 5]),
1121 (4u32, [3, 0, 1, 5]),
1122 (5u32, [4, 1, 2, 3]),
1123 ] {
1124 assert_eq!(
1125 qbox.ff_ccw_iter(fi.into())
1126 .map(|f| f.index())
1127 .collect::<Vec<_>>(),
1128 fis
1129 );
1130 }
1131 }
1132
1133 #[test]
1134 fn t_box_ff_cw_iter() {
1135 let qbox = quad_box();
1136 for (fi, fis) in [
1137 (0u32, [1, 2, 3, 4]),
1138 (1u32, [4, 5, 2, 0]),
1139 (2u32, [1, 5, 3, 0]),
1140 (3u32, [2, 5, 4, 0]),
1141 (4u32, [3, 5, 1, 0]),
1142 (5u32, [4, 3, 2, 1]),
1143 ] {
1144 assert_eq!(
1145 qbox.ff_cw_iter(fi.into())
1146 .map(|f| f.index())
1147 .collect::<Vec<_>>(),
1148 fis
1149 );
1150 }
1151 }
1152
1153 #[test]
1154 fn t_loop_mesh_vf_ccw_iter() {
1155 let topol = loop_mesh();
1156 for (v, fis) in [
1157 (0u32, vec![0u32]),
1158 (1, vec![1, 0]),
1159 (2, vec![2, 1]),
1160 (3, vec![2]),
1161 (4, vec![0, 3]),
1162 (5, vec![3, 0, 1]),
1163 (6, vec![1, 2, 4]),
1164 (7, vec![4, 2]),
1165 (8, vec![3, 5]),
1166 (9, vec![6, 5, 3]),
1167 (10, vec![4, 7, 6]),
1168 (11, vec![7, 4]),
1169 (12, vec![5]),
1170 (13, vec![5, 6]),
1171 (14, vec![6, 7]),
1172 (15, vec![7]),
1173 ] {
1174 assert_eq!(
1175 topol
1176 .vf_ccw_iter(v.into())
1177 .map(|i| i.index())
1178 .collect::<Vec<_>>(),
1179 fis
1180 );
1181 }
1182 }
1183
1184 #[test]
1185 fn t_loop_mesh_vf_cw_iter() {
1186 let topol = loop_mesh();
1187 for (v, fis) in [
1188 (0u32, vec![0u32]),
1189 (1, vec![0, 1]),
1190 (2, vec![1, 2]),
1191 (3, vec![2]),
1192 (4, vec![3, 0]),
1193 (5, vec![1, 0, 3]),
1194 (6, vec![4, 2, 1]),
1195 (7, vec![2, 4]),
1196 (8, vec![5, 3]),
1197 (9, vec![3, 5, 6]),
1198 (10, vec![6, 7, 4]),
1199 (11, vec![4, 7]),
1200 (12, vec![5]),
1201 (13, vec![6, 5]),
1202 (14, vec![7, 6]),
1203 (15, vec![7]),
1204 ] {
1205 assert_eq!(
1206 topol
1207 .vf_cw_iter(v.into())
1208 .map(|i| i.index())
1209 .collect::<Vec<_>>(),
1210 fis
1211 );
1212 }
1213 }
1214
1215 #[test]
1216 fn t_box_mesh_voh_ccw_iter_mut() {
1217 // I have other tests checking the mutability of the mesh etc. This is
1218 // just to make sure the mutable iterator walks the same topology as the
1219 // immutable iterator.
1220 let mut mesh = PolyMeshF32::unit_box().expect("Cannot create a box");
1221 let expected = mesh
1222 .vertices()
1223 .flat_map(|v| mesh.voh_ccw_iter(v))
1224 .collect::<Vec<_>>();
1225 let mut actual = Vec::new();
1226 for v in mesh.vertices() {
1227 actual.extend(mesh.voh_ccw_iter_mut(v).map(|(_mesh, h)| h));
1228 }
1229 assert_eq!(expected, actual);
1230 }
1231
1232 #[test]
1233 fn t_box_mesh_voh_cw_iter_mut() {
1234 // I have other tests checking the mutability of the mesh etc. This is
1235 // just to make sure the mutable iterator walks the same topology as the
1236 // immutable iterator.
1237 let mut mesh = PolyMeshF32::unit_box().expect("Cannot create a box");
1238 let expected = mesh
1239 .vertices()
1240 .flat_map(|v| mesh.voh_cw_iter(v))
1241 .collect::<Vec<_>>();
1242 let mut actual = Vec::new();
1243 for v in mesh.vertices() {
1244 actual.extend(mesh.voh_cw_iter_mut(v).map(|(_mesh, h)| h));
1245 }
1246 assert_eq!(expected, actual);
1247 }
1248
1249 #[test]
1250 fn t_box_mesh_fh_ccw_iter_mut() {
1251 // I have other tests checking the mutability of the mesh etc. This is
1252 // just to make sure the mutable iterator walks the same topology as the
1253 // immutable iterator.
1254 let mut mesh = PolyMeshF32::unit_box().expect("Cannot create a box");
1255 let expected = mesh
1256 .faces()
1257 .flat_map(|v| mesh.fh_ccw_iter(v))
1258 .collect::<Vec<_>>();
1259 let mut actual = Vec::new();
1260 for v in mesh.faces() {
1261 actual.extend(mesh.fh_ccw_iter_mut(v).map(|(_mesh, h)| h));
1262 }
1263 assert_eq!(expected, actual);
1264 }
1265
1266 #[test]
1267 fn t_box_mesh_fh_cw_iter_mut() {
1268 // I have other tests checking the mutability of the mesh etc. This is
1269 // just to make sure the mutable iterator walks the same topology as the
1270 // immutable iterator.
1271 let mut mesh = PolyMeshF32::unit_box().expect("Cannot create a box");
1272 let expected = mesh
1273 .faces()
1274 .flat_map(|v| mesh.fh_cw_iter(v))
1275 .collect::<Vec<_>>();
1276 let mut actual = Vec::new();
1277 for v in mesh.faces() {
1278 actual.extend(mesh.fh_cw_iter_mut(v).map(|(_mesh, h)| h));
1279 }
1280 assert_eq!(expected, actual);
1281 }
1282
1283 #[test]
1284 fn t_box_mesh_voh_ccw_iter_mut_delete_faces() {
1285 let mut mesh = PolyMeshF32::unit_box().expect("Cannot create a box");
1286 // Checking to make sure I can modify the mesh while iterating over it's
1287 // elements. The borrow checking and safety should still be enforced
1288 // because I can only modify the mesh via the mutable references that
1289 // the iteator provides.
1290 for v in mesh.vertices() {
1291 // using a random condition to delete some faces, to make sure I can
1292 // modify the mesh. If you try changing any of the `m` inside this
1293 // loop to `mesh`, the borrow checker should complain and the code
1294 // should not compile.
1295 for (m, h) in mesh.voh_ccw_iter_mut(v) {
1296 if let Some(f) = h.face(m)
1297 && !(f.index() + h.index()).is_multiple_of(2)
1298 {
1299 m.delete_face(f, true).expect("Cannot delete face");
1300 }
1301 }
1302 }
1303 mesh.garbage_collection()
1304 .expect("Garbage collection failed");
1305 mesh.check_topology().expect("Topological errors found");
1306 assert_eq!(2, mesh.num_faces());
1307 assert_eq!(8, mesh.num_edges());
1308 assert_eq!(16, mesh.num_halfedges());
1309 assert_eq!(8, mesh.num_vertices());
1310 }
1311}