mesh_graph/ops/add/
edge.rs1use tracing::{error, instrument};
2
3use crate::{Halfedge, HalfedgeId, MeshGraph, VertexId, error_none};
4
5impl MeshGraph {
6 #[instrument(skip(self))]
12 pub fn add_or_get_edge(
13 &mut self,
14 start_vertex_id: VertexId,
15 end_vertex_id: VertexId,
16 ) -> Option<AddOrGetEdge> {
17 let ret = match self.add_or_get_edge_inner(start_vertex_id, end_vertex_id) {
18 Some(ret) => ret,
19 None => {
20 let start_to_end_he_id = self.add_halfedge(start_vertex_id, end_vertex_id)?;
21 let twin_he_id = self.add_halfedge(end_vertex_id, start_vertex_id)?;
22
23 AddOrGetEdge {
24 start_to_end_he_id,
25 twin_he_id,
26 new_start_to_end: true,
27 new_twin: true,
28 }
29 }
30 };
31
32 self.halfedges[ret.start_to_end_he_id].twin = Some(ret.twin_he_id);
34 self.halfedges[ret.twin_he_id].twin = Some(ret.start_to_end_he_id);
35
36 let start_v = self
37 .vertices
38 .get_mut(start_vertex_id)
39 .or_else(error_none!("Vertex not found"))?;
40 start_v.outgoing_halfedge = Some(ret.start_to_end_he_id);
41
42 let end_v = self
43 .vertices
44 .get_mut(end_vertex_id)
45 .or_else(error_none!("Vertex not found"))?;
46 end_v.outgoing_halfedge = Some(ret.twin_he_id);
47
48 Some(ret)
49 }
50
51 pub fn add_or_get_boundary_edge(
57 &mut self,
58 start_vertex_id: VertexId,
59 end_vertex_id: VertexId,
60 ) -> Option<AddOrGetEdge> {
61 let existing_he_ids = self.halfedges_from_to(start_vertex_id, end_vertex_id);
62 if let Some(he_id) = existing_he_ids.into_iter().find(|he_id| {
63 let he = &self.halfedges[*he_id];
65 he.is_boundary() && he.twin.is_some()
66 }) {
67 let he = self.halfedges[he_id];
69
70 return Some(AddOrGetEdge {
71 start_to_end_he_id: he_id,
72 twin_he_id: he.twin.unwrap(), new_start_to_end: false,
74 new_twin: false,
75 });
76 }
77
78 let AddEdge {
79 start_to_end_he_id,
80 twin_he_id,
81 } = self.add_edge(start_vertex_id, end_vertex_id)?;
82
83 Some(AddOrGetEdge {
84 start_to_end_he_id,
85 twin_he_id,
86 new_start_to_end: true,
87 new_twin: true,
88 })
89 }
90
91 fn add_or_get_edge_inner(
92 &mut self,
93 start_vertex_id: VertexId,
94 end_vertex_id: VertexId,
95 ) -> Option<AddOrGetEdge> {
96 let mut he1_id = self.halfedge_from_to(start_vertex_id, end_vertex_id);
97 let mut he2_id = self.halfedge_from_to(end_vertex_id, start_vertex_id);
98 let mut new1 = false;
99 let mut new2 = false;
100
101 match (he1_id, he2_id) {
102 (Some(h1_id), Some(h2_id)) => {
103 let h1 = self
104 .halfedges
105 .get(h1_id)
106 .or_else(error_none!("Halfedge not found"))?;
107
108 let h2 = self
109 .halfedges
110 .get(h2_id)
111 .or_else(error_none!("Halfedge not found"))?;
112
113 if h1.twin != Some(h2_id) || h2.twin != Some(h1_id) {
114 error!("Halfedge twins are not consistent.");
115 }
116 }
117 (Some(_h1_id), None) => {
118 he2_id = Some(self.add_halfedge(end_vertex_id, start_vertex_id)?);
119 new2 = true;
120 }
121 (None, Some(_h2_id)) => {
122 he1_id = Some(self.add_halfedge(start_vertex_id, end_vertex_id)?);
123 new1 = true;
124 }
125 (None, None) => {
126 return None;
128 }
129 }
130
131 let start_to_end_he_id = he1_id.unwrap();
133 let twin_he_id = he2_id.unwrap();
134
135 Some(AddOrGetEdge {
136 start_to_end_he_id,
137 twin_he_id,
138 new_start_to_end: new1,
139 new_twin: new2,
140 })
141 }
142
143 pub fn add_edge(&mut self, start_vertex: VertexId, end_vertex: VertexId) -> Option<AddEdge> {
148 if !self.vertices.contains_key(start_vertex) || !self.vertices.contains_key(end_vertex) {
153 error!("add_edge: start {start_vertex:?} or end {end_vertex:?} vertex not found");
154 return None;
155 }
156
157 let start_to_end_he_id = self.add_halfedge(start_vertex, end_vertex)?;
158 let twin_he_id = self.add_halfedge(end_vertex, start_vertex)?;
159
160 self.halfedges[start_to_end_he_id].twin = Some(twin_he_id);
162 self.halfedges[twin_he_id].twin = Some(start_to_end_he_id);
163
164 self.vertices[start_vertex].outgoing_halfedge = Some(start_to_end_he_id);
166 self.vertices[end_vertex].outgoing_halfedge = Some(twin_he_id);
167
168 Some(AddEdge {
169 start_to_end_he_id,
170 twin_he_id,
171 })
172 }
173
174 #[instrument(skip(self))]
181 pub fn add_halfedge(
182 &mut self,
183 start_vertex: VertexId,
184 end_vertex: VertexId,
185 ) -> Option<HalfedgeId> {
186 let halfedge = Halfedge {
187 end_vertex,
188 next: None,
189 twin: None,
190 face: None,
191 };
192 let he_id = self.halfedges.insert(halfedge);
193
194 self.outgoing_halfedges
195 .entry(start_vertex)
196 .or_else(error_none!("Start vertex not found {start_vertex:?}"))?
197 .or_default()
198 .push(he_id);
199
200 Some(he_id)
201 }
202}
203
204pub struct AddOrGetEdge {
206 pub start_to_end_he_id: HalfedgeId,
208 pub twin_he_id: HalfedgeId,
210 pub new_start_to_end: bool,
212 pub new_twin: bool,
214}
215
216impl AddOrGetEdge {
217 pub fn created_he_ids(&self) -> Vec<HalfedgeId> {
219 let mut he_ids = vec![];
220 if self.new_start_to_end {
221 he_ids.push(self.start_to_end_he_id);
222 }
223 if self.new_twin {
224 he_ids.push(self.twin_he_id);
225 }
226 he_ids
227 }
228}
229
230pub struct AddEdge {
232 pub start_to_end_he_id: HalfedgeId,
234 pub twin_he_id: HalfedgeId,
236}