rstared/rstar/
geo_types.rs1use crate::rstar::primitives::Line as RstarLine;
8use crate::rstar::{AABB, Envelope, Point as RTreePoint, PointDistance, RTreeNum, RTreeObject};
9
10use geo_types::{Coord, CoordNum, Line, LineString, Point, Polygon, Rect};
11
12impl<T> RTreePoint for Coord<T>
13where
14 T: CoordNum + RTreeNum,
15{
16 type Scalar = T;
17
18 const DIMENSIONS: usize = 2;
19
20 fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
21 Coord {
22 x: generator(0),
23 y: generator(1),
24 }
25 }
26
27 fn nth(&self, index: usize) -> Self::Scalar {
28 match index {
29 0 => self.x,
30 1 => self.y,
31 _ => unreachable!(),
32 }
33 }
34
35 fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
36 match index {
37 0 => &mut self.x,
38 1 => &mut self.y,
39 _ => unreachable!(),
40 }
41 }
42}
43
44impl<T> RTreePoint for Point<T>
45where
46 T: CoordNum + RTreeNum,
47{
48 type Scalar = T;
49
50 const DIMENSIONS: usize = 2;
51
52 fn generate(mut generator: impl FnMut(usize) -> Self::Scalar) -> Self {
53 Point::new(generator(0), generator(1))
54 }
55
56 fn nth(&self, index: usize) -> Self::Scalar {
57 match index {
58 0 => self.x(),
59 1 => self.y(),
60 _ => unreachable!(),
61 }
62 }
63
64 fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
65 match index {
66 0 => &mut self.0.x,
67 1 => &mut self.0.y,
68 _ => unreachable!(),
69 }
70 }
71}
72
73impl<T> RTreeObject for Line<T>
74where
75 T: CoordNum + RTreeNum,
76{
77 type Envelope = AABB<Point<T>>;
78
79 fn envelope(&self) -> Self::Envelope {
80 AABB::from_corners(self.start_point(), self.end_point())
81 }
82}
83
84impl<T> PointDistance for Line<T>
85where
86 T: CoordNum + RTreeNum,
87{
88 fn distance_2(&self, point: &Point<T>) -> T {
89 RstarLine::new(self.start_point(), self.end_point()).distance_2(point)
90 }
91}
92
93impl<T> RTreeObject for LineString<T>
94where
95 T: CoordNum + RTreeNum,
96{
97 type Envelope = AABB<Point<T>>;
98
99 fn envelope(&self) -> Self::Envelope {
100 let mut iter = self.points();
101
102 let Some(first) = iter.next() else {
103 return AABB::from_corners(
104 Point::new(T::MIN_EXTENDED, T::MIN_EXTENDED),
105 Point::new(T::MAX_EXTENDED, T::MAX_EXTENDED),
106 );
107 };
108
109 let mut result = AABB::from_point(first);
110
111 for point in iter {
112 result.merge(&AABB::from_point(point));
113 }
114
115 result
116 }
117}
118
119impl<T> PointDistance for LineString<T>
120where
121 T: CoordNum + RTreeNum,
122{
123 fn distance_2(&self, point: &Point<T>) -> T {
124 if self.0.is_empty() {
125 return <T as numlike::elem::Zero>::zero();
126 }
127
128 self.lines()
129 .map(|line| RstarLine::new(line.start_point(), line.end_point()).distance_2(point))
130 .fold(T::MAX_EXTENDED, |accum, distance| {
131 if distance < accum { distance } else { accum }
132 })
133 }
134}
135
136impl<T> RTreeObject for Polygon<T>
137where
138 T: CoordNum + RTreeNum,
139{
140 type Envelope = AABB<Point<T>>;
141
142 fn envelope(&self) -> Self::Envelope {
143 self.exterior().envelope()
144 }
145}
146
147impl<T> RTreeObject for Rect<T>
148where
149 T: CoordNum + RTreeNum,
150{
151 type Envelope = AABB<Point<T>>;
152
153 fn envelope(&self) -> Self::Envelope {
154 AABB::from_corners(self.min().into(), self.max().into())
155 }
156}
157
158impl<T> PointDistance for Rect<T>
159where
160 T: CoordNum + RTreeNum,
161{
162 fn distance_2(&self, point: &Point<T>) -> T {
163 self.envelope().distance_2(point)
164 }
165}