Compare commits
8 commits
main
...
rtree-thef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36ffce22f9 | ||
|
|
0a54cad11e | ||
|
|
c9bab10f6b | ||
|
|
24b7709b4c | ||
|
|
ccb598ac1f | ||
|
|
969c84d9cc | ||
|
|
d8f1ffd801 | ||
|
|
228c6ff976 |
12 changed files with 535 additions and 56 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"
|
||||||
211
Cargo.lock
generated
211
Cargo.lock
generated
|
|
@ -103,6 +103,15 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloca"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
|
@ -173,6 +182,18 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anymap3"
|
name = "anymap3"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -330,16 +351,18 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autobats"
|
name = "autobarts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
"criterion",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"glam 0.31.0",
|
||||||
"include_dir",
|
"include_dir",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
|
"rand",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rusqlite_migration",
|
"rusqlite_migration",
|
||||||
"spart",
|
|
||||||
"steel-core",
|
"steel-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -964,7 +987,7 @@ dependencies = [
|
||||||
"arrayvec 0.7.6",
|
"arrayvec 0.7.6",
|
||||||
"bevy_reflect",
|
"bevy_reflect",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"glam",
|
"glam 0.30.10",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"libm",
|
"libm",
|
||||||
"rand",
|
"rand",
|
||||||
|
|
@ -1138,7 +1161,7 @@ dependencies = [
|
||||||
"downcast-rs 2.0.2",
|
"downcast-rs 2.0.2",
|
||||||
"erased-serde",
|
"erased-serde",
|
||||||
"foldhash 0.2.0",
|
"foldhash 0.2.0",
|
||||||
"glam",
|
"glam 0.30.10",
|
||||||
"indexmap 2.13.0",
|
"indexmap 2.13.0",
|
||||||
"inventory",
|
"inventory",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
|
|
@ -1198,7 +1221,7 @@ dependencies = [
|
||||||
"downcast-rs 2.0.2",
|
"downcast-rs 2.0.2",
|
||||||
"encase",
|
"encase",
|
||||||
"fixedbitset",
|
"fixedbitset",
|
||||||
"glam",
|
"glam 0.30.10",
|
||||||
"image",
|
"image",
|
||||||
"indexmap 2.13.0",
|
"indexmap 2.13.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
|
@ -1767,6 +1790,12 @@ dependencies = [
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cast"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "castaway"
|
name = "castaway"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|
@ -1826,6 +1855,33 @@ dependencies = [
|
||||||
"windows-link 0.2.1",
|
"windows-link 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"ciborium-ll",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clang-sys"
|
name = "clang-sys"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
|
@ -1837,6 +1893,31 @@ dependencies = [
|
||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codegen"
|
name = "codegen"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -2112,6 +2193,40 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf"
|
||||||
|
dependencies = [
|
||||||
|
"alloca",
|
||||||
|
"anes",
|
||||||
|
"cast",
|
||||||
|
"ciborium",
|
||||||
|
"clap",
|
||||||
|
"criterion-plot",
|
||||||
|
"itertools 0.13.0",
|
||||||
|
"num-traits",
|
||||||
|
"oorandom",
|
||||||
|
"page_size",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tinytemplate",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion-plot"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4"
|
||||||
|
dependencies = [
|
||||||
|
"cast",
|
||||||
|
"itertools 0.13.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "critical-section"
|
name = "critical-section"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
@ -2127,6 +2242,25 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
|
|
@ -2742,6 +2876,15 @@ dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.31.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74a4d85559e2637d3d839438b5b3d75c31e655276f9544d72475c36b92fabbed"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
|
@ -2941,7 +3084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b"
|
checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"constgebra",
|
"constgebra",
|
||||||
"glam",
|
"glam 0.30.10",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -4010,6 +4153,12 @@ version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oorandom"
|
||||||
|
version = "11.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option-ext"
|
name = "option-ext"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -4044,6 +4193,16 @@ dependencies = [
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "page_size"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
|
|
@ -4370,6 +4529,26 @@ version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "read-fonts"
|
name = "read-fonts"
|
||||||
version = "0.35.0"
|
version = "0.35.0"
|
||||||
|
|
@ -4795,16 +4974,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spart"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a05d85e94c16e35b2f963dee2eaa6f6b2494ee5dad740b045b139c5614872d6"
|
|
||||||
dependencies = [
|
|
||||||
"ordered-float",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
|
@ -5120,6 +5289,16 @@ dependencies = [
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytemplate"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
|
|
|
||||||
15
Cargo.toml
15
Cargo.toml
|
|
@ -1,16 +1,17 @@
|
||||||
[package]
|
[package]
|
||||||
name = "autobats"
|
name = "autobarts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.18", default-features = false, features = ["2d"] }
|
bevy = { version = "0.18", default-features = false, features = ["2d"] }
|
||||||
|
criterion = { version = "0.8.1", default-features = false, features = ["cargo_bench_support", "rayon"] }
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
|
glam = { version = "0.31.0", default-features = false, features = ["libm"] }
|
||||||
include_dir = "0.7.4"
|
include_dir = "0.7.4"
|
||||||
ordered-float = "5.1.0"
|
ordered-float = "5.1.0"
|
||||||
rusqlite = { version = "0.37", default-features = false, features = ["bundled", "blob", "functions", "jiff"] }
|
rusqlite = { version = "0.37", default-features = false, features = ["bundled", "blob", "functions", "jiff"] }
|
||||||
rusqlite_migration = { version = "2.3.0", features = ["from-directory"] }
|
rusqlite_migration = { version = "2.3.0", features = ["from-directory"] }
|
||||||
spart = "0.5.0"
|
|
||||||
steel-core = { git="https://github.com/mattwparas/steel.git", branch = "master" }
|
steel-core = { git="https://github.com/mattwparas/steel.git", branch = "master" }
|
||||||
|
|
||||||
# Enable a small amount of optimization in the dev profile.
|
# Enable a small amount of optimization in the dev profile.
|
||||||
|
|
@ -20,3 +21,13 @@ opt-level = 1
|
||||||
# Enable a large amount of optimization in the dev profile for dependencies.
|
# Enable a large amount of optimization in the dev profile for dependencies.
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.bench]
|
||||||
|
inherits = "release"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "main"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rand = "0.9.2"
|
||||||
|
|
|
||||||
26
benches/bench_insert_bulk.rs
Normal file
26
benches/bench_insert_bulk.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#[path = "shared.rs"]
|
||||||
|
mod shared;
|
||||||
|
use std::hint::black_box;
|
||||||
|
|
||||||
|
use autobarts::spindex::RStarTree;
|
||||||
|
use criterion::{Criterion, criterion_group};
|
||||||
|
use shared::*;
|
||||||
|
|
||||||
|
fn bench_insert_bulk_rstartree_2d(_c: &mut Criterion) {
|
||||||
|
let points = generate_2d_data();
|
||||||
|
let mut cc = configure_criterion();
|
||||||
|
cc.bench_function("insert_bulk_2d_rstartree", |b| {
|
||||||
|
b.iter_with_setup(
|
||||||
|
|| {
|
||||||
|
let tree = RStarTree::new(BENCH_NODE_CAPACITY);
|
||||||
|
(tree, points.clone())
|
||||||
|
},
|
||||||
|
|(mut tree, points)| {
|
||||||
|
tree.insert_bulk(points);
|
||||||
|
black_box(());
|
||||||
|
},
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, bench_insert_bulk_rstartree_2d,);
|
||||||
92
benches/bench_range_search.rs
Normal file
92
benches/bench_range_search.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
use std::hint::black_box;
|
||||||
|
|
||||||
|
use autobarts::{geom::Point, spindex::RStarTree};
|
||||||
|
use bevy::math::Vec2;
|
||||||
|
use criterion::{Criterion, criterion_group};
|
||||||
|
use rand::{Rng, SeedableRng, seq::SliceRandom};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Benchmark Parameters
|
||||||
|
//
|
||||||
|
pub const BENCH_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||||
|
pub const BENCH_NUM_INSERT: i32 = 50_000;
|
||||||
|
pub const BENCH_NODE_CAPACITY: usize = 5;
|
||||||
|
|
||||||
|
const SEED: u64 = 8;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data Generation Functions (Raw Data)
|
||||||
|
//
|
||||||
|
pub fn generate_2d_data() -> Vec<Point> {
|
||||||
|
let data: Vec<Point> = (0..BENCH_NUM_INSERT)
|
||||||
|
.map(|i| {
|
||||||
|
let point = bevy::prelude::Vec2::new(i as f32, i as f32);
|
||||||
|
|
||||||
|
Point {
|
||||||
|
point,
|
||||||
|
entity: bevy::prelude::Entity::PLACEHOLDER,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Criterion with a timeout for benchmarks
|
||||||
|
pub fn configure_criterion() -> Criterion {
|
||||||
|
Criterion::default()
|
||||||
|
.measurement_time(BENCH_TIMEOUT)
|
||||||
|
.sample_size(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
const BENCH_RANGE_RADIUS: f32 = 30.0;
|
||||||
|
|
||||||
|
fn benchmark_range_rstartree_2d(_c: &mut Criterion) {
|
||||||
|
let mut points = generate_2d_data();
|
||||||
|
let mut rng = rand::rngs::StdRng::seed_from_u64(SEED);
|
||||||
|
let len = points.len();
|
||||||
|
for i in 0..len {
|
||||||
|
let j = rng.random_range(0..len);
|
||||||
|
points.swap(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree = RStarTree::new(BENCH_NODE_CAPACITY);
|
||||||
|
|
||||||
|
tree.insert_bulk(points.clone());
|
||||||
|
|
||||||
|
let mut cc = configure_criterion();
|
||||||
|
let mut idx = 0;
|
||||||
|
let len = points.len();
|
||||||
|
cc.bench_function("range_rstartree_2d", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let res = tree.range_search(&points[idx], BENCH_RANGE_RADIUS);
|
||||||
|
idx = (idx + 1) % len;
|
||||||
|
black_box(res)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn benchmark_range_bbox_rstartree_2d(_c: &mut Criterion) {
|
||||||
|
let points = generate_2d_data();
|
||||||
|
let mut tree = RStarTree::new(BENCH_NODE_CAPACITY);
|
||||||
|
|
||||||
|
tree.insert_bulk(points);
|
||||||
|
|
||||||
|
let query_rect = bevy::math::bounding::Aabb2d::new(
|
||||||
|
Vec2::new(35.0 - BENCH_RANGE_RADIUS, 45.0 - BENCH_RANGE_RADIUS),
|
||||||
|
4.0 * Vec2::splat(BENCH_RANGE_RADIUS),
|
||||||
|
);
|
||||||
|
let mut cc = configure_criterion();
|
||||||
|
cc.bench_function("range_rstartree_2d", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let res = tree.range_search_bbox(&query_rect);
|
||||||
|
black_box(res)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(
|
||||||
|
benches,
|
||||||
|
benchmark_range_rstartree_2d,
|
||||||
|
//benchmark_range_bbox_rstartree_2d,
|
||||||
|
);
|
||||||
6
benches/main.rs
Normal file
6
benches/main.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
use criterion::criterion_main;
|
||||||
|
|
||||||
|
//mod bench_insert_bulk;
|
||||||
|
mod bench_range_search;
|
||||||
|
|
||||||
|
criterion_main!(bench_range_search::benches,);
|
||||||
34
benches/shared.rs
Normal file
34
benches/shared.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
use autobarts::geom::Point;
|
||||||
|
use criterion::Criterion;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Benchmark Parameters
|
||||||
|
//
|
||||||
|
pub const BENCH_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||||
|
pub const BENCH_NUM_INSERT: i32 = 50_000;
|
||||||
|
pub const BENCH_NODE_CAPACITY: usize = 5;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data Generation Functions (Raw Data)
|
||||||
|
//
|
||||||
|
pub fn generate_2d_data() -> Vec<Point> {
|
||||||
|
let data: Vec<Point> = (0..BENCH_NUM_INSERT)
|
||||||
|
.map(|i| {
|
||||||
|
let point = bevy::prelude::Vec2::new(i as f32, i as f32);
|
||||||
|
|
||||||
|
Point {
|
||||||
|
point,
|
||||||
|
entity: bevy::prelude::Entity::PLACEHOLDER,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Criterion with a timeout for benchmarks
|
||||||
|
pub fn configure_criterion() -> Criterion {
|
||||||
|
Criterion::default()
|
||||||
|
.measurement_time(BENCH_TIMEOUT)
|
||||||
|
.sample_size(10)
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{path::PathBuf, sync::LazyLock};
|
use std::{path::PathBuf, sync::LazyLock};
|
||||||
|
|
||||||
use include_dir::{include_dir, Dir};
|
use include_dir::{Dir, include_dir};
|
||||||
use rusqlite::{config::DbConfig, Connection};
|
use rusqlite::{Connection, config::DbConfig};
|
||||||
use rusqlite_migration::Migrations;
|
use rusqlite_migration::Migrations;
|
||||||
|
|
||||||
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations");
|
static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/migrations");
|
||||||
|
|
|
||||||
38
src/geom.rs
38
src/geom.rs
|
|
@ -1,8 +1,9 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{math::bounding::Aabb2d, prelude::*};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use spart::{geometry::BoundingVolume, rstar_tree::RStarTreeObject};
|
|
||||||
|
const POINT_RADIUS: f32 = f32::EPSILON * 16.0;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
|
|
@ -29,35 +30,8 @@ impl PartialOrd for Point {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RStarTreeObject for Point {
|
impl Point {
|
||||||
type B = PointBox;
|
pub fn mbr(&self) -> Aabb2d {
|
||||||
|
Aabb2d::new(self.point, Vec2::splat(POINT_RADIUS))
|
||||||
fn mbr(&self) -> Self::B {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PointBox;
|
|
||||||
|
|
||||||
impl BoundingVolume for PointBox {
|
|
||||||
fn area(&self) -> f64 {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn union(&self, other: &Self) -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn intersects(&self, other: &Self) -> bool {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overlap(&self, other: &Self) -> f64 {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn margin(&self) -> f64 {
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
src/lib.rs
Normal file
3
src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod db;
|
||||||
|
pub mod geom;
|
||||||
|
pub mod spindex;
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
|
use autobarts::db::init_db;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use db::init_db;
|
|
||||||
|
|
||||||
mod db;
|
|
||||||
mod geom;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
|
|
|
||||||
153
src/spindex.rs
Normal file
153
src/spindex.rs
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// based on code stolen under the terms of the MIT license from
|
||||||
|
// https://github.com/habedi/spart/blob/0f0e92c556b8906801d3f8b9c2a8a6491f493d9c/src/rstar_tree.rs
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
math::bounding::{Aabb2d, BoundingVolume, IntersectsVolume},
|
||||||
|
prelude::Vec2,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::geom::Point;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Entry {
|
||||||
|
Leaf { mbr: Aabb2d, object: Point },
|
||||||
|
Node { mbr: Aabb2d, child: TreeNode },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
/// Returns a reference to the minimum bounding volume for this entry.
|
||||||
|
pub fn mbr(&self) -> &Aabb2d {
|
||||||
|
match self {
|
||||||
|
Entry::Leaf { mbr, .. } | Entry::Node { mbr, .. } => mbr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TreeNode {
|
||||||
|
pub entries: Vec<Entry>,
|
||||||
|
pub is_leaf: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct RStarTree {
|
||||||
|
root: TreeNode,
|
||||||
|
max_entries: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
fn as_leaf_obj(&self) -> Option<&Point> {
|
||||||
|
match self {
|
||||||
|
Entry::Leaf { object, .. } => Some(object),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn child(&self) -> Option<&TreeNode> {
|
||||||
|
match self {
|
||||||
|
Entry::Node { child, .. } => Some(child),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeNode {
|
||||||
|
fn is_leaf(&self) -> bool {
|
||||||
|
self.is_leaf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entries(&self) -> &[Entry] {
|
||||||
|
&self.entries
|
||||||
|
}
|
||||||
|
|
||||||
|
fn range_search_bbox<'s>(&'s self, bbox: &Aabb2d, out: &mut Vec<&'s Point>) {
|
||||||
|
if self.is_leaf() {
|
||||||
|
for entry in self.entries() {
|
||||||
|
if let Some(obj) = entry.as_leaf_obj()
|
||||||
|
&& entry.mbr().intersects(bbox)
|
||||||
|
{
|
||||||
|
out.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for entry in self.entries() {
|
||||||
|
if let Some(child) = entry.child()
|
||||||
|
&& entry.mbr().intersects(bbox)
|
||||||
|
{
|
||||||
|
child.range_search_bbox(bbox, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mbr(&self) -> Option<Aabb2d> {
|
||||||
|
entries_mbr(self.entries())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RStarTree {
|
||||||
|
pub fn new(max_entries: usize) -> Self {
|
||||||
|
let max_entries = max_entries.max(4);
|
||||||
|
RStarTree {
|
||||||
|
root: TreeNode {
|
||||||
|
entries: Vec::new(),
|
||||||
|
is_leaf: true,
|
||||||
|
},
|
||||||
|
max_entries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range_search(&self, query_point: &Point, radius: f32) -> Vec<&Point> {
|
||||||
|
let query_bbox = Aabb2d::new(query_point.point, Vec2::splat(radius));
|
||||||
|
let r2 = radius.powi(2);
|
||||||
|
let candidates = self.range_search_bbox(&query_bbox);
|
||||||
|
candidates
|
||||||
|
.into_iter()
|
||||||
|
.filter(|&other| query_point.point.distance_squared(other.point) <= r2)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range_search_bbox(&self, query_bbox: &Aabb2d) -> Vec<&Point> {
|
||||||
|
let mut res = Vec::with_capacity(self.root.entries.len() / 10);
|
||||||
|
self.root.range_search_bbox(query_bbox, &mut res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_bulk(&mut self, objects: Vec<Point>) {
|
||||||
|
if objects.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut entries: Vec<Entry> = objects
|
||||||
|
.into_iter()
|
||||||
|
.map(|point| Entry::Leaf {
|
||||||
|
mbr: point.mbr(),
|
||||||
|
object: point,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
while entries.len() > self.max_entries {
|
||||||
|
let mut new_level_entries = Vec::new();
|
||||||
|
let chunks = entries.chunks(self.max_entries);
|
||||||
|
|
||||||
|
for chunk in chunks {
|
||||||
|
let child = TreeNode {
|
||||||
|
entries: chunk.to_vec(),
|
||||||
|
is_leaf: self.root.is_leaf,
|
||||||
|
};
|
||||||
|
if let Some(mbr) = child.mbr() {
|
||||||
|
new_level_entries.push(Entry::Node { mbr, child });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entries = new_level_entries;
|
||||||
|
self.root.is_leaf = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.root.entries.extend(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn entries_mbr(entries: &[Entry]) -> Option<Aabb2d> {
|
||||||
|
let mut iter = entries.iter();
|
||||||
|
let first = *iter.next()?.mbr();
|
||||||
|
Some(iter.fold(first, |acc, entry| acc.merge(entry.mbr())))
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue