Skip to main content

geop_core_topology/euler/
mve.rs

1use crate::{
2    Coedge, CoedgeGeometry, CoedgeId, Edge, EdgeId, FaceId, Model, Sense, Vertex, VertexId,
3    argument_validation::{validate_curve_start_and_end, validate_pcurve_start_and_end},
4    boundary::BoundaryType,
5};
6use geop_core_geometry::nurb_curve::{NurbCurve2D, NurbCurve3D};
7use geop_core_math::{
8    geop_error::{GeopError, GeopResult, WithContext},
9    scalars::Scalar,
10    vector::Vector3,
11};
12
13impl<S: Scalar> Model<S> {
14    // Add a new edge right after the coedge.
15    // Curve and pcurve must go from the coedge's end vertex to the new vertex `p`.
16    // PCurve reversed must go from the new vertex `p` to the coedge's end vertex.
17    // returns (new vertex, coedge_forward -> p, coedge_reversed <- p, new edge)
18    pub fn mve(
19        self: &mut Model<S>,
20        coedge: CoedgeId,
21        curve: NurbCurve3D<S>,
22        pcurve: NurbCurve2D<S>,
23        pcurve_reversed: NurbCurve2D<S>,
24        p: Vector3<S>,
25    ) -> GeopResult<(VertexId, CoedgeId, CoedgeId, EdgeId)> {
26        let ctx = |e: GeopError| {
27            e.with_context(format!(
28                "Model::mve(
29    coedge={coedge}
30    curve={curve}
31    pcurve={pcurve}
32    pcurve_reversed={pcurve_reversed}
33    p={p}
34)"
35            ))
36        };
37        let ce = self.get_coedge(coedge)?.clone();
38        let face = self.get_face(ce.face)?.clone();
39
40        let ce_end_id = self.coedge_end_vertex_id(coedge)?;
41        let ce_end = self.get_vertex(ce_end_id)?.clone();
42
43        validate_pcurve_start_and_end(&face.surface, &pcurve, &ce_end.point, &p)
44            .with_context(&ctx)?;
45        validate_pcurve_start_and_end(&face.surface, &pcurve_reversed, &p, &ce_end.point)
46            .with_context(&ctx)?;
47        validate_curve_start_and_end(&curve, &ce_end.point, &p).with_context(&ctx)?;
48
49        let v = self.insert_vertex(Vertex { point: p });
50        let edge_id = self.insert_edge(Edge {
51            curve: curve,
52            start_vertex: ce_end_id,
53            end_vertex: v,
54        });
55
56        let coedge_forward = self.insert_coedge(Coedge {
57            geometry: CoedgeGeometry::Edge(edge_id),
58            sense: Sense::Forward,
59            pcurve: pcurve,
60            next: CoedgeId(0), // set later
61            prev: coedge,
62            face: ce.face,
63        });
64
65        let coedge_reversed = self.insert_coedge(Coedge {
66            geometry: CoedgeGeometry::Edge(edge_id),
67            sense: Sense::Reversed,
68            pcurve: pcurve_reversed,
69            next: ce.next,     // set later
70            prev: CoedgeId(0), // set later
71            face: ce.face,
72        });
73
74        self.coedges.get_mut(&coedge_forward).unwrap().next = coedge_reversed;
75        self.coedges.get_mut(&coedge_reversed).unwrap().prev = coedge_forward;
76        self.coedges.get_mut(&coedge).unwrap().next = coedge_forward;
77        self.coedges.get_mut(&ce.next).unwrap().prev = coedge_reversed;
78
79        Ok((v, coedge_forward, coedge_reversed, edge_id))
80    }
81
82    // Add a new edge between the vertex and the new vertex `p`.
83    // Curve and pcurve must go from the existing vertex to the new vertex `p`.
84    // PCurve reversed must go from the new vertex `p` to the existing vertex.
85    // returns (new vertex, coedge_forward -> p, coedge_reversed <- p, new edge)
86    pub fn mve_from_vertex(
87        self: &mut Model<S>,
88        face_id: FaceId,
89        vertex: VertexId,
90        curve: NurbCurve3D<S>,
91        pcurve: NurbCurve2D<S>,
92        pcurve_reversed: NurbCurve2D<S>,
93        p: Vector3<S>,
94    ) -> GeopResult<(VertexId, CoedgeId, CoedgeId, EdgeId)> {
95        let face = self.get_face(face_id)?.clone();
96        let ce_end = self.get_vertex(vertex)?.clone();
97        validate_pcurve_start_and_end(&face.surface, &pcurve, &ce_end.point, &p)?;
98        validate_pcurve_start_and_end(&face.surface, &pcurve_reversed, &p, &ce_end.point)?;
99        validate_curve_start_and_end(&curve, &ce_end.point, &p)?;
100
101        let v = self.insert_vertex(Vertex { point: p });
102        let edge_id = self.insert_edge(Edge {
103            curve: curve,
104            start_vertex: vertex,
105            end_vertex: v,
106        });
107
108        let coedge_forward = self.insert_coedge(Coedge {
109            geometry: CoedgeGeometry::Edge(edge_id),
110            sense: Sense::Forward,
111            pcurve: pcurve,
112            next: CoedgeId(0), // set later
113            prev: CoedgeId(0), // set later
114            face: face_id,
115        });
116
117        let coedge_reversed = self.insert_coedge(Coedge {
118            geometry: CoedgeGeometry::Edge(edge_id),
119            sense: Sense::Reversed,
120            pcurve: pcurve_reversed,
121            next: CoedgeId(0), // set later
122            prev: CoedgeId(0), // set later
123            face: face_id,
124        });
125
126        self.coedges.get_mut(&coedge_forward).unwrap().next = coedge_reversed;
127        self.coedges.get_mut(&coedge_reversed).unwrap().prev = coedge_forward;
128        self.coedges.get_mut(&coedge_forward).unwrap().prev = coedge_reversed;
129        self.coedges.get_mut(&coedge_reversed).unwrap().next = coedge_forward;
130
131        // remove this vertex from the face boundary if it was there
132        let face = self.get_face_mut(face_id)?;
133        let is_this_vertex =
134            |b: &BoundaryType| matches!(b, BoundaryType::Vertex(v_id) if *v_id == vertex);
135        if is_this_vertex(&face.outer) {
136            face.outer = BoundaryType::Loop(coedge_reversed);
137        } else if let Some(hole) = face.holes.iter_mut().find(|b| is_this_vertex(b)) {
138            *hole = BoundaryType::Loop(coedge_reversed);
139        }
140
141        Ok((v, coedge_forward, coedge_reversed, edge_id))
142    }
143}