/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 | | } |