all impl'd, should work

This commit is contained in:
Joe 2026-01-21 19:02:22 -08:00
parent d8f1ffd801
commit 969c84d9cc
2 changed files with 48 additions and 25 deletions

4
.rustfmt.toml Normal file
View file

@ -0,0 +1,4 @@
imports_granularity = "Crate"
group_imports = "StdExternalCrate"
wrap_comments = true
edition = "2024"

View file

@ -1,10 +1,11 @@
use crate::geom::Point; use std::cmp::Ordering;
use bevy::{ use bevy::{
math::bounding::{Aabb2d, BoundingVolume, IntersectsVolume}, math::bounding::{Aabb2d, BoundingVolume, IntersectsVolume},
prelude::*, prelude::*,
}; };
use ordered_float::OrderedFloat;
use std::{cmp::Ordering, collections::BinaryHeap}; use crate::geom::Point;
// Epsilon value for zero-sizes bounding boxes/cubes. // Epsilon value for zero-sizes bounding boxes/cubes.
const EPSILON: f32 = 1e-10; const EPSILON: f32 = 1e-10;
@ -37,16 +38,15 @@ pub struct TreeNode {
/// R*tree data structure for indexing 2D or 3D points. /// R*tree data structure for indexing 2D or 3D points.
/// ///
/// The tree is initialized with a maximum number of entries per node. If a node exceeds this /// The tree is initialized with a maximum number of entries per node. If a node
/// number, it will split. The tree supports insertion, deletion, and range searches. /// exceeds this number, it will split. The tree supports insertion, deletion,
/// and range searches.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RStarTree { pub struct RStarTree {
root: TreeNode, root: TreeNode,
max_entries: usize, max_entries: usize,
min_entries: usize,
} }
// Common trait implementations for R*-tree to reuse shared algorithms.
impl Entry { impl Entry {
fn as_leaf_obj(&self) -> Option<&Point> { fn as_leaf_obj(&self) -> Option<&Point> {
match self { match self {
@ -94,18 +94,18 @@ impl TreeNode {
let mut result = Vec::new(); let mut result = Vec::new();
if self.is_leaf() { if self.is_leaf() {
for entry in self.entries() { for entry in self.entries() {
if let Some(obj) = entry.as_leaf_obj() { if let Some(obj) = entry.as_leaf_obj()
if entry.mbr().intersects(bbox) { && entry.mbr().intersects(bbox)
result.push(obj); {
} result.push(obj);
} }
} }
} else { } else {
for entry in self.entries() { for entry in self.entries() {
if let Some(child) = entry.child() { if let Some(child) = entry.child()
if entry.mbr().intersects(bbox) { && entry.mbr().intersects(bbox)
result.extend_from_slice(&child.range_search_bbox(bbox)); {
} result.extend_from_slice(&child.range_search_bbox(bbox));
} }
} }
} }
@ -119,14 +119,13 @@ impl TreeNode {
impl RStarTree { impl RStarTree {
pub fn new(max_entries: usize) -> Self { pub fn new(max_entries: usize) -> Self {
let max_entries = max_entries.max(2); let max_entries = max_entries.max(4);
RStarTree { RStarTree {
root: TreeNode { root: TreeNode {
entries: Vec::new(), entries: Vec::new(),
is_leaf: true, is_leaf: true,
}, },
max_entries, max_entries,
min_entries: (max_entries as f32 * 0.4).ceil() as usize,
} }
} }
@ -159,11 +158,11 @@ impl RStarTree {
if reinsert_level == Some(overflow_level) { if reinsert_level == Some(overflow_level) {
let old_entries = overflowed_node; let old_entries = overflowed_node;
let (group1, group2) = split_entries(old_entries, self.max_entries); let (group1, group2) = split_entries(old_entries, self.max_entries);
let mut mbr1 = group1[0].mbr().clone(); let mut mbr1 = *group1[0].mbr();
for entry in group1.iter() { for entry in group1.iter() {
mbr1 = mbr1.merge(entry.mbr()); mbr1 = mbr1.merge(entry.mbr());
} }
let mut mbr2 = group2[0].mbr().clone(); let mut mbr2 = *group2[0].mbr();
for entry in group2.iter() { for entry in group2.iter() {
mbr2 = mbr2.merge(entry.mbr()); mbr2 = mbr2.merge(entry.mbr());
} }
@ -212,7 +211,8 @@ impl RStarTree {
/// ///
/// # Returns /// # Returns
/// ///
/// A vector of references to the objects whose minimum bounding volumes intersect the query. /// A vector of references to the objects whose minimum bounding volumes
/// intersect the query.
pub fn range_search_bbox(&self, query_bbox: &Aabb2d) -> Vec<&Point> { pub fn range_search_bbox(&self, query_bbox: &Aabb2d) -> Vec<&Point> {
self.root.range_search_bbox(query_bbox) self.root.range_search_bbox(query_bbox)
} }
@ -481,11 +481,11 @@ fn split_entries(mut entries: Vec<Entry>, max_entries: usize) -> (Vec<Entry>, Ve
for k in min_entries..=entries.len() - min_entries { for k in min_entries..=entries.len() - min_entries {
let group1 = &entries[..k]; let group1 = &entries[..k];
let group2 = &entries[k..]; let group2 = &entries[k..];
let mut mbr1 = group1[0].mbr().clone(); let mut mbr1 = *group1[0].mbr();
for entry in group1 { for entry in group1 {
mbr1 = mbr1.merge(entry.mbr()); mbr1 = mbr1.merge(entry.mbr());
} }
let mbr2 = group2[0].mbr().clone(); let mbr2 = *group2[0].mbr();
let margin = mbr1.margin() + mbr2.margin(); let margin = mbr1.margin() + mbr2.margin();
if margin < min_margin { if margin < min_margin {
@ -532,7 +532,8 @@ fn split_entries(mut entries: Vec<Entry>, max_entries: usize) -> (Vec<Entry>, Ve
impl RStarTree { impl RStarTree {
/// Performs a range search on the R*tree using a query object and radius. /// Performs a range search on the R*tree using a query object and radius.
/// ///
/// The query object is wrapped into a bounding volume using `from_point_radius`. /// The query object is wrapped into a bounding volume using
/// `from_point_radius`.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -555,7 +556,7 @@ impl RStarTree {
fn entries_mbr(entries: &[Entry]) -> Option<Aabb2d> { fn entries_mbr(entries: &[Entry]) -> Option<Aabb2d> {
let mut iter = entries.iter(); let mut iter = entries.iter();
let first = iter.next()?.mbr().clone(); let first = *iter.next()?.mbr();
Some(iter.fold(first, |acc, entry| acc.merge(entry.mbr()))) Some(iter.fold(first, |acc, entry| acc.merge(entry.mbr())))
} }
@ -572,6 +573,24 @@ impl Bvr for Aabb2d {
} }
fn overlap(&self, other: &Aabb2d) -> f32 { fn overlap(&self, other: &Aabb2d) -> f32 {
todo!() let Vec2 {
x: self_width,
y: self_height,
} = 2.0 * self.half_size();
let self_center = self.center();
let other_center = other.center();
let Vec2 {
x: other_width,
y: other_height,
} = 2.0 * other.half_size();
let o_x = (self_center.x + self_width).min(other_center.x + other_width)
- self_center.x.max(other_center.x);
let o_y = (self_center.y + self_height).min(other_center.y + other_height)
- self_center.y.max(other_center.y);
(o_x * o_y).max(0.0)
} }
} }