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 let start_to_end_he_id = self.add_halfedge(start_vertex, end_vertex)?;
149 let twin_he_id = self.add_halfedge(end_vertex, start_vertex)?;
150
151 self.halfedges[start_to_end_he_id].twin = Some(twin_he_id);
153 self.halfedges[twin_he_id].twin = Some(start_to_end_he_id);
154
155 self.vertices[start_vertex].outgoing_halfedge = Some(start_to_end_he_id);
157 self.vertices[end_vertex].outgoing_halfedge = Some(twin_he_id);
158
159 Some(AddEdge {
160 start_to_end_he_id,
161 twin_he_id,
162 })
163 }
164
165 #[instrument(skip(self))]
172 pub fn add_halfedge(
173 &mut self,
174 start_vertex: VertexId,
175 end_vertex: VertexId,
176 ) -> Option<HalfedgeId> {
177 let halfedge = Halfedge {
178 end_vertex,
179 next: None,
180 twin: None,
181 face: None,
182 };
183 let he_id = self.halfedges.insert(halfedge);
184
185 self.outgoing_halfedges
186 .entry(start_vertex)
187 .or_else(error_none!("Start vertex not found {start_vertex:?}"))?
188 .or_default()
189 .push(he_id);
190
191 Some(he_id)
192 }
193}
194
195pub struct AddOrGetEdge {
197 pub start_to_end_he_id: HalfedgeId,
199 pub twin_he_id: HalfedgeId,
201 pub new_start_to_end: bool,
203 pub new_twin: bool,
205}
206
207impl AddOrGetEdge {
208 pub fn created_he_ids(&self) -> Vec<HalfedgeId> {
210 let mut he_ids = vec![];
211 if self.new_start_to_end {
212 he_ids.push(self.start_to_end_he_id);
213 }
214 if self.new_twin {
215 he_ids.push(self.twin_he_id);
216 }
217 he_ids
218 }
219}
220
221pub struct AddEdge {
223 pub start_to_end_he_id: HalfedgeId,
225 pub twin_he_id: HalfedgeId,
227}