Struct rstar::RTree[][src]

pub struct RTree<T, Params = DefaultParams> where
    Params: RTreeParams,
    T: RTreeObject
{ /* fields omitted */ }
Expand description

An n-dimensional r-tree data structure.

R-Trees

R-Trees are data structures containing multi-dimensional objects like points, rectangles or polygons. They are optimized for retrieving the nearest neighbor at any point.

R-trees can efficiently find answers to queries like “Find the nearest point of a polygon”, “Find all police stations within a rectangle” or “Find the 10 nearest restaurants, sorted by their distances”. Compared to a naive implementation for these scenarios that runs in O(n) for n inserted elements, r-trees reduce this time to O(log(n)).

However, creating an r-tree is time consuming and runs in O(n * log(n)). Thus, r-trees are suited best if many queries and only few insertions are made. Also, rstar supports bulk loading, which cuts down the constant factors when creating an r-tree significantly compared to sequential insertions.

R-trees are also dynamic, thus, points can be inserted and removed even if the tree has been created before.

Partitioning heuristics

The inserted objects are internally partitioned into several boxes which should have small overlap and volume. This is done heuristically. While the originally proposed heuristic focused on fast insertion operations, the resulting r-trees were often suboptimally structured. Another heuristic, called R*-tree (r-star-tree), was proposed to improve the tree structure at the cost of longer insertion operations and is currently the crate’s only implemented insertion strategy.

Further reading

For more information refer to the wikipedia article.

Usage

The items inserted into an r-tree must implement the RTreeObject trait. To support nearest neighbor queries, implement the PointDistance trait. Some useful geometric primitives that implement the above traits can be found in the primitives module.

Example

use rstar::RTree;

let mut tree = RTree::new();
tree.insert([0.1, 0.0f32]);
tree.insert([0.2, 0.1]);
tree.insert([0.3, 0.0]);

assert_eq!(tree.nearest_neighbor(&[0.4, -0.1]), Some(&[0.3, 0.0]));
tree.remove(&[0.3, 0.0]);
assert_eq!(tree.nearest_neighbor(&[0.4, 0.3]), Some(&[0.2, 0.1]));

assert_eq!(tree.size(), 2);
// &RTree implements IntoIterator!
for point in &tree {
    println!("Tree contains a point {:?}", point);
}

Supported point types

All types implementing the Point trait can be used as underlying point type. By default, fixed size arrays can be used as points.

Type Parameters

  • T: The type of objects stored in the r-tree.
  • Params: Compile time parameters that change the r-trees internal layout. Refer to the RTreeParams trait for more information.

Defining methods generic over r-trees

If a library defines a method that should be generic over the r-tree type signature, make sure to include both type parameters like this:

pub fn generic_rtree_function<T, Params>(tree: &mut RTree<T, Params>)
where
  T: RTreeObject,
  Params: RTreeParams
{
  // ...
}

Otherwise, any user of generic_rtree_function would be forced to use a tree with default parameters.

Runtime and Performance

The runtime of query operations (e.g. nearest neighbor or contains) is usually O(log(n)), where n refers to the number of elements contained in the r-tree. A naive sequential algorithm would take O(n) time. However, r-trees incur higher build up times: inserting an element into an r-tree costs O(log(n)) time.

Bulk loading

In many scenarios, insertion is only done once for many points. In this case, bulk_load will be considerably faster. Its total run time is still O(log(n)).

Element distribution

The tree’s performance heavily relies on the spatial distribution of its elements. Best performance is achieved if:

  • No element is inserted more than once
  • The overlapping area of elements should be as small a possible.

For the edge case that all elements are overlapping (e.g, one and the same element is contained n times), the performance of most operations usually degrades to O(n).

(De)Serialization

Enable the serde feature for Serde support.

Implementations

Creates a new, empty r-tree.

The created r-tree is configured with default parameters.

Creates a new r-tree with some elements already inserted.

This method should be the preferred way for creating r-trees. It both runs faster and yields an r-tree with better internal structure that improves query performance.

This method implements the overlap minimizing top down bulk loading algorithm as described in this paper.

Runtime

Bulk loading runs in O(n * log(n)), where n is the number of loaded elements.

Creates a new, empty r-tree.

The tree’s compile time parameters must be specified. Refer to the RTreeParams trait for more information and a usage example.

Creates a new r-tree with some given elements and configurable parameters.

For more information refer to bulk_load and RTreeParameters.

Returns the number of objects in an r-tree.

Example
use rstar::RTree;

let mut tree = RTree::new();
assert_eq!(tree.size(), 0);
tree.insert([0.0, 1.0, 2.0]);
assert_eq!(tree.size(), 1);
tree.remove(&[0.0, 1.0, 2.0]);
assert_eq!(tree.size(), 0);

Returns an iterator over all elements contained in the tree.

The order in which the elements are returned is not specified.

Example
use rstar::RTree;
let tree = RTree::bulk_load(vec![[0.0, 0.1], [0.3, 0.2], [0.4, 0.2]]);
for point in tree.iter() {
    println!("This tree contains point {:?}", point);
}

Returns an iterator over all mutable elements contained in the tree.

The order in which the elements are returned is not specified.

Note: It is a logic error to change an inserted item’s position or dimensions. This method is primarily meant for own implementations of RTreeObject which can contain arbitrary additional data. If the position or location of an inserted object need to change, you will need to [remove] and reinsert it.

Returns all elements contained in an Envelope.

Usually, an envelope is an axis aligned bounding box. This method can be used to get all elements that are fully contained within an envelope.

Example
use rstar::{RTree, AABB};
let mut tree = RTree::bulk_load(vec![
  [0.0, 0.0],
  [0.0, 1.0],
  [1.0, 1.0]
]);
let half_unit_square = AABB::from_corners([0.0, 0.0], [0.5, 1.0]);
let unit_square = AABB::from_corners([0.0, 0.0], [1.0, 1.0]);
let elements_in_half_unit_square = tree.locate_in_envelope(&half_unit_square);
let elements_in_unit_square = tree.locate_in_envelope(&unit_square);
assert_eq!(elements_in_half_unit_square.count(), 2);
assert_eq!(elements_in_unit_square.count(), 3);

Mutable variant of locate_in_envelope.

Returns all elements whose envelope intersects a given envelope.

Any element fully contained within an envelope is also returned by this method. Two envelopes that “touch” each other (e.g. by sharing only a common corner) are also considered to intersect. Usually, an envelope is an axis aligned bounding box. This method will return all elements whose AABB has some common area with a given AABB.

Example
use rstar::{RTree, AABB};
use rstar::primitives::Rectangle;

let left_piece = AABB::from_corners([0.0, 0.0], [0.4, 1.0]);
let right_piece = AABB::from_corners([0.6, 0.0], [1.0, 1.0]);
let middle_piece = AABB::from_corners([0.25, 0.0], [0.75, 1.0]);

let mut tree = RTree::<Rectangle<_>>::bulk_load(vec![
  left_piece.into(),
  right_piece.into(),
  middle_piece.into(),
]);

let elements_intersecting_left_piece = tree.locate_in_envelope_intersecting(&left_piece);
// The left piece should not intersect the right piece!
assert_eq!(elements_intersecting_left_piece.count(), 2);
let elements_intersecting_middle = tree.locate_in_envelope_intersecting(&middle_piece);
// Only the middle piece intersects all pieces within the tree
assert_eq!(elements_intersecting_middle.count(), 3);

let large_piece = AABB::from_corners([-100., -100.], [100., 100.]);
let elements_intersecting_large_piece = tree.locate_in_envelope_intersecting(&large_piece);
// Any element that is fully contained should also be returned:
assert_eq!(elements_intersecting_large_piece.count(), 3);

Locates elements in the r-tree defined by a selection function.

Refer to the documentation of SelectionFunction for more information.

Usually, other locate methods should cover most common use cases. This method is only required in more specific situations.

Mutable variant of locate_with_selection_function.

Gets all possible intersecting objects of this and another tree.

This will return all objects whose envelopes intersect. No geometric intersection checking is performed.

Returns the tree’s root node.

Usually, you will not require to call this method. However, for debugging purposes or for advanced algorithms, knowledge about the tree’s internal structure may be required. For these cases, this method serves as an entry point.

Removes and returns a single element from the tree. The element to remove is specified by a SelectionFunction.

See also: remove, remove_at_point

Returns a single object that covers a given point.

Method contains_point is used to determine if a tree element contains the given point.

If multiple elements contain the given point, any of them is returned.

Mutable variant of locate_at_point.

Locate all elements containing a given point.

Method contains_point is used to determine if a tree element contains the given point.

Example
use rstar::RTree;
use rstar::primitives::Rectangle;

let tree = RTree::bulk_load(vec![
  Rectangle::from_corners([0.0, 0.0], [2.0, 2.0]),
  Rectangle::from_corners([1.0, 1.0], [3.0, 3.0])
]);

assert_eq!(tree.locate_all_at_point(&[1.5, 1.5]).count(), 2);
assert_eq!(tree.locate_all_at_point(&[0.0, 0.0]).count(), 1);
assert_eq!(tree.locate_all_at_point(&[-1., 0.0]).count(), 0);

Mutable variant of locate_all_at_point.

Removes an element containing a given point.

The removed element, if any, is returned. If multiple elements cover the given point, only one of them is removed and returned.

Example
use rstar::RTree;
use rstar::primitives::Rectangle;

let mut tree = RTree::bulk_load(vec![
  Rectangle::from_corners([0.0, 0.0], [2.0, 2.0]),
  Rectangle::from_corners([1.0, 1.0], [3.0, 3.0])
]);

assert!(tree.remove_at_point(&[1.5, 1.5]).is_some());
assert!(tree.remove_at_point(&[1.5, 1.5]).is_some());
assert!(tree.remove_at_point(&[1.5, 1.5]).is_none());

Returns true if a given element is equal (==) to an element in the r-tree.

This method will only work correctly if two equal elements also have the same envelope.

Example
use rstar::RTree;

let mut tree = RTree::new();
assert!(!tree.contains(&[0.0, 2.0]));
tree.insert([0.0, 2.0]);
assert!(tree.contains(&[0.0, 2.0]));

Removes and returns an element of the r-tree equal (==) to a given element.

If multiple elements equal to the given elements are contained in the tree, only one of them is removed and returned.

This method will only work correctly if two equal elements also have the same envelope.

Example
use rstar::RTree;

let mut tree = RTree::new();
tree.insert([0.0, 2.0]);
// The element can be inserted twice just fine
tree.insert([0.0, 2.0]);
assert!(tree.remove(&[0.0, 2.0]).is_some());
assert!(tree.remove(&[0.0, 2.0]).is_some());
assert!(tree.remove(&[0.0, 2.0]).is_none());

Returns the nearest neighbor for a given point.

The distance is calculated by calling PointDistance::distance_2

Example
use rstar::RTree;
let tree = RTree::bulk_load(vec![
  [0.0, 0.0],
  [0.0, 1.0],
]);
assert_eq!(tree.nearest_neighbor(&[-1., 0.0]), Some(&[0.0, 0.0]));
assert_eq!(tree.nearest_neighbor(&[0.0, 2.0]), Some(&[0.0, 1.0]));

Returns all elements of the tree within a certain distance.

The elements may be returned in any order. Each returned element will have a squared distance less or equal to the given squared distance.

This method makes use of distance_2_if_less_or_equal. If performance is critical and the distance calculation to the object is fast, overwriting this function may be beneficial.

Returns all elements of the tree sorted by their distance to a given point.

Runtime

Every next() call runs in O(log(n)). Creating the iterator runs in O(log(n)). The r-tree documentation contains more information about r-tree performance.

Example
use rstar::RTree;
let tree = RTree::bulk_load(vec![
  [0.0, 0.0],
  [0.0, 1.0],
]);

let nearest_neighbors = tree.nearest_neighbor_iter(&[0.5, 0.0]).collect::<Vec<_>>();
assert_eq!(nearest_neighbors, vec![&[0.0, 0.0], &[0.0, 1.0]]);
👎 Deprecated:

Please use nearest_neighbor_iter_with_distance_2 instead

Returns (element, distance^2) tuples of the tree sorted by their distance to a given point.

The distance is calculated by calling PointDistance::distance_2.

Returns (element, distance^2) tuples of the tree sorted by their distance to a given point.

The distance is calculated by calling PointDistance::distance_2.

Removes the nearest neighbor for a given point and returns it.

The distance is calculated by calling PointDistance::distance_2.

Example
use rstar::RTree;
let mut tree = RTree::bulk_load(vec![
  [0.0, 0.0],
  [0.0, 1.0],
]);
assert_eq!(tree.pop_nearest_neighbor(&[0.0, 0.0]), Some([0.0, 0.0]));
assert_eq!(tree.pop_nearest_neighbor(&[0.0, 0.0]), Some([0.0, 1.0]));
assert_eq!(tree.pop_nearest_neighbor(&[0.0, 0.0]), None);

Inserts a new element into the r-tree.

If the element has already been present in the tree, it will now be present twice.

Runtime

This method runs in O(log(n)). The r-tree documentation contains more information about r-tree performance.

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns the “default value” for a type. Read more

Which kind of iterator are we turning this into?

The type of the elements being iterated over.

Creates an iterator from a value. Read more

Which kind of iterator are we turning this into?

The type of the elements being iterated over.

Creates an iterator from a value. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

Should always be Self

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.