1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
use crate::{
    delaunay_core::dcel_operations::{self},
    HasPosition, Point2,
};

pub use super::handle_defs::*;

use num_traits::Float;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// Returns a reference to the single outer face.
///
/// *See also [Triangulation::outer_face()](crate::Triangulation::outer_face()).*
pub const OUTER_FACE: FixedFaceHandle<PossiblyOuterTag> = dcel_operations::OUTER_FACE_HANDLE;

/// Marker trait for [InnerTag] and [PossiblyOuterTag].
///
/// There should be no need to implement this.
pub trait InnerOuterMarker:
    Clone + Copy + PartialEq + Eq + PartialOrd + Ord + core::fmt::Debug + Default + core::hash::Hash
{
    fn debug_string() -> &'static str;
}

/// Marker type that signifies that a face is an inner faces.
///
/// Used as type parameter for [FixedFaceHandle] and [FaceHandle] to indicate that a face
/// handle cannot possibly reference the outer face.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde")
)]
pub struct InnerTag;

/// Marker type that signifies that a face can possibly be the outer faces.
///
/// Used as type parameter for [FixedFaceHandle] and [FaceHandle] to indicate that a face
/// handle can possibly reference the outer face.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
#[cfg_attr(
    feature = "serde",
    derive(Serialize, Deserialize),
    serde(crate = "serde")
)]
pub struct PossiblyOuterTag;

impl InnerOuterMarker for InnerTag {
    fn debug_string() -> &'static str {
        "Inner"
    }
}

impl InnerOuterMarker for PossiblyOuterTag {
    fn debug_string() -> &'static str {
        "PossiblyOuter"
    }
}

/// Fixed handle to a vertex.
///
/// *See also the [handles](crate::handles) module.*
pub type FixedVertexHandle = FixedHandleImpl<VertexTag, InnerTag>;

/// Fixed handle to a directed edge.
///
/// *See also the [handles](crate::handles) module.*
pub type FixedDirectedEdgeHandle = FixedHandleImpl<DirectedEdgeTag, InnerTag>;

/// Fixed handle to an undirected edge.
///
/// *See also the [handles](crate::handles) module.*
pub type FixedUndirectedEdgeHandle = FixedHandleImpl<UndirectedEdgeTag, InnerTag>;

/// "Fixed handle to a face.
///
/// The type parameter is either [InnerTag] or [PossiblyOuterTag], depending on the face type.
///
/// "*See also the [handles module](crate::handles)*
pub type FixedFaceHandle<InnerOuter> = FixedHandleImpl<FaceTag, InnerOuter>;

/// Handle to a directed edge of a triangulation.
///
/// Use this handle to examine the edge's surroundings, e.g. its origin and destination
/// vertices or the adjacent face.
///
/// # Retrieving neighboring edges:
///
/// Use [Self::next], [Self::prev], [Self::rev] to access any adjacent edge:
///
#[doc = include_str!("../../../images/delaunay_directed_edge_details.svg")]
///
/// # Retrieving adjacent faces and vertices
///
/// Use [Self::face], [Self::from] and [Self::to] to access the adjacent face and vertices:
///
#[doc = include_str!("../../../images/delaunay_directed_edge_face_and_vertex.svg")]
///
/// *See also the [handles module](crate::handles).*
pub type DirectedEdgeHandle<'a, V, DE, UE, F> =
    DynamicHandleImpl<'a, V, DE, UE, F, DirectedEdgeTag, InnerTag>;

/// Handle to an undirected edge of a triangulation.
///
/// Use this handle to examine the edge's surroundings, e.g. its origin and destination
/// vertices or the adjacent face.
///
/// # Method overview
/// An undirected edge handle allows to explore the surroundings of an edge. This diagram
/// shows which methods are available to extract information about the edge's
/// neighboring elements.
///
/// ![DirectedEdgeHandle](../../../../images/DirectedEdgeHandle.svg)
///
/// *See also the [handles module](crate::handles)*
pub type UndirectedEdgeHandle<'a, V, DE = (), UE = (), F = ()> =
    DynamicHandleImpl<'a, V, DE, UE, F, UndirectedEdgeTag, InnerTag>;

/// Handle to a vertex of a triangulation.
///
/// Use this handle to retrieve the vertex [position](Self::position) or its
/// [outgoing edges](Self::out_edges).
///
///
/// *See also the [handles module](crate::handles).*
pub type VertexHandle<'a, V, DE = (), UE = (), F = ()> =
    DynamicHandleImpl<'a, V, DE, UE, F, VertexTag, InnerTag>;

/// Handle to a face of a triangulation.
///
/// Depending on the type parameter, the handle **can refer to the outer face**:
///
/// * `FaceHandle<'a, PossiblyOuterTag, ...>]`: The face may refer to the single outer face.
/// * `FaceHandle<'a, InnerTag, ...>`: The face refers to an inner triangle of the triangulation.
///
#[doc = include_str!("../../../images/outer_faces.svg")]
///
/// `FaceHandle<'a, InnerTag, ...>` implements some additional methods that require it to be an inner
/// face - e.g. [Self::vertices] will return an array containing exactly 3
/// vertices.
///
/// Use [Self::as_inner] to convert from a *possibly outer* face to an *inner*
/// face.
///
/// # Type parameters
/// The type parameters refer to the triangulations vertex, directed edge, undirected edge and
/// face type. See [Triangulation](crate::Triangulation) for more information.
///
/// *See also the [handles module](crate::handles) for more general information about handles.*
pub type FaceHandle<'a, InnerOuter, V, DE, UE, F> =
    DynamicHandleImpl<'a, V, DE, UE, F, FaceTag, InnerOuter>;

/// A handle to a directed edge of the Voronoi diagram.
///
/// Several methods are defined to explore adjacent edges, faces and vertices:
///
#[doc =  include_str!("../../../images/voronoi_edge_details.svg")]
pub type DirectedVoronoiEdge<'a, V, DE, UE, F> =
    DynamicHandleImpl<'a, V, DE, UE, F, DirectedVoronoiEdgeTag, InnerTag>;

/// A handle to an undirected edge of the Voronoi diagram.
pub type UndirectedVoronoiEdge<'a, V, DE, UE, F> =
    DynamicHandleImpl<'a, V, DE, UE, F, UndirectedVoronoiEdgeTag, InnerTag>;

/// A handle to a face of the voronoi diagram.
pub type VoronoiFace<'a, V, DE, UE, F> =
    DynamicHandleImpl<'a, V, DE, UE, F, VoronoiFaceTag, PossiblyOuterTag>;

/// A handle to a vertex of the voronoi diagram.
///
/// Refer to [DelaunayTriangulation](crate::DelaunayTriangulation) for an example on how
/// to extract the voronoi diagram from a triangulation.
pub enum VoronoiVertex<'a, V, DE, UE, F> {
    /// Refers to an inner vertex of the voronoi diagram.
    ///
    /// An inner vertex refers to an *inner face* of the original Delaunay triangulation.
    /// Its position is the circumcenter of that face.
    ///
    #[doc = include_str!("../../../images/inner_voronoi_vertex.svg")]
    ///
    /// *Displays several inner voronoi vertices in blue and an arrow towards the inner
    /// face to which they belong. Note that voronoi vertices are not necessarily
    /// located inside the convex hull.*
    Inner(
        /// The inner face handle to which this voronoi vertex refers.
        FaceHandle<'a, InnerTag, V, DE, UE, F>,
    ),

    /// Refers to an outer vertex of the voronoi diagram.
    ///
    /// These vertices don't have a well defined position as they don't have a dual inner
    /// face in the Delaunay triangulation.
    /// Instead, they are characterized by a dual outer edge (an edge that is part of the
    /// convex hull) of the underlying triangulation.
    ///
    /// Rather than a position, these vertices can be better described by a
    /// *half open line segment*: The voronoi vertex is placed infinitely far away in the
    /// direction the line segment is pointing to.
    /// The line segment's direction is the dual edge's normal (i.e., the dual edge
    /// rotated by 90 degrees).
    ///
    #[doc =include_str!("../../../images/outer_voronoi_vertex.svg")]
    ///
    /// *Displays 3 out of 6 outer Delaunay vertices. For each vertex, its dual outer edge
    /// is shown in blue. The line segment that points toward this vertex is shown in orange.*
    Outer(
        /// The outer directed edge handle dual to this voronoi vertex.
        DirectedVoronoiEdge<'a, V, DE, UE, F>,
    ),
}

impl<'a, V, DE, UE, F> VoronoiVertex<'a, V, DE, UE, F>
where
    V: HasPosition,
    V::Scalar: Float,
{
    /// The position of this voronoi vertex.
    ///
    /// Returns `None` if this vertex is an outer voronoi vertex.
    /// Otherwise, the returned position is the
    /// [circumcenter](crate::handles::FaceHandle::circumcenter())
    /// of the dual Delaunay face.
    pub fn position(&self) -> Option<Point2<V::Scalar>> {
        match self {
            VoronoiVertex::Inner(face) => Some(face.circumcenter()),
            VoronoiVertex::Outer(_) => None,
        }
    }

    /// Returns the dual delaunay face of this voronoi vertex.
    ///
    /// Returns `None` if this is an outer voronoi vertex.
    pub fn as_delaunay_face(&self) -> Option<FaceHandle<'a, InnerTag, V, DE, UE, F>> {
        match self {
            VoronoiVertex::Inner(face) => Some(*face),
            VoronoiVertex::Outer(_) => None,
        }
    }

    /// Returns all directed voronoi edges going out of this vertex.
    ///
    /// The edges are returned in counter clockwise order. Returns `None` if this is an outer
    /// voronoi vertex.
    pub fn out_edges(&self) -> Option<[DirectedVoronoiEdge<'a, V, DE, UE, F>; 3]> {
        match self {
            VoronoiVertex::Inner(face) => {
                let [e1, e2, e3] = face.adjacent_edges();
                Some([
                    e1.as_voronoi_edge(),
                    e2.as_voronoi_edge(),
                    e3.as_voronoi_edge(),
                ])
            }
            VoronoiVertex::Outer(_) => None,
        }
    }

    /// Returns a voronoi edge going out of this vertex.
    pub fn out_edge(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
        match self {
            VoronoiVertex::Inner(face) => face.adjacent_edge().as_voronoi_edge(),
            VoronoiVertex::Outer(edge) => *edge,
        }
    }
}

impl<'a, V, DE, UE, F> VoronoiFace<'a, V, DE, UE, F> {
    /// Converts this face into its dual vertex of the Delaunay Triangulation.
    pub fn as_delaunay_vertex(&self) -> VertexHandle<'a, V, DE, UE, F> {
        VertexHandle::new(self.dcel, FixedVertexHandle::new(self.handle.index()))
    }

    /// Returns an iterator that returns all edges adjacent to this face.
    ///
    /// The edges are returned in clockwise order.
    pub fn adjacent_edges(
        &self,
    ) -> impl DoubleEndedIterator<Item = DirectedVoronoiEdge<'a, V, DE, UE, F>> {
        self.as_delaunay_vertex()
            .out_edges()
            .map(|edge| edge.as_voronoi_edge())
    }
}

impl<'a, V, DE, UE, F> DirectedVoronoiEdge<'a, V, DE, UE, F> {
    /// Returns the voronoi edge's destination.
    pub fn to(&self) -> VoronoiVertex<'a, V, DE, UE, F> {
        self.rev().from()
    }

    /// Returns the voronoi vertex from which this edge originates.
    pub fn from(&self) -> VoronoiVertex<'a, V, DE, UE, F> {
        if let Some(face) = self.as_delaunay_edge().face().as_inner() {
            VoronoiVertex::Inner(face)
        } else {
            VoronoiVertex::Outer(*self)
        }
    }

    /// Returns the Voronoi face to the left of this Voronoi edge
    pub fn face(&self) -> VoronoiFace<'a, V, DE, UE, F> {
        self.as_delaunay_edge().from().as_voronoi_face()
    }

    /// Converts this directed edge handle into an undirected edge handle.
    ///
    /// *See also the [handles](crate::handles) module for more information.*
    pub fn as_undirected(&self) -> UndirectedVoronoiEdge<'a, V, DE, UE, F> {
        self.as_delaunay_edge().as_undirected().as_voronoi_edge()
    }

    /// Returns the directed dual edge of the underlying Delaunay triangulation.
    ///
    /// The dual edge is always orthogonal to to this edge.
    ///
    #[doc = include_str!("../../../images/dual_edges.svg")]
    ///
    /// *Shows various inner voronoi edges (blue) and their dual Delaunay edges (orange)*
    pub fn as_delaunay_edge(&self) -> DirectedEdgeHandle<'a, V, DE, UE, F> {
        DirectedEdgeHandle::new(self.dcel, FixedDirectedEdgeHandle::new(self.handle.index()))
    }

    /// Returns this edge with its direction reversed.
    pub fn rev(&self) -> Self {
        self.as_delaunay_edge().rev().as_voronoi_edge()
    }

    /// Returns the edge that is connected to this edge in counter clockwise order.
    ///
    /// See also [prev](Self::prev)
    pub fn next(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
        self.as_delaunay_edge().ccw().as_voronoi_edge()
    }

    /// Returns the edge that is connected to this edge in clockwise order.
    ///
    /// See also [next](Self::next)
    pub fn prev(&self) -> DirectedVoronoiEdge<'a, V, DE, UE, F> {
        self.as_delaunay_edge().cw().as_voronoi_edge()
    }
}

impl<'a, V, DE, UE, F> DirectedVoronoiEdge<'a, V, DE, UE, F>
where
    V: HasPosition,
{
    /// Returns a vector that is parallel to the voronoi edge.
    ///
    /// This vector is obtained by rotating the dual Delaunay edge by 90° degree
    /// The returned vector is not necessarily normalized.
    pub fn direction_vector(&self) -> Point2<V::Scalar> {
        let from = self.as_delaunay_edge().from().position();
        let to = self.as_delaunay_edge().to().position();
        let diff = Point2::sub(&to, from);

        Point2::new(-diff.y, diff.x)
    }
}