mod error;
mod iter;
mod merge;
mod proxy;
mod sample;
mod slice;
use std::{
collections::HashMap,
convert::TryInto,
ops::{Range, Shl, ShlAssign, Shr, ShrAssign},
};
pub use error::*;
pub use iter::*;
pub use merge::*;
use nalgebra::ClosedMul;
use num_traits::{AsPrimitive, PrimInt};
pub use proxy::*;
pub use sample::*;
pub use slice::*;
use crate::{stablevec, vec::StableVec, NodePoint, Octant, VoxelPoint};
use parking_lot::RwLock;
pub trait TreeIndex:
PrimInt
+ AsPrimitive<usize>
+ AsPrimitive<u8>
+ Shl<Self, Output = Self>
+ std::fmt::Debug
+ 'static
{
}
impl<P> TreeIndex for P where
P: PrimInt
+ AsPrimitive<usize>
+ AsPrimitive<u8>
+ Shl<Self, Output = Self>
+ std::fmt::Debug
+ 'static
{
}
#[derive(Debug)]
pub struct Octree<T, Idx: TreeIndex> {
proxies: StableVec<Proxy<Idx>>,
branch_data: StableVec<[Idx; 8]>,
leaf_data: StableVec<T>,
root: Idx,
height_cache: RwLock<Option<Idx>>,
}
impl<T, Idx: TreeIndex> Default for Octree<T, Idx> {
fn default() -> Self {
Self::new()
}
}
impl<T, Idx: TreeIndex> Octree<T, Idx> {
pub fn max_grid_size() -> Idx {
Idx::max_value()
}
pub fn new() -> Self {
Self {
proxies: stablevec![Proxy {
parent: Idx::zero(),
data: ProxyData::Void,
}],
branch_data: StableVec::default(),
leaf_data: StableVec::default(),
root: Idx::zero(),
height_cache: Default::default(),
}
}
pub fn depth_of_unchecked(&self, mut node: Idx) -> Idx {
let mut depth = Idx::zero();
let mut p = self.proxies[node.as_()];
while p.parent != node {
depth = depth + Idx::one();
node = p.parent;
p = self.proxies[node.as_()];
}
depth
}
pub fn depth_of(&self, node: Idx) -> Result<Idx, Error<Idx>> {
if !self.proxies.is_init(node.as_()) {
return Err(Error::InvalidIndex(node));
}
Ok(self.depth_of_unchecked(node))
}
pub fn branch(&mut self, target: Idx) -> Result<&[Idx; 8], Error<Idx>>
where
usize: AsPrimitive<Idx>,
u8: AsPrimitive<Idx>,
Range<Idx>: Iterator,
{
match self.proxies[target.as_()].data {
ProxyData::Branch(children) => Ok(&self.branch_data[children.as_()]),
ProxyData::Leaf(_) => Err(Error::BranchCollision),
ProxyData::Void => {
let children: [Idx; 8] = self
.proxies
.push_iter((0..8).map(|_| Proxy {
parent: target,
data: ProxyData::Void,
}))
.collect::<Vec<_>>()
.as_slice()
.try_into()
.unwrap();
let c_index = self.branch_data.push(children);
self.proxies[target.as_()].data = ProxyData::Branch(c_index.as_());
if let Some(height) = *self.height_cache.read() {
let pdepth = self.depth_of_unchecked(target);
self.height_cache.write().replace(height.max(pdepth));
}
Ok(&self.branch_data[c_index])
}
}
}
fn flatten_branch(
&mut self,
target: Idx,
children_idx: Idx,
new_data: ProxyData<Idx>,
) -> Vec<T> {
self.height_cache.write().take();
self.proxies[target.as_()].data = new_data;
let mut res = Vec::with_capacity(8);
let mut to_remove = unsafe {
self.branch_data
.remove_at_unchecked(children_idx.as_())
.unwrap()
.to_vec()
};
while let Some(c_idx) = to_remove.pop() {
match unsafe { self.proxies.remove_at_unchecked(c_idx.as_()).unwrap().data } {
ProxyData::Void => {}
ProxyData::Leaf(t) => {
res.push(unsafe { self.leaf_data.remove_at_unchecked(t.as_()).unwrap() })
}
ProxyData::Branch(c_idx) => {
to_remove.extend_from_slice(unsafe {
&self.branch_data.remove_at_unchecked(c_idx.as_()).unwrap()
});
}
}
}
res
}
pub fn void(&mut self, target: Idx) -> Vec<T> {
match self.proxies[target.as_()].data {
ProxyData::Void => Vec::with_capacity(0),
ProxyData::Leaf(l) => {
self.proxies[target.as_()].data = ProxyData::Void;
vec![self.leaf_data.remove(l.as_()).unwrap()]
}
ProxyData::Branch(c) => self.flatten_branch(target, c, ProxyData::Void),
}
}
pub fn set_leaf(&mut self, target: Idx, data: T) -> Vec<T>
where
usize: AsPrimitive<Idx>,
{
match self.proxies[target.as_()].data {
ProxyData::Leaf(l) => vec![self.leaf_data.replace(l.as_(), data).unwrap()],
ProxyData::Void => {
self.proxies[target.as_()].data = ProxyData::Leaf(self.leaf_data.push(data).as_());
Vec::with_capacity(0)
}
ProxyData::Branch(ch_idx) => {
let res = self.flatten_branch(target, ch_idx, ProxyData::Void);
self.proxies[target.as_()].data = ProxyData::Leaf(self.leaf_data.push(data).as_());
res
}
}
}
pub fn grow(&mut self, oct: Octant) -> Result<Idx, Error<Idx>>
where
u8: AsPrimitive<Idx>,
usize: AsPrimitive<Idx>,
{
let old_root = self.root;
if let Some(h) = self.height_cache.write().as_mut() {
*h = *h + Idx::one();
}
self.proxies.reserve(8);
let mut children: Vec<Idx> = self
.proxies
.push_iter(
std::iter::repeat(Proxy {
parent: self.root,
data: ProxyData::Void,
})
.take(7),
)
.collect::<Vec<Idx>>();
children.insert(oct.0 as usize, old_root);
self.root = self
.proxies
.push(Proxy {
parent: self.root,
data: ProxyData::Branch(
self.branch_data
.push(children.as_slice().try_into().unwrap())
.as_(),
),
})
.as_();
self.proxies[old_root.as_()].parent = self.root;
Ok(self.root)
}
fn internal_voxel_at(&self, p: &VoxelPoint<Idx>, size: Idx) -> Idx
where
Idx: Shr<u8, Output = Idx> + ShrAssign<u8> + PartialOrd + From<u8>,
{
let mut idx: Idx = 0u8.into();
let mut vox = self.proxies[self.root.as_()];
let mut s2 = size >> 1u8; while let ProxyData::Branch(ch_idx) = vox.data {
let children = &self.branch_data[ch_idx.as_()];
let oct = Octant::new(p.x > s2, p.y > s2, p.z > s2);
idx = children[oct.0 as usize];
vox = self.proxies[idx.as_()];
s2 >>= 1u8; }
idx
}
pub fn voxel_at_unchecked(&self, p: &VoxelPoint<Idx>) -> Idx
where
Idx: Shr<u8, Output = Idx> + ShrAssign<u8> + PartialOrd + From<u8> + Shl<Idx, Output = Idx>,
{
self.internal_voxel_at(p, self.grid_size())
}
pub fn voxel_at<'data>(&self, p: &'data VoxelPoint<Idx>) -> Result<Idx, Error<'data, Idx>>
where
Idx: Shr<u8, Output = Idx> + ShrAssign<u8> + PartialOrd + From<u8> + Shl<Idx, Output = Idx>,
{
let size = self.grid_size();
if p.x >= size || p.y >= size || p.z >= size {
return Err(Error::VoxelOutOfGrid(size, p));
}
Ok(self.internal_voxel_at(p, size))
}
pub fn node_at(&self, p: &NodePoint<Idx>) -> Idx
where
Idx: Shl<Idx, Output = Idx>
+ ShlAssign<Idx>
+ From<u8>
+ Shr<u8, Output = Idx>
+ ClosedMul
+ ShrAssign<u8>,
{
let mut idx = Idx::zero();
let mut vox = &self.proxies[self.root.as_()];
let ps = Idx::one() << p.0.w; let mut s2 = ps >> 1u8; let psp = VoxelPoint::new(p.0.x * ps, p.0.y * ps, p.0.z * ps); while let ProxyData::Branch(ch_idx) = &vox.data {
if s2.is_zero() {
break;
};
let children = &self.branch_data[ch_idx.as_()];
let oct = Octant::new(psp.x > s2, psp.y > s2, psp.z > s2);
idx = children[oct.0 as usize];
vox = &self.proxies[idx.as_()];
s2 >>= 1; }
idx
}
pub fn upcast<NIdx: TreeIndex>(mut self) -> Octree<T, NIdx>
where
usize: AsPrimitive<Idx>,
Idx: AsPrimitive<NIdx>,
{
debug_assert!(std::mem::size_of::<Idx>() <= std::mem::size_of::<NIdx>());
self.compress();
Octree {
proxies: self
.proxies
.iter()
.map(|p| Proxy::<NIdx> {
parent: p.parent.as_(),
data: match p.data {
ProxyData::Void => ProxyData::Void,
ProxyData::Leaf(l_idx) => ProxyData::Leaf(l_idx.as_()),
ProxyData::Branch(b_idx) => ProxyData::Branch(b_idx.as_()),
},
})
.collect(),
branch_data: self
.branch_data
.iter()
.map(|b| b.map(|c| c.as_()))
.collect(),
leaf_data: self.leaf_data,
root: self.root.as_(),
height_cache: RwLock::new(self.height_cache.read().map(|h| h.as_())),
}
}
pub fn defragment(&mut self)
where
usize: AsPrimitive<Idx>,
{
let p_swaps = HashMap::<usize, usize>::from_iter(self.proxies.defragment());
let l_swaps = HashMap::<usize, usize>::from_iter(self.leaf_data.defragment());
let b_swaps = HashMap::<usize, usize>::from_iter(self.branch_data.defragment());
for p in self.proxies.as_slice_mut().unwrap().iter_mut() {
if let Some(&parent) = p_swaps.get(&p.parent.as_()) {
p.parent = parent.as_();
}
match &mut p.data {
ProxyData::Void => {}
ProxyData::Leaf(ref mut l_idx) => {
if let Some(&leaf) = l_swaps.get(&l_idx.as_()) {
*l_idx = leaf.as_();
}
}
ProxyData::Branch(ref mut b_idx) => {
if let Some(&children) = b_swaps.get(&b_idx.as_()) {
*b_idx = children.as_();
}
let children = &mut self.branch_data[b_idx.as_()];
for c in children {
if let Some(&child) = p_swaps.get(&c.as_()) {
*c = child.as_();
}
}
}
}
}
}
pub fn compress(&mut self)
where
usize: AsPrimitive<Idx>,
{
self.defragment();
self.proxies.compress();
self.branch_data.compress();
self.leaf_data.compress();
}
pub fn leaf_unordered(&self) -> impl Iterator<Item = &T> {
self.leaf_data.iter()
}
pub fn node_point_of_unchecked(&self, mut index: Idx) -> NodePoint<Idx>
where
u8: AsPrimitive<Idx>,
{
let mut x = Idx::zero();
let mut y = Idx::zero();
let mut z = Idx::zero();
let mut d = Idx::zero();
let mut p = self.proxies[index.as_()];
while p.parent != index {
d = d + Idx::one();
match self.proxies[p.parent.as_()].data {
ProxyData::Branch(b_idx) => {
let oct = Octant(
self.branch_data[b_idx.as_()]
.into_iter()
.find(|&c| c == index)
.unwrap()
.as_(),
);
x = x + oct.i().as_();
y = y + oct.j().as_();
z = z + oct.k().as_();
}
_ => unreachable!(),
}
index = p.parent;
p = self.proxies[index.as_()];
}
NodePoint::new(x, y, z, d)
}
pub fn node_point_of(&self, index: Idx) -> Result<NodePoint<Idx>, Error<Idx>>
where
u8: AsPrimitive<Idx>,
{
if !self.proxies.is_init(index.as_()) {
return Err(Error::InvalidIndex(index));
}
Ok(self.node_point_of_unchecked(index))
}
pub fn graft_unchecked(&mut self, mut other: Self, node: Idx)
where
usize: AsPrimitive<Idx>,
{
let o_root = unsafe { other.proxies.remove_at_unchecked(other.root.as_()) }.unwrap();
self.proxies[node.as_()].data = o_root.data;
let l_swaps = self.leaf_data.extend_from_other(other.leaf_data);
let b_swaps = self.branch_data.extend_from_other(other.branch_data);
let mut p_swaps = self.proxies.extend_from_other(other.proxies);
p_swaps.insert(other.root.as_(), node.as_());
let mut max_depth = self.depth_of_unchecked(node);
let mut node_stack = vec![(node.as_(), self.proxies[node.as_()], max_depth)];
while let Some((i, p, d)) = node_stack.pop() {
if d > max_depth {
max_depth = d;
}
if i != node.as_() {
self.proxies[i].parent = p_swaps[&p.parent.as_()].as_();
}
match p.data {
ProxyData::Void => {}
ProxyData::Leaf(l_idx) => {
self.proxies[i].data = ProxyData::Leaf(l_swaps[&l_idx.as_()].as_())
}
ProxyData::Branch(b_idx) => {
let c_idx = b_swaps[&b_idx.as_()];
for c in &mut self.branch_data[c_idx] {
let ci = c.as_();
*c = p_swaps[&ci].as_();
node_stack.push((ci, self.proxies[ci], d + Idx::one()));
}
self.proxies[i].data = ProxyData::Branch(c_idx.as_());
}
}
}
let mut h_cache = self.height_cache.write();
if let Some(h) = *h_cache {
*h_cache = Some(h.max(max_depth))
}
}
pub fn graft(&mut self, other: Self, node: Idx) -> Result<(), Error<Idx>>
where
usize: AsPrimitive<Idx>,
{
if !matches!(
self.proxies
.get(node.as_())
.ok_or(Error::InvalidIndex(node))?
.data,
ProxyData::Branch(_)
) {
return Err(Error::NotAVoid(node));
}
self.graft_unchecked(other, node);
Ok(())
}
}