Expand description
Handle types used for traversal and modification of triangulations.
A handle can either be a “reference handle” or a “fixed handle”. Reference handles are used for immutable access to a triangulation. Fixed handles allow mutation but have a more limited API.
§Reference handles
Reference handles come in one of four variants:
- FaceHandles refer to a single face (triangle) of the triangulation. They are used get the triangle’s adjacent vertices and edges. They also may refer to the single outer face.
- VertexHandles refer to a single vertex of the triangulation. They allow to retrieve the vertex position and its outgoing edges.
- DirectedEdgeHandles refer to a single directed edge. They allow to retrieve the edges origin and destination vertex, its adjacent face as well as its previous and next edge.
- UndirectedEdgeHandles refer to an edge without specifying its direction.
All handles also allow to set and retrieve arbitrary additional data associated with that element. Refer to the type parameters of Triangulation for more details.
§Fixed handles
Reference handles all hold an immutable reference to the underlying triangulation.
This reference is used to implement a feature rich and intuitive API. However,
due to Rust’s ownership semantics, modification of a triangulation
can not be done using these handles as that would require a mutable reference. This is
required in some cases, e.g. whenever traversal of the triangulation is mixed with insertion
operations or when attempting to remove vertices.
As a solution, Spade relies on fixed handles for mutation: These are created from normal
handles by calling some_handle.fix()
and do not keep a reference to the triangulation.
Internally, fixed handles are implemented as indices into a Vec
. Removing elements from
the triangulation can possibly invalidate any fixed handle. Attempting to resolve an invalid
handle may either refer to a different element or panic at run time. It is the callers
responsibility to make sure that fixed handles are not used anymore after a removal operation
has taken place.
Fixed handles also come in four variants, depending on which element they refer to:
§Retrieving handles by iteration
The Triangulation trait defines iterators for all handle types:
Vertices | Directed Edges | Undirected Edges | Faces | |
---|---|---|---|---|
Reference | vertices() | directed_edges() | undirected_edges() | inner_faces() all_faces() |
Fixed | fixed_vertices() | fixed_directed_edges() | fixed_undirected_edges() | fixed_inner_faces() fixed_faces() |
§Creating handles directly
In some cases it may be desireable to create vertex handles artificially by providing the index manually. This can be done by calling handles::FixedVertexHandle::from_index. Make sure that the provided index is smaller than the number of vertices in the triangulation.
§Converting between reference and fixed handles
Converting a reference handle into its fixed counterpart is performed via the
fix()
method (defined on any handle type).
Converting a fixed handle type back into a reference handle requires calling either Triangulation::vertex, Triangulation::face, Triangulation::directed_edge or Triangulation::undirected_edge.
§Example: Using handles
This example implements a nearest neighbor algorithm on a delaunay triangulation. Starting from an arbitrary start vertex, it greedily walks to the closes vertex until arriving at a local minimum. Due to the special properties of Delaunay triangulations, this is also the global nearest neighbor.
Note: Spade already implements this method, see DelaunayTriangulation::nearest_neighbor
use spade::handles::VertexHandle;
use spade::{DelaunayTriangulation, Point2, Triangulation};
fn nearest_neighbor(
triangulation: &DelaunayTriangulation<Point2<f64>>,
target_point: Point2<f64>,
) -> VertexHandle<Point2<f64>> {
let mut current = triangulation.vertices().next().unwrap();
let mut best_distance = current.position().distance_2(target_point);
loop {
let mut closer = None;
for neighbor in current.out_edges().map(|edge| edge.to()) {
let neighbor_distance = neighbor.position().distance_2(target_point);
if neighbor_distance < best_distance {
best_distance = neighbor_distance;
closer = Some(neighbor);
break;
}
}
if let Some(closer) = closer {
current = closer;
} else {
return current;
}
}
}
let vertices = vec![
Point2::new(0.0, 1.0),
Point2::new(1.0, 1.0),
Point2::new(0.0, 0.0),
Point2::new(1.0, 0.0),
];
let triangulation: DelaunayTriangulation<Point2<f64>> = Triangulation::bulk_load(vertices)?;
// Check that everything works!
for vertex in triangulation.vertices() {
let nearest_neighbor = nearest_neighbor(&triangulation, vertex.position());
assert_eq!(nearest_neighbor, vertex);
}
Structs§
- Marker type that signifies that a face is an inner faces.
- Marker type that signifies that a face can possibly be the outer faces.
Enums§
- A handle to a vertex of the voronoi diagram.
Constants§
- Returns a reference to the single outer face.
Type Aliases§
- Handle to a directed edge of a triangulation.
- A handle to a directed edge of the Voronoi diagram.
- Handle to a face of a triangulation.
- Fixed handle to a directed edge.
- “Fixed handle to a face.
- Fixed handle to an undirected edge.
- Fixed handle to a vertex.
- Handle to an undirected edge of a triangulation.
- A handle to an undirected edge of the Voronoi diagram.
- Handle to a vertex of a triangulation.
- A handle to a face of the voronoi diagram.