pub use self::util::*;
pub use self::visitor::*;
pub use self::wrapped::TreeValueWrapped;
use std::cmp::max;
use std::fmt;
use cgmath::num_traits::NumCast;
use rand;
use rand::Rng;
use crate::prelude::*;
mod wrapped;
mod visitor;
mod util;
const SURFACE_AREA_IMPROVEMENT_FOR_ROTATION: f32 = 0.3;
const PERFORM_ROTATION_PERCENTAGE: u32 = 10;
pub trait TreeValue: Clone {
type Bound;
fn bound(&self) -> &Self::Bound;
fn get_bound_with_margin(&self) -> Self::Bound;
}
impl<T> HasBound for (usize, T)
where
T: TreeValue,
T::Bound: Bound,
{
type Bound = T::Bound;
fn bound(&self) -> &Self::Bound {
self.1.bound()
}
}
pub trait Visitor {
type Bound;
type Result;
fn accept(&mut self, bound: &Self::Bound, is_leaf: bool) -> Option<Self::Result>;
}
pub struct DynamicBoundingVolumeTree<T>
where
T: TreeValue,
{
nodes: Vec<Node<T::Bound>>,
values: Vec<(usize, T)>,
free_list: Vec<usize>,
updated_list: Vec<usize>,
root_index: usize,
refit_nodes: Vec<(u32, usize)>,
}
impl<T> Default for DynamicBoundingVolumeTree<T>
where
T: TreeValue,
{
fn default() -> Self {
DynamicBoundingVolumeTree {
nodes: vec![Node::Nil],
values: Vec::default(),
free_list: Vec::default(),
updated_list: Vec::default(),
root_index: 0,
refit_nodes: Vec::default(),
}
}
}
impl<T> fmt::Debug for DynamicBoundingVolumeTree<T>
where
T: TreeValue,
T::Bound: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "graph tree {{")?;
for n_index in 1..self.nodes.len() {
match self.nodes[n_index] {
Node::Branch(ref b) => {
write!(f, " n_{} [label=\"{:?}\"];", n_index, b.bound)?;
write!(f, " n_{} -- n_{};", n_index, b.left)?;
write!(f, " n_{} -- n_{};", n_index, b.right)?;
}
Node::Leaf(ref l) => {
write!(f, " n_{} [label=\"{:?}\"];", n_index, l.bound)?;
}
Node::Nil => (),
}
}
write!(f, "}}")
}
}
#[derive(Debug)]
struct Branch<B> {
parent: usize,
left: usize,
right: usize,
height: u32,
bound: B,
}
#[derive(Debug)]
struct Leaf<B> {
parent: usize,
value: usize,
bound: B,
}
#[derive(Debug)]
enum Node<B> {
Branch(Branch<B>),
Leaf(Leaf<B>),
Nil,
}
impl<T> DynamicBoundingVolumeTree<T>
where
T: TreeValue,
T::Bound: Clone + Contains<T::Bound> + Union<T::Bound, Output = T::Bound> + SurfaceArea,
{
pub fn new() -> Self {
Default::default()
}
pub fn size(&self) -> usize {
self.nodes.len() - self.free_list.len() - 1
}
pub fn height(&self) -> u32 {
if self.values.is_empty() {
0
} else {
match self.nodes[self.root_index] {
Node::Branch(ref b) => b.height,
Node::Leaf(_) => 1,
Node::Nil => 0,
}
}
}
pub fn values(&self) -> &Vec<(usize, T)> {
&self.values
}
pub fn values_mut(&mut self) -> &mut Vec<(usize, T)> {
&mut self.values
}
pub fn reindex_values(&mut self) {
for i in 0..self.values.len() {
if let Node::Leaf(ref mut leaf) = self.nodes[self.values[i].0] {
leaf.value = i;
}
}
}
pub fn clear(&mut self) {
self.root_index = 0;
self.nodes = vec![Node::Nil];
self.free_list.clear();
self.refit_nodes.clear();
self.values.clear();
}
pub fn value_index(&self, node_index: usize) -> Option<usize> {
match self.nodes[node_index] {
Node::Leaf(ref leaf) => Some(leaf.value),
_ => None,
}
}
pub fn query<V>(&self, visitor: &mut V) -> Vec<(&T, V::Result)>
where
V: Visitor<Bound = T::Bound>,
{
self.query_for_indices(visitor)
.into_iter()
.map(|(value_index, result)| (&self.values[value_index].1, result))
.collect()
}
pub fn query_for_indices<V>(&self, visitor: &mut V) -> Vec<(usize, V::Result)>
where
V: Visitor<Bound = T::Bound>,
{
let mut stack = [0; 256];
stack[0] = self.root_index;
let mut stack_pointer = 1;
let mut values = Vec::default();
while stack_pointer > 0 {
stack_pointer -= 1;
let node_index = stack[stack_pointer];
let node = &self.nodes[node_index];
match *node {
Node::Leaf(ref leaf) => {
if let Some(result) = visitor.accept(self.values[leaf.value].1.bound(), true) {
values.push((leaf.value, result));
}
}
Node::Branch(ref branch) => if visitor.accept(&branch.bound, false).is_some() {
stack[stack_pointer] = branch.left;
stack[stack_pointer + 1] = branch.right;
stack_pointer += 2;
},
Node::Nil => (),
}
}
values
}
pub fn update_node(&mut self, node_index: usize, new_value: T) {
if let Node::Leaf(ref mut leaf) = self.nodes[node_index] {
self.values[leaf.value].1 = new_value;
}
self.flag_updated(node_index);
}
pub fn flag_updated(&mut self, node_index: usize) {
self.updated_list.push(node_index);
}
pub fn update(&mut self) {
let nodes = self.updated_list
.iter()
.filter_map(|&index| {
if let Node::Leaf(ref l) = self.nodes[index] {
if !l.bound.contains(self.values[l.value].1.bound()) {
Some((
index,
l.parent,
self.values[l.value].1.get_bound_with_margin(),
))
} else {
None
}
} else {
None
}
})
.collect::<Vec<(usize, usize, T::Bound)>>();
for (node_index, parent_index, fat_bound) in nodes {
if let Node::Leaf(ref mut leaf) = self.nodes[node_index] {
leaf.bound = fat_bound;
}
self.mark_for_refit(parent_index, 2);
}
self.updated_list.clear();
}
pub fn tick(&mut self) {
self.update();
self.do_refit();
}
pub fn insert(&mut self, value: T) -> usize {
let fat_bound = value.get_bound_with_margin();
let value_index = self.values.len();
self.values.push((0, value));
let mut new_leaf = Leaf {
parent: 0,
value: value_index,
bound: fat_bound,
};
if self.root_index == 0 {
self.root_index = self.nodes.len();
self.nodes.push(Node::Leaf(new_leaf));
self.values[value_index].0 = self.root_index;
self.root_index
} else {
let mut node_index = self.root_index;
let (new_branch_index, new_leaf_index) = self.next_free();
self.values[value_index].0 = new_leaf_index;
new_leaf.parent = new_branch_index;
let mut branch_parent_index = 0;
loop {
let add_branch = match self.nodes[node_index] {
Node::Leaf(ref leaf) => {
let new_branch = Branch {
left: node_index, right: new_leaf_index, parent: leaf.parent, height: 2, bound: leaf.bound.union(&new_leaf.bound),
};
Some((node_index, new_branch))
}
Node::Branch(ref branch) => {
let left_bound = get_bound(&self.nodes[branch.left]);
let right_bound = get_bound(&self.nodes[branch.right]);
let left_area = left_bound.union(&new_leaf.bound).surface_area();
let right_area = right_bound.union(&new_leaf.bound).surface_area();
if left_area < right_area {
node_index = branch.left;
} else {
node_index = branch.right;
}
None
}
Node::Nil => break,
};
if let Some((leaf_index, branch)) = add_branch {
if let Node::Leaf(ref mut n) = self.nodes[leaf_index] {
n.parent = new_branch_index;
};
branch_parent_index = branch.parent;
if branch.parent != 0 {
if let Node::Branch(ref mut n) = self.nodes[branch.parent] {
if n.left == leaf_index {
n.left = new_branch_index;
} else {
n.right = new_branch_index;
}
}
}
self.nodes[new_branch_index] = Node::Branch(branch);
self.nodes[new_leaf_index] = Node::Leaf(new_leaf);
if leaf_index == self.root_index {
self.root_index = new_branch_index;
}
break;
}
}
if branch_parent_index != 0 {
self.mark_for_refit(branch_parent_index, 3);
}
new_leaf_index
}
}
pub fn remove(&mut self, node_index: usize) -> Option<T> {
let (value_index, parent_index) = if let Node::Leaf(ref leaf) = self.nodes[node_index] {
(leaf.value, leaf.parent)
} else {
return None;
};
let (_, value) = self.values.swap_remove(value_index);
if value_index < self.values.len() {
if let Node::Leaf(ref mut leaf) = self.nodes[self.values[value_index].0] {
leaf.value = value_index;
}
}
self.nodes[node_index] = Node::Nil;
self.free_list.push(node_index);
if parent_index != 0 {
let (parent_parent_index, sibling_index) =
if let Node::Branch(ref branch) = self.nodes[parent_index] {
(
branch.parent,
if branch.left == node_index {
branch.right
} else {
branch.left
},
)
} else {
return Some(value);
};
self.nodes[parent_index] = Node::Nil;
self.free_list.push(parent_index);
match self.nodes[sibling_index] {
Node::Branch(ref mut branch) => branch.parent = parent_parent_index,
Node::Leaf(ref mut leaf) => leaf.parent = parent_parent_index,
Node::Nil => (),
}
if parent_parent_index == 0 {
self.root_index = sibling_index;
} else {
if let Node::Branch(ref mut b) = self.nodes[parent_parent_index] {
if b.left == parent_index {
b.left = sibling_index;
} else {
b.right = sibling_index;
}
}
self.mark_for_refit(parent_parent_index, 0);
}
} else {
self.clear();
}
Some(value)
}
pub fn do_refit(&mut self) {
while !self.refit_nodes.is_empty() {
let (_, node_index) = self.refit_nodes.remove(0);
self.refit_node(node_index);
}
}
fn next_free(&mut self) -> (usize, usize) {
(self.take_free(), self.take_free())
}
fn take_free(&mut self) -> usize {
if self.free_list.is_empty() {
let index = self.nodes.len();
self.nodes.push(Node::Nil);
index
} else {
self.free_list.remove(0)
}
}
fn mark_for_refit(&mut self, node_index: usize, min_height: u32) {
let node_height = match self.nodes[node_index] {
Node::Branch(ref b) => b.height,
_ => 0,
};
let height = max(node_height, min_height);
let value = (height, node_index);
match self.refit_nodes.binary_search(&value) {
Ok(_) => (),
Err(i) => self.refit_nodes.insert(i, value),
}
}
fn refit_node(&mut self, node_index: usize) {
if let Some((parent_index, height)) = self.recalculate_node(node_index) {
if parent_index != 0 {
self.mark_for_refit(parent_index, height + 1);
}
}
if rand::thread_rng().gen_range(0, 100) < PERFORM_ROTATION_PERCENTAGE {
self.rotate(node_index);
}
}
fn recalculate_node(&mut self, node_index: usize) -> Option<(usize, u32)> {
let (height, bound, parent_index) = {
let (left_height, left_bound, right_height, right_bound, parent_index) =
if let Node::Branch(ref branch) = self.nodes[node_index] {
(
get_height(&self.nodes[branch.left]),
get_bound(&self.nodes[branch.left]),
get_height(&self.nodes[branch.right]),
get_bound(&self.nodes[branch.right]),
branch.parent,
)
} else {
return None;
};
(
1 + max(left_height, right_height),
left_bound.union(right_bound),
parent_index,
)
};
if let Node::Branch(ref mut branch) = self.nodes[node_index] {
branch.height = height;
branch.bound = bound;
}
Some((parent_index, height))
}
fn rotate(&mut self, node_index: usize) -> Option<usize> {
let improvement_percentage: <T::Bound as SurfaceArea>::Scalar =
NumCast::from(SURFACE_AREA_IMPROVEMENT_FOR_ROTATION).unwrap();
let (left_index, right_index, my_surface_area, parent_index) =
if let Node::Branch(ref branch) = self.nodes[node_index] {
(
branch.left,
branch.right,
branch.bound.surface_area(),
branch.parent,
)
} else {
return None;
};
let left_is_leaf = is_leaf(&self.nodes[left_index]);
let right_is_leaf = is_leaf(&self.nodes[right_index]);
if !left_is_leaf || !right_is_leaf {
let (rot, min_sa) = get_best_rotation(
&self.nodes,
left_index,
right_index,
my_surface_area,
left_is_leaf,
right_is_leaf,
);
if (my_surface_area - min_sa) / my_surface_area > improvement_percentage {
match rot {
Rotation::None => (),
Rotation::LeftRightLeft => {
let right_left_index = get_left_index(&self.nodes[right_index]);
swap(
&mut self.nodes,
left_index,
right_left_index,
node_index,
right_index,
);
self.recalculate_node(right_index);
self.recalculate_node(node_index);
}
Rotation::LeftRightRight => {
let right_right_index = get_right_index(&self.nodes[right_index]);
swap(
&mut self.nodes,
left_index,
right_right_index,
node_index,
right_index,
);
self.recalculate_node(right_index);
self.recalculate_node(node_index);
}
Rotation::RightLeftLeft => {
let left_left_index = get_left_index(&self.nodes[left_index]);
swap(
&mut self.nodes,
left_left_index,
right_index,
left_index,
node_index,
);
self.recalculate_node(left_index);
self.recalculate_node(node_index);
}
Rotation::RightLeftRight => {
let left_right_index = get_right_index(&self.nodes[left_index]);
swap(
&mut self.nodes,
left_right_index,
right_index,
left_index,
node_index,
);
self.recalculate_node(left_index);
self.recalculate_node(node_index);
}
Rotation::LeftLeftRightLeft => {
let left_left_index = get_left_index(&self.nodes[left_index]);
let right_left_index = get_left_index(&self.nodes[right_index]);
swap(
&mut self.nodes,
left_left_index,
right_left_index,
left_index,
right_index,
);
self.recalculate_node(left_index);
self.recalculate_node(right_index);
self.recalculate_node(node_index);
}
Rotation::LeftLeftRightRight => {
let left_left_index = get_left_index(&self.nodes[left_index]);
let right_right_index = get_right_index(&self.nodes[right_index]);
swap(
&mut self.nodes,
left_left_index,
right_right_index,
left_index,
right_index,
);
self.recalculate_node(left_index);
self.recalculate_node(right_index);
self.recalculate_node(node_index);
}
}
}
}
Some(parent_index)
}
}
enum Rotation {
None,
LeftRightLeft,
LeftRightRight,
RightLeftLeft,
RightLeftRight,
LeftLeftRightLeft,
LeftLeftRightRight,
}
#[inline]
fn swap<B>(
nodes: &mut Vec<Node<B>>,
left_swap_index: usize,
right_swap_index: usize,
left_parent_index: usize,
right_parent_index: usize,
) {
if let Node::Branch(ref mut left_parent) = nodes[left_parent_index] {
if left_parent.left == left_swap_index {
left_parent.left = right_swap_index;
} else {
left_parent.right = right_swap_index;
}
}
if let Node::Branch(ref mut right_parent) = nodes[right_parent_index] {
if right_parent.left == right_swap_index {
right_parent.left = left_swap_index;
} else {
right_parent.right = left_swap_index;
}
}
match nodes[left_swap_index] {
Node::Branch(ref mut left) => left.parent = right_parent_index,
Node::Leaf(ref mut left) => left.parent = right_parent_index,
_ => (),
}
match nodes[right_swap_index] {
Node::Branch(ref mut rl) => rl.parent = left_parent_index,
Node::Leaf(ref mut rl) => rl.parent = left_parent_index,
_ => (),
}
}
#[inline]
fn get_best_rotation<B>(
nodes: &[Node<B>],
left_index: usize,
right_index: usize,
node_surface_area: <B as SurfaceArea>::Scalar,
left_is_leaf: bool,
right_is_leaf: bool,
) -> (Rotation, <B as SurfaceArea>::Scalar)
where
B: Union<B, Output = B> + SurfaceArea,
{
let mut rot = Rotation::None;
let mut min_sa = node_surface_area;
let l_bound = get_bound(&nodes[left_index]);
let r_bound = get_bound(&nodes[right_index]);
if !right_is_leaf {
let (rl_bound, rr_bound) = match nodes[right_index] {
Node::Branch(ref right) => (
get_bound(&nodes[right.left]),
get_bound(&nodes[right.right]),
),
_ => panic!(),
};
let l_rl_sa = sa(rl_bound, l_bound, rr_bound);
if l_rl_sa < min_sa {
rot = Rotation::LeftRightLeft;
min_sa = l_rl_sa;
}
let l_rr_sa = sa(rr_bound, l_bound, rl_bound);
if l_rr_sa < min_sa {
rot = Rotation::LeftRightRight;
min_sa = l_rr_sa;
}
if !left_is_leaf {
let (ll_bound, lr_bound) = match nodes[left_index] {
Node::Branch(ref left) => {
(get_bound(&nodes[left.left]), get_bound(&nodes[left.right]))
}
_ => panic!(),
};
let ll_rl_sa = sa(&rl_bound.union(lr_bound), ll_bound, rr_bound);
if ll_rl_sa < min_sa {
rot = Rotation::LeftLeftRightLeft;
min_sa = ll_rl_sa;
}
let ll_rr_sa = sa(&rr_bound.union(lr_bound), rl_bound, ll_bound);
if ll_rr_sa < min_sa {
rot = Rotation::LeftLeftRightRight;
min_sa = ll_rr_sa;
}
}
}
if !left_is_leaf {
let (ll_bound, lr_bound) = match nodes[left_index] {
Node::Branch(ref left) => (get_bound(&nodes[left.left]), get_bound(&nodes[left.right])),
_ => panic!(),
};
let r_ll_sa = sa(ll_bound, r_bound, lr_bound);
if r_ll_sa < min_sa {
rot = Rotation::RightLeftLeft;
min_sa = r_ll_sa;
}
let r_lr_sa = sa(lr_bound, r_bound, ll_bound);
if r_lr_sa < min_sa {
rot = Rotation::RightLeftRight;
min_sa = r_lr_sa;
}
}
(rot, min_sa)
}
#[inline]
fn sa<B>(a: &B, b: &B, c: &B) -> <B as SurfaceArea>::Scalar
where
B: Union<B, Output = B> + SurfaceArea,
{
a.union(&b.union(c)).surface_area()
}
#[inline]
fn get_left_index<B>(node: &Node<B>) -> usize {
match *node {
Node::Branch(ref b) => b.left,
_ => panic!(),
}
}
#[inline]
fn get_right_index<B>(node: &Node<B>) -> usize {
match *node {
Node::Branch(ref b) => b.right,
_ => panic!(),
}
}
#[inline]
fn is_leaf<B>(node: &Node<B>) -> bool {
match *node {
Node::Leaf(_) => true,
_ => false,
}
}
#[inline]
fn get_height<B>(node: &Node<B>) -> u32 {
match *node {
Node::Branch(ref branch) => branch.height,
Node::Leaf(_) => 1,
Node::Nil => 0,
}
}
#[inline]
fn get_bound<B>(node: &Node<B>) -> &B {
match *node {
Node::Branch(ref branch) => &branch.bound,
Node::Leaf(ref leaf) => &leaf.bound,
Node::Nil => panic!(),
}
}