1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use fj_interop::mesh::Color;
use fj_math::Triangle;

use crate::builder::FaceBuilder;

use super::{Cycle, Surface};

/// A face of a shape
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum Face {
    /// A face of a shape
    ///
    /// A face is defined by a surface, and is bounded by edges that lie in that
    /// surface.
    Face(FaceBRep),

    /// The triangles of the face
    ///
    /// Representing faces as a collection of triangles is a temporary state.
    /// The plan is to eventually represent faces as a geometric surface,
    /// bounded by edges. While the transition is being made, this variant is
    /// still required.
    Triangles(Vec<(Triangle<3>, Color)>),
}

impl Face {
    /// Construct a new instance of `Face`
    pub fn new(
        surface: Surface,
        exteriors: impl IntoIterator<Item = Cycle>,
        interiors: impl IntoIterator<Item = Cycle>,
        color: [u8; 4],
    ) -> Self {
        let exteriors = CyclesInFace::new(exteriors);
        let interiors = CyclesInFace::new(interiors);

        Self::Face(FaceBRep {
            surface,
            exteriors,
            interiors,
            color,
        })
    }
    /// Build a face using the [`FaceBuilder`] API
    pub fn builder(surface: Surface) -> FaceBuilder {
        FaceBuilder::new(surface)
    }

    /// Access the boundary representation of the face
    pub fn brep(&self) -> &FaceBRep {
        match self {
            Self::Face(face) => face,
            _ => {
                // No code that still uses triangle representation is calling
                // this method.
                unreachable!()
            }
        }
    }

    /// Access this face's surface
    pub fn surface(&self) -> Surface {
        self.brep().surface()
    }

    /// Access this face's exterior cycles
    pub fn exteriors(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.brep().exteriors()
    }

    /// Access this face's interior cycles
    pub fn interiors(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.brep().interiors()
    }

    /// Access all cycles of this face
    ///
    /// This is equivalent to chaining the iterators returned by
    /// [`Face::exteriors`] and [`Face::interiors`].
    pub fn all_cycles(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.exteriors().chain(self.interiors())
    }

    /// Access the color of the face
    pub fn color(&self) -> [u8; 4] {
        self.brep().color
    }
}

/// The boundary representation of a face
///
/// This type exists to ease the handling of faces that use boundary
/// representation. It will eventually be merged into `Face`, once
/// `Face::Triangles` can finally be removed.
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct FaceBRep {
    /// The surface that defines this face
    pub surface: Surface,

    /// The cycles that bound the face on the outside
    ///
    /// # Implementation Note
    ///
    /// Since these cycles bound the face, the edges they consist of must
    /// lie in the surface. The data we're using here is 3-dimensional
    /// though, so no such limitation is enforced.
    ///
    /// It might be less error-prone to specify the cycles in surface
    /// coordinates.
    pub exteriors: CyclesInFace,

    /// The cycles that bound the face on the inside
    ///
    /// Each of these cycles defines a hole in the face.
    ///
    /// # Implementation note
    ///
    /// See note on `exterior` field.
    pub interiors: CyclesInFace,

    /// The color of the face
    pub color: [u8; 4],
}

impl FaceBRep {
    /// Access this face's surface
    pub fn surface(&self) -> Surface {
        self.surface
    }

    /// Access this face's exterior cycles
    pub fn exteriors(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.exteriors.as_local()
    }

    /// Access this face's interior cycles
    pub fn interiors(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.interiors.as_local()
    }

    /// Access all cycles of this face
    ///
    /// This is equivalent to chaining the iterators returned by
    /// [`Face::exteriors`] and [`Face::interiors`].
    pub fn all_cycles(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.exteriors().chain(self.interiors())
    }
}

/// A list of cycles, as they are stored in `Face`
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct CyclesInFace(Vec<Cycle>);

impl CyclesInFace {
    /// Create a new instance of `CyclesInFace`
    pub fn new(cycles: impl IntoIterator<Item = Cycle>) -> Self {
        Self(cycles.into_iter().collect())
    }

    /// Access an iterator over the canonical forms of the cycles
    pub fn as_local(&self) -> impl Iterator<Item = Cycle> + '_ {
        self.0.iter().cloned()
    }
}