use num_traits::AsPrimitive;
use crate::{Error, Octree, ProxyData, TreeIndex};
pub trait LeafMerge: Sized {
fn leaf_merge(a: Self, b: Self) -> Self;
}
impl<T: LeafMerge, Idx: TreeIndex> Octree<T, Idx> {
fn internal_merge_branch(&mut self, children_idx: Idx) -> Option<T> {
debug_assert!(self.branch_data.is_init(children_idx.as_()));
let mut res: Option<T> = None;
for c in unsafe { self.branch_data.remove_at_unchecked(children_idx.as_()) }.unwrap() {
match unsafe { self.proxies.remove_at_unchecked(c.as_()) }
.unwrap()
.data
{
ProxyData::Void => {}
ProxyData::Leaf(l_idx) => match res {
Some(r) => {
res = Some(T::leaf_merge(
r,
unsafe { self.leaf_data.remove_at_unchecked(l_idx.as_()) }.unwrap(),
))
}
None => {
res = Some(
unsafe { self.leaf_data.remove_at_unchecked(l_idx.as_()) }.unwrap(),
)
}
},
ProxyData::Branch(b_idx) => {
let data = match self.internal_merge_branch(b_idx) {
Some(d) => d,
None => continue,
};
match res {
Some(r) => res = Some(T::leaf_merge(r, data)),
None => res = Some(data),
}
}
}
}
res
}
pub fn merge_branch(&mut self, branch_idx: Idx) -> Result<&T, Error<Idx>>
where
usize: AsPrimitive<Idx>,
{
match self
.proxies
.get(branch_idx.as_())
.ok_or(Error::InvalidIndex(branch_idx))?
.data
{
crate::ProxyData::Branch(ch_idx) => match self.internal_merge_branch(ch_idx) {
Some(r) => {
let l_idx = self.leaf_data.push(r);
self.proxies[branch_idx.as_()].data = ProxyData::Leaf(l_idx.as_());
Ok(&self.leaf_data[l_idx])
}
None => {
self.proxies[branch_idx.as_()].data = ProxyData::Void;
Err(Error::NoLeafs(branch_idx))
}
},
_ => Err(Error::NotABranch(branch_idx)),
}
}
}
impl<T> LeafMerge for Vec<T> {
fn leaf_merge(mut a: Self, mut b: Self) -> Self {
a.append(&mut b);
a
}
}