Skip to main content

geop_core_topology/euler/
add_vertex_coedge.rs

1use crate::{
2    Coedge, CoedgeGeometry, CoedgeId, Model, Sense, VertexId,
3    argument_validation::validate_pcurve_start_and_end,
4};
5use geop_core_geometry::nurb_curve::NurbCurve2D;
6use geop_core_math::{
7    geop_error::{GeopError, GeopResult, WithContext},
8    scalars::Scalar,
9};
10
11impl<S: Scalar> Model<S> {
12    /// Splice a single degenerate coedge — backed directly by `vertex` (see
13    /// [`CoedgeGeometry::Vertex`]), not a real edge — into `after`'s own
14    /// loop, right after it. `pcurve` must both start and end at `vertex`'s
15    /// own position, as mapped through `after`'s face's surface (it's
16    /// meant to sweep some parameter-space range while sitting at that one
17    /// 3-D point the whole way, e.g. tracing a pole row's full angular
18    /// span).
19    ///
20    /// Unlike every other euler operator here, this isn't one: it doesn't
21    /// touch `V`, `E`, or `F` (`vertex` already exists, and no edge is
22    /// created), so there's no Euler–Poincaré invariant for it to need to
23    /// preserve — it's pure loop bookkeeping, letting a face's own
24    /// boundary legitimately pass through an already-shared vertex without
25    /// requiring a real (and, for a single-face-only detour, otherwise
26    /// unpaired) edge to carry a pcurve.
27    pub fn add_vertex_coedge(
28        self: &mut Model<S>,
29        after: CoedgeId,
30        vertex: VertexId,
31        pcurve: NurbCurve2D<S>,
32    ) -> GeopResult<CoedgeId> {
33        let ctx = |e: GeopError| {
34            e.with_context(format!(
35                "Model::add_vertex_coedge(after={after}, vertex={vertex}, pcurve={pcurve})"
36            ))
37        };
38
39        let ce = self.get_coedge(after)?.clone();
40        let face = self.get_face(ce.face)?.clone();
41        let p = self.get_vertex(vertex)?.point;
42
43        validate_pcurve_start_and_end(&face.surface, &pcurve, &p, &p).with_context(&ctx)?;
44
45        let new_coedge = self.insert_coedge(Coedge {
46            geometry: CoedgeGeometry::Vertex(vertex),
47            sense: Sense::Forward,
48            pcurve,
49            next: ce.next,
50            prev: after,
51            face: ce.face,
52        });
53
54        self.coedges.get_mut(&after).unwrap().next = new_coedge;
55        self.coedges.get_mut(&ce.next).unwrap().prev = new_coedge;
56
57        Ok(new_coedge)
58    }
59}