spade/delaunay_core/handles/
public_handles.rs

1use crate::{
2    delaunay_core::dcel_operations::{self},
3    HasPosition, Point2,
4};
5
6pub use super::handle_defs::*;
7
8use num_traits::Float;
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13/// Returns a reference to the single outer face.
14///
15/// *See also [Triangulation::outer_face()](crate::Triangulation::outer_face()).*
16pub const OUTER_FACE: FixedFaceHandle<PossiblyOuterTag> = dcel_operations::OUTER_FACE_HANDLE;
17
18/// Marker trait for [InnerTag] and [PossiblyOuterTag].
19///
20/// There should be no need to implement this.
21pub trait InnerOuterMarker:
22    Clone + Copy + PartialEq + Eq + PartialOrd + Ord + core::fmt::Debug + Default + core::hash::Hash
23{
24    fn debug_string() -> &'static str;
25}
26
27/// Marker type that signifies that a face is an inner faces.
28///
29/// Used as type parameter for [FixedFaceHandle] and [FaceHandle] to indicate that a face
30/// handle cannot possibly reference the outer face.
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
32#[cfg_attr(
33    feature = "serde",
34    derive(Serialize, Deserialize),
35    serde(crate = "serde")
36)]
37pub struct InnerTag;
38
39/// Marker type that signifies that a face can possibly be the outer faces.
40///
41/// Used as type parameter for [FixedFaceHandle] and [FaceHandle] to indicate that a face
42/// handle can possibly reference the outer face.
43#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
44#[cfg_attr(
45    feature = "serde",
46    derive(Serialize, Deserialize),
47    serde(crate = "serde")
48)]
49pub struct PossiblyOuterTag;
50
51impl InnerOuterMarker for InnerTag {
52    fn debug_string() -> &'static str {
53        "Inner"
54    }
55}
56
57impl InnerOuterMarker for PossiblyOuterTag {
58    fn debug_string() -> &'static str {
59        "PossiblyOuter"
60    }
61}
62
63/// Fixed handle to a vertex.
64///
65/// *See also the [handles](crate::handles) module.*
66pub type FixedVertexHandle = FixedHandleImpl<VertexTag, InnerTag>;
67
68/// Fixed handle to a directed edge.
69///
70/// *See also the [handles](crate::handles) module.*
71pub type FixedDirectedEdgeHandle = FixedHandleImpl<DirectedEdgeTag, InnerTag>;
72
73/// Fixed handle to an undirected edge.
74///
75/// *See also the [handles](crate::handles) module.*
76pub type FixedUndirectedEdgeHandle = FixedHandleImpl<UndirectedEdgeTag, InnerTag>;
77
78/// "Fixed handle to a face.
79///
80/// The type parameter is either [InnerTag] or [PossiblyOuterTag], depending on the face type.
81///
82/// "*See also the [handles module](crate::handles)*
83pub type FixedFaceHandle<InnerOuter> = FixedHandleImpl<FaceTag, InnerOuter>;
84
85/// Handle to a directed edge of a triangulation.
86///
87/// Use this handle to examine the edge's surroundings, e.g. its origin and destination
88/// vertices or the adjacent face.
89///
90/// # Retrieving neighboring edges:
91///
92/// Use [Self::next], [Self::prev], [Self::rev] to access any adjacent edge:
93///
94#[doc = include_str!("../../../images/delaunay_directed_edge_details.svg")]
95///
96/// # Retrieving adjacent faces and vertices
97///
98/// Use [Self::face], [Self::from] and [Self::to] to access the adjacent face and vertices:
99///
100#[doc = include_str!("../../../images/delaunay_directed_edge_face_and_vertex.svg")]
101///
102/// *See also the [handles module](crate::handles).*
103pub type DirectedEdgeHandle<'a, V, DE, UE, F> =
104    DynamicHandleImpl<'a, V, DE, UE, F, DirectedEdgeTag, InnerTag>;
105
106/// Handle to an undirected edge of a triangulation.
107///
108/// Use this handle to examine the edge's surroundings, e.g. its origin and destination
109/// vertices or the adjacent face.
110///
111/// # Method overview
112/// An undirected edge handle allows to explore the surroundings of an edge. This diagram
113/// shows which methods are available to extract information about the edge's
114/// neighboring elements.
115///
116/// ![DirectedEdgeHandle](../../../../images/DirectedEdgeHandle.svg)
117///
118/// *See also the [handles module](crate::handles)*
119pub type UndirectedEdgeHandle<'a, V, DE = (), UE = (), F = ()> =
120    DynamicHandleImpl<'a, V, DE, UE, F, UndirectedEdgeTag, InnerTag>;
121
122/// Handle to a vertex of a triangulation.
123///
124/// Use this handle to retrieve the vertex [position](Self::position) or its
125/// [outgoing edges](Self::out_edges).
126///
127///
128/// *See also the [handles module](crate::handles).*
129pub type VertexHandle<'a, V, DE = (), UE = (), F = ()> =
130    DynamicHandleImpl<'a, V, DE, UE, F, VertexTag, InnerTag>;
131
132/// Handle to a face of a triangulation.
133///
134/// Depending on the type parameter, the handle **can refer to the outer face**:
135///
136/// * `FaceHandle<'a, PossiblyOuterTag, ...>`: The face may refer to the single outer face.
137/// * `FaceHandle<'a, InnerTag, ...>`: The face refers to an inner triangle of the triangulation.
138///
139#[doc = include_str!("../../../images/outer_faces.svg")]
140///
141/// `FaceHandle<'a, InnerTag, ...>` implements some additional methods that require it to be an inner
142/// face - e.g. [Self::vertices] will return an array containing exactly 3
143/// vertices.
144///
145/// Use [Self::as_inner] to convert from a *possibly outer* face to an *inner*
146/// face.
147///
148/// # Type parameters
149/// The type parameters refer to the triangulations vertex, directed edge, undirected edge and
150/// face type. See [Triangulation](crate::Triangulation) for more information.
151///
152/// *See also the [handles module](crate::handles) for more general information about handles.*
153pub type FaceHandle<'a, InnerOuter, V, DE, UE, F> =
154    DynamicHandleImpl<'a, V, DE, UE, F, FaceTag, InnerOuter>;
155
156/// A handle to a directed edge of the Voronoi diagram.
157///
158/// Several methods are defined to explore adjacent edges, faces and vertices:
159///
160#[doc =  include_str!("../../../images/voronoi_edge_details.svg")]
161pub type DirectedVoronoiEdge<'a, V, DE, UE, F> =
162    DynamicHandleImpl<'a, V, DE, UE, F, DirectedVoronoiEdgeTag, InnerTag>;
163
164/// A handle to an undirected edge of the Voronoi diagram.
165pub type UndirectedVoronoiEdge<'a, V, DE, UE, F> =
166    DynamicHandleImpl<'a, V, DE, UE, F, UndirectedVoronoiEdgeTag, InnerTag>;
167
168/// A handle to a face of the voronoi diagram.
169pub type VoronoiFace<'a, V, DE, UE, F> =
170    DynamicHandleImpl<'a, V, DE, UE, F, VoronoiFaceTag, PossiblyOuterTag>;
171
172/// A handle to a vertex of the voronoi diagram.
173///
174/// Refer to [DelaunayTriangulation](crate::DelaunayTriangulation) for an example on how
175/// to extract the voronoi diagram from a triangulation.
176pub enum VoronoiVertex<'a, V, DE, UE, F> {
177    /// Refers to an inner vertex of the voronoi diagram.
178    ///
179    /// An inner vertex refers to an *inner face* of the original Delaunay triangulation.
180    /// Its position is the circumcenter of that face.
181    ///
182    #[doc = include_str!("../../../images/inner_voronoi_vertex.svg")]
183    ///
184    /// *Displays several inner voronoi vertices in blue and an arrow towards the inner
185    /// face to which they belong. Note that voronoi vertices are not necessarily
186    /// located inside the convex hull.*
187    Inner(
188        /// The inner face handle to which this voronoi vertex refers.
189        FaceHandle<'a, InnerTag, V, DE, UE, F>,
190    ),
191
192    /// Refers to an outer vertex of the voronoi diagram.
193    ///
194    /// These vertices don't have a well-defined position as they don't have a dual inner
195    /// face in the Delaunay triangulation.
196    /// Instead, they are characterized by a dual outer edge (an edge that is part of the
197    /// convex hull) of the underlying triangulation.
198    ///
199    /// Rather than a position, these vertices can be better described by a
200    /// *half open line segment*: The voronoi vertex is placed infinitely far away in the
201    /// direction the line segment is pointing to.
202    /// The line segment's direction is the dual edge's normal (i.e., the dual edge
203    /// rotated by 90 degrees).
204    ///
205    #[doc =include_str!("../../../images/outer_voronoi_vertex.svg")]
206    ///
207    /// *Displays 3 out of 6 outer Delaunay vertices. For each vertex, its dual outer edge
208    /// is shown in blue. The line segment that points toward this vertex is shown in orange.*
209    Outer(
210        /// The outer directed edge handle dual to this voronoi vertex.
211        DirectedVoronoiEdge<'a, V, DE, UE, F>,
212    ),
213}
214
215impl<'a, V, DE, UE, F> VoronoiVertex<'a, V, DE, UE, F>
216where
217    V: HasPosition,
218    V::Scalar: Float,
219{
220    /// The position of this voronoi vertex.
221    ///
222    /// Returns `None` if this vertex is an outer voronoi vertex.
223    /// Otherwise, the returned position is the
224    /// [circumcenter](crate::handles::FaceHandle::circumcenter())
225    /// of the dual Delaunay face.
226    pub fn position(&self) -> Option<Point2<V::Scalar>> {
227        match self {
228            VoronoiVertex::Inner(face) => Some(face.circumcenter()),
229            VoronoiVertex::Outer(_) => None,
230        }
231    }
232
233    /// Returns the dual delaunay face of this voronoi vertex.
234    ///
235    /// Returns `None` if this is an outer voronoi vertex.
236    pub fn as_delaunay_face(&self) -> Option<FaceHandle<'a, InnerTag, V, DE, UE, F>> {
237        match self {
238            VoronoiVertex::Inner(face) => Some(*face),
239            VoronoiVertex::Outer(_) => None,
240        }
241    }
242
243    /// Returns all directed voronoi edges going out of this vertex.
244    ///
245    /// The edges are returned in counterclockwise order. Returns `None` if this is an outer
246    /// voronoi vertex.
247    pub fn out_edges(&self) -> Option<[DirectedVoronoiEdge<'a, V, DE, UE, F>; 3]> {
248        match self {
249            VoronoiVertex::Inner(face) => {
250                let [e1, e2, e3] = face.adjacent_edges();
251                Some([
252                    e1.as_voronoi_edge(),
253                    e2.as_voronoi_edge(),
254                    e3.as_voronoi_edge(),
255                ])
256            }
257            VoronoiVertex::Outer(_) => None,
258        }
259    }
260
261    /// Returns a voronoi edge going out of this vertex.
262    pub fn out_edge(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
263        match self {
264            VoronoiVertex::Inner(face) => face.adjacent_edge().as_voronoi_edge(),
265            VoronoiVertex::Outer(edge) => *edge,
266        }
267    }
268}
269
270impl<'a, V, DE, UE, F> VoronoiFace<'a, V, DE, UE, F> {
271    /// Converts this face into its dual vertex of the Delaunay Triangulation.
272    pub fn as_delaunay_vertex(&self) -> VertexHandle<'a, V, DE, UE, F> {
273        VertexHandle::new(self.dcel, FixedVertexHandle::new(self.handle.index()))
274    }
275
276    /// Returns an iterator that returns all edges adjacent to this face.
277    ///
278    /// The edges are returned in clockwise order.
279    pub fn adjacent_edges(
280        &self,
281    ) -> impl DoubleEndedIterator<Item = DirectedVoronoiEdge<'a, V, DE, UE, F>> {
282        self.as_delaunay_vertex()
283            .out_edges()
284            .map(|edge| edge.as_voronoi_edge())
285    }
286}
287
288impl<'a, V, DE, UE, F> DirectedVoronoiEdge<'a, V, DE, UE, F> {
289    /// Returns the voronoi edge's destination.
290    pub fn to(&self) -> VoronoiVertex<'a, V, DE, UE, F> {
291        self.rev().from()
292    }
293
294    /// Returns the voronoi vertex from which this edge originates.
295    pub fn from(&self) -> VoronoiVertex<'a, V, DE, UE, F> {
296        if let Some(face) = self.as_delaunay_edge().face().as_inner() {
297            VoronoiVertex::Inner(face)
298        } else {
299            VoronoiVertex::Outer(*self)
300        }
301    }
302
303    /// Returns the Voronoi face to the left of this Voronoi edge
304    pub fn face(&self) -> VoronoiFace<'a, V, DE, UE, F> {
305        self.as_delaunay_edge().from().as_voronoi_face()
306    }
307
308    /// Converts this directed edge handle into an undirected edge handle.
309    ///
310    /// *See also the [handles](crate::handles) module for more information.*
311    pub fn as_undirected(&self) -> UndirectedVoronoiEdge<'a, V, DE, UE, F> {
312        self.as_delaunay_edge().as_undirected().as_voronoi_edge()
313    }
314
315    /// Returns the directed dual edge of the underlying Delaunay triangulation.
316    ///
317    /// The dual edge is always orthogonal to this edge.
318    ///
319    #[doc = include_str!("../../../images/dual_edges.svg")]
320    ///
321    /// *Shows various inner voronoi edges (blue) and their dual Delaunay edges (orange)*
322    pub fn as_delaunay_edge(&self) -> DirectedEdgeHandle<'a, V, DE, UE, F> {
323        DirectedEdgeHandle::new(self.dcel, FixedDirectedEdgeHandle::new(self.handle.index()))
324    }
325
326    /// Returns this edge with its direction reversed.
327    pub fn rev(&self) -> Self {
328        self.as_delaunay_edge().rev().as_voronoi_edge()
329    }
330
331    /// Returns the edge that is connected to this edge in counterclockwise order.
332    ///
333    /// See also [prev](Self::prev)
334    pub fn next(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
335        self.as_delaunay_edge().ccw().as_voronoi_edge()
336    }
337
338    /// Returns the edge that is connected to this edge in clockwise order.
339    ///
340    /// See also [next](Self::next)
341    pub fn prev(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
342        self.as_delaunay_edge().cw().as_voronoi_edge()
343    }
344}
345
346impl<V, DE, UE, F> DirectedVoronoiEdge<'_, V, DE, UE, F>
347where
348    V: HasPosition,
349{
350    /// Returns a vector that is parallel to the voronoi edge.
351    ///
352    /// This vector is obtained by rotating the dual Delaunay edge by 90° degree
353    /// The returned vector is not necessarily normalized.
354    pub fn direction_vector(&self) -> Point2<V::Scalar> {
355        let from = self.as_delaunay_edge().from().position();
356        let to = self.as_delaunay_edge().to().position();
357        let diff = Point2::sub(&to, from);
358
359        Point2::new(-diff.y, diff.x)
360    }
361}