Skip to main content

axiolid_topology/
brep.rs

1//! Append-only typed arenas for B-rep topology.
2
3use crate::{
4    Edge, EdgeId, Face, FaceId, Loop, LoopId, Shell, ShellId, Solid, SolidId, Vertex, VertexId,
5};
6
7/// Owned B-rep. Generic geometry handles avoid a dependency cycle with the
8/// model graph that stores exact curves and surfaces.
9#[derive(Debug, Clone, PartialEq)]
10#[cfg_attr(
11    feature = "serde",
12    derive(serde::Serialize, serde::Deserialize),
13    serde(deny_unknown_fields)
14)]
15pub struct BRep<Curve3, Curve2 = Curve3, Surface = Curve3> {
16    vertices: Vec<Vertex>,
17    edges: Vec<Edge<Curve3>>,
18    loops: Vec<Loop<Curve2>>,
19    faces: Vec<Face<Surface>>,
20    shells: Vec<Shell>,
21    solids: Vec<Solid>,
22}
23
24impl<Curve3, Curve2, Surface> Default for BRep<Curve3, Curve2, Surface> {
25    fn default() -> Self {
26        Self {
27            vertices: Vec::new(),
28            edges: Vec::new(),
29            loops: Vec::new(),
30            faces: Vec::new(),
31            shells: Vec::new(),
32            solids: Vec::new(),
33        }
34    }
35}
36
37impl<Curve3, Curve2, Surface> BRep<Curve3, Curve2, Surface> {
38    /// Fallibly reserve append-only arena capacity for bounded construction.
39    pub fn try_reserve(
40        &mut self,
41        vertices: usize,
42        edges: usize,
43        loops: usize,
44        faces: usize,
45        shells: usize,
46        solids: usize,
47    ) -> Result<(), std::collections::TryReserveError> {
48        self.vertices.try_reserve_exact(vertices)?;
49        self.edges.try_reserve_exact(edges)?;
50        self.loops.try_reserve_exact(loops)?;
51        self.faces.try_reserve_exact(faces)?;
52        self.shells.try_reserve_exact(shells)?;
53        self.solids.try_reserve_exact(solids)?;
54        Ok(())
55    }
56
57    /// Add a vertex and return its typed handle.
58    pub fn add_vertex(&mut self, value: Vertex) -> VertexId {
59        let id = VertexId::from_index(self.vertices.len());
60        self.vertices.push(value);
61        id
62    }
63
64    /// Add an edge and return its typed handle.
65    pub fn add_edge(&mut self, value: Edge<Curve3>) -> EdgeId {
66        let id = EdgeId::from_index(self.edges.len());
67        self.edges.push(value);
68        id
69    }
70
71    /// Add a loop and return its typed handle.
72    pub fn add_loop(&mut self, value: Loop<Curve2>) -> LoopId {
73        let id = LoopId::from_index(self.loops.len());
74        self.loops.push(value);
75        id
76    }
77
78    /// Add a face and return its typed handle.
79    pub fn add_face(&mut self, value: Face<Surface>) -> FaceId {
80        let id = FaceId::from_index(self.faces.len());
81        self.faces.push(value);
82        id
83    }
84
85    /// Add a shell and return its typed handle.
86    pub fn add_shell(&mut self, value: Shell) -> ShellId {
87        let id = ShellId::from_index(self.shells.len());
88        self.shells.push(value);
89        id
90    }
91
92    /// Add a solid and return its typed handle.
93    pub fn add_solid(&mut self, value: Solid) -> SolidId {
94        let id = SolidId::from_index(self.solids.len());
95        self.solids.push(value);
96        id
97    }
98
99    /// Vertices in stable insertion order.
100    pub fn vertices(&self) -> &[Vertex] {
101        &self.vertices
102    }
103
104    /// Edge handle at a dense arena index, if present.
105    pub fn edge_id_at(&self, index: usize) -> Option<EdgeId> {
106        (index < self.edges.len()).then(|| EdgeId::from_index(index))
107    }
108
109    /// Loop handle at a dense arena index, if present.
110    pub fn loop_id_at(&self, index: usize) -> Option<LoopId> {
111        (index < self.loops.len()).then(|| LoopId::from_index(index))
112    }
113
114    /// All edges in insertion order.
115    pub fn edges(&self) -> &[Edge<Curve3>] {
116        &self.edges
117    }
118
119    /// Loops in stable insertion order.
120    pub fn loops(&self) -> &[Loop<Curve2>] {
121        &self.loops
122    }
123
124    /// Face handle at a dense arena index, if present.
125    pub fn face_id_at(&self, index: usize) -> Option<FaceId> {
126        (index < self.faces.len()).then(|| FaceId::from_index(index))
127    }
128
129    /// All faces in insertion order.
130    pub fn faces(&self) -> &[Face<Surface>] {
131        &self.faces
132    }
133
134    /// Shells in stable insertion order.
135    pub fn shells(&self) -> &[Shell] {
136        &self.shells
137    }
138
139    /// Solids in stable insertion order.
140    pub fn solids(&self) -> &[Solid] {
141        &self.solids
142    }
143}