plexus/graph/view/
face.rs

1use either::Either;
2use fool::prelude::*;
3use std::cmp;
4use std::marker::PhantomData;
5use std::mem;
6use std::ops::{Add, Deref, DerefMut, Mul};
7
8use crate::geometry::alias::{ScaledFaceNormal, VertexPosition};
9use crate::geometry::convert::AsPosition;
10use crate::geometry::Geometry;
11use crate::graph::container::{Bind, Consistent, Reborrow, ReborrowMut};
12use crate::graph::geometry::{FaceCentroid, FaceNormal};
13use crate::graph::mutation::alias::Mutable;
14use crate::graph::mutation::face::{
15    self, FaceBridgeCache, FaceExtrudeCache, FaceInsertCache, FacePokeCache, FaceRemoveCache,
16    FaceSplitCache,
17};
18use crate::graph::mutation::{Mutate, Mutation};
19use crate::graph::payload::{ArcPayload, EdgePayload, FacePayload, Payload, VertexPayload};
20use crate::graph::storage::convert::{AsStorage, AsStorageMut};
21use crate::graph::storage::{ArcKey, FaceKey, Storage, VertexKey};
22use crate::graph::view::convert::{FromKeyedSource, IntoKeyedSource, IntoView};
23use crate::graph::view::{ArcNeighborhood, ArcView, OrphanArcView, OrphanVertexView, VertexView};
24use crate::graph::{GraphError, OptionExt, ResultExt, Selector};
25
26use Selector::ByIndex;
27
28/// View of a face.
29///
30/// Provides traversals, queries, and mutations related to faces in a graph.
31/// See the module documentation for more information about topological views.
32pub struct FaceView<M, G>
33where
34    M: Reborrow,
35    M::Target: AsStorage<FacePayload<G>>,
36    G: Geometry,
37{
38    key: FaceKey,
39    storage: M,
40    phantom: PhantomData<G>,
41}
42
43/// Storage.
44impl<M, G> FaceView<M, G>
45where
46    M: Reborrow,
47    M::Target: AsStorage<FacePayload<G>>,
48    G: Geometry,
49{
50    // TODO: This may become useful as the `mutation` module is developed. It
51    //       may also be necessary to expose this API to user code.
52    #[allow(dead_code)]
53    pub(in crate::graph) fn bind<T, N>(self, storage: N) -> FaceView<<M as Bind<T, N>>::Output, G>
54    where
55        T: Payload,
56        M: Bind<T, N>,
57        M::Output: Reborrow,
58        <M::Output as Reborrow>::Target: AsStorage<FacePayload<G>>,
59        N: AsStorage<T>,
60    {
61        let (key, origin) = self.into_keyed_source();
62        FaceView::from_keyed_source_unchecked((key, origin.bind(storage)))
63    }
64}
65
66impl<'a, M, G> FaceView<&'a mut M, G>
67where
68    M: 'a + AsStorage<FacePayload<G>> + AsStorageMut<FacePayload<G>>,
69    G: 'a + Geometry,
70{
71    /// Converts a mutable view into an orphan view.
72    pub fn into_orphan(self) -> OrphanFaceView<'a, G> {
73        let (key, storage) = self.into_keyed_source();
74        (key, storage).into_view().unwrap()
75    }
76
77    /// Converts a mutable view into an immutable view.
78    ///
79    /// This is useful when mutations are not (or no longer) needed and mutual
80    /// access is desired.
81    ///
82    /// # Examples
83    ///
84    /// ```rust
85    /// # extern crate nalgebra;
86    /// # extern crate plexus;
87    /// use nalgebra::Point3;
88    /// use plexus::graph::MeshGraph;
89    /// use plexus::prelude::*;
90    /// use plexus::primitive::cube::Cube;
91    ///
92    /// # fn main() {
93    /// let mut graph = Cube::new()
94    ///     .polygons_with_position()
95    ///     .collect::<MeshGraph<Point3<f32>>>();
96    /// let key = graph.faces().nth(0).unwrap().key();
97    /// let face = graph
98    ///     .face_mut(key)
99    ///     .unwrap()
100    ///     .extrude(1.0)
101    ///     .unwrap()
102    ///     .into_ref();
103    ///
104    /// // This would not be possible without conversion into an immutable view.
105    /// let _ = face.into_arc();
106    /// let _ = face.into_arc().into_next_arc();
107    /// # }
108    /// ```
109    pub fn into_ref(self) -> FaceView<&'a M, G> {
110        let (key, storage) = self.into_keyed_source();
111        (key, &*storage).into_view().unwrap()
112    }
113
114    /// Reborrows the view and constructs another mutable view from a given
115    /// key.
116    ///
117    /// This allows for fallible traversals from a mutable view without the
118    /// need for direct access to the source `MeshGraph`. If the given function
119    /// emits a key, then that key will be used to convert this view into
120    /// another. If no key is emitted, then the original mutable view is
121    /// returned.
122    pub fn with_ref<T, K, F>(self, f: F) -> Either<Result<T, GraphError>, Self>
123    where
124        T: FromKeyedSource<(K, &'a mut M)>,
125        F: FnOnce(FaceView<&M, G>) -> Option<K>,
126    {
127        if let Some(key) = f(self.interior_reborrow()) {
128            let (_, storage) = self.into_keyed_source();
129            Either::Left(
130                T::from_keyed_source((key, storage)).ok_or_else(|| GraphError::TopologyNotFound),
131            )
132        }
133        else {
134            Either::Right(self)
135        }
136    }
137}
138
139impl<M, G> FaceView<M, G>
140where
141    M: Reborrow,
142    M::Target: AsStorage<FacePayload<G>>,
143    G: Geometry,
144{
145    /// Gets the key for the face.
146    pub fn key(&self) -> FaceKey {
147        self.key
148    }
149
150    fn from_keyed_source_unchecked(source: (FaceKey, M)) -> Self {
151        let (key, storage) = source;
152        FaceView {
153            key,
154            storage,
155            phantom: PhantomData,
156        }
157    }
158
159    fn interior_reborrow(&self) -> FaceView<&M::Target, G> {
160        let key = self.key;
161        let storage = self.storage.reborrow();
162        FaceView::from_keyed_source_unchecked((key, storage))
163    }
164}
165
166impl<M, G> FaceView<M, G>
167where
168    M: Reborrow + ReborrowMut,
169    M::Target: AsStorage<FacePayload<G>>,
170    G: Geometry,
171{
172    fn interior_reborrow_mut(&mut self) -> FaceView<&mut M::Target, G> {
173        let key = self.key;
174        let storage = self.storage.reborrow_mut();
175        FaceView::from_keyed_source_unchecked((key, storage))
176    }
177}
178
179/// Reachable API.
180impl<M, G> FaceView<M, G>
181where
182    M: Reborrow,
183    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>>,
184    G: Geometry,
185{
186    pub(in crate::graph) fn reachable_arc(&self) -> Option<ArcView<&M::Target, G>> {
187        let key = self.arc;
188        let storage = self.storage.reborrow();
189        (key, storage).into_view()
190    }
191
192    pub(in crate::graph) fn into_reachable_arc(self) -> Option<ArcView<M, G>> {
193        let key = self.arc;
194        let (_, storage) = self.into_keyed_source();
195        (key, storage).into_view()
196    }
197
198    pub(in crate::graph) fn reachable_interior_arcs(
199        &self,
200    ) -> impl Clone + Iterator<Item = ArcView<&M::Target, G>> {
201        ArcCirculator::from(self.interior_reborrow())
202    }
203
204    pub(in crate::graph) fn reachable_neighboring_faces(
205        &self,
206    ) -> impl Clone + Iterator<Item = FaceView<&M::Target, G>> {
207        FaceCirculator::from(ArcCirculator::from(self.interior_reborrow()))
208    }
209
210    pub(in crate::graph) fn reachable_arity(&self) -> usize {
211        self.reachable_interior_arcs().count()
212    }
213}
214
215impl<M, G> FaceView<M, G>
216where
217    M: Reborrow,
218    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>> + Consistent,
219    G: Geometry,
220{
221    /// Converts the face into its interior path.
222    pub fn into_interior_path(self) -> InteriorPathView<M, G> {
223        let key = self.arc().key();
224        let (_, storage) = self.into_keyed_source();
225        (key, storage).into_view().expect_consistent()
226    }
227
228    /// Converts the face into its leading arc.
229    pub fn into_arc(self) -> ArcView<M, G> {
230        self.into_reachable_arc().expect_consistent()
231    }
232
233    /// Gets the interior path of the face.
234    pub fn interior_path(&self) -> InteriorPathView<&M::Target, G> {
235        let key = self.arc().key();
236        let storage = self.storage.reborrow();
237        (key, storage).into_view().expect_consistent()
238    }
239
240    /// Gets the leading arc of the face.
241    pub fn arc(&self) -> ArcView<&M::Target, G> {
242        self.reachable_arc().expect_consistent()
243    }
244
245    /// Gets an iterator of views over the arcs in the face's interior path.
246    pub fn interior_arcs(&self) -> impl Clone + Iterator<Item = ArcView<&M::Target, G>> {
247        self.reachable_interior_arcs()
248    }
249
250    /// Gets an iterator of views over neighboring faces.
251    pub fn neighboring_faces(&self) -> impl Clone + Iterator<Item = FaceView<&M::Target, G>> {
252        self.reachable_neighboring_faces()
253    }
254
255    /// Gets the arity of the face. This is the number of arcs that form the
256    /// face's interior path.
257    pub fn arity(&self) -> usize {
258        self.reachable_arity()
259    }
260}
261
262/// Reachable API.
263impl<M, G> FaceView<M, G>
264where
265    M: Reborrow,
266    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>> + AsStorage<VertexPayload<G>>,
267    G: Geometry,
268{
269    pub(in crate::graph) fn reachable_vertices(
270        &self,
271    ) -> impl Clone + Iterator<Item = VertexView<&M::Target, G>> {
272        VertexCirculator::from(ArcCirculator::from(self.interior_reborrow()))
273    }
274}
275
276impl<M, G> FaceView<M, G>
277where
278    M: Reborrow,
279    M::Target: AsStorage<ArcPayload<G>>
280        + AsStorage<FacePayload<G>>
281        + AsStorage<VertexPayload<G>>
282        + Consistent,
283    G: Geometry,
284{
285    pub fn neighborhood(&self) -> FaceNeighborhood {
286        FaceNeighborhood::from(self.interior_reborrow())
287    }
288
289    /// Gets an iterator of views over the vertices that form the face.
290    pub fn vertices(&self) -> impl Clone + Iterator<Item = VertexView<&M::Target, G>> {
291        self.reachable_vertices()
292    }
293}
294
295/// Reachable API.
296impl<M, G> FaceView<M, G>
297where
298    M: Reborrow + ReborrowMut,
299    M::Target: AsStorage<ArcPayload<G>> + AsStorageMut<ArcPayload<G>> + AsStorage<FacePayload<G>>,
300    G: Geometry,
301{
302    pub(in crate::graph) fn reachable_interior_orphan_arcs(
303        &mut self,
304    ) -> impl Iterator<Item = OrphanArcView<G>> {
305        ArcCirculator::from(self.interior_reborrow_mut())
306    }
307}
308
309impl<M, G> FaceView<M, G>
310where
311    M: Reborrow + ReborrowMut,
312    M::Target: AsStorage<ArcPayload<G>>
313        + AsStorageMut<ArcPayload<G>>
314        + AsStorage<FacePayload<G>>
315        + Consistent,
316    G: Geometry,
317{
318    /// Gets an iterator of orphan views over the arcs in the face's interior
319    /// path.
320    pub fn interior_orphan_arcs(&mut self) -> impl Iterator<Item = OrphanArcView<G>> {
321        self.reachable_interior_orphan_arcs()
322    }
323}
324
325/// Reachable API.
326impl<M, G> FaceView<M, G>
327where
328    M: Reborrow + ReborrowMut,
329    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>> + AsStorageMut<FacePayload<G>>,
330    G: Geometry,
331{
332    pub(in crate::graph) fn reachable_neighboring_orphan_faces(
333        &mut self,
334    ) -> impl Iterator<Item = OrphanFaceView<G>> {
335        FaceCirculator::from(ArcCirculator::from(self.interior_reborrow_mut()))
336    }
337}
338
339impl<M, G> FaceView<M, G>
340where
341    M: Reborrow + ReborrowMut,
342    M::Target: AsStorage<ArcPayload<G>>
343        + AsStorage<FacePayload<G>>
344        + AsStorageMut<FacePayload<G>>
345        + Consistent,
346    G: Geometry,
347{
348    /// Gets an iterator of orphan views over neighboring faces.
349    pub fn neighboring_orphan_faces(&mut self) -> impl Iterator<Item = OrphanFaceView<G>> {
350        self.reachable_neighboring_orphan_faces()
351    }
352}
353
354/// Reachable API.
355impl<M, G> FaceView<M, G>
356where
357    M: Reborrow + ReborrowMut,
358    M::Target: AsStorage<ArcPayload<G>>
359        + AsStorage<FacePayload<G>>
360        + AsStorage<VertexPayload<G>>
361        + AsStorageMut<VertexPayload<G>>,
362    G: Geometry,
363{
364    pub(in crate::graph) fn reachable_orphan_vertices(
365        &mut self,
366    ) -> impl Iterator<Item = OrphanVertexView<G>> {
367        VertexCirculator::from(ArcCirculator::from(self.interior_reborrow_mut()))
368    }
369}
370
371impl<M, G> FaceView<M, G>
372where
373    M: Reborrow + ReborrowMut,
374    M::Target: AsStorage<ArcPayload<G>>
375        + AsStorage<FacePayload<G>>
376        + AsStorage<VertexPayload<G>>
377        + AsStorageMut<VertexPayload<G>>
378        + Consistent,
379    G: Geometry,
380{
381    /// Gets an iterator of orphan views over the vertices that form the face.
382    pub fn orphan_vertices(&mut self) -> impl Iterator<Item = OrphanVertexView<G>> {
383        self.reachable_orphan_vertices()
384    }
385}
386
387impl<'a, M, G> FaceView<&'a mut M, G>
388where
389    M: AsStorage<ArcPayload<G>>
390        + AsStorage<EdgePayload<G>>
391        + AsStorage<FacePayload<G>>
392        + AsStorage<VertexPayload<G>>
393        + Default
394        + Mutable<G>,
395    G: 'a + Geometry,
396{
397    /// Splits the face by bisecting it with an edge (and arcs) inserted
398    /// between two non-neighboring vertices within the face's perimeter.
399    ///
400    /// The vertices can be chosen by key or index, where index selects the nth
401    /// vertex within the face's interior path.
402    ///
403    /// This can be thought of as the opposite of `merge`.
404    ///
405    /// Returns the inserted arc that spans from the source vertex to the
406    /// destination vertex if successful.
407    ///
408    /// # Errors
409    ///
410    /// Returns an error if either of the given vertices cannot be found, are
411    /// not within the face's perimeter, or the distance between the vertices
412    /// along the interior path is less than two.
413    ///
414    /// # Examples
415    ///
416    /// Splitting a quadrilateral face:
417    ///
418    /// ```rust
419    /// # extern crate nalgebra;
420    /// # extern crate plexus;
421    /// #
422    /// use nalgebra::Point2;
423    /// use plexus::graph::MeshGraph;
424    /// use plexus::prelude::*;
425    /// use plexus::primitive::Quad;
426    ///
427    /// # fn main() {
428    /// let mut graph = MeshGraph::<Point2<f64>>::from_raw_buffers(
429    ///     vec![Quad::new(0usize, 1, 2, 3)],
430    ///     vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)],
431    /// )
432    /// .unwrap();
433    /// let key = graph.faces().nth(0).unwrap().key();
434    /// let arc = graph
435    ///     .face_mut(key)
436    ///     .unwrap()
437    ///     .split(ByIndex(0), ByIndex(2))
438    ///     .unwrap()
439    ///     .into_ref();
440    /// # }
441    /// ```
442    pub fn split(
443        self,
444        source: Selector<VertexKey>,
445        destination: Selector<VertexKey>,
446    ) -> Result<ArcView<&'a mut M, G>, GraphError> {
447        let source = source.key_or_else(|index| {
448            self.vertices()
449                .nth(index)
450                .ok_or_else(|| GraphError::TopologyNotFound)
451                .map(|vertex| vertex.key())
452        })?;
453        let destination = destination.key_or_else(|index| {
454            self.vertices()
455                .nth(index)
456                .ok_or_else(|| GraphError::TopologyNotFound)
457                .map(|vertex| vertex.key())
458        })?;
459        let (abc, storage) = self.into_keyed_source();
460        let cache = FaceSplitCache::snapshot(&storage, abc, source, destination)?;
461        Mutation::replace(storage, Default::default())
462            .commit_with(move |mutation| face::split_with_cache(mutation, cache))
463            .map(|(storage, arc)| (arc, storage).into_view().expect_consistent())
464    }
465
466    /// Merges the face into a neighboring face over their shared edge (and
467    /// arcs).
468    ///
469    /// The neighboring face can be chosen by key or index, where index selects
470    /// the nth neighbor of the face.
471    ///
472    /// This can be thought of as the opposite of `split`.
473    ///
474    /// Returns the merged face if successful.
475    ///
476    /// # Errors
477    ///
478    /// Returns an error if the destination face cannot be found or is not a
479    /// neighbor of the initiating face.
480    ///
481    /// # Examples
482    ///
483    /// Merging two neighboring quadrilateral faces:
484    ///
485    /// ```rust
486    /// # extern crate nalgebra;
487    /// # extern crate plexus;
488    /// #
489    /// use nalgebra::Point2;
490    /// use plexus::graph::MeshGraph;
491    /// use plexus::prelude::*;
492    /// use plexus::primitive::Quad;
493    ///
494    /// # fn main() {
495    /// let mut graph = MeshGraph::<Point2<f32>>::from_raw_buffers(
496    ///     vec![Quad::new(0usize, 1, 2, 3), Quad::new(0, 3, 4, 5)],
497    ///     vec![
498    ///         (0.0, 0.0),  // 0
499    ///         (1.0, 0.0),  // 1
500    ///         (1.0, 1.0),  // 2
501    ///         (0.0, 1.0),  // 3
502    ///         (-1.0, 1.0), // 4
503    ///         (-1.0, 0.0), // 5
504    ///     ],
505    /// )
506    /// .unwrap();
507    ///
508    /// let key = graph.faces().nth(0).unwrap().key();
509    /// let face = graph
510    ///     .face_mut(key)
511    ///     .unwrap()
512    ///     .merge(ByIndex(0))
513    ///     .unwrap()
514    ///     .into_ref();
515    /// # }
516    /// ```
517    pub fn merge(self, destination: Selector<FaceKey>) -> Result<Self, GraphError> {
518        let destination = destination.key_or_else(|index| {
519            self.neighboring_faces()
520                .nth(index)
521                .ok_or_else(|| GraphError::TopologyNotFound)
522                .map(|face| face.key())
523        })?;
524        let ab = self
525            .interior_arcs()
526            .find(|arc| match arc.opposite_arc().face() {
527                Some(face) => face.key() == destination,
528                _ => false,
529            })
530            .map(|arc| arc.key())
531            .ok_or_else(|| GraphError::TopologyNotFound)?;
532        let geometry = self.geometry.clone();
533        let (_, storage) = self.into_keyed_source();
534        Ok(ArcView::from_keyed_source((ab, storage))
535            .expect_consistent()
536            .remove()
537            .into_outgoing_arc()
538            .into_interior_path()
539            .get_or_insert_face_with(|| geometry))
540    }
541
542    /// Connects faces with equal arity with faces inserted along their
543    /// perimeters.
544    ///
545    /// The inserted faces are always quadrilateral. Both the initiating face
546    /// and destination face are removed.
547    ///
548    /// # Errors
549    ///
550    /// Returns an error if the destination face cannot be found or the arity
551    /// of the face and its destination are not the same.
552    pub fn bridge(self, destination: FaceKey) -> Result<(), GraphError> {
553        let (source, storage) = self.into_keyed_source();
554        let cache = FaceBridgeCache::snapshot(&storage, source, destination)?;
555        Mutation::replace(storage, Default::default())
556            .commit_with(move |mutation| face::bridge_with_cache(mutation, cache))
557            .map(|_| ())
558    }
559
560    /// Decomposes the face into triangles. Does nothing if the face is
561    /// triangular.
562    ///
563    /// Returns the terminating face of the decomposition.
564    pub fn triangulate(self) -> Self {
565        let mut face = self;
566        while face.arity() > 3 {
567            face = face
568                .split(ByIndex(0), ByIndex(2))
569                .expect_consistent()
570                .into_face()
571                .expect_consistent();
572        }
573        face
574    }
575
576    /// Subdivides the face about a vertex. A triangle fan is formed from each
577    /// arc in the face's perimeter and the vertex.
578    ///
579    /// Poking inserts a new vertex with geometry provided by the given
580    /// function.
581    ///
582    /// Returns the inserted vertex.
583    pub fn poke_with<F>(self, f: F) -> VertexView<&'a mut M, G>
584    where
585        F: FnOnce() -> G::Vertex,
586    {
587        (move || {
588            let (abc, storage) = self.into_keyed_source();
589            let cache = FacePokeCache::snapshot(&storage, abc, f())?;
590            Mutation::replace(storage, Default::default())
591                .commit_with(move |mutation| face::poke_with_cache(mutation, cache))
592                .map(|(storage, vertex)| (vertex, storage).into_view().expect_consistent())
593        })()
594        .expect_consistent()
595    }
596
597    /// Subdivides the face about its centroid. A triangle fan is formed from each
598    /// arc in the face's perimeter and a vertex inserted at the centroid.
599    ///
600    /// Returns the inserted vertex.
601    ///
602    /// # Examples
603    ///
604    /// Forming a baseless triangular pyramid from a face:
605    ///
606    /// ```rust
607    /// # extern crate nalgebra;
608    /// # extern crate plexus;
609    /// #
610    /// use nalgebra::Point3;
611    /// use plexus::geometry::convert::AsPosition;
612    /// use plexus::graph::MeshGraph;
613    /// use plexus::prelude::*;
614    /// use plexus::primitive::Triangle;
615    ///
616    /// # fn main() {
617    /// let mut graph = MeshGraph::<Point3<f64>>::from_raw_buffers(
618    ///     vec![Triangle::new(0usize, 1, 2)],
619    ///     vec![(-1.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.0, 2.0, 0.0)],
620    /// )
621    /// .unwrap();
622    /// let key = graph.faces().nth(0).unwrap().key();
623    /// let mut face = graph.face_mut(key).unwrap();
624    ///
625    /// // Use the face's normal to translate the vertex from the centroid.
626    /// let normal = face.normal();
627    /// let mut vertex = face.poke_at_centroid();
628    /// let position = vertex.geometry.as_position() + (normal * 2.0);
629    /// *vertex.geometry.as_position_mut() = position;
630    /// # }
631    /// ```
632    pub fn poke_at_centroid(self) -> VertexView<&'a mut M, G>
633    where
634        G: FaceCentroid<Centroid = <G as Geometry>::Vertex>,
635    {
636        let centroid = self.centroid();
637        self.poke_with(move || centroid)
638    }
639
640    pub fn extrude<T>(self, distance: T) -> Result<FaceView<&'a mut M, G>, GraphError>
641    where
642        G: FaceNormal,
643        G::Normal: Mul<T>,
644        G::Vertex: AsPosition,
645        ScaledFaceNormal<G, T>: Clone,
646        VertexPosition<G>: Add<ScaledFaceNormal<G, T>, Output = VertexPosition<G>> + Clone,
647    {
648        let (abc, storage) = self.into_keyed_source();
649        let cache = FaceExtrudeCache::snapshot(&storage, abc, distance)?;
650        Mutation::replace(storage, Default::default())
651            .commit_with(move |mutation| face::extrude_with_cache(mutation, cache))
652            .map(|(storage, face)| (face, storage).into_view().expect_consistent())
653    }
654
655    /// Removes the face.
656    ///
657    /// Returns the interior path of the face.
658    pub fn remove(self) -> InteriorPathView<&'a mut M, G> {
659        (move || {
660            let (abc, storage) = self.into_keyed_source();
661            let cache = FaceRemoveCache::snapshot(&storage, abc)?;
662            Mutation::replace(storage, Default::default())
663                .commit_with(move |mutation| face::remove_with_cache(mutation, cache))
664                .map(|(storage, face)| (face.arc, storage).into_view().expect_consistent())
665        })()
666        .expect_consistent()
667    }
668}
669
670impl<M, G> FaceView<M, G>
671where
672    M: Reborrow,
673    M::Target: AsStorage<ArcPayload<G>>
674        + AsStorage<FacePayload<G>>
675        + AsStorage<VertexPayload<G>>
676        + Consistent,
677    G: FaceCentroid + Geometry,
678{
679    pub fn centroid(&self) -> G::Centroid {
680        G::centroid(self.interior_reborrow()).expect_consistent()
681    }
682}
683
684impl<M, G> FaceView<M, G>
685where
686    M: Reborrow,
687    M::Target: AsStorage<ArcPayload<G>>
688        + AsStorage<FacePayload<G>>
689        + AsStorage<VertexPayload<G>>
690        + Consistent,
691    G: FaceNormal + Geometry,
692{
693    pub fn normal(&self) -> G::Normal {
694        G::normal(self.interior_reborrow()).expect_consistent()
695    }
696}
697
698impl<M, G> Clone for FaceView<M, G>
699where
700    M: Clone + Reborrow,
701    M::Target: AsStorage<FacePayload<G>>,
702    G: Geometry,
703{
704    fn clone(&self) -> Self {
705        FaceView {
706            storage: self.storage.clone(),
707            key: self.key,
708            phantom: PhantomData,
709        }
710    }
711}
712
713impl<M, G> Copy for FaceView<M, G>
714where
715    M: Copy + Reborrow,
716    M::Target: AsStorage<FacePayload<G>>,
717    G: Geometry,
718{
719}
720
721impl<M, G> Deref for FaceView<M, G>
722where
723    M: Reborrow,
724    M::Target: AsStorage<FacePayload<G>>,
725    G: Geometry,
726{
727    type Target = FacePayload<G>;
728
729    fn deref(&self) -> &Self::Target {
730        self.storage.reborrow().as_storage().get(&self.key).unwrap()
731    }
732}
733
734impl<M, G> DerefMut for FaceView<M, G>
735where
736    M: Reborrow + ReborrowMut,
737    M::Target: AsStorage<FacePayload<G>> + AsStorageMut<FacePayload<G>>,
738    G: Geometry,
739{
740    fn deref_mut(&mut self) -> &mut Self::Target {
741        self.storage
742            .reborrow_mut()
743            .as_storage_mut()
744            .get_mut(&self.key)
745            .unwrap()
746    }
747}
748
749impl<M, G> FromKeyedSource<(FaceKey, M)> for FaceView<M, G>
750where
751    M: Reborrow,
752    M::Target: AsStorage<FacePayload<G>>,
753    G: Geometry,
754{
755    fn from_keyed_source(source: (FaceKey, M)) -> Option<Self> {
756        let (key, storage) = source;
757        storage
758            .reborrow()
759            .as_storage()
760            .contains_key(&key)
761            .some(FaceView::from_keyed_source_unchecked((key, storage)))
762    }
763}
764
765impl<M, G> IntoKeyedSource<(FaceKey, M)> for FaceView<M, G>
766where
767    M: Reborrow,
768    M::Target: AsStorage<FacePayload<G>>,
769    G: Geometry,
770{
771    fn into_keyed_source(self) -> (FaceKey, M) {
772        let FaceView { key, storage, .. } = self;
773        (key, storage)
774    }
775}
776
777/// Orphan view of a face.
778///
779/// Provides mutable access to a face's geometry. See the module documentation
780/// for more information about topological views.
781pub struct OrphanFaceView<'a, G>
782where
783    G: 'a + Geometry,
784{
785    key: FaceKey,
786    face: &'a mut FacePayload<G>,
787}
788
789impl<'a, G> OrphanFaceView<'a, G>
790where
791    G: 'a + Geometry,
792{
793    pub fn key(&self) -> FaceKey {
794        self.key
795    }
796}
797
798impl<'a, G> Deref for OrphanFaceView<'a, G>
799where
800    G: 'a + Geometry,
801{
802    type Target = FacePayload<G>;
803
804    fn deref(&self) -> &Self::Target {
805        &*self.face
806    }
807}
808
809impl<'a, G> DerefMut for OrphanFaceView<'a, G>
810where
811    G: 'a + Geometry,
812{
813    fn deref_mut(&mut self) -> &mut Self::Target {
814        self.face
815    }
816}
817
818impl<'a, M, G> FromKeyedSource<(FaceKey, &'a mut M)> for OrphanFaceView<'a, G>
819where
820    M: AsStorage<FacePayload<G>> + AsStorageMut<FacePayload<G>>,
821    G: 'a + Geometry,
822{
823    fn from_keyed_source(source: (FaceKey, &'a mut M)) -> Option<Self> {
824        let (key, storage) = source;
825        storage
826            .as_storage_mut()
827            .get_mut(&key)
828            .map(|face| OrphanFaceView { key, face })
829    }
830}
831
832impl<'a, G> FromKeyedSource<(FaceKey, &'a mut FacePayload<G>)> for OrphanFaceView<'a, G>
833where
834    G: 'a + Geometry,
835{
836    fn from_keyed_source(source: (FaceKey, &'a mut FacePayload<G>)) -> Option<Self> {
837        let (key, face) = source;
838        Some(OrphanFaceView { key, face })
839    }
840}
841
842#[derive(Clone, Debug)]
843pub struct FaceNeighborhood {
844    key: FaceKey,
845    arcs: Vec<ArcNeighborhood>,
846}
847
848impl FaceNeighborhood {
849    pub fn key(&self) -> FaceKey {
850        self.key
851    }
852
853    pub fn interior_arcs(&self) -> &[ArcNeighborhood] {
854        self.arcs.as_slice()
855    }
856}
857
858impl<M, G> From<FaceView<M, G>> for FaceNeighborhood
859where
860    M: Reborrow,
861    M::Target: AsStorage<ArcPayload<G>>
862        + AsStorage<FacePayload<G>>
863        + AsStorage<VertexPayload<G>>
864        + Consistent,
865    G: Geometry,
866{
867    fn from(face: FaceView<M, G>) -> Self {
868        FaceNeighborhood {
869            key: face.key,
870            arcs: face
871                .reachable_interior_arcs()
872                .map(|arc| arc.neighborhood())
873                .collect(),
874        }
875    }
876}
877
878/// View of an interior path.
879///
880/// Interior paths are closed paths formed by arcs and their immediate
881/// neighboring arcs. In a consistent graph, every arc forms such a path. Such
882/// paths may or may not be occupied by faces.
883///
884/// Interior paths have no associated payload and do not directly expose
885/// geometry.
886///
887/// See the module documentation for more information about topological views.
888pub struct InteriorPathView<M, G>
889where
890    M: Reborrow,
891    M::Target: AsStorage<ArcPayload<G>> + Consistent,
892    G: Geometry,
893{
894    storage: M,
895    arc: ArcKey,
896    face: Option<FaceKey>,
897    phantom: PhantomData<G>,
898}
899
900impl<'a, M, G> InteriorPathView<&'a mut M, G>
901where
902    M: AsStorage<ArcPayload<G>> + Consistent,
903    G: 'a + Geometry,
904{
905    /// Converts a mutable view into an immutable view.
906    ///
907    /// This is useful when mutations are not (or no longer) needed and mutual
908    /// access is desired.
909    pub fn into_ref(self) -> InteriorPathView<&'a M, G> {
910        let (arc, face, storage) = self.into_keyed_source();
911        InteriorPathView::from_keyed_source_unchecked((arc, face, &*storage))
912    }
913
914    /// Reborrows the view and constructs another mutable view from a given
915    /// key.
916    ///
917    /// This allows for fallible traversals from a mutable view without the
918    /// need for direct access to the source `MeshGraph`. If the given function
919    /// emits a key, then that key will be used to convert this view into
920    /// another. If no key is emitted, then the original mutable view is
921    /// returned.
922    pub fn with_ref<T, K, F>(self, f: F) -> Either<Result<T, GraphError>, Self>
923    where
924        T: FromKeyedSource<(K, &'a mut M)>,
925        F: FnOnce(InteriorPathView<&M, G>) -> Option<K>,
926    {
927        if let Some(key) = f(self.interior_reborrow()) {
928            let (_, _, storage) = self.into_keyed_source();
929            Either::Left(
930                T::from_keyed_source((key, storage)).ok_or_else(|| GraphError::TopologyNotFound),
931            )
932        }
933        else {
934            Either::Right(self)
935        }
936    }
937}
938
939impl<M, G> InteriorPathView<M, G>
940where
941    M: Reborrow,
942    M::Target: AsStorage<ArcPayload<G>> + Consistent,
943    G: Geometry,
944{
945    fn from_keyed_source_unchecked(source: (ArcKey, Option<FaceKey>, M)) -> Self {
946        let (arc, face, storage) = source;
947        InteriorPathView {
948            storage,
949            arc,
950            face,
951            phantom: PhantomData,
952        }
953    }
954
955    /// Gets the arity of the interior path. This is the number of arcs that
956    /// form the path.
957    pub fn arity(&self) -> usize {
958        self.arcs().count()
959    }
960
961    /// Gets an iterator of views over the arcs within the interior path.
962    pub fn arcs(&self) -> impl Clone + Iterator<Item = ArcView<&M::Target, G>> {
963        ArcCirculator::from(self.interior_reborrow())
964    }
965
966    fn interior_reborrow(&self) -> InteriorPathView<&M::Target, G> {
967        let arc = self.arc;
968        let face = self.face;
969        let storage = self.storage.reborrow();
970        InteriorPathView::from_keyed_source_unchecked((arc, face, storage))
971    }
972}
973
974impl<M, G> InteriorPathView<M, G>
975where
976    M: Reborrow,
977    M::Target: AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + Consistent,
978    G: Geometry,
979{
980    /// Converts the interior path into its originating arc.
981    pub fn into_arc(self) -> ArcView<M, G> {
982        let (arc, _, storage) = self.into_keyed_source();
983        (arc, storage).into_view().expect_consistent()
984    }
985
986    /// Gets the originating arc of the interior path.
987    pub fn arc(&self) -> ArcView<&M::Target, G> {
988        let arc = self.arc;
989        let storage = self.storage.reborrow();
990        (arc, storage).into_view().expect_consistent()
991    }
992
993    /// Gets the distance (number of arcs) between two vertices within the
994    /// interior path.
995    pub fn distance(
996        &self,
997        source: Selector<VertexKey>,
998        destination: Selector<VertexKey>,
999    ) -> Result<usize, GraphError> {
1000        let arity = self.arity();
1001        let select = |selector: Selector<_>| {
1002            selector
1003                .index_or_else(|key| {
1004                    self.vertices()
1005                        .map(|vertex| vertex.key())
1006                        .enumerate()
1007                        .find(|(_, a)| *a == key)
1008                        .map(|(index, _)| index)
1009                        .ok_or_else(|| GraphError::TopologyNotFound)
1010                })
1011                .and_then(|index| {
1012                    if index >= arity {
1013                        Err(GraphError::TopologyNotFound)
1014                    }
1015                    else {
1016                        Ok(index)
1017                    }
1018                })
1019        };
1020        let source = select(source)? as isize;
1021        let destination = select(destination)? as isize;
1022        let difference = (source - destination).abs() as usize;
1023        Ok(cmp::min(difference, arity - difference))
1024    }
1025
1026    /// Gets an iterator of views over the vertices within the interior path.
1027    pub fn vertices(&self) -> impl Clone + Iterator<Item = VertexView<&M::Target, G>> {
1028        VertexCirculator::from(ArcCirculator::from(self.interior_reborrow()))
1029    }
1030}
1031
1032impl<M, G> InteriorPathView<M, G>
1033where
1034    M: Reborrow,
1035    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>> + Consistent,
1036    G: Geometry,
1037{
1038    /// Converts the interior path into its face.
1039    ///
1040    /// If the path has no associated face, then `None` is returned.
1041    pub fn into_face(self) -> Option<FaceView<M, G>> {
1042        let (_, face, storage) = self.into_keyed_source();
1043        if let Some(face) = face {
1044            Some((face, storage).into_view().expect_consistent())
1045        }
1046        else {
1047            None
1048        }
1049    }
1050
1051    /// Gets the face of the interior path.
1052    ///
1053    /// If the path has no associated face, then `None` is returned.
1054    pub fn face(&self) -> Option<FaceView<&M::Target, G>> {
1055        if let Some(face) = self.face {
1056            let storage = self.storage.reborrow();
1057            Some((face, storage).into_view().expect_consistent())
1058        }
1059        else {
1060            None
1061        }
1062    }
1063}
1064
1065impl<'a, M, G> InteriorPathView<&'a mut M, G>
1066where
1067    M: AsStorage<VertexPayload<G>>
1068        + AsStorage<ArcPayload<G>>
1069        + AsStorage<FacePayload<G>>
1070        + Default
1071        + Mutable<G>,
1072    G: 'a + Geometry,
1073{
1074    /// Gets the face of the interior path or inserts a face if one does not
1075    /// already exist.
1076    ///
1077    /// Returns the inserted face.
1078    pub fn get_or_insert_face(self) -> FaceView<&'a mut M, G> {
1079        self.get_or_insert_face_with(|| Default::default())
1080    }
1081
1082    /// Gets the face of the interior path or inserts a face if one does not
1083    /// already exist.
1084    ///
1085    /// If a face is inserted, then the given function is used to get the
1086    /// geometry for the face.
1087    ///
1088    /// Returns the inserted face.
1089    pub fn get_or_insert_face_with<F>(self, f: F) -> FaceView<&'a mut M, G>
1090    where
1091        F: FnOnce() -> G::Face,
1092    {
1093        if let Some(face) = self.face.clone().take() {
1094            let (_, _, storage) = self.into_keyed_source();
1095            (face, storage).into_view().expect_consistent()
1096        }
1097        else {
1098            (move || {
1099                let vertices = self
1100                    .vertices()
1101                    .map(|vertex| vertex.key())
1102                    .collect::<Vec<_>>();
1103                let (_, _, storage) = self.into_keyed_source();
1104                let cache =
1105                    FaceInsertCache::snapshot(&storage, &vertices, (Default::default(), f()))?;
1106                Mutation::replace(storage, Default::default())
1107                    .commit_with(move |mutation| mutation.insert_face_with_cache(cache))
1108                    .map(|(storage, face)| (face, storage).into_view().expect_consistent())
1109            })()
1110            .expect_consistent()
1111        }
1112    }
1113}
1114
1115impl<M, G> FromKeyedSource<(ArcKey, M)> for InteriorPathView<M, G>
1116where
1117    M: Reborrow,
1118    M::Target: AsStorage<ArcPayload<G>> + Consistent,
1119    G: Geometry,
1120{
1121    fn from_keyed_source(source: (ArcKey, M)) -> Option<Self> {
1122        // Because the storage is consistent, this code assumes that any and
1123        // all arcs in the graph will form a loop. Note that this allows
1124        // exterior arcs of non-enclosed meshes to form a region. For
1125        // conceptually flat meshes, this is odd, but is topologically
1126        // consistent.
1127        let (key, storage) = source;
1128        if let Some(arc) = storage.reborrow().as_storage().get(&key) {
1129            let face = arc.face.clone();
1130            Some(InteriorPathView {
1131                storage,
1132                arc: key,
1133                face,
1134                phantom: PhantomData,
1135            })
1136        }
1137        else {
1138            None
1139        }
1140    }
1141}
1142
1143impl<M, G> IntoKeyedSource<(ArcKey, Option<FaceKey>, M)> for InteriorPathView<M, G>
1144where
1145    M: Reborrow,
1146    M::Target: AsStorage<ArcPayload<G>> + Consistent,
1147    G: Geometry,
1148{
1149    fn into_keyed_source(self) -> (ArcKey, Option<FaceKey>, M) {
1150        let InteriorPathView {
1151            storage, arc, face, ..
1152        } = self;
1153        (arc, face, storage)
1154    }
1155}
1156
1157struct VertexCirculator<M, G>
1158where
1159    M: Reborrow,
1160    M::Target: AsStorage<ArcPayload<G>>,
1161    G: Geometry,
1162{
1163    input: ArcCirculator<M, G>,
1164}
1165
1166impl<M, G> VertexCirculator<M, G>
1167where
1168    M: Reborrow,
1169    M::Target: AsStorage<ArcPayload<G>>,
1170    G: Geometry,
1171{
1172    fn next(&mut self) -> Option<VertexKey> {
1173        let ab = self.input.next();
1174        ab.map(|ab| {
1175            let (_, b) = ab.into();
1176            b
1177        })
1178    }
1179}
1180
1181impl<M, G> Clone for VertexCirculator<M, G>
1182where
1183    M: Clone + Reborrow,
1184    M::Target: AsStorage<ArcPayload<G>>,
1185    G: Geometry,
1186{
1187    fn clone(&self) -> Self {
1188        VertexCirculator {
1189            input: self.input.clone(),
1190        }
1191    }
1192}
1193
1194impl<M, G> From<ArcCirculator<M, G>> for VertexCirculator<M, G>
1195where
1196    M: Reborrow,
1197    M::Target: AsStorage<ArcPayload<G>>,
1198    G: Geometry,
1199{
1200    fn from(input: ArcCirculator<M, G>) -> Self {
1201        VertexCirculator { input }
1202    }
1203}
1204
1205// TODO: This iterator could provide a size hint of `(3, None)`, but this is
1206//       only the case when the underlying mesh is consistent.
1207impl<'a, M, G> Iterator for VertexCirculator<&'a M, G>
1208where
1209    M: 'a + AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>>,
1210    G: 'a + Geometry,
1211{
1212    type Item = VertexView<&'a M, G>;
1213
1214    fn next(&mut self) -> Option<Self::Item> {
1215        VertexCirculator::next(self).and_then(|key| (key, self.input.storage).into_view())
1216    }
1217}
1218
1219// TODO: This iterator could provide a size hint of `(3, None)`, but this is
1220//       only the case when the underlying mesh is consistent.
1221impl<'a, M, G> Iterator for VertexCirculator<&'a mut M, G>
1222where
1223    M: 'a + AsStorage<ArcPayload<G>> + AsStorage<VertexPayload<G>> + AsStorageMut<VertexPayload<G>>,
1224    G: 'a + Geometry,
1225{
1226    type Item = OrphanVertexView<'a, G>;
1227
1228    fn next(&mut self) -> Option<Self::Item> {
1229        VertexCirculator::next(self).and_then(|key| {
1230            (key, unsafe {
1231                mem::transmute::<&'_ mut Storage<VertexPayload<G>>, &'a mut Storage<VertexPayload<G>>>(
1232                    self.input.storage.as_storage_mut(),
1233                )
1234            })
1235                .into_view()
1236        })
1237    }
1238}
1239
1240struct ArcCirculator<M, G>
1241where
1242    M: Reborrow,
1243    M::Target: AsStorage<ArcPayload<G>>,
1244    G: Geometry,
1245{
1246    storage: M,
1247    arc: Option<ArcKey>,
1248    breadcrumb: Option<ArcKey>,
1249    phantom: PhantomData<G>,
1250}
1251
1252impl<M, G> ArcCirculator<M, G>
1253where
1254    M: Reborrow,
1255    M::Target: AsStorage<ArcPayload<G>>,
1256    G: Geometry,
1257{
1258    fn next(&mut self) -> Option<ArcKey> {
1259        self.arc.and_then(|arc| {
1260            let next = self
1261                .storage
1262                .reborrow()
1263                .as_storage()
1264                .get(&arc)
1265                .and_then(|arc| arc.next);
1266            self.breadcrumb.map(|_| {
1267                if self.breadcrumb == next {
1268                    self.breadcrumb = None;
1269                }
1270                else {
1271                    self.arc = next;
1272                }
1273                arc
1274            })
1275        })
1276    }
1277}
1278
1279impl<M, G> Clone for ArcCirculator<M, G>
1280where
1281    M: Clone + Reborrow,
1282    M::Target: AsStorage<ArcPayload<G>>,
1283    G: Geometry,
1284{
1285    fn clone(&self) -> Self {
1286        ArcCirculator {
1287            storage: self.storage.clone(),
1288            arc: self.arc,
1289            breadcrumb: self.breadcrumb,
1290            phantom: PhantomData,
1291        }
1292    }
1293}
1294
1295impl<M, G> From<FaceView<M, G>> for ArcCirculator<M, G>
1296where
1297    M: Reborrow,
1298    M::Target: AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>>,
1299    G: Geometry,
1300{
1301    fn from(face: FaceView<M, G>) -> Self {
1302        let arc = face.arc;
1303        let (_, storage) = face.into_keyed_source();
1304        ArcCirculator {
1305            storage,
1306            arc: Some(arc),
1307            breadcrumb: Some(arc),
1308            phantom: PhantomData,
1309        }
1310    }
1311}
1312
1313impl<M, G> From<InteriorPathView<M, G>> for ArcCirculator<M, G>
1314where
1315    M: Reborrow,
1316    M::Target: AsStorage<ArcPayload<G>> + Consistent,
1317    G: Geometry,
1318{
1319    fn from(path: InteriorPathView<M, G>) -> Self {
1320        let (arc, _, storage) = path.into_keyed_source();
1321        ArcCirculator {
1322            storage,
1323            arc: Some(arc),
1324            breadcrumb: Some(arc),
1325            phantom: PhantomData,
1326        }
1327    }
1328}
1329
1330// TODO: This iterator could provide a size hint of `(3, None)`, but this is
1331//       only the case when the underlying mesh is consistent.
1332impl<'a, M, G> Iterator for ArcCirculator<&'a M, G>
1333where
1334    M: 'a + AsStorage<ArcPayload<G>>,
1335    G: 'a + Geometry,
1336{
1337    type Item = ArcView<&'a M, G>;
1338
1339    fn next(&mut self) -> Option<Self::Item> {
1340        ArcCirculator::next(self).and_then(|key| (key, self.storage).into_view())
1341    }
1342}
1343
1344// TODO: This iterator could provide a size hint of `(3, None)`, but this is
1345//       only the case when the underlying mesh is consistent.
1346impl<'a, M, G> Iterator for ArcCirculator<&'a mut M, G>
1347where
1348    M: 'a + AsStorage<ArcPayload<G>> + AsStorageMut<ArcPayload<G>>,
1349    G: 'a + Geometry,
1350{
1351    type Item = OrphanArcView<'a, G>;
1352
1353    fn next(&mut self) -> Option<Self::Item> {
1354        ArcCirculator::next(self).and_then(|key| {
1355            (key, unsafe {
1356                mem::transmute::<&'_ mut Storage<ArcPayload<G>>, &'a mut Storage<ArcPayload<G>>>(
1357                    self.storage.as_storage_mut(),
1358                )
1359            })
1360                .into_view()
1361        })
1362    }
1363}
1364
1365struct FaceCirculator<M, G>
1366where
1367    M: Reborrow,
1368    M::Target: AsStorage<ArcPayload<G>>,
1369    G: Geometry,
1370{
1371    input: ArcCirculator<M, G>,
1372}
1373
1374impl<M, G> FaceCirculator<M, G>
1375where
1376    M: Reborrow,
1377    M::Target: AsStorage<ArcPayload<G>>,
1378    G: Geometry,
1379{
1380    fn next(&mut self) -> Option<FaceKey> {
1381        while let Some(ba) = self.input.next().map(|ab| ab.opposite()) {
1382            if let Some(abc) = self
1383                .input
1384                .storage
1385                .reborrow()
1386                .as_storage()
1387                .get(&ba)
1388                .and_then(|opposite| opposite.face)
1389            {
1390                return Some(abc);
1391            }
1392            else {
1393                // Skip arcs with no opposing face. This can occur within
1394                // non-enclosed meshes.
1395                continue;
1396            }
1397        }
1398        None
1399    }
1400}
1401
1402impl<M, G> Clone for FaceCirculator<M, G>
1403where
1404    M: Clone + Reborrow,
1405    M::Target: AsStorage<ArcPayload<G>>,
1406    G: Geometry,
1407{
1408    fn clone(&self) -> Self {
1409        FaceCirculator {
1410            input: self.input.clone(),
1411        }
1412    }
1413}
1414
1415impl<M, G> From<ArcCirculator<M, G>> for FaceCirculator<M, G>
1416where
1417    M: Reborrow,
1418    M::Target: AsStorage<ArcPayload<G>>,
1419    G: Geometry,
1420{
1421    fn from(input: ArcCirculator<M, G>) -> Self {
1422        FaceCirculator { input }
1423    }
1424}
1425
1426impl<'a, M, G> Iterator for FaceCirculator<&'a M, G>
1427where
1428    M: 'a + AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>>,
1429    G: 'a + Geometry,
1430{
1431    type Item = FaceView<&'a M, G>;
1432
1433    fn next(&mut self) -> Option<Self::Item> {
1434        FaceCirculator::next(self).and_then(|key| (key, self.input.storage).into_view())
1435    }
1436}
1437
1438impl<'a, M, G> Iterator for FaceCirculator<&'a mut M, G>
1439where
1440    M: 'a + AsStorage<ArcPayload<G>> + AsStorage<FacePayload<G>> + AsStorageMut<FacePayload<G>>,
1441    G: 'a + Geometry,
1442{
1443    type Item = OrphanFaceView<'a, G>;
1444
1445    fn next(&mut self) -> Option<Self::Item> {
1446        FaceCirculator::next(self).and_then(|key| {
1447            (key, unsafe {
1448                mem::transmute::<&'_ mut Storage<FacePayload<G>>, &'a mut Storage<FacePayload<G>>>(
1449                    self.input.storage.as_storage_mut(),
1450                )
1451            })
1452                .into_view()
1453        })
1454    }
1455}
1456
1457#[cfg(test)]
1458mod tests {
1459    use nalgebra::{Point2, Point3};
1460
1461    use crate::graph::*;
1462    use crate::primitive::cube::Cube;
1463    use crate::primitive::generate::*;
1464    use crate::primitive::index::*;
1465    use crate::primitive::sphere::UvSphere;
1466    use crate::*;
1467
1468    #[test]
1469    fn circulate_over_arcs() {
1470        let graph = UvSphere::new(3, 2)
1471            .polygons_with_position() // 6 triangles, 18 vertices.
1472            .collect::<MeshGraph<Point3<f32>>>();
1473        let face = graph.faces().nth(0).unwrap();
1474
1475        // All faces should be triangles and should have three edges.
1476        assert_eq!(3, face.interior_arcs().count());
1477    }
1478
1479    #[test]
1480    fn circulate_over_faces() {
1481        let graph = UvSphere::new(3, 2)
1482            .polygons_with_position() // 6 triangles, 18 vertices.
1483            .collect::<MeshGraph<Point3<f32>>>();
1484        let face = graph.faces().nth(0).unwrap();
1485
1486        // No matter which face is selected, it should have three neighbors.
1487        assert_eq!(3, face.neighboring_faces().count());
1488    }
1489
1490    #[test]
1491    fn remove_face() {
1492        let mut graph = UvSphere::new(3, 2)
1493            .polygons_with_position() // 6 triangles, 18 vertices.
1494            .collect::<MeshGraph<Point3<f32>>>();
1495
1496        // The graph should begin with 6 faces.
1497        assert_eq!(6, graph.face_count());
1498
1499        // Remove a face from the graph.
1500        let abc = graph.faces().nth(0).unwrap().key();
1501        {
1502            let face = graph.face_mut(abc).unwrap();
1503            assert_eq!(3, face.arity()); // The face should be triangular.
1504
1505            let path = face.remove().into_ref();
1506            assert_eq!(3, path.arity()); // The path should also be triangular.
1507        }
1508
1509        // After the removal, the graph should have only 5 faces.
1510        assert_eq!(5, graph.face_count());
1511    }
1512
1513    #[test]
1514    fn split_face() {
1515        let mut graph = MeshGraph::<Point2<f32>>::from_raw_buffers_with_arity(
1516            vec![0u32, 1, 2, 3],
1517            vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)],
1518            4,
1519        )
1520        .unwrap();
1521        let abc = graph.faces().nth(0).unwrap().key();
1522        let arc = graph
1523            .face_mut(abc)
1524            .unwrap()
1525            .split(ByIndex(0), ByIndex(2))
1526            .unwrap()
1527            .into_ref();
1528
1529        assert!(arc.face().is_some());
1530        assert!(arc.opposite_arc().face().is_some());
1531        assert_eq!(4, graph.vertex_count());
1532        assert_eq!(10, graph.arc_count());
1533        assert_eq!(2, graph.face_count());
1534    }
1535
1536    #[test]
1537    fn extrude_face() {
1538        let mut graph = UvSphere::new(3, 2)
1539            .polygons_with_position() // 6 triangles, 18 vertices.
1540            .collect::<MeshGraph<Point3<f32>>>();
1541        {
1542            let key = graph.faces().nth(0).unwrap().key();
1543            let face = graph
1544                .face_mut(key)
1545                .unwrap()
1546                .extrude(1.0)
1547                .unwrap()
1548                .into_ref();
1549
1550            // The extruded face, being a triangle, should have three
1551            // neighboring faces.
1552            assert_eq!(3, face.neighboring_faces().count());
1553        }
1554
1555        assert_eq!(8, graph.vertex_count());
1556        // The mesh begins with 18 arcs. The extrusion adds three quads
1557        // with four interior arcs each, so there are `18 + (3 * 4)`
1558        // arcs.
1559        assert_eq!(30, graph.arc_count());
1560        // All faces are triangles and the mesh begins with six such faces. The
1561        // extruded face remains, in addition to three connective faces, each
1562        // of which is constructed from quads.
1563        assert_eq!(9, graph.face_count());
1564    }
1565
1566    #[test]
1567    fn merge_faces() {
1568        // Construct a graph with two connected quads.
1569        let mut graph = MeshGraph::<Point2<f32>>::from_raw_buffers_with_arity(
1570            vec![0u32, 1, 2, 3, 0, 3, 4, 5],
1571            vec![
1572                (0.0, 0.0),  // 0
1573                (1.0, 0.0),  // 1
1574                (1.0, 1.0),  // 2
1575                (0.0, 1.0),  // 3
1576                (-1.0, 1.0), // 4
1577                (-1.0, 0.0), // 5
1578            ],
1579            4,
1580        )
1581        .unwrap();
1582
1583        // The graph should begin with 2 faces.
1584        assert_eq!(2, graph.face_count());
1585
1586        // Get the keys for the two faces and join them.
1587        let abc = graph.faces().nth(0).unwrap().key();
1588        let def = graph.faces().nth(1).unwrap().key();
1589        graph.face_mut(abc).unwrap().merge(ByKey(def)).unwrap();
1590
1591        // After the removal, the graph should have 1 face.
1592        assert_eq!(1, graph.face_count());
1593        assert_eq!(6, graph.faces().nth(0).unwrap().arity());
1594    }
1595
1596    #[test]
1597    fn poke_face() {
1598        let mut graph = Cube::new()
1599            .polygons_with_position() // 6 quads, 24 vertices.
1600            .collect::<MeshGraph<Point3<f32>>>();
1601        let key = graph.faces().nth(0).unwrap().key();
1602        let vertex = graph.face_mut(key).unwrap().poke_at_centroid();
1603
1604        // Diverging a quad yields a tetrahedron.
1605        assert_eq!(4, vertex.neighboring_faces().count());
1606
1607        // Traverse to one of the triangles in the tetrahedron.
1608        let face = vertex.into_outgoing_arc().into_face().unwrap();
1609
1610        assert_eq!(3, face.arity());
1611
1612        // Diverge the triangle.
1613        let vertex = face.poke_at_centroid();
1614
1615        assert_eq!(3, vertex.neighboring_faces().count());
1616    }
1617
1618    #[test]
1619    fn triangulate_mesh() {
1620        let (indices, vertices) = Cube::new()
1621            .polygons_with_position() // 6 quads, 24 vertices.
1622            .index_vertices(HashIndexer::default());
1623        let mut graph = MeshGraph::<Point3<f32>>::from_raw_buffers(indices, vertices).unwrap();
1624        graph.triangulate();
1625
1626        assert_eq!(8, graph.vertex_count());
1627        assert_eq!(36, graph.arc_count());
1628        assert_eq!(18, graph.edge_count());
1629        // Each quad becomes 2 triangles, so 6 quads become 12 triangles.
1630        assert_eq!(12, graph.face_count());
1631    }
1632
1633    #[test]
1634    fn interior_path_distance() {
1635        let graph = MeshGraph::<Point2<f32>>::from_raw_buffers_with_arity(
1636            vec![0u32, 1, 2, 3],
1637            vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)],
1638            4,
1639        )
1640        .unwrap();
1641        let face = graph.faces().nth(0).unwrap();
1642        let keys = face
1643            .vertices()
1644            .map(|vertex| vertex.key())
1645            .collect::<Vec<_>>();
1646        let path = face.into_interior_path();
1647        assert_eq!(2, path.distance(keys[0].into(), keys[2].into()).unwrap());
1648        assert_eq!(1, path.distance(keys[0].into(), keys[3].into()).unwrap());
1649        assert_eq!(0, path.distance(keys[0].into(), keys[0].into()).unwrap());
1650    }
1651}