all impl'd, should work
This commit is contained in:
parent
d8f1ffd801
commit
969c84d9cc
2 changed files with 48 additions and 25 deletions
4
.rustfmt.toml
Normal file
4
.rustfmt.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
imports_granularity = "Crate"
|
||||
group_imports = "StdExternalCrate"
|
||||
wrap_comments = true
|
||||
edition = "2024"
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
use crate::geom::Point;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use bevy::{
|
||||
math::bounding::{Aabb2d, BoundingVolume, IntersectsVolume},
|
||||
prelude::*,
|
||||
};
|
||||
use ordered_float::OrderedFloat;
|
||||
use std::{cmp::Ordering, collections::BinaryHeap};
|
||||
|
||||
use crate::geom::Point;
|
||||
|
||||
// Epsilon value for zero-sizes bounding boxes/cubes.
|
||||
const EPSILON: f32 = 1e-10;
|
||||
|
|
@ -37,16 +38,15 @@ pub struct TreeNode {
|
|||
|
||||
/// 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
|
||||
/// number, it will split. The tree supports insertion, deletion, and range searches.
|
||||
/// The tree is initialized with a maximum number of entries per node. If a node
|
||||
/// exceeds this number, it will split. The tree supports insertion, deletion,
|
||||
/// and range searches.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RStarTree {
|
||||
root: TreeNode,
|
||||
max_entries: usize,
|
||||
min_entries: usize,
|
||||
}
|
||||
|
||||
// Common trait implementations for R*-tree to reuse shared algorithms.
|
||||
impl Entry {
|
||||
fn as_leaf_obj(&self) -> Option<&Point> {
|
||||
match self {
|
||||
|
|
@ -94,18 +94,18 @@ impl TreeNode {
|
|||
let mut result = Vec::new();
|
||||
if self.is_leaf() {
|
||||
for entry in self.entries() {
|
||||
if let Some(obj) = entry.as_leaf_obj() {
|
||||
if entry.mbr().intersects(bbox) {
|
||||
result.push(obj);
|
||||
}
|
||||
if let Some(obj) = entry.as_leaf_obj()
|
||||
&& entry.mbr().intersects(bbox)
|
||||
{
|
||||
result.push(obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for entry in self.entries() {
|
||||
if let Some(child) = entry.child() {
|
||||
if entry.mbr().intersects(bbox) {
|
||||
result.extend_from_slice(&child.range_search_bbox(bbox));
|
||||
}
|
||||
if let Some(child) = entry.child()
|
||||
&& entry.mbr().intersects(bbox)
|
||||
{
|
||||
result.extend_from_slice(&child.range_search_bbox(bbox));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,14 +119,13 @@ impl TreeNode {
|
|||
|
||||
impl RStarTree {
|
||||
pub fn new(max_entries: usize) -> Self {
|
||||
let max_entries = max_entries.max(2);
|
||||
let max_entries = max_entries.max(4);
|
||||
RStarTree {
|
||||
root: TreeNode {
|
||||
entries: Vec::new(),
|
||||
is_leaf: true,
|
||||
},
|
||||
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) {
|
||||
let old_entries = overflowed_node;
|
||||
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() {
|
||||
mbr1 = mbr1.merge(entry.mbr());
|
||||
}
|
||||
let mut mbr2 = group2[0].mbr().clone();
|
||||
let mut mbr2 = *group2[0].mbr();
|
||||
for entry in group2.iter() {
|
||||
mbr2 = mbr2.merge(entry.mbr());
|
||||
}
|
||||
|
|
@ -212,7 +211,8 @@ impl RStarTree {
|
|||
///
|
||||
/// # 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> {
|
||||
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 {
|
||||
let group1 = &entries[..k];
|
||||
let group2 = &entries[k..];
|
||||
let mut mbr1 = group1[0].mbr().clone();
|
||||
let mut mbr1 = *group1[0].mbr();
|
||||
for entry in group1 {
|
||||
mbr1 = mbr1.merge(entry.mbr());
|
||||
}
|
||||
let mbr2 = group2[0].mbr().clone();
|
||||
let mbr2 = *group2[0].mbr();
|
||||
|
||||
let margin = mbr1.margin() + mbr2.margin();
|
||||
if margin < min_margin {
|
||||
|
|
@ -532,7 +532,8 @@ fn split_entries(mut entries: Vec<Entry>, max_entries: usize) -> (Vec<Entry>, Ve
|
|||
impl RStarTree {
|
||||
/// 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
|
||||
///
|
||||
|
|
@ -555,7 +556,7 @@ impl RStarTree {
|
|||
|
||||
fn entries_mbr(entries: &[Entry]) -> Option<Aabb2d> {
|
||||
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())))
|
||||
}
|
||||
|
||||
|
|
@ -572,6 +573,24 @@ impl Bvr for Aabb2d {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue