Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 committed Mar 17, 2024
1 parent dbb6959 commit a3fa642
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
3 changes: 3 additions & 0 deletions crates/quadtree/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use glam::Vec2;
use quadrants::{Quadrants, Rect};
use tree::Tree;

mod packed;
mod quadrants;
mod tree;

pub struct Tree<T>
where
Expand Down
37 changes: 37 additions & 0 deletions crates/quadtree/src/packed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::ops::{Deref, DerefMut};

pub(super) struct Packed<T>(Vec<T>);

impl<T> Packed<T> {
pub(super) fn new() -> Self {
Self(Vec::new())
}

/// Removes an item from the Vec with O(1) efficiency.
///
/// It can move another item to the new position as a side effect. The
/// original index of the moved item is returned in such a case.
pub(super) fn swap_remove(&mut self, index: usize) -> (T, Option<usize>) {
let removed = self.0.swap_remove(index);
let moved = if index < self.0.len() {
Some(self.0.len())
} else {
None
};
(removed, moved)
}
}

impl<T> Deref for Packed<T> {
type Target = Vec<T>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T> DerefMut for Packed<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
116 changes: 116 additions & 0 deletions crates/quadtree/src/tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use crate::{packed::Packed, quadrants::Quadrants};

pub(super) struct Tree<S>
where
S: Default,
{
inner: Packed<Inner>,
leafs: Packed<Leaf<S>>,
}

impl<S> Tree<S>
where
S: Default,
{
pub(super) fn new() -> Self {
let mut inner = Packed::new();
// Add empty root.
inner.push(Inner::new(usize::MAX, Quadrants::default()));
Self {
inner,
leafs: Packed::new(),
}
}

pub(super) fn get_leaf_mut(&self, index: usize) -> Option<&mut S> {
self.leafs.get_mut(index).map(|l| &mut l.item)
}

// TODO remove
// TODO replace (auto crate the replacement)

fn replace(&mut self, node: Node, replacement: Option<Node>) -> Option<S> {
let (removed_parent, moved, item) = match node {
Node::Inner(index) => {
if index == 0 {
panic!("Cannot remove or replace root node.");
}

let (removed, moved) = self.inner.swap_remove(index);
(removed.parent, moved.map(|index| Node::Inner(index)), None)
}
Node::Leaf(index) => {
let (removed, moved) = self.leafs.swap_remove(index);
(
removed.parent,
moved.map(|index| Node::Leaf(index)),
Some(removed.item),
)
}
};

self.inner
.get_mut(removed_parent)
.unwrap()
.replace_child(node, replacement);

if let Some(moved) = moved {
let moved_parent = match node {
Node::Inner(index) => self.inner.get(index).unwrap().parent,
Node::Leaf(index) => self.leafs.get(index).unwrap().parent,
};

self.inner
.get_mut(moved_parent)
.unwrap()
.replace_child(moved, Some(node));
}

item
}
}

// TODO rename to Node
#[derive(Clone, Copy, PartialEq, Eq)]
enum Node {
// TODO consider compressing usize to something smaller & saving the extra
// byte for enum
Inner(usize),
Leaf(usize),
}

struct Inner {
// TODO consider using MAX value for no parent
// TODO consider using something smaller than usize
parent: usize,
children: Quadrants<Node>,
}

impl Inner {
fn new(parent: usize, children: Quadrants<Node>) -> Self {
Self { parent, children }
}

fn replace_child(&mut self, old: Node, new: Option<Node>) {
self.children.replace(&old, new);
}
}

struct Leaf<S> {
// TODO consider using something smaller than usize
parent: usize,
// TODO consider using different array len
item: S,
}

impl<S> Leaf<S>
where
S: Default,
{
fn new(parent: usize) -> Self {
Self {
parent,
item: S::default(),
}
}
}

0 comments on commit a3fa642

Please sign in to comment.