geop_core_topology/euler/
mekr.rs1use crate::{
2 Coedge, CoedgeGeometry, CoedgeId, Edge, EdgeId, Model, Sense,
3 argument_validation::{
4 validate_curve_start_and_end, validate_different_loop, validate_pcurve_start_and_end,
5 },
6};
7use geop_core_geometry::nurb_curve::{NurbCurve2D, NurbCurve3D};
8use geop_core_math::{
9 geop_error::{GeopError, GeopResult, WithContext},
10 scalars::Scalar,
11};
12
13impl<S: Scalar> Model<S> {
14 pub fn mekr(
23 self: &mut Model<S>,
24 coedge1: CoedgeId,
25 coedge2: CoedgeId,
26 curve: NurbCurve3D<S>,
27 pcurve: NurbCurve2D<S>,
28 ) -> GeopResult<(EdgeId, CoedgeId, CoedgeId)> {
29 let ctx = |e: GeopError| {
30 e.with_context(format!(
31 "Model::mekr(
32 coedge1={coedge1}
33 coedge2={coedge2}
34 curve={curve}
35 pcurve={pcurve}
36)"
37 ))
38 };
39
40 let ce1 = self.get_coedge(coedge1)?.clone();
41 let ce2 = self.get_coedge(coedge2)?.clone();
42 if ce1.face != ce2.face {
43 return Err(ctx(GeopError::new(
44 "coedge1 and coedge2 must belong to the same face",
45 )));
46 }
47 validate_different_loop(&self, coedge1, coedge2).with_context(&ctx)?;
48 let face = self.get_face(ce1.face)?.clone();
49
50 let start_id = self.coedge_end_vertex_id(coedge1)?;
51 let end_id = self.coedge_start_vertex_id(coedge2)?;
52 let start = self.get_vertex(start_id)?.clone();
53 let end = self.get_vertex(end_id)?.clone();
54
55 validate_pcurve_start_and_end(&face.surface, &pcurve, &start.point, &end.point)
56 .with_context(&ctx)?;
57 validate_curve_start_and_end(&curve, &start.point, &end.point).with_context(&ctx)?;
58
59 let killed_ring_index = self
62 .find_boundary_containing(ce1.face, coedge2)
63 .with_context(&ctx)?;
64
65 let edge_id = self.insert_edge(Edge {
66 curve,
67 start_vertex: start_id,
68 end_vertex: end_id,
69 });
70
71 let reversed_pcurve = pcurve.reverse();
72 let next1 = ce1.next;
73 let prev2 = ce2.prev;
74
75 let coedge_a = self.insert_coedge(Coedge {
77 geometry: CoedgeGeometry::Edge(edge_id),
78 sense: Sense::Forward,
79 pcurve,
80 next: coedge2,
81 prev: coedge1,
82 face: ce1.face,
83 });
84
85 let coedge_b = self.insert_coedge(Coedge {
87 geometry: CoedgeGeometry::Edge(edge_id),
88 sense: Sense::Reversed,
89 pcurve: reversed_pcurve,
90 next: next1,
91 prev: prev2,
92 face: ce1.face,
93 });
94
95 self.coedges.get_mut(&coedge1).unwrap().next = coedge_a;
96 self.coedges.get_mut(&coedge2).unwrap().prev = coedge_a;
97 self.coedges.get_mut(&prev2).unwrap().next = coedge_b;
98 self.coedges.get_mut(&next1).unwrap().prev = coedge_b;
99
100 self.remove_boundary(ce1.face, killed_ring_index)
107 .with_context(&|e: GeopError| {
108 e.with_context(format!(
109 "mekr(coedge1={coedge1}, coedge2={coedge2}): absorbing the ring containing coedge2"
110 ))
111 })?;
112
113 Ok((edge_id, coedge_a, coedge_b))
114 }
115}