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