Coverage Report

Created: 2025-02-21 07:11

/rust/registry/src/index.crates.io-6f17d22bba15001f/rstar-0.12.2/src/primitives/rectangle.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::aabb::AABB;
2
use crate::envelope::Envelope;
3
use crate::object::{PointDistance, RTreeObject};
4
use crate::point::{Point, PointExt};
5
6
/// An n-dimensional rectangle defined by its two corners.
7
///
8
/// This rectangle can be directly inserted into an r-tree.
9
///
10
/// *Note*: Despite being called rectangle, this struct can be used
11
/// with more than two dimensions by using an appropriate point type.
12
///
13
/// # Type parameters
14
/// `P`: The rectangle's [Point] type.
15
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
16
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17
pub struct Rectangle<P>
18
where
19
    P: Point,
20
{
21
    aabb: AABB<P>,
22
}
23
24
impl<P> Rectangle<P>
25
where
26
    P: Point,
27
{
28
    /// Creates a new rectangle defined by two corners.
29
0
    pub fn from_corners(corner_1: P, corner_2: P) -> Self {
30
0
        AABB::from_corners(corner_1, corner_2).into()
31
0
    }
32
33
    /// Creates a new rectangle defined by it's [axis aligned bounding box(AABB).
34
0
    pub fn from_aabb(aabb: AABB<P>) -> Self {
35
0
        Rectangle { aabb }
36
0
    }
37
38
    /// Returns the rectangle's lower corner.
39
    ///
40
    /// This is the point contained within the rectangle with the smallest coordinate value in each
41
    /// dimension.
42
0
    pub fn lower(&self) -> P {
43
0
        self.aabb.lower()
44
0
    }
45
46
    /// Returns the rectangle's upper corner.
47
    ///
48
    /// This is the point contained within the AABB with the largest coordinate value in each
49
    /// dimension.
50
0
    pub fn upper(&self) -> P {
51
0
        self.aabb.upper()
52
0
    }
53
}
54
55
impl<P> From<AABB<P>> for Rectangle<P>
56
where
57
    P: Point,
58
{
59
0
    fn from(aabb: AABB<P>) -> Self {
60
0
        Self::from_aabb(aabb)
61
0
    }
62
}
63
64
impl<P> RTreeObject for Rectangle<P>
65
where
66
    P: Point,
67
{
68
    type Envelope = AABB<P>;
69
70
0
    fn envelope(&self) -> Self::Envelope {
71
0
        self.aabb.clone()
72
0
    }
73
}
74
75
impl<P> Rectangle<P>
76
where
77
    P: Point,
78
{
79
    /// Returns the nearest point within this rectangle to a given point.
80
    ///
81
    /// If `query_point` is contained within this rectangle, `query_point` is returned.
82
0
    pub fn nearest_point(&self, query_point: &P) -> P {
83
0
        self.aabb.min_point(query_point)
84
0
    }
85
}
86
87
impl<P> PointDistance for Rectangle<P>
88
where
89
    P: Point,
90
{
91
0
    fn distance_2(
92
0
        &self,
93
0
        point: &<Self::Envelope as Envelope>::Point,
94
0
    ) -> <<Self::Envelope as Envelope>::Point as Point>::Scalar {
95
0
        self.nearest_point(point).sub(point).length_2()
96
0
    }
97
98
0
    fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
99
0
        self.aabb.contains_point(point)
100
0
    }
101
102
0
    fn distance_2_if_less_or_equal(
103
0
        &self,
104
0
        point: &<Self::Envelope as Envelope>::Point,
105
0
        max_distance_2: <<Self::Envelope as Envelope>::Point as Point>::Scalar,
106
0
    ) -> Option<<<Self::Envelope as Envelope>::Point as Point>::Scalar> {
107
0
        let distance_2 = self.distance_2(point);
108
0
        if distance_2 <= max_distance_2 {
109
0
            Some(distance_2)
110
        } else {
111
0
            None
112
        }
113
0
    }
114
}
115
116
#[cfg(test)]
117
mod test {
118
    use super::Rectangle;
119
    use crate::object::PointDistance;
120
    use approx::*;
121
122
    #[test]
123
    fn rectangle_distance() {
124
        let rectangle = Rectangle::from_corners([0.5, 0.5], [1.0, 2.0]);
125
126
        assert_abs_diff_eq!(rectangle.distance_2(&[0.5, 0.5]), 0.0);
127
        assert_abs_diff_eq!(rectangle.distance_2(&[0.0, 0.5]), 0.5 * 0.5);
128
        assert_abs_diff_eq!(rectangle.distance_2(&[0.5, 1.0]), 0.0);
129
        assert_abs_diff_eq!(rectangle.distance_2(&[0.0, 0.0]), 0.5);
130
        assert_abs_diff_eq!(rectangle.distance_2(&[0.0, 1.0]), 0.5 * 0.5);
131
        assert_abs_diff_eq!(rectangle.distance_2(&[1.0, 3.0]), 1.0);
132
        assert_abs_diff_eq!(rectangle.distance_2(&[1.0, 1.0]), 0.0);
133
    }
134
}