use geo_traits::{
GeometryTrait, RectTrait, UnimplementedGeometryCollection, UnimplementedLine,
UnimplementedLineString, UnimplementedMultiLineString, UnimplementedMultiPoint,
UnimplementedMultiPolygon, UnimplementedPoint, UnimplementedPolygon, UnimplementedTriangle,
};
use crate::kdtree::KDTreeIndex;
use crate::r#type::{Coord, IndexableNum};
use std::marker::PhantomData;
#[derive(Debug, Clone)]
pub struct Node<'a, N: IndexableNum, T: KDTreeIndex<N>> {
tree: &'a T,
axis: usize,
right_child: usize,
left_child: usize,
min_x: N,
min_y: N,
max_x: N,
max_y: N,
phantom: PhantomData<N>,
}
impl<'a, N: IndexableNum, T: KDTreeIndex<N>> Node<'a, N, T> {
pub(crate) fn from_root(tree: &'a T) -> Self {
Self {
tree,
axis: 0,
right_child: tree.indices().len() - 1,
left_child: 0,
min_x: N::max_value(),
min_y: N::max_value(),
max_x: N::min_value(),
max_y: N::min_value(),
phantom: PhantomData,
}
}
#[inline]
pub(crate) fn middle_index(&self) -> usize {
(self.left_child + self.right_child) >> 1
}
#[inline]
pub(crate) fn middle_xy(&self, m: usize) -> (N, N) {
let x = self.tree.coords()[2 * m];
let y = self.tree.coords()[2 * m + 1];
(x, y)
}
pub fn left_child(&self) -> Option<Node<'_, N, T>> {
if self.is_parent() {
Some(self.left_child_unchecked())
} else {
None
}
}
pub fn left_child_unchecked(&self) -> Node<'_, N, T> {
debug_assert!(self.is_parent());
let m = self.middle_index();
let (x, y) = self.middle_xy(m);
let mut max_x = self.max_x;
let mut max_y = self.max_y;
if self.axis == 0 {
max_x = x;
} else {
max_y = y;
};
Self {
tree: self.tree,
axis: 1 - self.axis,
right_child: m - 1,
left_child: self.left_child,
min_x: self.min_x,
min_y: self.min_y,
max_x,
max_y,
phantom: self.phantom,
}
}
pub fn right_child(&self) -> Option<Node<'_, N, T>> {
if self.is_parent() {
Some(self.right_child_unchecked())
} else {
None
}
}
pub fn right_child_unchecked(&self) -> Node<'_, N, T> {
debug_assert!(self.is_parent());
let m = self.middle_index();
let (x, y) = self.middle_xy(m);
let mut min_x = self.min_x;
let mut min_y = self.min_y;
if self.axis == 0 {
min_x = x;
} else {
min_y = y;
};
Self {
tree: self.tree,
axis: 1 - self.axis,
right_child: self.right_child,
left_child: m + 1,
min_x,
min_y,
max_x: self.max_x,
max_y: self.max_y,
phantom: self.phantom,
}
}
#[inline]
pub fn is_leaf(&self) -> bool {
self.right_child - self.left_child <= self.tree.node_size() as usize
}
#[inline]
pub fn is_parent(&self) -> bool {
!self.is_leaf()
}
#[inline]
pub fn middle_insertion_index(&self) -> Option<u32> {
if self.is_parent() {
Some(self.middle_insertion_index_unchecked())
} else {
None
}
}
#[inline]
pub fn middle_insertion_index_unchecked(&self) -> u32 {
debug_assert!(self.is_parent());
let m = self.middle_index();
let indices = self.tree.indices();
indices.get(m) as u32
}
#[inline]
pub fn leaf_insertion_indices(&self) -> Option<Vec<u32>> {
if self.is_leaf() {
Some(self.leaf_insertion_indices_unchecked())
} else {
None
}
}
#[inline]
pub fn leaf_insertion_indices_unchecked(&self) -> Vec<u32> {
debug_assert!(self.is_leaf());
let mut result = Vec::with_capacity(self.tree.node_size() as _);
let indices = self.tree.indices();
for i in self.left_child..self.right_child + 1 {
result.push(indices.get(i) as u32);
}
result
}
}
impl<N: IndexableNum, T: KDTreeIndex<N>> RectTrait for Node<'_, N, T> {
type CoordType<'a>
= Coord<N>
where
Self: 'a;
fn min(&self) -> Self::CoordType<'_> {
Coord {
x: self.min_x,
y: self.min_y,
}
}
fn max(&self) -> Self::CoordType<'_> {
Coord {
x: self.max_x,
y: self.max_y,
}
}
}
impl<N: IndexableNum, T: KDTreeIndex<N>> GeometryTrait for Node<'_, N, T> {
type T = N;
type PointType<'a>
= UnimplementedPoint<N>
where
Self: 'a;
type LineStringType<'a>
= UnimplementedLineString<N>
where
Self: 'a;
type PolygonType<'a>
= UnimplementedPolygon<N>
where
Self: 'a;
type MultiPointType<'a>
= UnimplementedMultiPoint<N>
where
Self: 'a;
type MultiLineStringType<'a>
= UnimplementedMultiLineString<N>
where
Self: 'a;
type MultiPolygonType<'a>
= UnimplementedMultiPolygon<N>
where
Self: 'a;
type GeometryCollectionType<'a>
= UnimplementedGeometryCollection<N>
where
Self: 'a;
type RectType<'a>
= Node<'a, N, T>
where
Self: 'a;
type TriangleType<'a>
= UnimplementedTriangle<N>
where
Self: 'a;
type LineType<'a>
= UnimplementedLine<N>
where
Self: 'a;
fn dim(&self) -> geo_traits::Dimensions {
geo_traits::Dimensions::Xy
}
fn as_type(
&self,
) -> geo_traits::GeometryType<
'_,
Self::PointType<'_>,
Self::LineStringType<'_>,
Self::PolygonType<'_>,
Self::MultiPointType<'_>,
Self::MultiLineStringType<'_>,
Self::MultiPolygonType<'_>,
Self::GeometryCollectionType<'_>,
Self::RectType<'_>,
Self::TriangleType<'_>,
Self::LineType<'_>,
> {
geo_traits::GeometryType::Rect(self)
}
}