1
use std::{cmp::Ordering, mem, ops::{Index, IndexMut}};
2

            
3
use num_traits::Zero;
4

            
5
use crate::{get_bounds, mmheap::MmHeap, KdPoint, KdRegion, WalkDecision};
6

            
7
/// Represents an inner / outer limit for a query within the tree ([`KdTree::k_closest`]).
8
/// See [`QueryOptions`] for more info
9
pub enum QueryBound<'a, R: KdRegion> {
10
    SqDist(<R::Point as KdPoint>::Distance),
11
    Region(&'a R),
12
    None
13
}
14

            
15
/// Fine grained control over a query within the tree ([`KdTree::k_closest`]).
16
pub struct QueryOptions<'a, R: KdRegion> {
17
    /// Points within this bound will be EXCLUDED from the query result.
18
    /// Points ON the inner boundary will also be EXCLUDED (ie the excluded region is a closed set).
19
    /// Useful to exclude points that are "too close" to the query point,
20
    /// for example when iteratively increasing a sampling radius in a shortest path algorithm
21
    /// or some other situation where the number of k_closest points needed is not know a prior.
22
    /// For `QueryBound::SqDist(d)`, this means points whose sqdist from the query point is <= d will be excluded.
23
    /// Since the query point itself is included by default if it is in the tree, passing `QueryBound::SqDist(Distance::zero())`
24
    /// here can be used to exclude it.
25
    /// For `QueryBound::Region(&r)`, this means points within `r` (where `r.min_sqdist` is `Distance::zero()`) will excluded.
26
    /// NB this cannot be conservative like an unbounded search.
27
    /// That is, if `R::min_sqdist` can be an underestimate, then `QueryBound::Region` should not be used.
28
    /// For `QueryBound::None`, no points will be excluded for being "too close" to the query point.
29
    pub inner_bound: QueryBound<'a, R>,
30
    /// Points outside this bound will be EXCLUDED from the query result.
31
    /// Points ON the outer boundary will be INCLUDED (ie the excluded region is an open set).
32
    /// This makes the overall included region a half open set, excluding the inner bound but including
33
    /// the outer bound.  This is to make it easy to have successive queries cover additional area without duplicate results.
34
    /// For `QueryBound::SqDist(d)`, points whose sqdist from the query point is > d will be excluded.
35
    /// For `QueryBount::Region(&r)`, points outside `r` (where `r.min_sqdist` is not `Distance::zero()`) will be excluded.
36
    /// Unlike the inner bound, this will work correctly with a conservative `R::min_sqdist` (ie if min_sqdist is an underestimate
37
    /// it can only cause the result to include extra points, not miss points that should be included).
38
    /// For `QueryBound::None`, no points will be excluded for being "too far" from the query point.
39
    pub outer_bound: QueryBound<'a, R>,
40
    /// If false, if multiple points are tied for being the kth closest, which one will be returned is arbitrary,
41
    /// but exactly k points will be returned.
42
    /// If true, if multiple points are tied for being the kth closest, all of them will be returned,
43
    /// and more than k points will be returned in this case.
44
    /// Setting this to true is necessary to correctly call [`KdTree::k_closest`] with an iteratively increasing sampling
45
    /// radius.
46
    pub keep_ties: bool
47
}
48

            
49
impl<'a, R: KdRegion> QueryOptions<'a, R> {
50
    /// Default `QueryOptions` to have the included region be the entire tree,
51
    /// and return all points which are tied for being the kth-closest
52
    pub const ALL_KEEP_TIES: Self = Self{inner_bound: QueryBound::None, outer_bound: QueryBound::None, keep_ties: true};
53
    /// Default `QueryOptions` to have the included region be the entire tree,
54
    /// and arbitrarily break ties for the kth-closest point so no more than k points are ever returned.
55
    pub const ALL_NO_TIES: Self = Self{inner_bound: QueryBound::None, outer_bound: QueryBound::None, keep_ties: false};
56
    /// Returns true if the included region contains the point `pt`, where `point` is the center of the query,
57
    /// or false if `pt` is in the excluded region.
58
500000
    pub fn contains(&self, point: &R::Point, pt: &R::Point) -> bool {
59
500000
        match &self.outer_bound {
60
            QueryBound::SqDist(max_sqdist) => if point.sqdist(pt) > *max_sqdist { return false },
61
            QueryBound::Region(r) => if r.min_sqdist(pt) > <R::Point as KdPoint>::Distance::zero() { return false },
62
500000
            QueryBound::None => ()
63
        }
64
500000
        match &self.inner_bound {
65
            QueryBound::SqDist(lb_sqdist) => point.sqdist(pt) > *lb_sqdist,
66
            QueryBound::Region(r) => r.min_sqdist(pt) > <R::Point as KdPoint>::Distance::zero(),
67
500000
            QueryBound::None => true
68
        }
69
500000
    }
70
    /// Returns true if the included region might overlap with `bounds` and
71
    /// might contain additional points within `max_sqdist` of the center of the query, `point`.
72
    /// When some of the required functions of `<R as KdRegion>` are implemented conservatively,
73
    /// this function will return true in cases where the query region and `bounds` can't
74
    /// actually contain any additional points in the result set.
75
    /// However, when this function returns false, the query region will always be disjoint from `bounds`,
76
    /// UNLESS `self.inner_bound` is not `QueryBound::None` and a conservative implementation is used for [`KdRegion`].
77
    pub fn might_overlap(&self, point: &R::Point, max_sqdist: Option<&<R::Point as KdPoint>::Distance>, bounds: &R) -> bool {
78
        if let Some(d) = max_sqdist {
79
            match bounds.min_sqdist(point).cmp(d) {
80
                Ordering::Greater => return false,
81
                Ordering::Equal => if !self.keep_ties { return false },
82
                Ordering::Less => ()
83
            }
84
        }
85
        match &self.outer_bound {
86
            QueryBound::SqDist(outer_sqdist) => if bounds.min_sqdist(point) > *outer_sqdist { return false },
87
            QueryBound::Region(r) => if !r.might_overlap(bounds) { return false },
88
            QueryBound::None => ()
89
        }
90
        match &self.inner_bound {
91
            QueryBound::SqDist(inner_sqdist) => !bounds.max_sqdist(point).is_some_and(|d|d <= *inner_sqdist),
92
            QueryBound::Region(r) => !r.is_superset(bounds),
93
            QueryBound::None => true
94
        }
95
    }
96
}
97

            
98
/// A KD tree represents a collection of points in space, with the ability to answer distance related queries, mainly:
99
/// - What are the k closest points to a given point?  (The first k points in the tree, ordered by increasing squared
100
///   distance from the given point, including the given point if it is in the tree).  (Sometimes called a nearest
101
///   neighbors query)
102
/// - What are all the points within a distance d of a given point?  (All points whose squared distance from a given
103
///   point is at most d^2).  (Sometimes called a ball query)
104
/// - What are all the points within a given region?  (Sometimes called a cuboid query)
105
/// This implementation uses an implicit tree, meaning all points are stored in one contiguous buffer and no dereferences
106
/// are needed to traverse the tree.  This is good for lookup performance, but unfortunately it means that adding/removing
107
/// points can't be done currently without rebuilding the tree.
108
/// Besides the three basic distance related queries, KD trees can be used to some extent to help with more complicated
109
/// distance related queries, like finding the closest pairs of points.
110
#[derive(Debug)]
111
pub struct KdTree<R: KdRegion, V = ()> {
112
    pub bounds: Option<R>,
113
    points: Box<[(R::Point, V)]>
114
}
115

            
116
impl<R: KdRegion, V> KdTree<R, V> {
117
    /// Get the number of points in the kdtree
118
500
    pub fn len(&self) -> usize {
119
500
        self.points.len()
120
500
    }
121

            
122
	/// Iterate over all point, value pairs in the tree in depth first order,
123
	/// calling a visitor function on each.  The visitor function gets a const reference
124
	/// to the point, the value, and the bounds of the subtree corresponding to the point,
125
	/// and may return a [`WalkDecision`] to instruct the traversal to skip the
126
	/// subtree or to stop the traversal entirely.
127
500
    pub fn walk<'a>(&'a self, visitor: &mut impl FnMut(&R, &'a R::Point, &'a V) -> WalkDecision) {
128
500
        let Some(bounds) = self.bounds.clone() else { return };
129
500
        let mut todo = vec![(bounds, 0, self.len(), 0)];
130
500500
        while let Some((bounds, a, b, layer)) = todo.pop() {
131
500000
            let mid_idx = (a + b)/2;
132
500000
            // safe because a < b <= self.points.len() so mid_idx < self.points.len()
133
500000
            let point = &self.points[mid_idx].0;
134
500000
            let value = &self.points[mid_idx].1;
135
500000
            match visitor(&bounds, point, value) {
136
                WalkDecision::Stop => return,
137
                WalkDecision::SkipChildren => continue,
138
500000
                WalkDecision::Continue => ()
139
500000
            }
140
500000
            let (sub0, sub1) = bounds.split(point, layer);
141
500000
            if a < mid_idx { todo.push((sub0, a, mid_idx, layer + 1)) }
142
500000
            if mid_idx + 1 < b { todo.push((sub1, mid_idx + 1, b, layer + 1)) }
143
        }
144
500
    }
145

            
146
    /// Iterate over all point, value pairs in the tree in depth first order,
147
    /// calling a visitor function on each.  The visitor function gets a mutable reference
148
    /// to the value, but a const reference
149
	/// to the point and the bounds of the subtree corresponding to the point,
150
	/// and may return a [`WalkDecision`] to instruct the traversal to skip the
151
	/// subtree or to stop the traversal entirely.
152
    pub fn walk_mut<'a>(&'a mut self, visitor: &mut impl FnMut(&R, &'a R::Point, &mut V) -> WalkDecision) {
153
        let Some(bounds) = self.bounds.clone() else { return };
154
        let mut todo = vec![(bounds, 0, self.len(), 0)];
155
        while let Some((bounds, a, b, layer)) = todo.pop() {
156
            let mid_idx = (a + b)/2;
157
            // safe because a < b <= self.points.len() so mid_idx < self.points.len()
158
            let point = &self.points[mid_idx].0;
159
            let value = &mut self.points[mid_idx].1;
160
            match visitor(&bounds, point, value) {
161
                WalkDecision::Stop => return,
162
                WalkDecision::SkipChildren => continue,
163
                WalkDecision::Continue => ()
164
            }
165
            let (sub0, sub1) = bounds.split(point, layer);
166
            if a < mid_idx { todo.push((sub0, a, mid_idx, layer + 1)) }
167
            if mid_idx + 1 < b { todo.push((sub1, mid_idx + 1, b, layer + 1)) }
168
        }
169
    }
170

            
171
	/// Return the k points in the tree which are the closest to a given point.
172
    /// Behavior can be fine-tuned using `cfg`:
173
    /// - Can restrict the result set to only include points within a certain sqdist of the query point
174
    ///   or withn a certain region, as well as to exclude points within another smaller sqdist or subregion.
175
    /// - Can specify how any points tied for kth closest should be handled (keep all or keep one arbitrarily).
176
	/// If there are fewer than k points in the tree, returns all the points.
177
    /// If k is 0, returns an empty minmax heap without looking at the tree
178
500
    pub fn k_closest<'a>(&'a self, point: &R::Point, k: usize, cfg: QueryOptions<'a, R>) -> MmHeap<(&'a R::Point, &'a V)> {
179
500
        let mut res = MmHeap::new();
180
500
        if k == 0 { return res }
181
500
        let mut tied_points = Vec::new();
182
500
        let mut max_sqdist = if let QueryBound::SqDist(max_sqdist) = &cfg.outer_bound { Some(max_sqdist.clone()) } else { None };
183
7633862
        let cmp_fn = &|&(a, _): &_, &(b, _): &_|point.sqdist(a).cmp(&point.sqdist(b));
184
500000
        self.walk(&mut |bounds, pt, v|{
185
500000
            if cfg.contains(point, pt) {
186
500000
                if res.len() + tied_points.len() < k {
187
25000
                    res.push_by((pt, v), cmp_fn);
188
475000
                } else if !cfg.keep_ties {
189
475000
                    max_sqdist = Some(point.sqdist(res.pushpop_max_by((pt, v), cmp_fn).0))
190
                } else {
191
                    if max_sqdist.is_none() {
192
                        max_sqdist = Some(point.sqdist(res.peek_max_by(cmp_fn).unwrap().0))
193
                    }
194
                    match point.sqdist(pt).cmp(max_sqdist.as_ref().unwrap()) {
195
                        Ordering::Greater => (),
196
                        Ordering::Equal => tied_points.push((pt, v)),
197
                        Ordering::Less => {
198
                            res.push_by((pt, v), cmp_fn);
199
                            if res.len() >= k {
200
                                tied_points.clear();
201
                                tied_points.push(res.pop_max_by(cmp_fn).unwrap());
202
                                max_sqdist = Some(point.sqdist(tied_points[0].0));
203
                                while res.peek_max_by(cmp_fn).is_some_and(
204
                                    |&(p, _)|point.sqdist(p) == *max_sqdist.as_ref().unwrap()
205
                                ) {
206
                                    tied_points.push(res.pop_max_by(cmp_fn).unwrap())
207
                                }
208
                            }
209
                        }
210
                    }
211
                }
212
            } else if !cfg.might_overlap(point, max_sqdist.as_ref(), bounds) {
213
                return WalkDecision::SkipChildren;
214
            }
215
500000
            WalkDecision::Continue
216
500000
        });
217
500
        res.extend_by(tied_points, cmp_fn);
218
500
        res
219
500
    }
220

            
221
    /// Borrowing iterator over only references to points.
222
    /// The order of the result is arbitrary, but all points will be visited exactly once.
223
10
    pub fn iter_points(&self) -> impl Iterator<Item=&R::Point> + '_ {
224
10000
        self.into_iter().map(|(p,_)|p)
225
10
    }
226

            
227
    /// Consuming iterator over only points, which are moved out of self.
228
    /// The order of the result is arbitrarily, but all points will be visited exactly once.
229
    pub fn into_points(self) -> impl Iterator<Item=R::Point> {
230
        self.into_iter().map(|(p,_)|p)
231
    }
232

            
233
    /// Borrowing iterator over only references to values.
234
    /// The order of the result is arbitrary, but the value for each point will be visited exactly once.
235
    pub fn iter_values(&self) -> impl Iterator<Item=&V> + '_ {
236
        self.into_iter().map(|(_,v)|v)
237
    }
238

            
239
    /// Mutable borrowing iterator over only references to values.
240
    /// The order of the result is arbitrary, but the value for each point will be visited exactly once.
241
    /// This is a splitting borrow, so it is safe to store a reference to some value and mutate it even
242
    /// after subsequent values have been visited.
243
    pub fn mut_values(&mut self) -> impl Iterator<Item=&mut V> + '_ {
244
        self.into_iter().map(|(_,v)|v)
245
    }
246

            
247
    /// Consuming iterator over only values, which are moved out of self.
248
    /// The order of the result is arbitrary, but the value for each point will be visited exactly once.
249
    pub fn into_values(self) -> impl Iterator<Item=V> {
250
        self.into_iter().map(|(_,v)|v)
251
    }
252

            
253
    /// Return a reference to the value for some point in the tree, or None if the point is not found
254
    pub fn get(&self, point: &R::Point) -> Option<&V> {
255
        self.points.get(self.find(point)).map(|(_,v)|v)
256
    }
257

            
258
    /// Return a reference to a point in the tree and the corresponding value, or None if the point is not found
259
    pub fn get_point_value(&self, point: &R::Point) -> Option<(&R::Point, &V)> {
260
        self.points.get(self.find(point)).map(|(p,v)|(p,v))
261
    }
262

            
263
    /// Return true if the tree contains some point or false otherwise
264
    pub fn contains_point(&self, point: &R::Point) -> bool {
265
        self.find(point) != self.len()
266
    }
267

            
268
    /// Return a mutable reference to the value for some point in the tree, or None if the point is not found
269
    pub fn get_mut(&mut self, point: &R::Point) -> Option<&mut V> {
270
        self.points.get_mut(self.find(point)).map(|(_,v)|v)
271
    }
272

            
273
    /// Convert a const reference to a point in the tree into an internal index.
274
    /// This function is unsafe because it can't be used productively without
275
    /// [`Self::launder_idx_mut`].  `ent` MUST be a reference to one of the points actually stored in
276
    /// the tree, NOT an identical point elsewhere, or this function invokes undefined behavior.
277
    pub unsafe fn launder_point_ref(&self, ent: &R::Point) -> usize {
278
        (ent as *const R::Point as *const (R::Point, V))
279
            .offset_from(self.points.as_ptr()) as usize
280
    }
281

            
282
    /// Convert a const reference to a value in the tree into an internal index.
283
    /// This function is unsafe because it can't be used productively without
284
    /// [`Self::launder_idx_point`].  `ent` MUST be a reference to one of the values actually stored in
285
    /// the tree, NOT an identical point elsewhere, or this function invokes undefined behavior.
286
    pub unsafe fn launder_value_ref(&self, ent: &V) -> usize {
287
        ((ent as *const V).byte_sub(mem::offset_of!((R::Point, V), 1))
288
            as *const (R::Point, V)
289
        ).offset_from(self.points.as_ptr()) as usize
290
    }
291

            
292
    /// Convert an internal index into a reference to a point in the tree.
293
    /// The internal index must have come from [`Self::launder_point_ref`] or [`Self::launder_value_ref`]
294
    /// called on the same tree.
295
    /// The intent of this function is to allow finding the points corresponding to values
296
    /// given a value reference, like for example if some of the values are made into
297
    /// an intrusive linked data structure.
298
    pub unsafe fn launder_idx_point(&self, idx: usize) -> &R::Point {
299
        &self.points[idx].0
300
    }
301

            
302
    /// Convert an internal index into a mutable reference to a value in the tree.
303
    /// The internal index must have come from [`Self::launder_point_ref`] or [`Self::launder_value_ref`]
304
    /// called on the same tree.
305
    /// The intent of this function is to allow mutating the values of the points in the
306
    /// result set of `k_closest` etc.
307
    pub unsafe fn launder_idx_mut(&mut self, idx: usize) -> &mut V {
308
        &mut self.points[idx].1
309
    }
310

            
311
    fn find(&self, point: &R::Point) -> usize {
312
        self.find_r(point, 0, self.len(), 0)
313
    }
314

            
315
    fn find_r(&self, point: &R::Point, mut a: usize, mut b: usize, mut layer: usize) -> usize {
316
        while a < b {
317
            let mid_idx = (a + b)/2;
318
            let p = &self.points[mid_idx].0;
319
            match point.cmp(p, layer) {
320
                Ordering::Less => b = mid_idx,
321
                Ordering::Greater => a = mid_idx + 1,
322
                Ordering::Equal => {
323
                    if point == p { return mid_idx }
324
                    a = self.find_r(point, a, mid_idx, layer + 1);
325
                    if a != self.len() { return a }
326
                    a = mid_idx + 1
327
                }
328
            }
329
            layer += 1
330
        }
331
        self.len()
332
    }
333

            
334
10
    fn ify(&mut self) {
335
10
        self.ify_r(0, self.points.len(), 0)
336
10
    }
337

            
338
10010
    fn ify_r(&mut self, a: usize, mut b: usize, mut layer: usize) {
339
20010
        while a < b {
340
10000
            let med_idx = (a + b)/2;
341
204114
            self.points[a..b].select_nth_unstable_by(med_idx - a, |(p, _), (q, _)| p.cmp(q, layer)); // rust picks up Ord::cmp if we don't handhold it
342
10000
            layer += 1;
343
10000
            self.ify_r(med_idx + 1, b, layer);
344
10000
            b = med_idx;
345
10000
        }
346
10010
    }
347

            
348
    #[cfg(test)]
349
10000
    fn check_layer(&self, a: usize, b: usize, layer: usize) -> bool {
350
10000
        if b > self.points.len() || a > b {
351
            return false
352
10000
        } if a == b {
353
            return true
354
10000
        }
355
10000
        let mid_idx = (a + b)/2;
356
10000
        let m = &self.points[mid_idx].0;
357
40490
        for (e, _) in self.points.get(a..mid_idx).unwrap_or(&[]) {
358
40490
            if KdPoint::cmp(e, m, layer) == Ordering::Greater {
359
                return false;
360
40490
            }
361
        }
362
39380
        for (e, _) in self.points.get(mid_idx+1..b).unwrap_or(&[]) {
363
39380
            if KdPoint::cmp(e, m, layer) == Ordering::Less {
364
                return false;
365
39380
            }
366
        }
367
10000
        true
368
10000
    }
369

            
370
    #[cfg(test)]
371
10010
    fn check_tree_r(&self, a: usize, mut b: usize, mut layer: usize) -> bool {
372
20010
        while b > a {
373
10000
            if !self.check_layer(a, b, layer) {
374
                return false;
375
10000
            }
376
10000
            let mid_idx = (a + b)/2;
377
10000
            layer += 1;
378
10000
            if !self.check_tree_r(mid_idx + 1, b, layer) {
379
                return false;
380
10000
            }
381
10000
            b = mid_idx;
382
        }
383
10010
        true
384
10010
    }
385

            
386
    #[cfg(test)]
387
10
    pub(crate) fn check_tree(&self) -> bool {
388
10
        self.check_tree_r(0, self.points.len(), 0)
389
10
    }
390

            
391
    #[cfg(test)]
392
500
    pub(crate) fn k_closest_naive<'a>(&'a self, point: &R::Point, k: usize) -> Vec<(&'a R::Point, &'a V)> {
393
500
        let mut res = MmHeap::new();
394
7646114
        let cmp_fn = &|&(a, _): &_, &(b, _): &_|point.sqdist(a).cmp(&point.sqdist(b));
395
500000
        (&self).into_iter().for_each(&mut |(p, v)|{
396
500000
            if res.len() < k {
397
25000
                res.push_by((p, v), cmp_fn)
398
475000
            } else {
399
475000
                res.pushpop_max_by((p, v), cmp_fn);
400
475000
            }
401
500000
        });
402
500
        res.into()
403
500
    }
404
}
405

            
406
pub struct Iter<'a, P: KdPoint, V> {
407
    buf: &'a [(P, V)],
408
    idx: usize
409
}
410

            
411
impl<'a, P: KdPoint, V> Iterator for Iter<'a, P, V> {
412
    type Item = (&'a P, &'a V);
413
510510
    fn next(&mut self) -> Option<Self::Item> {
414
510510
        self.buf.get(self.idx).inspect(|_|self.idx += 1).map(|(a,b)|(a,b))
415
510510
    }
416
}
417

            
418
pub struct IterMut<'a, P: KdPoint, V> {
419
    tail: &'a mut [(P, V)],
420
}
421

            
422
impl<'a, P, V> Iterator for IterMut<'a, P, V>
423
where P: KdPoint {
424
    type Item = (&'a P, &'a mut V);
425
    fn next(&mut self) -> Option<Self::Item> {
426
        let Some(([(a, b)], tail)) = mem::take(&mut self.tail).split_at_mut_checked(1) else { return None };
427
        self.tail = tail;
428
        Some((a, b))
429
    }
430
}
431

            
432
impl<'a, R: KdRegion, V> IntoIterator for &'a KdTree<R, V> {
433
	type Item = (&'a R::Point, &'a V);
434
	type IntoIter = Iter<'a, R::Point, V>;
435
510
	fn into_iter(self) -> Self::IntoIter {
436
510
		Iter{buf: &self.points, idx: 0}
437
510
	}
438
}
439

            
440
impl<'a, R: KdRegion, V> IntoIterator for &'a mut KdTree<R, V> {
441
    type Item = (&'a R::Point, &'a mut V);
442
    type IntoIter = IterMut<'a, R::Point, V>;
443
    fn into_iter(self) -> Self::IntoIter {
444
        IterMut{tail: &mut self.points}
445
    }
446
}
447

            
448
impl<R: KdRegion, V> IntoIterator for KdTree<R, V> {
449
    type Item = (R::Point, V);
450
    type IntoIter = <Vec<(R::Point, V)> as IntoIterator>::IntoIter;
451
    fn into_iter(self) -> Self::IntoIter {
452
        self.points.into_vec().into_iter()
453
    }
454
}
455

            
456
impl<R: KdRegion, V, const N: usize> From<[(R::Point, V); N]> for KdTree<R, V> {
457
    fn from(ents: [(R::Point, V); N]) -> Self {
458
        let bounds = get_bounds((&ents).into_iter().map(|(p,_)|p));
459
        let points = ents.into_iter().collect();
460
        let mut res = Self{points, bounds};
461
        res.ify();
462
        res
463
    }
464
}
465

            
466
impl<R: KdRegion, V> FromIterator<(R::Point, V)> for KdTree<R, V> {
467
10
    fn from_iter<T: IntoIterator<Item = (R::Point, V)>>(iter: T) -> Self {
468
10
        let points: Box<[_]> = iter.into_iter().collect();
469
10000
        let bounds = get_bounds((&points).into_iter().map(|(p,_)|p));
470
10
        let mut res = Self{points, bounds};
471
10
        res.ify();
472
10
        res
473
10
    }
474
}
475

            
476
impl<R: KdRegion, V> Index<&R::Point> for KdTree<R, V> {
477
    type Output = V;
478
    fn index(&self, point: &R::Point) -> &V {
479
        self.get(point).unwrap()
480
    }
481
}
482

            
483
impl<R: KdRegion, V> IndexMut<&R::Point> for KdTree<R, V> {
484
    fn index_mut(&mut self, point: &R::Point) -> &mut Self::Output {
485
        self.get_mut(point).unwrap()
486
    }
487
}
488