1mod get;
6mod insert;
7mod iter;
8mod merge;
9mod remove;
10mod split;
11mod track;
12mod triangulate;
13mod walkers;
14
15#[cfg(test)]
16pub mod test_common;
17
18#[cfg(feature = "stable-vec")]
19mod stable_vec;
20
21#[cfg(feature = "stable-vec")]
22pub use stable_vec::StableDcel;
23
24#[cfg(feature = "rstar")]
25mod rstar;
26
27#[cfg(feature = "rstar")]
28pub use rstar::{RTreedDcel, RTreedStableDcel};
29
30use maplike::{Get, Insert, Push};
31
32pub use walkers::{
33 HalfSpokesIter, HalfSpokesReverseIter, HalfSpokesReverseWalker, HalfSpokesWalker, SpokesIter,
34 SpokesReverseIter, SpokesReverseWalker, SpokesWalker,
35};
36
37#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
38pub struct VertexId(usize);
39
40impl VertexId {
41 #[inline]
42 pub fn new(id: usize) -> Self {
43 Self(id)
44 }
45
46 #[inline]
47 pub fn id(self) -> usize {
48 self.0
49 }
50}
51
52#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
53pub struct HalfEdgeId(usize);
54
55impl HalfEdgeId {
56 #[inline]
57 pub fn new(id: usize) -> Self {
58 Self(id)
59 }
60
61 #[inline]
62 pub fn id(self) -> usize {
63 self.0
64 }
65}
66
67#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
68pub struct EdgeId(HalfEdgeId, HalfEdgeId);
69
70impl EdgeId {
71 #[inline]
72 pub(crate) fn new(half_edge1: HalfEdgeId, half_edge2: HalfEdgeId) -> EdgeId {
73 Self(
74 std::cmp::min(half_edge1, half_edge2),
75 std::cmp::max(half_edge1, half_edge2),
76 )
77 }
78
79 #[inline]
80 pub fn lesser(self) -> HalfEdgeId {
81 self.0
82 }
83
84 #[inline]
85 pub fn greater(self) -> HalfEdgeId {
86 self.1
87 }
88}
89
90#[derive(Clone, Copy, Debug, Eq, PartialEq)]
91pub struct FaceId(usize);
92
93impl FaceId {
94 #[inline]
95 pub fn new(id: usize) -> Self {
96 Self(id)
97 }
98
99 #[inline]
100 pub fn id(self) -> usize {
101 self.0
102 }
103}
104
105#[derive(Clone, Debug)]
106pub struct Vertex<VW> {
107 outgoing_next_half_edge: HalfEdgeId,
108 weight: VW,
109}
110
111#[derive(Clone, Debug)]
112pub struct HalfEdge<HEW> {
113 origin: VertexId,
114 twin: HalfEdgeId,
115 prev: HalfEdgeId,
116 next: HalfEdgeId,
117 face: FaceId,
118 weight: HEW,
119}
120
121#[derive(Clone, Debug)]
122pub struct Face<FW> {
123 incident_half_edge: Option<HalfEdgeId>,
124 weight: FW,
125}
126
127#[derive(Clone, Debug)]
128pub struct Dcel<
129 VW,
130 HEW = (),
131 FW = (),
132 VC = Vec<Vertex<VW>>,
133 HEC = Vec<HalfEdge<HEW>>,
134 FC = Vec<Face<FW>>,
135> {
136 vertexes: VC,
137 half_edges: HEC,
138 faces: FC,
139 vertex_weight_marker: std::marker::PhantomData<VW>,
140 half_edge_weight_marker: std::marker::PhantomData<HEW>,
141 face_weight_marker: std::marker::PhantomData<FW>,
142}
143
144impl<VW, HEW, FW: Default, VC: Default, HEC: Default, FC: Default + Push<usize, Value = Face<FW>>>
145 Dcel<VW, HEW, FW, VC, HEC, FC>
146{
147 #[inline]
148 pub fn new() -> Self {
149 let mut faces = FC::default();
150
151 faces.push(Face {
153 incident_half_edge: None,
154 weight: FW::default(),
155 });
156
157 Self {
158 vertexes: VC::default(),
159 half_edges: HEC::default(),
160 faces,
161 vertex_weight_marker: std::marker::PhantomData,
162 half_edge_weight_marker: std::marker::PhantomData,
163 face_weight_marker: std::marker::PhantomData,
164 }
165 }
166}
167
168impl<VW, HEW, FW: Default, VC: Default, HEC: Default, FC: Default + Push<usize, Value = Face<FW>>>
169 Default for Dcel<VW, HEW, FW, VC, HEC, FC>
170{
171 #[inline]
172 fn default() -> Self {
173 Self::new()
174 }
175}
176
177impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
178 #[inline]
179 pub fn from_collections(vertexes: VC, half_edges: HEC, faces: FC) -> Self {
180 Self {
181 vertexes,
182 half_edges,
183 faces,
184 vertex_weight_marker: std::marker::PhantomData,
185 half_edge_weight_marker: std::marker::PhantomData,
186 face_weight_marker: std::marker::PhantomData,
187 }
188 }
189}
190
191impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC>
192where
193 for<'a> &'a VC: IntoIterator<Item = &'a usize>,
194{
195 #[inline]
196 pub fn vertex_ids(&self) -> impl Iterator<Item = VertexId> {
197 self.vertexes.into_iter().map(|id| VertexId(*id))
198 }
199}
200
201impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC>
202where
203 for<'a> &'a HEC: IntoIterator<Item = &'a usize>,
204{
205 #[inline]
206 pub fn half_edge_ids(&self) -> impl Iterator<Item = HalfEdgeId> {
207 self.half_edges.into_iter().map(|id| HalfEdgeId(*id))
208 }
209}
210
211impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC>
212where
213 for<'a> &'a FC: IntoIterator<Item = &'a usize>,
214{
215 #[inline]
216 pub fn face_ids(&self) -> impl Iterator<Item = FaceId> {
217 self.faces.into_iter().map(|id| FaceId(*id))
218 }
219}
220
221impl<
222 VW: Clone,
223 HEW: Clone,
224 FW: Clone,
225 VC: Get<usize, Value = Vertex<VW>> + Insert<usize>,
226 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize>,
227 FC: Get<usize, Value = Face<FW>> + Insert<usize>,
228> Dcel<VW, HEW, FW, VC, HEC, FC>
229{
230 fn wire_inner_half_edge_chain(&mut self, face: FaceId, half_edges: &[HalfEdgeId]) {
231 let half_edges_circular_tuple_windows = half_edges
232 .iter()
233 .zip(half_edges.iter().skip(1).chain(half_edges.iter().take(1)));
234
235 for (&half_edge, &next_half_edge) in half_edges_circular_tuple_windows {
236 self.link_vertex_with_half_edge(self.origin(half_edge), half_edge);
237 self.link_subsequent_half_edges(half_edge, next_half_edge);
238 self.link_face_with_half_edge(face, half_edge);
239 }
240 }
241
242 fn wire_outer_half_edge_chain_circularly(&mut self, outer_half_edges: &[HalfEdgeId]) {
243 let outer_half_edges_circular_tuple_windows = outer_half_edges.iter().zip(
244 outer_half_edges
245 .iter()
246 .skip(1)
247 .chain(outer_half_edges.iter().take(1)),
248 );
249
250 for (&outer_half_edge, &next_outer_half_edge) in outer_half_edges_circular_tuple_windows {
251 self.link_subsequent_half_edges(outer_half_edge, next_outer_half_edge);
252 }
253 }
254
255 fn wire_outer_half_edge_chain_adjoiningly(
256 &mut self,
257 outer_face: FaceId,
258 outer_half_edges: &[HalfEdgeId],
259 ) {
260 let outer_half_edges_circular_tuple_windows = outer_half_edges.iter().zip(
261 outer_half_edges
262 .iter()
263 .skip(1)
264 .chain(outer_half_edges.iter().take(1)),
265 );
266
267 for (&outer_half_edge, &next_outer_half_edge) in outer_half_edges_circular_tuple_windows {
268 let is_edge_outward = self.face_in_front(outer_half_edge) == outer_face;
269 let is_next_edge_outward = self.face_in_front(next_outer_half_edge) == outer_face;
270
271 if is_edge_outward && is_next_edge_outward {
272 self.link_subsequent_half_edges(next_outer_half_edge, outer_half_edge);
273 } else if !is_edge_outward && is_next_edge_outward {
274 self.link_subsequent_half_edges(
275 next_outer_half_edge,
276 self.turn_half_edge(outer_half_edge),
277 );
278 } else if is_edge_outward && !is_next_edge_outward {
279 self.link_subsequent_half_edges(
280 self.twin(self.turn_back_half_edge(self.twin(next_outer_half_edge))),
281 outer_half_edge,
282 );
283 } else {
284 }
287 }
288 }
289}
290
291impl<VW, HEW, FW, VC: Push<usize, Value = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
292 fn add_unwired_vertex(&mut self, weight: VW) -> VertexId {
293 VertexId(self.vertexes.push(Vertex {
294 outgoing_next_half_edge: HalfEdgeId(0),
299 weight,
300 }))
301 }
302}
303
304impl<VW: Clone, HEW, FW, VC: Get<usize, Value = Vertex<VW>> + Insert<usize>, HEC, FC>
305 Dcel<VW, HEW, FW, VC, HEC, FC>
306{
307 fn link_vertex_with_half_edge(&mut self, vertex: VertexId, outgoing_half_edge: HalfEdgeId) {
308 self.vertexes.insert(
309 vertex.id(),
310 Vertex {
311 outgoing_next_half_edge: outgoing_half_edge,
312 weight: self.vertexes.get(&vertex.id()).unwrap().weight.clone(),
313 },
314 )
315 }
316}
317
318impl<VW, HEW: Clone, FW, VC, HEC: Insert<usize, Value = HalfEdge<HEW>> + Push<usize>, FC>
319 Dcel<VW, HEW, FW, VC, HEC, FC>
320{
321 fn add_unwired_edge(
322 &mut self,
323 origin: VertexId,
324 twin_origin: VertexId,
325 face: FaceId,
326 twin_face: FaceId,
327 weight: HEW,
328 twin_weight: HEW,
329 ) -> (HalfEdgeId, HalfEdgeId) {
330 let forward_half_edge = HalfEdgeId(self.half_edges.push(HalfEdge {
331 origin,
332 twin: HalfEdgeId(0),
334 prev: HalfEdgeId(0),
337 next: HalfEdgeId(0),
338 face,
339 weight: weight.clone(),
340 }));
341
342 let backward_half_edge = HalfEdgeId(self.half_edges.push(HalfEdge {
343 origin: twin_origin,
344 twin: forward_half_edge,
345 prev: HalfEdgeId(0),
348 next: HalfEdgeId(0),
349 face: twin_face,
350 weight: twin_weight,
351 }));
352
353 self.half_edges.insert(
357 forward_half_edge.id(),
358 HalfEdge {
359 origin,
360 twin: backward_half_edge,
362 prev: HalfEdgeId(0),
365 next: HalfEdgeId(0),
366 face,
367 weight,
368 },
369 );
370
371 (forward_half_edge, backward_half_edge)
372 }
373}
374
375impl<VW, HEW: Clone, FW, VC, HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize>, FC>
376 Dcel<VW, HEW, FW, VC, HEC, FC>
377{
378 fn link_subsequent_half_edges(&mut self, half_edge: HalfEdgeId, next_half_edge: HalfEdgeId) {
379 self.half_edges.insert(
380 half_edge.id(),
381 HalfEdge {
382 next: next_half_edge,
383 ..self.half_edges.get(&half_edge.id()).unwrap().clone()
384 },
385 );
386 self.half_edges.insert(
387 next_half_edge.id(),
388 HalfEdge {
389 prev: half_edge,
390 ..self.half_edges.get(&next_half_edge.id()).unwrap().clone()
391 },
392 );
393 }
394}
395
396impl<VW, HEW, FW, VC, HEC, FC: Push<usize, Value = Face<FW>>> Dcel<VW, HEW, FW, VC, HEC, FC> {
397 fn add_unwired_face(&mut self, weight: FW) -> FaceId {
398 FaceId(self.faces.push(Face {
399 incident_half_edge: None,
400 weight,
401 }))
402 }
403}
404
405impl<
406 VW,
407 HEW: Clone,
408 FW: Clone,
409 VC,
410 HEC: Get<usize, Value = HalfEdge<HEW>> + Insert<usize>,
411 FC: Get<usize, Value = Face<FW>> + Insert<usize>,
412> Dcel<VW, HEW, FW, VC, HEC, FC>
413{
414 fn link_face_with_half_edge(&mut self, face: FaceId, half_edge: HalfEdgeId) {
415 self.half_edges.insert(
416 half_edge.id(),
417 HalfEdge {
418 face,
419 ..self.half_edges.get(&half_edge.id()).unwrap().clone()
420 },
421 );
422 self.faces.insert(
423 face.id(),
424 Face {
425 incident_half_edge: Some(half_edge),
426 weight: self.faces.get(&face.id()).unwrap().weight.clone(),
427 },
428 );
429 }
430}