geo_index/kdtree/
traversal.rs

1//! Utilities to traverse the KDTree structure.
2
3use geo_traits::{
4    GeometryTrait, RectTrait, UnimplementedGeometryCollection, UnimplementedLine,
5    UnimplementedLineString, UnimplementedMultiLineString, UnimplementedMultiPoint,
6    UnimplementedMultiPolygon, UnimplementedPoint, UnimplementedPolygon, UnimplementedTriangle,
7};
8
9use crate::kdtree::KDTreeIndex;
10use crate::r#type::{Coord, IndexableNum};
11use std::marker::PhantomData;
12
13/// An internal node in the KDTree.
14#[derive(Debug, Clone)]
15pub struct Node<'a, N: IndexableNum, T: KDTreeIndex<N>> {
16    /// The tree that this node is a reference onto
17    tree: &'a T,
18
19    /// The axis that the children of this node are split over.
20    /// 0 for x axis, 1 for y axis
21    /// TODO: switch to bool
22    axis: usize,
23
24    /// The index of the right child.
25    right_child: usize,
26
27    /// The index of the left child.
28    left_child: usize,
29
30    /// The min_x of this node.
31    min_x: N,
32    /// The min_y of this node.
33    min_y: N,
34    /// The max_x of this node.
35    max_x: N,
36    /// The max_y of this node.
37    max_y: N,
38
39    phantom: PhantomData<N>,
40}
41
42impl<'a, N: IndexableNum, T: KDTreeIndex<N>> Node<'a, N, T> {
43    pub(crate) fn from_root(tree: &'a T) -> Self {
44        Self {
45            tree,
46            axis: 0,
47            right_child: tree.indices().len() - 1,
48            left_child: 0,
49            min_x: N::max_value(),
50            min_y: N::max_value(),
51            max_x: N::min_value(),
52            max_y: N::min_value(),
53            phantom: PhantomData,
54        }
55    }
56
57    // TODO: perhaps this should be state stored on the node, so we don't have to recompute it
58    // But it's only valid for nodes that have children
59    /// Note: this is the index into the coords array, not the insertion index.
60    #[inline]
61    pub(crate) fn middle_index(&self) -> usize {
62        (self.left_child + self.right_child) >> 1
63    }
64
65    // TODO: perhaps this should be state stored on the node, so we don't have to recompute it
66    // But it's only valid for nodes that have children
67    #[inline]
68    pub(crate) fn middle_xy(&self, m: usize) -> (N, N) {
69        let x = self.tree.coords()[2 * m];
70        let y = self.tree.coords()[2 * m + 1];
71        (x, y)
72    }
73
74    /// The child node representing the "left" half.
75    ///
76    /// Returns `None` if [`Self::is_parent`] is `false`.
77    pub fn left_child(&self) -> Option<Node<'_, N, T>> {
78        if self.is_parent() {
79            Some(self.left_child_unchecked())
80        } else {
81            None
82        }
83    }
84
85    /// The child node representing the "left" half.
86    ///
87    /// Note that this **does not include** the middle index of the current node.
88    pub fn left_child_unchecked(&self) -> Node<'_, N, T> {
89        debug_assert!(self.is_parent());
90
91        let m = self.middle_index();
92        let (x, y) = self.middle_xy(m);
93
94        let mut max_x = self.max_x;
95        let mut max_y = self.max_y;
96        if self.axis == 0 {
97            max_x = x;
98        } else {
99            max_y = y;
100        };
101
102        Self {
103            tree: self.tree,
104            axis: 1 - self.axis,
105            right_child: m - 1,
106            left_child: self.left_child,
107            min_x: self.min_x,
108            min_y: self.min_y,
109            max_x,
110            max_y,
111            phantom: self.phantom,
112        }
113    }
114
115    /// The child node representing the "right" half.
116    ///
117    /// Returns `None` if [`Self::is_parent`] is `false`.
118    pub fn right_child(&self) -> Option<Node<'_, N, T>> {
119        if self.is_parent() {
120            Some(self.right_child_unchecked())
121        } else {
122            None
123        }
124    }
125
126    /// The child node representing the "right" half.
127    ///
128    /// Note that this **does not include** the middle index of the current node.
129    pub fn right_child_unchecked(&self) -> Node<'_, N, T> {
130        debug_assert!(self.is_parent());
131
132        let m = self.middle_index();
133        let (x, y) = self.middle_xy(m);
134
135        let mut min_x = self.min_x;
136        let mut min_y = self.min_y;
137        if self.axis == 0 {
138            min_x = x;
139        } else {
140            min_y = y;
141        };
142
143        Self {
144            tree: self.tree,
145            axis: 1 - self.axis,
146            right_child: self.right_child,
147            left_child: m + 1,
148            min_x,
149            min_y,
150            max_x: self.max_x,
151            max_y: self.max_y,
152            phantom: self.phantom,
153        }
154    }
155
156    /// Returns `true` if this is a leaf node without children.
157    #[inline]
158    pub fn is_leaf(&self) -> bool {
159        self.right_child - self.left_child <= self.tree.node_size() as usize
160    }
161
162    /// Returns `true` if this is an intermediate node with children.
163    #[inline]
164    pub fn is_parent(&self) -> bool {
165        !self.is_leaf()
166    }
167
168    /// The original insertion index of the "middle child" of this node. This is only valid when
169    /// this is a parent node, which you can check with `Self::is_parent`.
170    ///
171    /// Returns `None` if [`Self::is_parent`] is `false`.
172    #[inline]
173    pub fn middle_insertion_index(&self) -> Option<u32> {
174        if self.is_parent() {
175            Some(self.middle_insertion_index_unchecked())
176        } else {
177            None
178        }
179    }
180
181    /// The original insertion index of the "middle child" of this node. This is only valid when
182    /// this is a parent node, which you can check with `Self::is_parent`.
183    #[inline]
184    pub fn middle_insertion_index_unchecked(&self) -> u32 {
185        debug_assert!(self.is_parent());
186
187        let m = self.middle_index();
188        let indices = self.tree.indices();
189        indices.get(m) as u32
190    }
191
192    /// The original insertion indices. This is only valid when this is a leaf node, which you can
193    /// check with `Self::is_leaf`.
194    ///
195    /// Returns `None` if [`Self::is_leaf`] is `false`.
196    #[inline]
197    pub fn leaf_insertion_indices(&self) -> Option<Vec<u32>> {
198        if self.is_leaf() {
199            Some(self.leaf_insertion_indices_unchecked())
200        } else {
201            None
202        }
203    }
204
205    /// The original insertion indices. This is only valid when this is a leaf node, which you can
206    /// check with `Self::is_leaf`.
207    #[inline]
208    pub fn leaf_insertion_indices_unchecked(&self) -> Vec<u32> {
209        debug_assert!(self.is_leaf());
210
211        let mut result = Vec::with_capacity(self.tree.node_size() as _);
212
213        let indices = self.tree.indices();
214        for i in self.left_child..self.right_child + 1 {
215            result.push(indices.get(i) as u32);
216        }
217
218        result
219    }
220}
221
222impl<N: IndexableNum, T: KDTreeIndex<N>> RectTrait for Node<'_, N, T> {
223    type CoordType<'a>
224        = Coord<N>
225    where
226        Self: 'a;
227
228    fn min(&self) -> Self::CoordType<'_> {
229        Coord {
230            x: self.min_x,
231            y: self.min_y,
232        }
233    }
234
235    fn max(&self) -> Self::CoordType<'_> {
236        Coord {
237            x: self.max_x,
238            y: self.max_y,
239        }
240    }
241}
242
243impl<N: IndexableNum, T: KDTreeIndex<N>> GeometryTrait for Node<'_, N, T> {
244    type T = N;
245
246    type PointType<'a>
247        = UnimplementedPoint<N>
248    where
249        Self: 'a;
250
251    type LineStringType<'a>
252        = UnimplementedLineString<N>
253    where
254        Self: 'a;
255
256    type PolygonType<'a>
257        = UnimplementedPolygon<N>
258    where
259        Self: 'a;
260
261    type MultiPointType<'a>
262        = UnimplementedMultiPoint<N>
263    where
264        Self: 'a;
265
266    type MultiLineStringType<'a>
267        = UnimplementedMultiLineString<N>
268    where
269        Self: 'a;
270
271    type MultiPolygonType<'a>
272        = UnimplementedMultiPolygon<N>
273    where
274        Self: 'a;
275
276    type GeometryCollectionType<'a>
277        = UnimplementedGeometryCollection<N>
278    where
279        Self: 'a;
280
281    type RectType<'a>
282        = Node<'a, N, T>
283    where
284        Self: 'a;
285
286    type TriangleType<'a>
287        = UnimplementedTriangle<N>
288    where
289        Self: 'a;
290
291    type LineType<'a>
292        = UnimplementedLine<N>
293    where
294        Self: 'a;
295
296    fn dim(&self) -> geo_traits::Dimensions {
297        geo_traits::Dimensions::Xy
298    }
299
300    fn as_type(
301        &self,
302    ) -> geo_traits::GeometryType<
303        '_,
304        Self::PointType<'_>,
305        Self::LineStringType<'_>,
306        Self::PolygonType<'_>,
307        Self::MultiPointType<'_>,
308        Self::MultiLineStringType<'_>,
309        Self::MultiPolygonType<'_>,
310        Self::GeometryCollectionType<'_>,
311        Self::RectType<'_>,
312        Self::TriangleType<'_>,
313        Self::LineType<'_>,
314    > {
315        geo_traits::GeometryType::Rect(self)
316    }
317}