spade/triangulation.rs
1use num_traits::Float;
2
3use crate::delaunay_core::iterators::HullIterator;
4use crate::delaunay_core::InnerOuterMarker;
5use crate::flood_fill_iterator::CircleMetric;
6use crate::flood_fill_iterator::EdgesInShapeIterator;
7use crate::flood_fill_iterator::FloodFillIterator;
8use crate::flood_fill_iterator::RectangleMetric;
9use crate::flood_fill_iterator::VerticesInShapeIterator;
10use crate::iterators::*;
11use crate::Barycentric;
12use crate::DelaunayTriangulation;
13use crate::HintGenerator;
14use crate::{delaunay_core::Dcel, handles::*};
15use crate::{HasPosition, InsertionError, Point2, TriangulationExt};
16
17use alloc::vec::Vec;
18
19/// Describes a position in a triangulation.
20///
21/// The position is set in relation to the triangulation's vertices, edges and faces.
22/// This type is usually the result of calling [Triangulation::locate]
23#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
24pub enum PositionInTriangulation {
25 /// A position lies exactly on an existing vertex. The verticis handle is given.
26 OnVertex(FixedVertexHandle),
27
28 /// A position lies exactly on an edge. The edge's handle is given.
29 OnEdge(FixedDirectedEdgeHandle),
30
31 /// A position lies in the interior of a face. The face's handle is given.
32 OnFace(FixedFaceHandle<InnerTag>),
33
34 /// A position lies outside the convex hull. The given edge handle refers to an edge
35 /// of the convex hull which has both the point and the outer face on its left side.
36 ///
37 /// *Note*: The given edge is *not* necessarily the *closest* edge to a position.
38 OutsideOfConvexHull(FixedDirectedEdgeHandle),
39
40 /// The triangulation contains either no vertices or exactly one vertex which has a
41 /// different position than the query point.
42 NoTriangulation,
43}
44
45/// Defines common operations on triangulations.
46///
47/// These operations are both available for
48/// [ConstrainedDelaunayTriangulations](crate::ConstrainedDelaunayTriangulation) and
49/// regular [DelaunayTriangulations](crate::DelaunayTriangulation).
50pub trait Triangulation: Default {
51 /// The triangulation's vertex type.
52 type Vertex: HasPosition;
53 /// The triangulation's edge type. Any new edge is created by using the `Default` trait.
54 type DirectedEdge: Default;
55 /// The triangulation's undirected edge type. Any new edge is created by using the `Default` trait.
56 type UndirectedEdge: Default;
57 /// The triangulation's face type. Any new face is created by using the `Default` trait.
58 type Face: Default;
59
60 /// The hint generator used by the triangulation. See [HintGenerator] for more information.
61 type HintGenerator: HintGenerator<<Self::Vertex as HasPosition>::Scalar>;
62
63 #[doc(hidden)]
64 fn s(&self) -> &Dcel<Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>;
65
66 #[doc(hidden)]
67 fn s_mut(
68 &mut self,
69 ) -> &mut Dcel<Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>;
70
71 #[doc(hidden)]
72 fn is_defined_legal(&self, _: FixedUndirectedEdgeHandle) -> bool {
73 false
74 }
75
76 #[doc(hidden)]
77 fn handle_legal_edge_split(&mut self, _: [FixedDirectedEdgeHandle; 2]) {}
78
79 #[doc(hidden)]
80 fn hint_generator(&self) -> &Self::HintGenerator;
81
82 #[doc(hidden)]
83 fn hint_generator_mut(&mut self) -> &mut Self::HintGenerator;
84
85 #[doc(hidden)]
86 fn from_parts(
87 dcel: Dcel<Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>,
88 hint_generator: Self::HintGenerator,
89 num_constraints: usize,
90 ) -> Self;
91
92 #[doc(hidden)]
93 #[allow(clippy::type_complexity)]
94 fn into_parts(
95 self,
96 ) -> (
97 Dcel<Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>,
98 Self::HintGenerator,
99 usize,
100 );
101
102 /// Creates a new triangulation.
103 ///
104 /// A newly created triangulation contains no vertices, no edges and the single
105 /// outer face.
106 ///
107 /// # Example
108 /// ```
109 /// use spade::{DelaunayTriangulation, Point2, Triangulation};
110 ///
111 /// let mut triangulation: DelaunayTriangulation<Point2<f64>> = DelaunayTriangulation::new();
112 /// // An empty triangulation has no vertices and one face
113 /// assert_eq!(triangulation.num_vertices(), 0);
114 /// assert_eq!(triangulation.num_all_faces(), 1);
115 /// assert_eq!(triangulation.num_inner_faces(), 0); // This count excludes the outer face
116 /// assert_eq!(triangulation.num_directed_edges(), 0);
117 ///
118 /// triangulation.insert(Point2::new(0.0, 1.0));
119 /// assert_eq!(triangulation.num_vertices(), 1);
120 /// assert_eq!(triangulation.num_inner_faces(), 0);
121 ///
122 /// triangulation.insert(Point2::new(1.0, 1.0));
123 /// // Two vertices define the first edge
124 /// assert_eq!(triangulation.num_undirected_edges(), 1);
125 ///
126 /// triangulation.insert(Point2::new(1.0, 0.0));
127 /// assert_eq!(triangulation.num_vertices(), 3);
128 // // The third point will generate the first inner face!
129 /// assert_eq!(triangulation.num_inner_faces(), 1);
130 /// ```
131 fn new() -> Self {
132 Self::default()
133 }
134
135 /// Creates a new triangulation and pre-allocates some space for vertices, edges and faces
136 fn with_capacity(num_vertices: usize, num_undirected_edges: usize, num_faces: usize) -> Self {
137 let mut result = Self::new();
138 result
139 .s_mut()
140 .reserve_capacity(num_vertices, num_undirected_edges, num_faces);
141 result
142 }
143
144 /// Removes all edges, faces and vertices from the triangulation.
145 ///
146 /// This method does not change the allocated internal capacity.
147 fn clear(&mut self) {
148 self.s_mut().clear();
149 let new_hint_generator = HintGenerator::initialize_from_triangulation(self);
150 *self.hint_generator_mut() = new_hint_generator;
151 }
152
153 /// Creates a new triangulation populated with some vertices.
154 ///
155 /// This will usually be more efficient than inserting the elements sequentially by calling
156 /// [insert](Triangulation::insert).
157 ///
158 /// Returns an [InsertionError] if any input coordinate is invalid. This method should never fail
159 /// if all vertices were successfully checked with [crate::validate_vertex].
160 ///
161 /// # Runtime
162 ///
163 /// This method has a run time of `O(n)` but will run near linearly in practice.
164 /// The runtime can be as bad as `O(n²)` if the inputs are very degenerate, e.g.
165 /// if all input vertices lie on the same line.
166 ///
167 /// # Comparison to incremental insertion
168 ///
169 /// This graph shows the difference between incremental and bulk loading for a different number of random points - bulk loading becomes
170 /// more efficient very quickly.
171 #[doc = include_str!("../images/bulk_load_vs_incremental_graph.svg")]
172 fn bulk_load(elements: Vec<Self::Vertex>) -> Result<Self, InsertionError> {
173 let with_incorrect_hint_generator: DelaunayTriangulation<_, _, _, _> =
174 crate::delaunay_core::bulk_load(elements)?;
175 let hint_generator =
176 Self::HintGenerator::initialize_from_triangulation(&with_incorrect_hint_generator);
177 let (dcel, _, _) = with_incorrect_hint_generator.into_parts();
178
179 Ok(Self::from_parts(dcel, hint_generator, 0))
180 }
181
182 /// Converts a fixed vertex handle to a reference vertex handle.
183 ///
184 /// *See also the [handles](crate::handles) module for more information.*
185 fn vertex(
186 &self,
187 handle: FixedVertexHandle,
188 ) -> VertexHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face> {
189 self.s().vertex(handle)
190 }
191
192 /// Returns a mutable reference to the associated data of a vertex.
193 fn vertex_data_mut(&mut self, handle: FixedVertexHandle) -> &mut Self::Vertex {
194 self.s_mut().vertex_data_mut(handle)
195 }
196
197 /// Converts a fixed face handle to a reference face handle.
198 ///
199 /// *See also the [handles](crate::handles) module for more information.*
200 fn face<InnerOuter: InnerOuterMarker>(
201 &self,
202 handle: FixedFaceHandle<InnerOuter>,
203 ) -> FaceHandle<
204 '_,
205 InnerOuter,
206 Self::Vertex,
207 Self::DirectedEdge,
208 Self::UndirectedEdge,
209 Self::Face,
210 > {
211 self.s().face(handle)
212 }
213
214 /// Returns a reference handle to the single outer face of this triangulation.
215 fn outer_face(
216 &self,
217 ) -> FaceHandle<
218 '_,
219 PossiblyOuterTag,
220 Self::Vertex,
221 Self::DirectedEdge,
222 Self::UndirectedEdge,
223 Self::Face,
224 > {
225 self.s().outer_face()
226 }
227
228 /// Converts a fixed directed edge handle to a reference directed edge handle.
229 ///
230 /// *See also the [handles](crate::handles) module for more information.*
231 fn directed_edge(
232 &self,
233 handle: FixedDirectedEdgeHandle,
234 ) -> DirectedEdgeHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
235 {
236 DirectedEdgeHandle::new(self.s(), handle)
237 }
238
239 /// Converts a fixed undirected edge handle to a reference undirected edge handle.
240 ///
241 /// *See also the [handles](crate::handles) module for more information.*
242 fn undirected_edge(
243 &self,
244 handle: FixedUndirectedEdgeHandle,
245 ) -> UndirectedEdgeHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
246 {
247 UndirectedEdgeHandle::new(self.s(), handle)
248 }
249
250 /// Returns a mutable reference ot the associated data of an undirected edge.
251 fn undirected_edge_data_mut(
252 &mut self,
253 handle: FixedUndirectedEdgeHandle,
254 ) -> &mut Self::UndirectedEdge {
255 self.s_mut().undirected_edge_data_mut(handle)
256 }
257
258 /// Returns the number of all faces, including the single outer face, of this
259 /// triangulation.
260 ///
261 /// This is always equal to `triangulation.num_inner_faces() + 1`.
262 fn num_all_faces(&self) -> usize {
263 self.s().num_faces()
264 }
265
266 /// Returns the number of inner faces in this triangulation.
267 fn num_inner_faces(&self) -> usize {
268 self.s().num_faces() - 1
269 }
270
271 /// Returns the number of undirected edges in this triangulation.
272 fn num_undirected_edges(&self) -> usize {
273 self.s().num_undirected_edges()
274 }
275
276 /// Returns the number of directed edges in this triangulation.
277 fn num_directed_edges(&self) -> usize {
278 self.s().num_directed_edges()
279 }
280
281 /// Returns the number of edges of the convex hull.
282 ///
283 /// *See also [convex_hull](Triangulation::convex_hull)*
284 ///
285 /// # Complexity
286 /// This method does not need to iterate through the convex hull and has a complexity of O(1)
287 fn convex_hull_size(&self) -> usize {
288 if self.all_vertices_on_line() {
289 self.num_directed_edges()
290 } else {
291 let num_inner_edges = self.num_inner_faces() * 3;
292 self.num_directed_edges() - num_inner_edges
293 }
294 }
295
296 /// An iterator visiting all directed edges.
297 ///
298 /// The iterator type is [DirectedEdgeHandle].
299 fn directed_edges(
300 &self,
301 ) -> DirectedEdgeIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
302 {
303 self.s().directed_edges()
304 }
305
306 /// An iterator over all undirected edges.
307 ///
308 /// The iterator type is [UndirectedEdgeHandle]
309 fn undirected_edges(
310 &self,
311 ) -> UndirectedEdgeIterator<
312 '_,
313 Self::Vertex,
314 Self::DirectedEdge,
315 Self::UndirectedEdge,
316 Self::Face,
317 > {
318 self.s().undirected_edges()
319 }
320
321 /// Returns the number vertices in this triangulation.
322 fn num_vertices(&self) -> usize {
323 self.s().num_vertices()
324 }
325
326 /// An iterator visiting all vertices.
327 ///
328 /// The iterator type is [VertexHandle]
329 fn vertices(
330 &self,
331 ) -> VertexIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
332 {
333 self.s().vertices()
334 }
335
336 /// An iterator visiting all vertices.
337 ///
338 /// The iterator type is [FixedVertexHandle]
339 fn fixed_vertices(&self) -> FixedVertexIterator {
340 self.s().fixed_vertices()
341 }
342
343 /// Get a vertex by its index
344 ///
345 /// To get the handle, wrap your local index in a FixedVertexHandle:
346 /// `let handle = FixedVertexHandle::from_index(my_index);`
347 #[allow(clippy::type_complexity)]
348 fn get_vertex(
349 &self,
350 handle: FixedVertexHandle,
351 ) -> Option<VertexHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>>
352 {
353 self.s().get_vertex(handle)
354 }
355
356 /// An iterator visiting all faces.
357 ///
358 /// The first returned face is the outer face, all other faces will be inner faces.
359 /// The iterator type is [FaceHandle<PossiblyOuterTag, ...>](FaceHandle).
360 ///
361 /// *See also [inner_faces()](Triangulation::inner_faces())*
362 fn all_faces(
363 &self,
364 ) -> FaceIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face> {
365 self.s().faces()
366 }
367
368 /// An iterator visiting all inner faces.
369 //
370 /// The iterator type is [FaceHandle<InnerTag, ...>](FaceHandle).
371 fn inner_faces(
372 &self,
373 ) -> InnerFaceIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
374 {
375 self.s().inner_faces()
376 }
377
378 /// An iterator visiting all faces of the Voronoi diagram.
379 ///
380 /// The iterator type is [VoronoiFace]
381 fn voronoi_faces(
382 &self,
383 ) -> VoronoiFaceIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>
384 {
385 VoronoiFaceIterator::new(self.s())
386 }
387
388 /// An iterator visiting all directed voronoi edges.
389 ///
390 /// The iterator type is [DirectedVoronoiEdge]
391 fn directed_voronoi_edges(
392 &self,
393 ) -> DirectedVoronoiEdgeIterator<
394 '_,
395 Self::Vertex,
396 Self::DirectedEdge,
397 Self::UndirectedEdge,
398 Self::Face,
399 > {
400 DirectedVoronoiEdgeIterator::new(self.s())
401 }
402
403 /// An iterator visiting all undirected voronoi edges.
404 ///
405 /// The iterator type is [UndirectedVoronoiEdge]
406 fn undirected_voronoi_edges(
407 &self,
408 ) -> UndirectedVoronoiEdgeIterator<
409 '_,
410 Self::Vertex,
411 Self::DirectedEdge,
412 Self::UndirectedEdge,
413 Self::Face,
414 > {
415 UndirectedVoronoiEdgeIterator::new(self.s())
416 }
417
418 /// Returns information about the location of a point in a triangulation.
419 ///
420 /// # Panics
421 ///
422 /// Panics if the target point has any `NAN` coordinate.
423 fn locate(
424 &self,
425 point: Point2<<Self::Vertex as HasPosition>::Scalar>,
426 ) -> PositionInTriangulation {
427 let hint = self.hint_generator().get_hint(point);
428 self.locate_with_hint_option_core(point, Some(hint))
429 }
430
431 /// Locates a vertex at a given position.
432 ///
433 /// Returns `None` if the point could not be found.
434 ///
435 /// # Panics
436 ///
437 /// Panics if the target point has any `NAN` coordinate.
438 #[allow(clippy::type_complexity)]
439 fn locate_vertex(
440 &self,
441 point: Point2<<Self::Vertex as HasPosition>::Scalar>,
442 ) -> Option<VertexHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>>
443 {
444 match self.locate(point) {
445 PositionInTriangulation::OnVertex(vertex) => Some(self.vertex(vertex)),
446 _ => None,
447 }
448 }
449
450 /// Returns an edge between two vertices.
451 ///
452 /// If the edge does not exist, `None` is returned.
453 /// This operation runs in `O(n)` time, where `n` is
454 /// the degree of `from`.
455 #[allow(clippy::type_complexity)]
456 fn get_edge_from_neighbors(
457 &self,
458 from: FixedVertexHandle,
459 to: FixedVertexHandle,
460 ) -> Option<
461 DirectedEdgeHandle<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face>,
462 > {
463 self.s().get_edge_from_neighbors(from, to)
464 }
465
466 /// Returns information about the location of a point in a triangulation.
467 ///
468 /// Additionally, a hint can be given to speed up computation.
469 /// The hint should be a vertex close to the position that
470 /// is being looked up.
471 ///
472 /// # Panics
473 ///
474 /// Panics if the target vertex has any `NAN` coordinate.
475 ///
476 /// *See also [locate](Triangulation::locate), [locate_vertex](Triangulation::locate_vertex)*
477 fn locate_with_hint(
478 &self,
479 point: Point2<<Self::Vertex as HasPosition>::Scalar>,
480 hint: FixedVertexHandle,
481 ) -> PositionInTriangulation {
482 self.locate_with_hint_option_core(point, Some(hint))
483 }
484
485 /// Inserts a new vertex into the triangulation.
486 ///
487 /// A hint can be given to speed up the process.
488 /// The hint should be a handle of a vertex close to the new vertex.
489 /// in this case the insertion time can be reduced to O(1) on average
490 /// if the hint is close. If the hint is randomized, running time will
491 /// be O(sqrt(n)) on average with an O(n) worst case.
492 ///
493 /// *See also [insert](Triangulation::insert)*
494 fn insert_with_hint(
495 &mut self,
496 t: Self::Vertex,
497 hint: FixedVertexHandle,
498 ) -> Result<FixedVertexHandle, InsertionError> {
499 self.insert_with_hint_option(t, Some(hint))
500 }
501
502 /// Attempts to remove a vertex from the triangulation.
503 ///
504 /// Returns the removed vertex data if it could be found.
505 ///
506 /// # Handle invalidation
507 /// This method will invalidate all vertex, edge and face handles
508 /// upon successful removal.
509 ///
510 /// # Panics
511 ///
512 /// Panics if the target position has any `NAN` coordinate.
513 ///
514 /// *See also [remove](Triangulation::remove)*
515 fn locate_and_remove(
516 &mut self,
517 point: Point2<<Self::Vertex as HasPosition>::Scalar>,
518 ) -> Option<Self::Vertex> {
519 match self.locate_with_hint_option_core(point, None) {
520 PositionInTriangulation::OnVertex(handle) => Some(self.remove(handle)),
521 _ => None,
522 }
523 }
524
525 /// Removes a vertex from the triangulation.
526 ///
527 /// This operation runs in O(d²), where d is the degree of the
528 /// removed vertex (the number of its outgoing edges).
529 ///
530 /// # Handle invalidation
531 /// This method will invalidate all vertex, edge and face handles.
532 fn remove(&mut self, vertex: FixedVertexHandle) -> Self::Vertex {
533 self.remove_and_notify(vertex)
534 }
535
536 /// Inserts a new vertex into the triangulation.
537 ///
538 /// This operation runs in O(log(n)) on average when using a tree
539 /// lookup to back up the triangulation, or in O(sqrt(n)) when using
540 /// a walk lookup. n denotes the number of vertices, the given
541 /// running times assume that input data is given uniformly randomly
542 /// distributed. If the point has already been contained in the
543 /// triangulation, the old vertex is overwritten.
544 ///
545 /// Returns either a handle to the new vertex or an error if the vertex could not be inserted.
546 /// The triangulation will remain unchanged if an error ocurred.
547 ///
548 /// Use [vertex](Triangulation::vertex) to retrieve more information about the inserted vertex.
549 ///
550 /// # Example
551 /// ```
552 /// # fn main() -> Result<(), spade::InsertionError> {
553 /// use spade::{DelaunayTriangulation, InsertionError, Triangulation, Point2};
554 ///
555 /// let mut triangulation = DelaunayTriangulation::<_>::default();
556 ///
557 /// let vertices = vec![Point2::new(0.0, 1.0), Point2::new(4.0, 2.0), Point2::new(3.0, 4.0)];
558 /// for vertex in vertices {
559 /// // While not required in this example, it might be a good idea in general to prevent underflow errors like this:
560 /// let corrected_position = spade::mitigate_underflow(vertex);
561 /// triangulation.insert(corrected_position)?;
562 /// }
563 ///
564 /// // Done!
565 /// assert_eq!(triangulation.num_inner_faces(), 1);
566 /// assert_eq!(triangulation.num_vertices(), 3);
567 /// # Ok(()) }
568 /// ```
569 ///
570 /// *See also [insert_with_hint](Triangulation::insert_with_hint), [validate_vertex](crate::validate_vertex),
571 /// [mitigate_underflow](crate::mitigate_underflow), [bulk_load](Triangulation::bulk_load)*
572 fn insert(&mut self, vertex: Self::Vertex) -> Result<FixedVertexHandle, InsertionError> {
573 self.insert_with_hint_option(vertex, None)
574 }
575
576 /// An iterator visiting all undirected edges.
577 ///
578 /// The iterator type is [FixedUndirectedEdgeHandle].
579 fn fixed_undirected_edges(&self) -> FixedUndirectedEdgeIterator {
580 FixedUndirectedEdgeIterator::new(self.num_undirected_edges())
581 }
582
583 /// An iterator visiting all directed edges.
584 ///
585 /// The iterator type is [FixedDirectedEdgeHandle].
586 fn fixed_directed_edges(&self) -> FixedDirectedEdgeIterator {
587 FixedDirectedEdgeIterator::new(self.num_directed_edges())
588 }
589
590 /// An iterator visiting all faces.
591 ///
592 /// The first returned element is the outer face. All other
593 /// faces are inner faces.
594 ///
595 /// The iterator type is [FixedFaceHandle<PossiblyOuterTag, ...>](FixedFaceHandle).
596 fn fixed_all_faces(&self) -> FixedFaceIterator {
597 FixedFaceIterator::new(self.num_all_faces())
598 }
599
600 /// An iterator visiting all inner faces of the triangulation.
601 ///
602 /// The iterator type is [FixedFaceHandle<InnerTag, ...>](FixedFaceHandle).
603 fn fixed_inner_faces(&self) -> FixedInnerFaceIterator {
604 let mut result = FixedInnerFaceIterator::new(self.num_all_faces());
605 result.next();
606 result
607 }
608
609 /// Returns `true` if all vertices lie on a single line.
610 ///
611 /// This is always the case for triangulations with 0, 1 or two vertices.
612 fn all_vertices_on_line(&self) -> bool {
613 self.num_all_faces() == 1
614 }
615
616 /// Returns an iterator over all convex hull edges.
617 ///
618 /// The edges are returned in clockwise order as seen from any point in the triangulation.
619 ///
620 #[doc = include_str!("../images/convex_hull.svg")]
621 ///
622 /// *A triangulation with its convex hull being highlighted. `e0` .. `e5` denote the returned
623 /// edges in clockwise order.*
624 ///
625 /// *See also [convex_hull_size](Triangulation::convex_hull_size)*
626 fn convex_hull(
627 &self,
628 ) -> HullIterator<'_, Self::Vertex, Self::DirectedEdge, Self::UndirectedEdge, Self::Face> {
629 {
630 HullIterator::new(self.s())
631 }
632 }
633
634 /// Returns a mutable reference to the associated data of a face.
635 fn face_data_mut<InnerOuter: InnerOuterMarker>(
636 &mut self,
637 handle: FixedFaceHandle<InnerOuter>,
638 ) -> &mut Self::Face {
639 self.s_mut().face_data_mut(handle)
640 }
641
642 /// Returns a mutable reference to the associated data of a directed edge.
643 fn directed_edge_data_mut(
644 &mut self,
645 handle: FixedDirectedEdgeHandle,
646 ) -> &mut Self::DirectedEdge {
647 self.s_mut().directed_edge_data_mut(handle)
648 }
649}
650
651/// Implements general functions for triangulations over floating point data types.
652///
653/// This trait is implemented for any triangulation (constrained and regular Delaunay triangulations)
654/// over `f32` and `f64`.
655pub trait FloatTriangulation: Triangulation
656where
657 <Self::Vertex as HasPosition>::Scalar: Float,
658{
659 /// Returns all edges contained in a rectangle.
660 ///
661 /// An edge is considered to be contained in the rectangle if at least one point exists
662 /// that is both on the edge and inside the rectangle (including its boundary).
663 ///
664 /// The rectangle is specified by its lower and upper corners. Yields an empty iterator
665 /// if `lower.x > upper.x` or `lower.y > upper.y`.
666 ///
667 #[doc = include_str!("../images/shape_iterator_rectangle_edges.svg")]
668 ///
669 /// *Example: Shows all edges (red) that are returned when iterating over a rectangle (teal)*
670 ///
671 /// # Memory consumption
672 ///
673 /// Memory usage is, on average, in O(|convex_hull(E)|) where "E" refers to all edges that
674 /// have been returned so far.
675 fn get_edges_in_rectangle(
676 &self,
677 lower: Point2<<Self::Vertex as HasPosition>::Scalar>,
678 upper: Point2<<Self::Vertex as HasPosition>::Scalar>,
679 ) -> EdgesInShapeIterator<'_, Self, RectangleMetric<<Self::Vertex as HasPosition>::Scalar>>
680 {
681 let distance_metric = RectangleMetric::new(lower, upper);
682 let center = lower.add(upper).mul(0.5f32.into());
683 EdgesInShapeIterator {
684 inner_iter: FloodFillIterator::new(self, distance_metric, center),
685 }
686 }
687
688 /// Returns all edges contained in a circle.
689 ///
690 /// An edge is considered to be contained in a circle if at least one point exists that is both
691 /// on the edge and within the circle (including its boundary).
692 ///
693 /// `radius_2` refers to the **squared radius** of the circle.
694 ///
695 #[doc = include_str!("../images/shape_iterator_circle_edges.svg")]
696 ///
697 /// *Example: Shows all edges (red) that are returned when iterating over a circle (teal)*
698 ///
699 /// # Panics
700 ///
701 /// Panics if `radius_2 < 0.0`
702 ///
703 /// # Memory consumption
704 ///
705 /// Memory usage is, on average, in O(|convex_hull(E)|) where "E" refers to all edges that
706 /// have been returned so far.
707 fn get_edges_in_circle(
708 &self,
709 center: Point2<<Self::Vertex as HasPosition>::Scalar>,
710 radius_2: <Self::Vertex as HasPosition>::Scalar,
711 ) -> EdgesInShapeIterator<'_, Self, CircleMetric<<Self::Vertex as HasPosition>::Scalar>> {
712 let metric = CircleMetric::new(center, radius_2);
713 EdgesInShapeIterator {
714 inner_iter: FloodFillIterator::new(self, metric, center),
715 }
716 }
717
718 /// Returns all vertices in a rectangle.
719 ///
720 /// Any vertex on the rectangle's boundary or corners is also returned.
721 ///
722 /// The rectangle is specified by its lower and upper corners. Yields an empty iterator
723 /// if `lower.x > upper.x || lower.y > upper.y`.
724 ///
725 #[doc = include_str!("../images/shape_iterator_rectangle_vertices.svg")]
726 ///
727 /// *Example: Shows all vertices (red) that are returned when iterating over a rectangle (teal)*
728 ///
729 /// # Memory consumption
730 ///
731 /// Consumed memory is in `O(|convex_hull(V)|)` where `V` refers to all vertices that have been
732 /// returned so far.
733 fn get_vertices_in_rectangle(
734 &self,
735 lower: Point2<<Self::Vertex as HasPosition>::Scalar>,
736 upper: Point2<<Self::Vertex as HasPosition>::Scalar>,
737 ) -> VerticesInShapeIterator<'_, Self, RectangleMetric<<Self::Vertex as HasPosition>::Scalar>>
738 {
739 let distance_metric = RectangleMetric::new(lower, upper);
740 let center = lower.add(upper).mul(0.5f32.into());
741
742 VerticesInShapeIterator::new(FloodFillIterator::new(self, distance_metric, center))
743 }
744
745 /// Returns all vertices in a circle.
746 ///
747 /// Any vertex on the circle's boundary is also returned.
748 ///
749 /// `radius_2` refers to the **squared radius** of the circle.
750 ///
751 #[doc = include_str!("../images/shape_iterator_circle_vertices.svg")]
752 ///
753 /// *Example: Shows all vertices (red) that are returned when iterating over a circle (teal)*
754 ///
755 /// # Panics
756 ///
757 /// Panics if `radius_2 < 0.0`
758 ///
759 /// # Memory consumption
760 ///
761 /// Consumed memory is in `O(|convex_hull(V)|)` where `V` refers to all vertices that have been
762 /// returned so far.
763 fn get_vertices_in_circle(
764 &self,
765 center: Point2<<Self::Vertex as HasPosition>::Scalar>,
766 radius_2: <Self::Vertex as HasPosition>::Scalar,
767 ) -> VerticesInShapeIterator<'_, Self, CircleMetric<<Self::Vertex as HasPosition>::Scalar>>
768 {
769 let distance_metric = CircleMetric::new(center, radius_2);
770
771 VerticesInShapeIterator::new(FloodFillIterator::new(self, distance_metric, center))
772 }
773
774 /// Used for barycentric interpolation on this triangulation. Refer to the documentation of
775 /// [Barycentric] and [crate::NaturalNeighbor] for more information.
776 ///
777 /// *Note:* In contrast to the other interpolation algorithms, barycentric interpolation also works
778 /// for [crate::ConstrainedDelaunayTriangulation]s.
779 fn barycentric(&self) -> Barycentric<'_, Self> {
780 Barycentric::new(self)
781 }
782}
783
784impl<T> FloatTriangulation for T
785where
786 T: Triangulation,
787 <T::Vertex as HasPosition>::Scalar: Float,
788{
789}