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
//! ## The Common Spatial Index Interface
//!
//! Every tree in this crate answers the same questions: store an item, drop an item, count what is
//! stored, find the nearest items to a query, and find the items inside a region. [`SpatialIndex`]
//! states those operations once so that code can be written against "a spatial index" rather than
//! against one specific tree, and so that one test harness can hold every tree to the same contract.
//!
//! ### Example
//!
//! ```
//! use spart::geometry::{EuclideanDistance, Point2D, Rectangle};
//! use spart::index::SpatialIndex;
//! use spart::kdtree::KdTree;
//! use spart::quadtree::Quadtree;
//!
//! // One function, any tree.
//! fn nearest_label<I>(index: &I, query: &Point2D<&'static str>) -> Option<&'static str>
//! where
//! I: SpatialIndex<Item = Point2D<&'static str>>,
//! {
//! index
//! .knn_search::<EuclideanDistance>(query, 1)
//! .first()
//! .and_then(|point| point.data)
//! }
//!
//! let boundary = Rectangle { x: 0.0, y: 0.0, width: 100.0, height: 100.0 };
//! let mut quadtree: Quadtree<&'static str> = Quadtree::new(&boundary, 4).unwrap();
//! let mut kdtree: KdTree<Point2D<&'static str>> = KdTree::new();
//! for point in [Point2D::new(10.0, 10.0, Some("near")), Point2D::new(90.0, 90.0, Some("far"))] {
//! // Called through the trait, so both trees answer with the same `Result<bool, _>`.
//! assert!(SpatialIndex::insert(&mut quadtree, point.clone()).unwrap());
//! assert!(SpatialIndex::insert(&mut kdtree, point).unwrap());
//! }
//!
//! let query = Point2D::new(12.0, 12.0, None);
//! assert_eq!(nearest_label(&quadtree, &query), Some("near"));
//! assert_eq!(nearest_label(&kdtree, &query), Some("near"));
//! ```
use crateSpartError;
use crateDistanceMetric;
/// The operations every spatial index in this crate provides.
///
/// ### Contract
///
/// * `insert` returns `Ok(false)` for an item the index declines to store, which for a tree built
/// over a fixed boundary means an item outside it. It returns `Err` only when the item cannot be
/// interpreted at all, such as a point whose dimension does not match the tree's.
/// * `insert_bulk` reports how many items it stored. It stores every item it accepts and skips the
/// rest, so a count below `items.len()` means the remainder was declined, not that nothing was
/// stored. An `Err` is different: it means the batch was rejected before anything was stored, so
/// the index is unchanged and the whole batch can be retried.
/// * Queries borrow from the index rather than cloning, so a caller that wants owned items clones
/// only the ones it keeps.
/// * `knn_search` returns at most `k` items ordered nearest first. Items at equal distance are
/// ordered deterministically for a given tree and insertion history, but the order is the tree's
/// traversal order rather than the order they were inserted in, and it differs between trees. Do
/// not rely on which of several equidistant items comes back first.
/// * `range_search_bbox` returns exactly the items the volume contains, on every tree.
///
/// Pruning throughout assumes the metric agrees with Euclidean distance on which of two points is
/// nearer. A metric that does not may return fewer items than it should.
///
/// ### Inherent Methods Take Precedence
///
/// Each tree also has inherent methods of the same names, kept because they can be more precise
/// about what that particular tree does: `Quadtree::insert` returns a plain `bool` because a quadtree
/// cannot fail for any other reason, and `RTree::insert` returns nothing at all because it cannot
/// fail. Rust resolves `tree.insert(item)` to the inherent method, so reach for this trait through
/// `SpatialIndex::insert(&mut tree, item)` or from a generic function when you want the uniform
/// contract above.