use num_traits::AsPrimitive;
use crate::{Error, LeafIter, NodePoint, Octant, Octree, ProxyData, TreeIndex};
#[derive(Debug, Clone, Copy)]
pub struct TreeSlice<'tree, T, Idx: TreeIndex> {
tree: &'tree Octree<T, Idx>,
root: Idx,
height: Idx,
}
impl<T, Idx: TreeIndex> Octree<T, Idx> {
pub fn slice(&self, index: Idx) -> Result<TreeSlice<T, Idx>, Error<Idx>> {
if !self.proxies.is_init(index.as_()) {
Err(Error::InvalidIndex(index))
} else {
Ok(TreeSlice {
tree: self,
root: index,
height: if index == self.root {
self.height()
} else {
self.height_from(index)
},
})
}
}
pub fn as_slice(&self) -> TreeSlice<T, Idx> {
TreeSlice {
tree: self,
root: self.root,
height: self.height(),
}
}
}
impl<'tree, T, Idx: TreeIndex> TreeSlice<'tree, T, Idx> {
pub fn base(&self) -> &'tree Octree<T, Idx> {
self.tree
}
}
pub trait OctreeSlice<T, Idx: TreeIndex> {
fn root_idx(&self) -> Idx;
fn height_from(&self, index: Idx) -> Idx;
fn height(&self) -> Idx {
self.height_from(self.root_idx())
}
fn grid_size(&self) -> Idx {
Idx::one() << self.height()
}
fn leaf_dfi(&self) -> LeafIter<T, Idx>;
}
impl<T, Idx: TreeIndex> OctreeSlice<T, Idx> for Octree<T, Idx> {
fn root_idx(&self) -> Idx {
self.root
}
fn height_from(&self, index: Idx) -> Idx {
let mut max_depth = Idx::zero();
let mut node_stack = vec![(self.proxies[index.as_()], Idx::zero())];
while let Some((p, depth)) = node_stack.pop() {
if depth > max_depth {
max_depth = depth;
}
if let ProxyData::Branch(b_idx) = p.data {
node_stack.extend(
self.branch_data[b_idx.as_()]
.into_iter()
.map(|c| (self.proxies[c.as_()], depth + Idx::one())),
);
}
}
max_depth
}
fn height(&self) -> Idx {
match *self.height_cache.read() {
Some(h) => h,
None => {
let mut height_cache = self.height_cache.write();
if let Some(h) = *height_cache {
return h;
} #[cfg(feature = "tracing")]
tracing::trace!("Recalculating tree height...");
let height = self.height_from(self.root);
height_cache.replace(height);
height
}
}
}
fn leaf_dfi(&self) -> LeafIter<T, Idx> {
LeafIter {
tree: self,
node_stack: Vec::default(),
curr_node: Some((
&self.proxies[self.root.as_()],
Octant(0),
NodePoint::new(Idx::zero(), Idx::zero(), Idx::zero(), Idx::zero()),
)),
}
}
}
impl<'tree, T, Idx: TreeIndex> OctreeSlice<T, Idx> for TreeSlice<'tree, T, Idx>
where
u8: AsPrimitive<Idx>,
{
fn root_idx(&self) -> Idx {
self.root
}
fn height_from(&self, index: Idx) -> Idx {
self.tree.height_from(index)
}
fn height(&self) -> Idx {
self.height
}
fn leaf_dfi(&self) -> LeafIter<T, Idx> {
LeafIter {
tree: self.tree,
node_stack: Vec::default(),
curr_node: Some((
&self.tree.proxies[self.root.as_()],
Octant(0),
self.tree.node_point_of_unchecked(self.root),
)),
}
}
}