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/// 
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}