geop_core_topology/euler/
mef.rs1use crate::{
2 Coedge, CoedgeGeometry, CoedgeId, Edge, EdgeId, Face, FaceId, Model, Sense,
3 argument_validation::{
4 validate_curve_start_and_end, validate_pcurve_start_and_end, validate_same_loop,
5 },
6 boundary::BoundaryType,
7};
8use geop_core_geometry::{
9 nurb_curve::{NurbCurve2D, NurbCurve3D},
10 nurb_surface::NurbSurface3D,
11};
12use geop_core_math::{
13 geop_error::{GeopError, GeopResult, WithContext},
14 scalars::Scalar,
15 with_context,
16};
17
18impl<S: Scalar> Model<S> {
19 pub fn mef(
27 self: &mut Model<S>,
28 coedge1: CoedgeId,
29 coedge2: CoedgeId,
30 curve: NurbCurve3D<S>,
31 pcurve: NurbCurve2D<S>,
32 pcurve_reversed: NurbCurve2D<S>,
33 new_surface: NurbSurface3D<S>,
34 ) -> GeopResult<(EdgeId, FaceId, CoedgeId, CoedgeId)> {
35 let ctx = |e: GeopError| {
36 e.with_context(format!(
37 "Model::mef(
38 coedge1={coedge1}
39 coedge2={coedge2}
40 curve={curve}
41 pcurve={pcurve}
42 pcurve_reversed={pcurve_reversed}
43 new_surface={new_surface}"
44 ))
45 };
46
47 let ce1 = self.get_coedge(coedge1)?.clone();
48 let ce2 = self.get_coedge(coedge2)?.clone();
49 validate_same_loop(self, coedge1, coedge2)?;
50 let old_face_id = ce1.face;
51 let old_face = self.get_face(old_face_id)?.clone();
52
53 let start = self
54 .get_vertex(self.coedge_end_vertex_id(coedge1)?)?
55 .clone()
56 .point;
57 let end = self
58 .get_vertex(self.coedge_start_vertex_id(coedge2)?)?
59 .clone()
60 .point;
61
62 validate_pcurve_start_and_end(&new_surface, &pcurve, &start, &end)
63 .with_context("initial arg validation")
64 .with_context(&ctx)?;
65 validate_pcurve_start_and_end(&old_face.surface, &pcurve_reversed, &end, &start)
66 .with_context("initial arg validation")
67 .with_context(&ctx)?;
68 validate_curve_start_and_end(&curve, &start, &end)
69 .with_context("initial arg validation")
70 .with_context(&ctx)?;
71
72 let old_boundary_idx = self
81 .find_boundary_containing(old_face_id, coedge1)
82 .with_context(&ctx)?;
83
84 let mut ring_members = vec![coedge2];
86 while *ring_members.last().unwrap() != coedge1 {
87 ring_members.push(self.get_coedge(*ring_members.last().unwrap())?.next);
88 }
89 for &member in &ring_members {
90 let c = self.get_coedge(member)?.clone();
91 let sp = self.coedge_start_vertex(member)?.point;
92 let ep = self.coedge_end_vertex(member)?.point;
93 validate_pcurve_start_and_end(&new_surface, &c.pcurve, &sp, &ep)
94 .with_context(with_context!("reassigning coedge {member} to new face"))
95 .with_context(&ctx)?;
96 }
97
98 let edge_id = self.insert_edge(Edge {
100 curve,
101 start_vertex: self.coedge_end_vertex_id(coedge1)?,
102 end_vertex: self.coedge_start_vertex_id(coedge2)?,
103 });
104 let next1 = ce1.next;
105 let prev2 = ce2.prev;
106
107 let coedge_forward = self.insert_coedge(Coedge {
109 geometry: CoedgeGeometry::Edge(edge_id),
110 sense: Sense::Forward,
111 pcurve: pcurve,
112 next: coedge2,
113 prev: coedge1,
114 face: ce1.face, });
116
117 let coedge_backward = self.insert_coedge(Coedge {
119 geometry: CoedgeGeometry::Edge(edge_id),
120 sense: Sense::Reversed,
121 pcurve: pcurve_reversed,
122 next: next1,
123 prev: prev2,
124 face: ce1.face,
125 });
126
127 self.coedges.get_mut(&coedge1).unwrap().next = coedge_forward;
128 self.coedges.get_mut(&coedge2).unwrap().prev = coedge_forward;
129 self.coedges.get_mut(&prev2).unwrap().next = coedge_backward;
130 self.coedges.get_mut(&next1).unwrap().prev = coedge_backward;
131
132 let new_face_id = self.insert_face(Face {
134 surface: new_surface,
135 outer: BoundaryType::Loop(coedge2),
136 holes: Vec::new(),
137 shell: old_face.shell,
138 });
139 self.shells
140 .get_mut(&old_face.shell)
141 .unwrap()
142 .faces
143 .push(new_face_id);
144
145 self.coedges.get_mut(&coedge_forward).unwrap().face = new_face_id;
147 for &member in &ring_members {
148 self.coedges.get_mut(&member).unwrap().face = new_face_id;
149 }
150
151 self.faces
169 .get_mut(&old_face_id)
170 .unwrap()
171 .set_boundary(old_boundary_idx, BoundaryType::Loop(next1));
172
173 Ok((edge_id, new_face_id, coedge_forward, coedge_backward))
174 }
175}