Skip to main content

geop_core_part/
euler.rs

1//! Forwarding wrappers for every `Model` euler operator: each method here
2//! calls the identically-named `geop_core_topology::Model` method, then
3//! registers whichever new vertex/edge/face/solid it created under the name
4//! the caller supplied for it (see the crate docs for how names are chosen), and forgets the name of whichever
5//! one it deleted.
6
7use geop_core_geometry::{
8    nurb_curve::{NurbCurve2D, NurbCurve3D},
9    nurb_surface::NurbSurface3D,
10};
11use geop_core_math::{
12    geop_error::{GeopError, GeopResult},
13    scalars::Scalar,
14    vector::Vector3,
15};
16use geop_core_topology::{CoedgeId, EdgeId, FaceId, SolidId, VertexId, boundary::BoundaryType};
17
18use crate::part::Part;
19
20impl<S: Scalar> Part<S> {
21    /// Forwards to [`geop_core_topology::Model::mvfs`], naming the new
22    /// vertex, face and solid it creates.
23    pub fn mvfs(
24        &mut self,
25        point: Vector3<S>,
26        vertex_name: impl Into<String>,
27        face_name: impl Into<String>,
28        solid_name: impl Into<String>,
29    ) -> GeopResult<(VertexId, FaceId, SolidId)> {
30        let (vertex, face, solid) = self.topology.mvfs(point);
31        self.names.insert(vertex, vertex_name)?;
32        self.names.insert(face, face_name)?;
33        self.names.insert(solid, solid_name)?;
34        Ok((vertex, face, solid))
35    }
36
37    /// Forwards to [`geop_core_topology::Model::mve`], naming the new vertex
38    /// and edge it creates.
39    pub fn mve(
40        &mut self,
41        coedge: CoedgeId,
42        curve: NurbCurve3D<S>,
43        pcurve: NurbCurve2D<S>,
44        pcurve_reversed: NurbCurve2D<S>,
45        p: Vector3<S>,
46        vertex_name: impl Into<String>,
47        edge_name: impl Into<String>,
48    ) -> GeopResult<(VertexId, CoedgeId, CoedgeId, EdgeId)> {
49        let (vertex, c_out, c_in, edge) =
50            self.topology
51                .mve(coedge, curve, pcurve, pcurve_reversed, p)?;
52        self.names.insert(vertex, vertex_name)?;
53        self.names.insert(edge, edge_name)?;
54        Ok((vertex, c_out, c_in, edge))
55    }
56
57    /// Forwards to [`geop_core_topology::Model::mve_from_vertex`], naming the
58    /// new vertex and edge it creates.
59    pub fn mve_from_vertex(
60        &mut self,
61        face_id: FaceId,
62        vertex: VertexId,
63        curve: NurbCurve3D<S>,
64        pcurve: NurbCurve2D<S>,
65        pcurve_reversed: NurbCurve2D<S>,
66        p: Vector3<S>,
67        vertex_name: impl Into<String>,
68        edge_name: impl Into<String>,
69    ) -> GeopResult<(VertexId, CoedgeId, CoedgeId, EdgeId)> {
70        let (new_vertex, c_out, c_in, edge) =
71            self.topology
72                .mve_from_vertex(face_id, vertex, curve, pcurve, pcurve_reversed, p)?;
73        self.names.insert(new_vertex, vertex_name)?;
74        self.names.insert(edge, edge_name)?;
75        Ok((new_vertex, c_out, c_in, edge))
76    }
77
78    /// Forwards to [`geop_core_topology::Model::mef`], naming the new edge
79    /// and face it creates.
80    pub fn mef(
81        &mut self,
82        coedge1: CoedgeId,
83        coedge2: CoedgeId,
84        curve: NurbCurve3D<S>,
85        pcurve: NurbCurve2D<S>,
86        pcurve_reversed: NurbCurve2D<S>,
87        new_surface: NurbSurface3D<S>,
88        edge_name: impl Into<String>,
89        face_name: impl Into<String>,
90    ) -> GeopResult<(EdgeId, FaceId, CoedgeId, CoedgeId)> {
91        let (edge, face, c_forward, c_backward) = self.topology.mef(
92            coedge1,
93            coedge2,
94            curve,
95            pcurve,
96            pcurve_reversed,
97            new_surface,
98        )?;
99        self.names.insert(edge, edge_name)?;
100        self.names.insert(face, face_name)?;
101        Ok((edge, face, c_forward, c_backward))
102    }
103
104    /// Forwards to [`geop_core_topology::Model::mer`], naming the new edge it
105    /// creates (`existing_face_id` already has a name of its own).
106    pub fn mer(
107        &mut self,
108        coedge1: CoedgeId,
109        coedge2: CoedgeId,
110        curve: NurbCurve3D<S>,
111        pcurve: NurbCurve2D<S>,
112        pcurve_reversed: NurbCurve2D<S>,
113        existing_face_id: FaceId,
114        edge_name: impl Into<String>,
115    ) -> GeopResult<(EdgeId, CoedgeId, CoedgeId)> {
116        let (edge, c_backward, c_forward) = self.topology.mer(
117            coedge1,
118            coedge2,
119            curve,
120            pcurve,
121            pcurve_reversed,
122            existing_face_id,
123        )?;
124        self.names.insert(edge, edge_name)?;
125        Ok((edge, c_backward, c_forward))
126    }
127
128    /// Forwards to [`geop_core_topology::Model::mekr`], naming the new edge
129    /// it creates.
130    pub fn mekr(
131        &mut self,
132        coedge1: CoedgeId,
133        coedge2: CoedgeId,
134        curve: NurbCurve3D<S>,
135        pcurve: NurbCurve2D<S>,
136        edge_name: impl Into<String>,
137    ) -> GeopResult<(EdgeId, CoedgeId, CoedgeId)> {
138        let (edge, c_a, c_b) = self.topology.mekr(coedge1, coedge2, curve, pcurve)?;
139        self.names.insert(edge, edge_name)?;
140        Ok((edge, c_a, c_b))
141    }
142
143    /// Forwards to [`geop_core_topology::Model::mvr`], naming the new vertex
144    /// it creates.
145    pub fn mvr(
146        &mut self,
147        face_id: FaceId,
148        point: Vector3<S>,
149        vertex_name: impl Into<String>,
150    ) -> GeopResult<VertexId> {
151        let vertex = self.topology.mvr(face_id, point)?;
152        self.names.insert(vertex, vertex_name)?;
153        Ok(vertex)
154    }
155
156    /// Forwards to [`geop_core_topology::Model::add_vertex_coedge`]. Creates
157    /// no vertex/edge/face/solid of its own (only a coedge, which `Part`
158    /// never names), so it takes no name argument.
159    pub fn add_vertex_coedge(
160        &mut self,
161        after: CoedgeId,
162        vertex: VertexId,
163        pcurve: NurbCurve2D<S>,
164    ) -> GeopResult<CoedgeId> {
165        self.topology.add_vertex_coedge(after, vertex, pcurve)
166    }
167
168    /// Forwards to [`geop_core_topology::Model::kill_vertex_coedge`]. Deletes
169    /// no named entity, so it takes no name argument.
170    pub fn kill_vertex_coedge(&mut self, coedge: CoedgeId) -> GeopResult<()> {
171        self.topology.kill_vertex_coedge(coedge)
172    }
173
174    /// Forwards to [`geop_core_topology::Model::replace_face`]. Creates and
175    /// deletes nothing: the face keeps its name with its new surface.
176    pub fn replace_face(&mut self, face_id: FaceId, surface: NurbSurface3D<S>) -> GeopResult<()> {
177        self.topology.replace_face(face_id, surface)
178    }
179
180    /// Forwards to [`geop_core_topology::Model::replace_pcurve`]. Coedges are
181    /// never named, so this takes no name.
182    pub fn replace_pcurve(
183        &mut self,
184        coedge_id: CoedgeId,
185        pcurve: NurbCurve2D<S>,
186    ) -> GeopResult<()> {
187        self.topology.replace_pcurve(coedge_id, pcurve)
188    }
189
190    /// Forwards to [`geop_core_topology::Model::kef`], forgetting the names
191    /// of the edge and face it deletes (both already given as arguments).
192    pub fn kef(&mut self, edge: EdgeId, killed_face: FaceId) -> GeopResult<()> {
193        self.topology.kef(edge, killed_face)?;
194        self.names.remove(edge);
195        self.names.remove(killed_face);
196        Ok(())
197    }
198
199    /// Forwards to [`geop_core_topology::Model::kemr`], forgetting the name
200    /// of the edge it deletes (`ca_id`/`cb_id`'s shared edge).
201    pub fn kemr(&mut self, ca_id: CoedgeId, cb_id: CoedgeId) -> GeopResult<()> {
202        let edge = self.topology.get_coedge(ca_id)?.edge()?;
203        self.topology.kemr(ca_id, cb_id)?;
204        self.names.remove(edge);
205        Ok(())
206    }
207
208    /// Forwards to [`geop_core_topology::Model::ker`], forgetting the name of
209    /// the edge it deletes (`coedge_backward`/`coedge_forward`'s shared edge).
210    pub fn ker(&mut self, coedge_backward: CoedgeId, coedge_forward: CoedgeId) -> GeopResult<()> {
211        let edge = self.topology.get_coedge(coedge_forward)?.edge()?;
212        self.topology.ker(coedge_backward, coedge_forward)?;
213        self.names.remove(edge);
214        Ok(())
215    }
216
217    /// Forwards to [`geop_core_topology::Model::kve`], forgetting the names
218    /// of the edge (`c_out`/`c_in`'s shared edge) and vertex it deletes.
219    pub fn kve(&mut self, c_out: CoedgeId, c_in: CoedgeId, vertex: VertexId) -> GeopResult<()> {
220        let edge = self.topology.get_coedge(c_out)?.edge()?;
221        self.topology.kve(c_out, c_in, vertex)?;
222        self.names.remove(edge);
223        self.names.remove(vertex);
224        Ok(())
225    }
226
227    /// Forwards to [`geop_core_topology::Model::kvfs`], forgetting the names
228    /// of the vertex, face and solid it deletes. `Model::kvfs` doesn't hand
229    /// those ids back (it just takes `solid`), so they're read off the
230    /// still-intact topology first, the same way `Model::kvfs` itself finds
231    /// them; if that shape isn't there, `Model::kvfs` below rejects it for
232    /// the same reason, so nothing is left half-forgotten.
233    pub fn kvfs(&mut self, solid: SolidId) -> GeopResult<()> {
234        let shell_id = *self
235            .topology
236            .get_solid(solid)?
237            .shells
238            .first()
239            .ok_or_else(|| GeopError::new(format!("solid {solid} must have exactly one shell")))?;
240        let face_id = *self
241            .topology
242            .get_shell(shell_id)?
243            .faces
244            .first()
245            .ok_or_else(|| {
246                GeopError::new(format!("shell {shell_id} must have exactly one face"))
247            })?;
248        let vertex_id = match self.topology.get_face(face_id)?.outer {
249            BoundaryType::Vertex(v) => v,
250            BoundaryType::Loop(_) => {
251                return Err(GeopError::new(format!(
252                    "face {face_id}'s boundary must be a bare vertex"
253                )));
254            }
255        };
256        self.topology.kvfs(solid)?;
257        self.names.remove(vertex_id);
258        self.names.remove(face_id);
259        self.names.remove(solid);
260        Ok(())
261    }
262
263    /// Forwards to [`geop_core_topology::Model::kvr`], forgetting the name of
264    /// the vertex it deletes (already given as an argument).
265    pub fn kvr(&mut self, face_id: FaceId, vertex: VertexId) -> GeopResult<()> {
266        self.topology.kvr(face_id, vertex)?;
267        self.names.remove(vertex);
268        Ok(())
269    }
270}