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}