Coverage Report

Created: 2026-03-31 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rstar-0.12.2/src/point.rs
Line
Count
Source
1
use core::fmt::Debug;
2
use num_traits::{Bounded, Num, Signed, Zero};
3
4
/// Defines a number type that is compatible with rstar.
5
///
6
/// rstar works out of the box with the following standard library types:
7
///  - i8, i16, i32, i64, i128, isize
8
///  - [Wrapping](core::num::Wrapping) versions of the above
9
///  - f32, f64
10
///
11
/// This type cannot be implemented directly. Instead, it is required to implement
12
/// all required traits from the `num_traits` crate.
13
///
14
/// # Example
15
/// ```
16
/// # extern crate num_traits;
17
/// use num_traits::{Bounded, Num, Signed};
18
///
19
/// #[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
20
/// struct MyFancyNumberType(f32);
21
///
22
/// impl num_traits::Bounded for MyFancyNumberType {
23
///   // ... details hidden ...
24
/// # fn min_value() -> Self { Self(Bounded::min_value()) }
25
/// #
26
/// # fn max_value() -> Self { Self(Bounded::max_value()) }
27
/// }
28
///
29
/// impl Signed for MyFancyNumberType {
30
///   // ... details hidden ...
31
/// # fn abs(&self) -> Self { unimplemented!() }
32
/// #
33
/// # fn abs_sub(&self, other: &Self) -> Self { unimplemented!() }
34
/// #
35
/// # fn signum(&self) -> Self { unimplemented!() }
36
/// #
37
/// # fn is_positive(&self) -> bool { unimplemented!() }
38
/// #
39
/// # fn is_negative(&self) -> bool { unimplemented!() }
40
/// }
41
///
42
/// impl Num for MyFancyNumberType {
43
///   // ... details hidden ...
44
/// # type FromStrRadixErr = num_traits::ParseFloatError;
45
/// # fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> { unimplemented!() }
46
/// }
47
///
48
/// // Lots of traits are still missing to make the above code compile, but
49
/// // let's assume they're implemented. `MyFancyNumberType` type now readily implements
50
/// // RTreeNum and can be used with r-trees:
51
/// # fn main() {
52
/// use rstar::RTree;
53
/// let mut rtree = RTree::new();
54
/// rtree.insert([MyFancyNumberType(0.0), MyFancyNumberType(0.0)]);
55
/// # }
56
///
57
/// # impl num_traits::Zero for MyFancyNumberType {
58
/// #   fn zero() -> Self { unimplemented!() }
59
/// #   fn is_zero(&self) -> bool { unimplemented!() }
60
/// # }
61
/// #
62
/// # impl num_traits::One for MyFancyNumberType {
63
/// #   fn one() -> Self { unimplemented!() }
64
/// # }
65
/// #
66
/// # impl core::ops::Mul for MyFancyNumberType {
67
/// #   type Output = Self;
68
/// #   fn mul(self, rhs: Self) -> Self { unimplemented!() }
69
/// # }
70
/// #
71
/// # impl core::ops::Add for MyFancyNumberType {
72
/// #   type Output = Self;
73
/// #   fn add(self, rhs: Self) -> Self { unimplemented!() }
74
/// # }
75
/// #
76
/// # impl core::ops::Sub for MyFancyNumberType {
77
/// #   type Output = Self;
78
/// #   fn sub(self, rhs: Self) -> Self { unimplemented!() }
79
/// # }
80
/// #
81
/// # impl core::ops::Div for MyFancyNumberType {
82
/// #   type Output = Self;
83
/// #   fn div(self, rhs: Self) -> Self { unimplemented!() }
84
/// # }
85
/// #
86
/// # impl core::ops::Rem for MyFancyNumberType {
87
/// #   type Output = Self;
88
/// #   fn rem(self, rhs: Self) -> Self { unimplemented!() }
89
/// # }
90
/// #
91
/// # impl core::ops::Neg for MyFancyNumberType {
92
/// #   type Output = Self;
93
/// #   fn neg(self) -> Self { unimplemented!() }
94
/// # }
95
/// #
96
/// ```
97
///
98
pub trait RTreeNum: Bounded + Num + Clone + Copy + Signed + PartialOrd + Debug {}
99
100
impl<S> RTreeNum for S where S: Bounded + Num + Clone + Copy + Signed + PartialOrd + Debug {}
101
102
/// Defines a point type that is compatible with rstar.
103
///
104
/// This trait should be used for interoperability with other point types, not to define custom objects
105
/// that can be inserted into r-trees. Use [`crate::RTreeObject`] or
106
/// [`crate::primitives::GeomWithData`] instead.
107
/// This trait defines points, not points with metadata.
108
///
109
/// `Point` is implemented out of the box for arrays like `[f32; 2]` or `[f64; 7]` (for any number of dimensions),
110
/// and for tuples like `(int, int)` and `(f64, f64, f64)` so tuples with only elements of the same type (up to dimension 9).
111
///
112
///
113
/// # Implementation example
114
/// Supporting a custom point type might look like this:
115
///
116
/// ```
117
/// use rstar::Point;
118
///
119
/// #[derive(Copy, Clone, PartialEq, Debug)]
120
/// struct IntegerPoint
121
/// {
122
///     x: i32,
123
///     y: i32
124
/// }
125
///
126
/// impl Point for IntegerPoint
127
/// {
128
///   type Scalar = i32;
129
///   const DIMENSIONS: usize = 2;
130
///
131
///   fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self
132
///   {
133
///     IntegerPoint {
134
///       x: generator(0),
135
///       y: generator(1)
136
///     }
137
///   }
138
///
139
///   fn nth(&self, index: usize) -> Self::Scalar
140
///   {
141
///     match index {
142
///       0 => self.x,
143
///       1 => self.y,
144
///       _ => unreachable!()
145
///     }
146
///   }
147
///
148
///   fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar
149
///   {
150
///     match index {
151
///       0 => &mut self.x,
152
///       1 => &mut self.y,
153
///       _ => unreachable!()
154
///     }
155
///   }
156
/// }
157
/// ```
158
pub trait Point: Clone + PartialEq + Debug {
159
    /// The number type used by this point type.
160
    type Scalar: RTreeNum;
161
162
    /// The number of dimensions of this point type.
163
    const DIMENSIONS: usize;
164
165
    /// Creates a new point value with given values for each dimension.
166
    ///
167
    /// The value that each dimension should be initialized with is given by the parameter `generator`.
168
    /// Calling `generator(n)` returns the value of dimension `n`, `n` will be in the range `0 .. Self::DIMENSIONS`,
169
    /// and will be called with values of `n` in ascending order.
170
    fn generate(generator: impl FnMut(usize) -> Self::Scalar) -> Self;
171
172
    /// Returns a single coordinate of this point.
173
    ///
174
    /// Returns the coordinate indicated by `index`. `index` is always smaller than `Self::DIMENSIONS`.
175
    fn nth(&self, index: usize) -> Self::Scalar;
176
177
    /// Mutable variant of [nth](#methods.nth).
178
    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar;
179
}
180
181
impl<T> PointExt for T where T: Point {}
182
183
/// Utility functions for Point
184
pub trait PointExt: Point {
185
    /// Returns a new Point with all components set to zero.
186
0
    fn new() -> Self {
187
0
        Self::from_value(Zero::zero())
188
0
    }
189
190
    /// Applies `f` to each pair of components of `self` and `other`.
191
0
    fn component_wise(
192
0
        &self,
193
0
        other: &Self,
194
0
        mut f: impl FnMut(Self::Scalar, Self::Scalar) -> Self::Scalar,
195
0
    ) -> Self {
196
0
        Self::generate(|i| f(self.nth(i), other.nth(i)))
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::component_wise::<rstar::point::max_inline<f64>>::{closure#0}
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::component_wise::<rstar::point::min_inline<f64>>::{closure#0}
Unexecuted instantiation: <_ as rstar::point::PointExt>::component_wise::<_>::{closure#0}
197
0
    }
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::component_wise::<rstar::point::max_inline<f64>>
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::component_wise::<rstar::point::min_inline<f64>>
Unexecuted instantiation: <_ as rstar::point::PointExt>::component_wise::<_>
198
199
    /// Returns whether all pairs of components of `self` and `other` pass test closure `f`. Short circuits if any result is false.
200
0
    fn all_component_wise(
201
0
        &self,
202
0
        other: &Self,
203
0
        mut f: impl FnMut(Self::Scalar, Self::Scalar) -> bool,
204
0
    ) -> bool {
205
0
        (0..Self::DIMENSIONS).all(|i| f(self.nth(i), other.nth(i)))
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::all_component_wise::<<rstar::aabb::AABB<geo_types::geometry::coord::Coord> as rstar::envelope::Envelope>::intersects::{closure#0}>::{closure#0}
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::all_component_wise::<<rstar::aabb::AABB<geo_types::geometry::coord::Coord> as rstar::envelope::Envelope>::intersects::{closure#1}>::{closure#0}
Unexecuted instantiation: <_ as rstar::point::PointExt>::all_component_wise::<_>::{closure#0}
206
0
    }
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::all_component_wise::<<rstar::aabb::AABB<geo_types::geometry::coord::Coord> as rstar::envelope::Envelope>::intersects::{closure#0}>
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::all_component_wise::<<rstar::aabb::AABB<geo_types::geometry::coord::Coord> as rstar::envelope::Envelope>::intersects::{closure#1}>
Unexecuted instantiation: <_ as rstar::point::PointExt>::all_component_wise::<_>
207
208
    /// Returns the dot product of `self` and `rhs`.
209
0
    fn dot(&self, rhs: &Self) -> Self::Scalar {
210
0
        self.component_wise(rhs, |l, r| l * r)
211
0
            .fold(Zero::zero(), |acc, val| acc + val)
212
0
    }
213
214
    /// Folds (aka reduces or injects) the Point component wise using `f` and returns the result.
215
    /// fold() takes two arguments: an initial value, and a closure with two arguments: an 'accumulator', and the value of the current component.
216
    /// The closure returns the value that the accumulator should have for the next iteration.
217
    ///
218
    /// The `start_value` is the value the accumulator will have on the first call of the closure.
219
    ///
220
    /// After applying the closure to every component of the Point, fold() returns the accumulator.
221
0
    fn fold<T>(&self, start_value: T, mut f: impl FnMut(T, Self::Scalar) -> T) -> T {
222
0
        (0..Self::DIMENSIONS).fold(start_value, |accumulated, i| f(accumulated, self.nth(i)))
223
0
    }
224
225
    /// Returns a Point with every component set to `value`.
226
0
    fn from_value(value: Self::Scalar) -> Self {
227
0
        Self::generate(|_| value)
228
0
    }
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::from_value
Unexecuted instantiation: <_ as rstar::point::PointExt>::from_value
229
230
    /// Returns a Point with each component set to the smallest of each component pair of `self` and `other`.
231
0
    fn min_point(&self, other: &Self) -> Self {
232
0
        self.component_wise(other, min_inline)
233
0
    }
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::min_point
Unexecuted instantiation: <_ as rstar::point::PointExt>::min_point
234
235
    /// Returns a Point with each component set to the biggest of each component pair of `self` and `other`.
236
0
    fn max_point(&self, other: &Self) -> Self {
237
0
        self.component_wise(other, max_inline)
238
0
    }
Unexecuted instantiation: <geo_types::geometry::coord::Coord as rstar::point::PointExt>::max_point
Unexecuted instantiation: <_ as rstar::point::PointExt>::max_point
239
240
    /// Returns the squared length of this Point as if it was a vector.
241
0
    fn length_2(&self) -> Self::Scalar {
242
0
        self.fold(Zero::zero(), |acc, cur| cur * cur + acc)
243
0
    }
244
245
    /// Substracts `other` from `self` component wise.
246
0
    fn sub(&self, other: &Self) -> Self {
247
0
        self.component_wise(other, |l, r| l - r)
248
0
    }
249
250
    /// Adds `other` to `self` component wise.
251
0
    fn add(&self, other: &Self) -> Self {
252
0
        self.component_wise(other, |l, r| l + r)
253
0
    }
254
255
    /// Multiplies `self` with `scalar` component wise.
256
0
    fn mul(&self, scalar: Self::Scalar) -> Self {
257
0
        self.map(|coordinate| coordinate * scalar)
258
0
    }
259
260
    /// Applies `f` to `self` component wise.
261
0
    fn map(&self, mut f: impl FnMut(Self::Scalar) -> Self::Scalar) -> Self {
262
0
        Self::generate(|i| f(self.nth(i)))
263
0
    }
264
265
    /// Returns the squared distance between `self` and `other`.
266
0
    fn distance_2(&self, other: &Self) -> Self::Scalar {
267
0
        self.sub(other).length_2()
268
0
    }
269
}
270
271
#[inline]
272
0
pub fn min_inline<S>(a: S, b: S) -> S
273
0
where
274
0
    S: RTreeNum,
275
{
276
0
    if a < b {
277
0
        a
278
    } else {
279
0
        b
280
    }
281
0
}
Unexecuted instantiation: rstar::point::min_inline::<f64>
Unexecuted instantiation: rstar::point::min_inline::<_>
282
283
#[inline]
284
0
pub fn max_inline<S>(a: S, b: S) -> S
285
0
where
286
0
    S: RTreeNum,
287
{
288
0
    if a > b {
289
0
        a
290
    } else {
291
0
        b
292
    }
293
0
}
Unexecuted instantiation: rstar::point::max_inline::<f64>
Unexecuted instantiation: rstar::point::max_inline::<_>
294
295
impl<S, const N: usize> Point for [S; N]
296
where
297
    S: RTreeNum,
298
{
299
    type Scalar = S;
300
301
    const DIMENSIONS: usize = N;
302
303
0
    fn generate(mut generator: impl FnMut(usize) -> S) -> Self {
304
        // The same implementation used in std::array::from_fn
305
        // Since this is a const generic it gets unrolled
306
0
        let mut idx = 0;
307
0
        [(); N].map(|_| {
308
0
            let res = generator(idx);
309
0
            idx += 1;
310
0
            res
311
0
        })
312
0
    }
313
314
    #[inline]
315
0
    fn nth(&self, index: usize) -> Self::Scalar {
316
0
        self[index]
317
0
    }
318
319
    #[inline]
320
0
    fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
321
0
        &mut self[index]
322
0
    }
323
}
324
325
macro_rules! count_exprs {
326
    () => (0);
327
    ($head:expr) => (1);
328
    ($head:expr, $($tail:expr),*) => (1 + count_exprs!($($tail),*));
329
}
330
331
macro_rules! fixed_type {
332
    ($expr:expr, $type:ty) => {
333
        $type
334
    };
335
}
336
337
macro_rules! impl_point_for_tuple {
338
    ($($index:expr => $name:ident),+) => {
339
        impl<S> Point for ($(fixed_type!($index, S),)+)
340
        where
341
            S: RTreeNum
342
        {
343
            type Scalar = S;
344
345
            const DIMENSIONS: usize = count_exprs!($($index),*);
346
347
0
            fn generate(mut generator: impl FnMut(usize) -> S) -> Self {
348
0
                ($(generator($index),)+)
349
0
            }
Unexecuted instantiation: <(_,) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as rstar::point::Point>::generate::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as rstar::point::Point>::generate::<_>
350
351
            #[inline]
352
0
            fn nth(&self, index: usize) -> Self::Scalar {
353
0
                let ($($name,)+) = self;
354
355
0
                match index {
356
0
                    $($index => *$name,)+
357
0
                    _ => unreachable!("index {} out of bounds for tuple", index),
358
                }
359
0
            }
Unexecuted instantiation: <(_,) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as rstar::point::Point>::nth
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as rstar::point::Point>::nth
360
361
            #[inline]
362
0
            fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
363
0
                let ($($name,)+) = self;
364
365
0
                match index {
366
0
                    $($index => $name,)+
367
0
                    _ => unreachable!("index {} out of bounds for tuple", index),
368
                }
369
0
            }
Unexecuted instantiation: <(_,) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as rstar::point::Point>::nth_mut
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as rstar::point::Point>::nth_mut
370
        }
371
    };
372
}
373
374
impl_point_for_tuple!(0 => a);
375
impl_point_for_tuple!(0 => a, 1 => b);
376
impl_point_for_tuple!(0 => a, 1 => b, 2 => c);
377
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d);
378
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e);
379
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e, 5 => f);
380
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e, 5 => f, 6 => g);
381
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e, 5 => f, 6 => g, 7 => h);
382
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e, 5 => f, 6 => g, 7 => h, 8 => i);
383
impl_point_for_tuple!(0 => a, 1 => b, 2 => c, 3 => d, 4 => e, 5 => f, 6 => g, 7 => h, 8 => i, 9 => j);
384
385
#[cfg(test)]
386
mod tests {
387
    use super::*;
388
    use core::num::Wrapping;
389
390
    #[test]
391
    fn test_types() {
392
        fn assert_impl_rtreenum<S: RTreeNum>() {}
393
394
        assert_impl_rtreenum::<i8>();
395
        assert_impl_rtreenum::<i16>();
396
        assert_impl_rtreenum::<i32>();
397
        assert_impl_rtreenum::<i64>();
398
        assert_impl_rtreenum::<i128>();
399
        assert_impl_rtreenum::<isize>();
400
        assert_impl_rtreenum::<Wrapping<i8>>();
401
        assert_impl_rtreenum::<Wrapping<i16>>();
402
        assert_impl_rtreenum::<Wrapping<i32>>();
403
        assert_impl_rtreenum::<Wrapping<i64>>();
404
        assert_impl_rtreenum::<Wrapping<i128>>();
405
        assert_impl_rtreenum::<Wrapping<isize>>();
406
        assert_impl_rtreenum::<f32>();
407
        assert_impl_rtreenum::<f64>();
408
    }
409
410
    macro_rules! test_tuple_configuration {
411
        ($($index:expr),*) => {
412
            let a = ($($index),*);
413
            $(assert_eq!(a.nth($index), $index));*
414
        }
415
    }
416
417
    #[test]
418
    fn test_tuples() {
419
        // Test a couple of simple cases
420
        let simple_int = (0, 1, 2);
421
        assert_eq!(simple_int.nth(2), 2);
422
        let simple_float = (0.5, 0.67, 1234.56);
423
        assert_eq!(simple_float.nth(2), 1234.56);
424
        let long_int = (0, 1, 2, 3, 4, 5, 6, 7, 8);
425
        assert_eq!(long_int.nth(8), 8);
426
427
        // Generate the code to test every nth function for every Tuple length
428
        test_tuple_configuration!(0, 1);
429
        test_tuple_configuration!(0, 1, 2);
430
        test_tuple_configuration!(0, 1, 2, 3);
431
        test_tuple_configuration!(0, 1, 2, 3, 4);
432
        test_tuple_configuration!(0, 1, 2, 3, 4, 5);
433
        test_tuple_configuration!(0, 1, 2, 3, 4, 5, 6);
434
        test_tuple_configuration!(0, 1, 2, 3, 4, 5, 6, 7);
435
        test_tuple_configuration!(0, 1, 2, 3, 4, 5, 6, 7, 8);
436
    }
437
}