dcel/
lib.rs

1// SPDX-FileCopyrightText: 2026 dcel contributors
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5mod iter;
6mod triangulate;
7
8pub use iter::{
9    CcwEdgesIter, CcwEdgesWalker, CcwHalfEdgesIter, CcwHalfEdgesWalker, CwEdgesIter, CwEdgesWalker,
10    CwHalfEdgesIter, CwHalfEdgesWalker, FaceEdgesIter, FaceEdgesWalker, FaceHalfEdgesIter,
11    FaceHalfEdgesWalker,
12};
13use maplike::{Get, Insert, Push, Remove};
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct VertexId(usize);
17
18impl VertexId {
19    #[inline]
20    pub fn id(self) -> usize {
21        self.0
22    }
23}
24
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub struct HalfEdgeId(usize);
27
28impl HalfEdgeId {
29    #[inline]
30    pub fn id(self) -> usize {
31        self.0
32    }
33}
34
35#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub struct EdgeId(HalfEdgeId, HalfEdgeId);
37
38impl EdgeId {
39    #[inline]
40    pub fn forward(self) -> HalfEdgeId {
41        self.0
42    }
43
44    #[inline]
45    pub fn backward(self) -> HalfEdgeId {
46        self.1
47    }
48}
49
50#[derive(Clone, Copy, Debug, Eq, PartialEq)]
51pub struct FaceId(usize);
52
53impl FaceId {
54    #[inline]
55    pub fn id(self) -> usize {
56        self.0
57    }
58}
59
60#[derive(Clone, Debug)]
61pub struct Vertex<VW> {
62    outgoing_next_half_edge: HalfEdgeId,
63    weight: VW,
64}
65
66#[derive(Clone, Debug)]
67pub struct HalfEdge<HEW> {
68    origin: VertexId,
69    twin: HalfEdgeId,
70    prev: HalfEdgeId,
71    next: HalfEdgeId,
72    face: FaceId,
73    weight: HEW,
74}
75
76#[derive(Clone, Debug)]
77pub struct Face<FW> {
78    incident_half_edge: Option<HalfEdgeId>,
79    weight: FW,
80}
81
82#[derive(Clone, Debug)]
83pub struct Dcel<
84    VW,
85    HEW = (),
86    FW = (),
87    VC = Vec<Vertex<VW>>,
88    HEC = Vec<HalfEdge<HEW>>,
89    FC = Vec<Face<FW>>,
90> {
91    vertexes: VC,
92    half_edges: HEC,
93    faces: FC,
94    vertex_weight_marker: std::marker::PhantomData<VW>,
95    half_edge_weight_marker: std::marker::PhantomData<HEW>,
96    face_weight_marker: std::marker::PhantomData<FW>,
97}
98
99impl<VW, HEW, FW: Default, VC: Default, HEC: Default, FC: Default + Push<usize, Item = FW>>
100    Dcel<VW, HEW, FW, VC, HEC, FC>
101{
102    #[inline]
103    pub fn new() -> Self {
104        let mut faces = FC::default();
105
106        // Push the outermost face.
107        faces.push(FW::default());
108
109        Self {
110            vertexes: VC::default(),
111            half_edges: HEC::default(),
112            faces,
113            vertex_weight_marker: std::marker::PhantomData,
114            half_edge_weight_marker: std::marker::PhantomData,
115            face_weight_marker: std::marker::PhantomData,
116        }
117    }
118}
119
120impl<VW, HEW, FW: Default, VC: Default, HEC: Default, FC: Default + Push<usize, Item = FW>> Default
121    for Dcel<VW, HEW, FW, VC, HEC, FC>
122{
123    #[inline]
124    fn default() -> Self {
125        Self::new()
126    }
127}
128
129impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
130    #[inline]
131    pub fn from_parts(vertexes: VC, half_edges: HEC, faces: FC) -> Self {
132        Self {
133            vertexes,
134            half_edges,
135            faces,
136            vertex_weight_marker: std::marker::PhantomData,
137            half_edge_weight_marker: std::marker::PhantomData,
138            face_weight_marker: std::marker::PhantomData,
139        }
140    }
141}
142
143impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
144    #[inline]
145    pub fn vertexes(&self) -> &VC {
146        &self.vertexes
147    }
148
149    #[inline]
150    pub fn half_edges(&self) -> &HEC {
151        &self.half_edges
152    }
153
154    #[inline]
155    pub fn faces(&self) -> &FC {
156        &self.faces
157    }
158
159    #[inline]
160    pub fn dissolve(self) -> (VC, HEC, FC) {
161        (self.vertexes, self.half_edges, self.faces)
162    }
163}
164
165impl<
166    VW: Clone,
167    HEW: Clone + Default,
168    FW: Clone + Default,
169    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Push<usize>,
170    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
171    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Push<usize>,
172> Dcel<VW, HEW, FW, VC, HEC, FC>
173{
174    pub fn insert_polygon(&mut self, vertex_weights: impl IntoIterator<Item = VW>) {
175        self.insert_polygon_in_face(self.unbounded_face(), vertex_weights);
176    }
177
178    pub fn insert_polygon_in_face(
179        &mut self,
180        target_face: FaceId,
181        vertex_weights: impl IntoIterator<Item = VW>,
182    ) {
183        self.insert_polygon_in_face_with_all_weights(
184            target_face,
185            vertex_weights,
186            std::iter::repeat((HEW::default(), HEW::default())),
187            FW::default(),
188        );
189    }
190}
191
192impl<
193    VW: Clone,
194    HEW: Clone,
195    FW: Clone,
196    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Push<usize>,
197    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
198    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Push<usize>,
199> Dcel<VW, HEW, FW, VC, HEC, FC>
200{
201    pub fn insert_polygon_with_all_weights(
202        &mut self,
203        vertex_weights: impl IntoIterator<Item = VW>,
204        edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
205        face_weight: FW,
206    ) {
207        self.insert_polygon_in_face_with_all_weights(
208            self.unbounded_face(),
209            vertex_weights,
210            edge_weights,
211            face_weight,
212        );
213    }
214
215    pub fn insert_polygon_in_face_with_all_weights(
216        &mut self,
217        outer_face: FaceId,
218        vertex_weights: impl IntoIterator<Item = VW>,
219        edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
220        face_weight: FW,
221    ) {
222        let new_face = self.add_unwired_face(face_weight);
223        let vertexes = self.add_unwired_polygon_vertexes(vertex_weights);
224        let edges = self.add_unwired_polygon_edges(&vertexes, new_face, outer_face, edge_weights);
225
226        self.wire_face_edges_vertexes(new_face, &edges);
227    }
228
229    fn add_unwired_polygon_vertexes(
230        &mut self,
231        vertex_weights: impl IntoIterator<Item = VW>,
232    ) -> Vec<VertexId> {
233        let vertexes: Vec<VertexId> = vertex_weights
234            .into_iter()
235            .map(|vertex_weight| self.add_unwired_vertex(vertex_weight))
236            .collect();
237
238        vertexes
239    }
240
241    fn add_unwired_polygon_edges(
242        &mut self,
243        vertexes: &[VertexId],
244        new_face: FaceId,
245        target_face: FaceId,
246        edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
247    ) -> Vec<EdgeId> {
248        let vertexes_circular_pair_windows = vertexes
249            .iter()
250            .zip(vertexes.iter().skip(1).chain(vertexes.iter().take(1)));
251
252        let mut edges = vec![];
253        let edge_weights: Vec<(HEW, HEW)> = edge_weights.into_iter().collect();
254
255        for ((from_vertex, to_vertex), (forward_half_edge_weight, backward_half_edge_weight)) in
256            vertexes_circular_pair_windows.zip(edge_weights.clone().into_iter())
257        {
258            let edge = self.add_unwired_edge(
259                *from_vertex,
260                *to_vertex,
261                new_face,
262                target_face,
263                forward_half_edge_weight,
264                backward_half_edge_weight,
265            );
266            edges.push(edge);
267        }
268
269        edges
270    }
271}
272
273impl<
274    VW: Clone,
275    HEW: Clone,
276    FW: Clone,
277    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Remove<usize>,
278    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Remove<usize>,
279    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Remove<usize>,
280> Dcel<VW, HEW, FW, VC, HEC, FC>
281{
282    pub fn merge_faces_around_vertex(&mut self, inner_vertex: VertexId) {
283        let absorbing_face = self.face_in_front(
284            self.vertexes
285                .get(&inner_vertex.id())
286                .unwrap()
287                .outgoing_next_half_edge,
288        );
289        self.absorb_faces_around_vertex(absorbing_face, inner_vertex);
290    }
291
292    pub fn absorb_faces_around_vertex(&mut self, absorbing_face: FaceId, inner_vertex: VertexId) {
293        let initial_half_edge = self
294            .vertexes
295            .get(&inner_vertex.id())
296            .unwrap()
297            .outgoing_next_half_edge;
298        let initial_edge = self.full_edge(
299            self.vertexes
300                .get(&inner_vertex.id())
301                .unwrap()
302                .outgoing_next_half_edge,
303        );
304        let inner_edges: Vec<EdgeId> = self.cw_edges(initial_edge).collect();
305        let perimeter_edges: Vec<EdgeId> = self
306            .edges_with_excludes(initial_edge, inner_edges.clone())
307            .collect();
308
309        self.remove_faces(
310            self.cw_faces(self.face_in_front(initial_half_edge))
311                .collect::<Vec<FaceId>>(),
312        );
313        self.remove_edges(inner_edges);
314        self.remove_vertex(inner_vertex);
315
316        self.wire_face_edges_vertexes(absorbing_face, &perimeter_edges);
317    }
318}
319
320impl<
321    VW: Clone,
322    HEW: Clone,
323    FW: Clone,
324    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Remove<usize>,
325    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Remove<usize>,
326    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Remove<usize>,
327> Dcel<VW, HEW, FW, VC, HEC, FC>
328{
329    pub fn merge_faces_over_edges_and_vertexes(
330        &mut self,
331        faces: impl IntoIterator<Item = FaceId>,
332        edges: impl IntoIterator<Item = EdgeId>,
333        vertexes: impl IntoIterator<Item = VertexId>,
334    ) {
335        let mut faces = faces.into_iter();
336        let absorbing_face = faces.next().unwrap();
337
338        self.absorb_faces_over_edges_and_vertexes(absorbing_face, faces, edges, vertexes)
339    }
340
341    pub fn absorb_faces_over_edges_and_vertexes(
342        &mut self,
343        absorbing_face: FaceId,
344        faces: impl IntoIterator<Item = FaceId>,
345        edges: impl IntoIterator<Item = EdgeId>,
346        vertexes: impl IntoIterator<Item = VertexId>,
347    ) {
348        let edges: Vec<EdgeId> = edges.into_iter().collect();
349        let perimeter_edges: Vec<EdgeId> = self
350            .edges_with_excludes(
351                self.full_edge(
352                    self.faces
353                        .get(&absorbing_face.id())
354                        .unwrap()
355                        .incident_half_edge
356                        .unwrap(),
357                ),
358                edges.clone(),
359            )
360            .collect();
361
362        self.remove_faces(faces);
363        self.remove_edges(edges);
364        self.remove_vertexes(vertexes);
365
366        self.wire_face_edges_vertexes(absorbing_face, &perimeter_edges);
367    }
368}
369
370impl<
371    VW: Clone,
372    HEW: Clone,
373    FW: Clone,
374    VC: Get<usize, Item = Vertex<VW>> + Insert<usize>,
375    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize>,
376    FC: Get<usize, Item = Face<FW>> + Insert<usize>,
377> Dcel<VW, HEW, FW, VC, HEC, FC>
378{
379    fn wire_edge_chain(&mut self, face: FaceId, edges: &[EdgeId]) {
380        self.wire_face(face, edges[0].forward());
381
382        let edges_circular_pair_windows = edges
383            .iter()
384            .zip(edges.iter().skip(1).chain(edges.iter().take(1)));
385
386        for (edge, next_edge) in edges_circular_pair_windows {
387            self.wire_edge(*edge, *next_edge);
388            self.wire_vertex(self.origin(edge.forward()), edge.forward());
389        }
390    }
391
392    fn wire_face_edges_vertexes(&mut self, face: FaceId, edges: &[EdgeId]) {
393        self.wire_face(face, edges[0].forward());
394
395        let edges_circular_pair_windows = edges
396            .iter()
397            .zip(edges.iter().skip(1).chain(edges.iter().take(1)));
398
399        for (edge, next_edge) in edges_circular_pair_windows {
400            self.wire_edge(*edge, *next_edge);
401            self.wire_vertex(self.origin(edge.forward()), edge.forward());
402        }
403    }
404}
405
406impl<VW, HEW, FW, VC: Push<usize, Item = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
407    fn add_unwired_vertex(&mut self, weight: VW) -> VertexId {
408        VertexId(self.vertexes.push(Vertex {
409            // Since we do not use optionals, we cannot use `None` as the uninitialized value.
410            // So instead uninitialized edge ids are edge 0.
411            // Initializing `.outward_edge` to a correct value is the
412            // responsibility of the caller.
413            outgoing_next_half_edge: HalfEdgeId(0),
414            weight,
415        }))
416    }
417}
418
419impl<VW, HEW, FW, VC: Remove<usize, Item = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
420    fn remove_vertexes(&mut self, vertexes: impl IntoIterator<Item = VertexId>) {
421        for vertex in vertexes.into_iter() {
422            self.remove_vertex(vertex);
423        }
424    }
425
426    fn remove_vertex(&mut self, vertex: VertexId) {
427        self.vertexes.remove(&vertex.id());
428    }
429}
430
431impl<VW: Clone, HEW, FW, VC: Get<usize, Item = Vertex<VW>> + Insert<usize>, HEC, FC>
432    Dcel<VW, HEW, FW, VC, HEC, FC>
433{
434    fn wire_vertex(&mut self, vertex: VertexId, outgoing_half_edge: HalfEdgeId) {
435        self.vertexes.insert(
436            vertex.id(),
437            Vertex {
438                outgoing_next_half_edge: outgoing_half_edge,
439                weight: self.vertexes.get(&vertex.id()).unwrap().weight.clone(),
440            },
441        )
442    }
443}
444
445impl<
446    VW: Clone,
447    HEW: Clone + Default,
448    FW: Clone + Default,
449    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Push<usize>,
450    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
451    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Push<usize>,
452> Dcel<VW, HEW, FW, VC, HEC, FC>
453{
454    pub fn split_face_by_edge_chain(
455        &mut self,
456        from: VertexId,
457        to: VertexId,
458        vertex_weights: impl IntoIterator<Item = VW>,
459        split_face: FaceId,
460    ) {
461        self.split_face_by_edge_chain_with_all_weights(
462            from,
463            to,
464            vertex_weights,
465            std::iter::repeat((HEW::default(), HEW::default())),
466            split_face,
467            FW::default(),
468        )
469    }
470}
471
472impl<
473    VW: Clone,
474    HEW: Clone,
475    FW: Clone,
476    VC: Get<usize, Item = Vertex<VW>> + Insert<usize> + Push<usize>,
477    HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize> + Push<usize>,
478    FC: Get<usize, Item = Face<FW>> + Insert<usize> + Push<usize>,
479> Dcel<VW, HEW, FW, VC, HEC, FC>
480{
481    pub fn split_face_by_edge_chain_with_all_weights(
482        &mut self,
483        from: VertexId,
484        to: VertexId,
485        vertex_weights: impl IntoIterator<Item = VW>,
486        edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
487        split_face: FaceId,
488        new_face_weight: FW,
489    ) {
490        let new_face = self.add_unwired_face(new_face_weight);
491        let (new_edges, last_vertex, last_edge_weight) = self.add_unwired_dangling_edge_chain(
492            from,
493            vertex_weights,
494            edge_weights,
495            split_face,
496            new_face,
497        );
498        self.add_unwired_edge(
499            last_vertex,
500            to,
501            split_face,
502            new_face,
503            last_edge_weight.0,
504            last_edge_weight.1,
505        );
506
507        let mut edges = vec![];
508        edges.push(self.vertex_prev_edge(from));
509        edges.extend(new_edges);
510        edges.push(self.vertex_next_edge(to));
511
512        self.wire_edge_chain(new_face, &edges);
513    }
514
515    fn add_unwired_dangling_edge_chain(
516        &mut self,
517        from: VertexId,
518        dangling_vertex_weights: impl IntoIterator<Item = VW>,
519        edge_weights: impl IntoIterator<Item = (HEW, HEW)>,
520        face: FaceId,
521        twin_face: FaceId,
522    ) -> (Vec<EdgeId>, VertexId, (HEW, HEW)) {
523        let mut edge_weights = edge_weights.into_iter();
524        let mut edges = vec![];
525        let mut last_vertex = from;
526
527        for (vertex_weight, edge_weight) in dangling_vertex_weights
528            .into_iter()
529            .zip(edge_weights.by_ref())
530        {
531            let (new_edge, new_vertex) = self.add_unwired_dangling_edge(
532                last_vertex,
533                vertex_weight,
534                edge_weight,
535                face,
536                twin_face,
537            );
538
539            edges.push(new_edge);
540            last_vertex = new_vertex;
541        }
542
543        (edges, last_vertex, edge_weights.next().unwrap())
544    }
545
546    fn add_unwired_dangling_edge(
547        &mut self,
548        from: VertexId,
549        dangling_vertex_weight: VW,
550        edge_weight: (HEW, HEW),
551        face: FaceId,
552        twin_face: FaceId,
553    ) -> (EdgeId, VertexId) {
554        let dangling_vertex = self.add_unwired_vertex(dangling_vertex_weight);
555        let dangling_edge = self.add_unwired_edge(
556            from,
557            dangling_vertex,
558            face,
559            twin_face,
560            edge_weight.0,
561            edge_weight.1,
562        );
563
564        (dangling_edge, dangling_vertex)
565    }
566}
567
568impl<VW, HEW: Clone, FW, VC, HEC: Insert<usize, Item = HalfEdge<HEW>> + Push<usize>, FC>
569    Dcel<VW, HEW, FW, VC, HEC, FC>
570{
571    fn add_unwired_edge(
572        &mut self,
573        origin: VertexId,
574        twin_origin: VertexId,
575        face: FaceId,
576        twin_face: FaceId,
577        weight: HEW,
578        twin_weight: HEW,
579    ) -> EdgeId {
580        let forward_half_edge = HalfEdgeId(self.half_edges.push(HalfEdge {
581            origin,
582            // Uninitialized as edge 0 before until the twin is created in the next few lines of this method.
583            twin: HalfEdgeId(0),
584            // Uninitialized as edge 0. Initializing `.prev` and `.next` to
585            // correct value is the responsibility of the caller.
586            prev: HalfEdgeId(0),
587            next: HalfEdgeId(0),
588            face,
589            weight: weight.clone(),
590        }));
591
592        let backward_half_edge = HalfEdgeId(self.half_edges.push(HalfEdge {
593            origin: twin_origin,
594            twin: forward_half_edge,
595            // Uninitialized as edge 0. Initializing `.prev` and `.next` to
596            // correct value is the responsibility of the caller.
597            prev: HalfEdgeId(0),
598            next: HalfEdgeId(0),
599            face: twin_face,
600            weight: twin_weight,
601        }));
602
603        // Now actually initialize `halfedge0`'s twin.
604        // PERF: This could actually be optimized away by making it the
605        // responsibility of the caller
606        self.half_edges.insert(
607            forward_half_edge.id(),
608            HalfEdge {
609                origin,
610                // Uninitialized as edge 0 before until the twin is created in the next few lines of this method.
611                twin: backward_half_edge,
612                // Uninitialized as edge 0. Initializing `.prev` and `.next` to
613                // correct value is the responsibility of the caller.
614                prev: HalfEdgeId(0),
615                next: HalfEdgeId(0),
616                face,
617                weight,
618            },
619        );
620
621        EdgeId(forward_half_edge, backward_half_edge)
622    }
623}
624
625impl<VW, HEW, FW, VC, HEC: Remove<usize, Item = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
626    fn remove_edges(&mut self, edges: impl IntoIterator<Item = EdgeId>) {
627        for edge in edges.into_iter() {
628            self.remove_edge(edge);
629        }
630    }
631
632    fn remove_edge(&mut self, edge: EdgeId) {
633        self.half_edges.remove(&edge.forward().id());
634        self.half_edges.remove(&edge.backward().id());
635    }
636}
637
638impl<VW, HEW: Clone, FW, VC, HEC: Get<usize, Item = HalfEdge<HEW>> + Insert<usize>, FC>
639    Dcel<VW, HEW, FW, VC, HEC, FC>
640{
641    fn wire_edge(&mut self, edge: EdgeId, next_edge: EdgeId) {
642        self.half_edges.insert(
643            edge.forward().id(),
644            HalfEdge {
645                next: next_edge.forward(),
646                ..self.half_edges.get(&edge.forward().id()).unwrap().clone()
647            },
648        );
649        self.half_edges.insert(
650            next_edge.backward().id(),
651            HalfEdge {
652                next: edge.backward(),
653                ..self.half_edges.get(&edge.forward().id()).unwrap().clone()
654            },
655        );
656    }
657}
658
659impl<VW, HEW, FW, VC, HEC, FC: Push<usize, Item = Face<FW>>> Dcel<VW, HEW, FW, VC, HEC, FC> {
660    fn add_unwired_face(&mut self, weight: FW) -> FaceId {
661        FaceId(self.faces.push(Face {
662            incident_half_edge: None,
663            weight,
664        }))
665    }
666}
667
668impl<VW, HEW, FW, VC, HEC, FC: Remove<usize>> Dcel<VW, HEW, FW, VC, HEC, FC> {
669    fn remove_faces(&mut self, faces: impl IntoIterator<Item = FaceId>) {
670        for face in faces.into_iter() {
671            self.remove_face(face);
672        }
673    }
674
675    fn remove_face(&mut self, face: FaceId) {
676        self.faces.remove(&face.id());
677    }
678}
679
680impl<VW, HEW, FW: Clone, VC, HEC, FC: Get<usize, Item = Face<FW>> + Insert<usize>>
681    Dcel<VW, HEW, FW, VC, HEC, FC>
682{
683    fn wire_face(&mut self, face: FaceId, incident_half_edge: HalfEdgeId) {
684        self.faces.insert(
685            face.id(),
686            Face {
687                incident_half_edge: Some(incident_half_edge),
688                weight: self.faces.get(&face.id()).unwrap().weight.clone(),
689            },
690        );
691    }
692}
693
694impl<VW, HEW, FW, VC: Get<usize, Item = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
695    #[inline]
696    fn outgoing_next_half_edge(&self, vertex: VertexId) -> HalfEdgeId {
697        self.vertexes
698            .get(&vertex.id())
699            .unwrap()
700            .outgoing_next_half_edge
701    }
702}
703
704impl<VW, HEW, FW, VC: Get<usize, Item = Vertex<VW>>, HEC: Get<usize, Item = HalfEdge<HEW>>, FC>
705    Dcel<VW, HEW, FW, VC, HEC, FC>
706{
707    #[inline]
708    fn incoming_next_half_edge(&self, vertex: VertexId) -> HalfEdgeId {
709        self.twin(self.outgoing_next_half_edge(vertex))
710    }
711
712    #[inline]
713    fn vertex_next_edge(&self, vertex: VertexId) -> EdgeId {
714        EdgeId(
715            self.outgoing_next_half_edge(vertex),
716            self.incoming_next_half_edge(vertex),
717        )
718    }
719
720    #[inline]
721    fn incoming_prev_half_edge(&self, vertex: VertexId) -> HalfEdgeId {
722        self.prev_half_edge(self.outgoing_next_half_edge(vertex))
723    }
724
725    #[inline]
726    fn outgoing_prev_half_edge(&self, vertex: VertexId) -> HalfEdgeId {
727        self.twin(self.incoming_prev_half_edge(vertex))
728    }
729
730    #[inline]
731    fn vertex_prev_edge(&self, vertex: VertexId) -> EdgeId {
732        EdgeId(
733            self.incoming_prev_half_edge(vertex),
734            self.outgoing_prev_half_edge(vertex),
735        )
736    }
737}
738
739impl<VW, HEW, FW, VC: Get<usize, Item = Vertex<VW>>, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
740    #[inline]
741    fn vertex_weight(&self, vertex: VertexId) -> &VW {
742        &self.vertexes.get(&vertex.id()).unwrap().weight
743    }
744}
745
746impl<VW, HEW, FW, VC: Get<usize, Item = Vertex<VW>>, HEC: Get<usize, Item = HalfEdge<HEW>>, FC>
747    Dcel<VW, HEW, FW, VC, HEC, FC>
748{
749    #[inline]
750    fn prev_vertex(&self, vertex: VertexId) -> VertexId {
751        self.origin(self.prev_half_edge(self.outgoing_next_half_edge(vertex)))
752    }
753
754    #[inline]
755    fn next_vertex(&self, vertex: VertexId) -> VertexId {
756        self.origin(self.next_half_edge(self.outgoing_next_half_edge(vertex)))
757    }
758}
759
760impl<VW, HEW, FW, VC, HEC: Get<usize, Item = HalfEdge<HEW>>, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
761    #[inline]
762    pub fn origin(&self, half_edge: HalfEdgeId) -> VertexId {
763        self.half_edges.get(&half_edge.id()).unwrap().origin
764    }
765
766    #[inline]
767    pub fn endpoints(&self, edge: EdgeId) -> (VertexId, VertexId) {
768        (self.origin(edge.forward()), self.origin(edge.backward()))
769    }
770
771    #[inline]
772    pub fn twin(&self, half_edge: HalfEdgeId) -> HalfEdgeId {
773        self.half_edges.get(&half_edge.id()).unwrap().twin
774    }
775
776    #[inline]
777    pub fn full_edge(&self, half_edge: HalfEdgeId) -> EdgeId {
778        EdgeId(half_edge, self.twin(half_edge))
779    }
780
781    #[inline]
782    pub fn face_in_front(&self, half_edge: HalfEdgeId) -> FaceId {
783        self.half_edges.get(&half_edge.id()).unwrap().face
784    }
785
786    #[inline]
787    pub fn face_behind(&self, half_edge: HalfEdgeId) -> FaceId {
788        self.face_in_front(self.twin(half_edge))
789    }
790
791    #[inline]
792    pub fn edge_faces(&self, edge: EdgeId) -> (FaceId, FaceId) {
793        (
794            self.face_in_front(edge.forward()),
795            self.face_behind(edge.backward()),
796        )
797    }
798
799    #[inline]
800    pub fn prev_half_edge(&self, half_edge: HalfEdgeId) -> HalfEdgeId {
801        self.half_edges.get(&half_edge.id()).unwrap().prev
802    }
803
804    #[inline]
805    pub fn next_half_edge(&self, half_edge: HalfEdgeId) -> HalfEdgeId {
806        self.half_edges.get(&half_edge.id()).unwrap().next
807    }
808
809    #[inline]
810    pub fn prev_edge(&self, edge: EdgeId) -> EdgeId {
811        let next_forward_half_edge = self.half_edges.get(&edge.forward().id()).unwrap().prev;
812        let next_backward_half_edge = self
813            .half_edges
814            .get(&next_forward_half_edge.id())
815            .unwrap()
816            .twin;
817
818        EdgeId(next_forward_half_edge, next_backward_half_edge)
819    }
820
821    #[inline]
822    pub fn next_edge(&self, edge: EdgeId) -> EdgeId {
823        let next_forward_half_edge = self.half_edges.get(&edge.forward().id()).unwrap().next;
824        let next_backward_half_edge = self
825            .half_edges
826            .get(&next_forward_half_edge.id())
827            .unwrap()
828            .twin;
829
830        EdgeId(next_forward_half_edge, next_backward_half_edge)
831    }
832
833    #[inline]
834    pub fn cw_half_edge(&self, half_edge: HalfEdgeId) -> HalfEdgeId {
835        self.twin(self.prev_half_edge(half_edge))
836    }
837
838    #[inline]
839    pub fn ccw_half_edge(&self, half_edge: HalfEdgeId) -> HalfEdgeId {
840        self.next_half_edge(self.twin(half_edge))
841    }
842
843    #[inline]
844    pub fn cw_edge(&self, edge: EdgeId) -> EdgeId {
845        self.full_edge(self.cw_half_edge(edge.forward()))
846    }
847
848    #[inline]
849    pub fn ccw_edge(&self, edge: EdgeId) -> EdgeId {
850        self.full_edge(self.ccw_half_edge(edge.forward()))
851    }
852
853    #[inline]
854    pub fn half_edge_weight(&self, half_edge: HalfEdgeId) -> &HEW {
855        &self.half_edges.get(&half_edge.id()).unwrap().weight
856    }
857
858    #[inline]
859    pub fn edge_weights(&self, edge: EdgeId) -> (&HEW, &HEW) {
860        (
861            self.half_edge_weight(edge.forward()),
862            self.half_edge_weight(edge.backward()),
863        )
864    }
865}
866
867impl<VW, HEW, FW, VC, HEC, FC: Get<usize, Item = Face<FW>>> Dcel<VW, HEW, FW, VC, HEC, FC> {
868    #[inline]
869    pub fn incident_half_edge(&self, face: FaceId) -> Option<HalfEdgeId> {
870        self.faces.get(&face.id()).unwrap().incident_half_edge
871    }
872
873    #[inline]
874    pub fn face_weight(&self, face: FaceId) -> &FW {
875        &self.faces.get(&face.id()).unwrap().weight
876    }
877}
878
879impl<VW, HEW, FW, VC, HEC, FC> Dcel<VW, HEW, FW, VC, HEC, FC> {
880    /// Returns the id of the unbounded face.
881    ///
882    /// The unbounded face is always the first element of the face list.
883    #[inline]
884    pub fn unbounded_face(&self) -> FaceId {
885        FaceId(0)
886    }
887}