use crate::quad_helper::{intersects, QuadTree as QuadTreeInner};
use nalgebra::Point2;
use parry2d::bounding_volume::Aabb as AABB;
use pi_slotmap::{DefaultKey, Key, KeyData, SlotMap};
use wasm_bindgen::prelude::wasm_bindgen;
pub struct AbQueryArgs {
pub aabb: AABB,
len: usize,
pub result: Vec<f64>,
}
impl AbQueryArgs {
pub fn new(aabb: AABB, len: usize) -> AbQueryArgs {
AbQueryArgs {
aabb: aabb,
len,
result: vec![],
}
}
}
pub fn ab_query_func(arg: &mut AbQueryArgs, id: DefaultKey, aabb: &AABB, bind: &i32) {
if intersects(&arg.aabb, aabb) {
if arg.result.len() <= arg.len {
arg.result.push(id.data().as_ffi() as f64);
}
}
}
#[wasm_bindgen]
pub struct QuadTree(QuadTreeInner<DefaultKey, i32>, SlotMap<DefaultKey, ()>);
#[wasm_bindgen]
impl QuadTree {
pub fn default() -> Self {
let max = nalgebra::Vector2::new(100f32, 100f32);
let min = max / 100f32;
Self(
QuadTreeInner::new(
AABB::new(
Point2::new(-1024f32, -1024f32),
Point2::new(3072f32, 3072f32),
),
max,
min,
0,
0,
0,
),
SlotMap::new(),
)
}
pub fn new(
min_x: f64,
min_y: f64,
max_x: f64,
max_y: f64,
min_loose_x: f64,
min_loose_y: f64,
max_loose_x: f64,
max_loose_y: f64,
) -> Self {
let max = nalgebra::Vector2::new(max_loose_x as f32, max_loose_y as f32);
let min = nalgebra::Vector2::new(min_loose_x as f32, min_loose_y as f32);
Self(
QuadTreeInner::new(
AABB::new(
Point2::new(min_x as f32, min_y as f32),
Point2::new(max_x as f32, max_y as f32),
),
max,
min,
0,
0,
0,
),
SlotMap::new(),
)
}
pub fn add(&mut self, min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> f64 {
let min = Point2::new(min_x as f32, min_y as f32);
let max = Point2::new(max_x as f32, max_y as f32);
let id = self.1.insert(());
let res = id.data().as_ffi() as f64;
self.0.add(id, AABB::new(min, max), 1);
res
}
pub fn remove(&mut self, id: f64) {
self.0
.remove(DefaultKey::from(KeyData::from_ffi(id as u64)));
}
pub fn update(&mut self, id: f64, min_x: f64, min_y: f64, max_x: f64, max_y: f64) {
let min = Point2::new(min_x as f32, min_y as f32);
let max = Point2::new(max_x as f32, max_y as f32);
self.0.update(
DefaultKey::from(KeyData::from_ffi(id as u64)),
AABB::new(min, max),
);
}
pub fn query(&self, min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Vec<f64> {
let min = Point2::new(min_x as f32, min_y as f32);
let max = Point2::new(max_x as f32, max_y as f32);
let ab = AABB::new(min, max);
let mut args = AbQueryArgs::new(ab, usize::MAX);
self.0
.query(&AABB::new(min, max), intersects, &mut args, ab_query_func);
args.result
}
pub fn query_max(
&self,
min_x: f64,
min_y: f64,
max_x: f64,
max_y: f64,
result: &mut [f64],
max_len: u32,
) -> f64 {
let min = Point2::new(min_x as f32, min_y as f32);
let max = Point2::new(max_x as f32, max_y as f32);
let ab = AABB::new(min, max);
let mut args = AbQueryArgs::new(ab, max_len as usize);
self.0
.query(&AABB::new(min, max), intersects, &mut args, ab_query_func);
for i in 0..args.result.len() {
result[i] = args.result[i] as f64;
}
args.result.len() as f64
}
}