rstar/primitives/
rectangle.rs1use crate::aabb::AABB;
2use crate::envelope::Envelope;
3use crate::object::{PointDistance, RTreeObject};
4use crate::point::{Point, PointExt};
5
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct Rectangle<P>
18where
19 P: Point,
20{
21 aabb: AABB<P>,
22}
23
24impl<P> Rectangle<P>
25where
26 P: Point,
27{
28 pub fn from_corners(corner_1: P, corner_2: P) -> Self {
30 AABB::from_corners(corner_1, corner_2).into()
31 }
32
33 pub fn from_aabb(aabb: AABB<P>) -> Self {
35 Rectangle { aabb }
36 }
37
38 pub fn lower(&self) -> P {
43 self.aabb.lower()
44 }
45
46 pub fn upper(&self) -> P {
51 self.aabb.upper()
52 }
53}
54
55impl<P> From<AABB<P>> for Rectangle<P>
56where
57 P: Point,
58{
59 fn from(aabb: AABB<P>) -> Self {
60 Self::from_aabb(aabb)
61 }
62}
63
64impl<P> RTreeObject for Rectangle<P>
65where
66 P: Point,
67{
68 type Envelope = AABB<P>;
69
70 fn envelope(&self) -> Self::Envelope {
71 self.aabb.clone()
72 }
73}
74
75impl<P> Rectangle<P>
76where
77 P: Point,
78{
79 pub fn nearest_point(&self, query_point: &P) -> P {
83 self.aabb.min_point(query_point)
84 }
85}
86
87impl<P> PointDistance for Rectangle<P>
88where
89 P: Point,
90{
91 fn distance_2(
92 &self,
93 point: &<Self::Envelope as Envelope>::Point,
94 ) -> <<Self::Envelope as Envelope>::Point as Point>::Scalar {
95 self.nearest_point(point).sub(point).length_2()
96 }
97
98 fn contains_point(&self, point: &<Self::Envelope as Envelope>::Point) -> bool {
99 self.aabb.contains_point(point)
100 }
101
102 fn distance_2_if_less_or_equal(
103 &self,
104 point: &<Self::Envelope as Envelope>::Point,
105 max_distance_2: <<Self::Envelope as Envelope>::Point as Point>::Scalar,
106 ) -> Option<<<Self::Envelope as Envelope>::Point as Point>::Scalar> {
107 let distance_2 = self.distance_2(point);
108 if distance_2 <= max_distance_2 {
109 Some(distance_2)
110 } else {
111 None
112 }
113 }
114}
115
116#[cfg(test)]
117mod 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}