use std::fmt;
use std::fmt::{Debug, Formatter};
use crate::boxes::BBox;
use crate::{median, Rng};
#[derive(Clone)]
pub struct BBoxSet<B: BBox, ID> {
pub boxes: Vec<(B, ID)>,
}
impl<B, ID> Debug for BBoxSet<B, ID>
where
B: BBox + Debug,
ID: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.boxes.iter().map(|(_r, id)| id))
.finish()
}
}
impl<B, ID> BBoxSet<B, ID>
where
B: BBox,
ID: Copy + PartialEq,
B::Num: PartialOrd,
{
pub fn new() -> Self {
Self { boxes: Vec::new() }
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
boxes: Vec::with_capacity(capacity),
}
}
pub fn push(&mut self, id: ID, bbox: B) {
self.boxes.push((bbox, id));
}
pub fn clear(&mut self) {
self.boxes.clear();
}
pub fn sort(&mut self) {
self.boxes
.sort_by(|(a, _), (b, _)| a.lo(0).partial_cmp(&b.lo(0)).unwrap());
}
pub fn len(&self) -> usize {
self.boxes.len()
}
pub fn get(&self, idx: usize) -> (B, ID) {
self.boxes[idx]
}
pub fn find(&self, id: ID) -> Option<B> {
self.boxes
.iter()
.find(|x| x.1 == id)
.and_then(|x| Some(x.0))
}
pub fn empty(&self) -> bool {
self.len() == 0
}
pub fn filter<P>(&self, pred: P) -> Self
where
P: FnMut(&&(B, ID)) -> bool,
{
Self {
boxes: self.boxes.iter().filter(pred).cloned().collect(),
}
}
pub fn partition<P>(&self, pred: P) -> (Self, Self)
where
P: FnMut(&&(B, ID)) -> bool,
{
let (tr, fls) = self.boxes.iter().partition(pred);
(Self { boxes: tr }, Self { boxes: fls })
}
pub fn approx_median<R: Rng>(&self, dim: usize, rand: &mut R) -> B::Num {
let mut levels = (0.91 * ((self.len() as f64) / 137.0 + 1.0).ln().floor()) as u32;
if levels == 0 {
levels = 1;
}
let cap = 3usize.pow(levels);
let mut random_indices = Vec::<usize>::with_capacity(cap);
let points: Vec<B::Num> = self.boxes.iter().map(|&(bbox, _id)| bbox.lo(dim)).collect();
for _ in 0..cap {
random_indices.push(rand.rand_usize(points.len()));
}
median::approx_median(&points, levels as u8, &mut random_indices)
}
}