Skip to main content

Fast quadtree in Rust with a Python API

Project description

quadtree-rs

Rust-accelerated quadtree with a simple Python API.

  • Python package: quadtree_rs
  • Python ≥ 3.8
  • Import path: from quadtree_rs import QuadTree

Install

pip install quadtree_rs

If you are developing locally:

# optimized dev install
maturin develop --release

Quickstart

from quadtree_rs import QuadTree

# Bounds are (min_x, min_y, max_x, max_y)
qt = QuadTree(bounds=(0, 0, 1000, 1000), capacity=20)  # max_depth is optional

# Insert points. You supply an integer id and a point (x, y)
for i, (x, y) in enumerate([(10, 10), (200, 300), (999, 500)]):
    ok = qt.insert(i, (x, y))
    assert ok  # False means the point was outside the bounds

# Axis-aligned rectangle query
hits = qt.query((0, 0, 250, 350))
# hits is a list of tuples: (id, x, y)
print(hits)  # e.g. [(0, 10.0, 10.0), (1, 200.0, 300.0)]

# Nearest neighbor
best = qt.nearest_neighbor((210, 310))
print(best)  # e.g. (1, 200.0, 300.0)

# k-nearest neighbors
top3 = qt.nearest_neighbors((210, 310), 3)
print(top3)  # list of up to 3 (id, x, y) tuples

Mapping your Python objects

The quadtree stores ids and points for speed. Keep a side map in Python:

from quadtree_rs import QuadTree

qt = QuadTree((0, 0, 1000, 1000), capacity=16)
objects = {}  # id -> your object

def add(obj_id: int, obj):
    objects[obj_id] = obj
    qt.insert(obj_id, obj.position)  # where obj.position is (x, y)

# Later, resolve ids back to objects
ids = [obj_id for (obj_id, x, y) in qt.query((100, 100, 300, 300))]
selected = [objects[i] for i in ids]

API

QuadTree(bounds, capacity, *, max_depth=None)

  • bounds – tuple (min_x, min_y, max_x, max_y) covering all points you will insert
  • capacity – max number of items kept in a leaf before a split
  • max_depth – optional depth cap. If omitted, the tree can grow until data distribution stops forcing splits

Methods

  • insert(id: int, xy: tuple[float, float]) -> bool Inserts a point with your integer id. Returns False if the point is outside bounds.

  • query(rect: tuple[float, float, float, float]) -> list[tuple[int, float, float]] Returns all items whose point lies inside the axis-aligned rectangle. Each item is (id, x, y).

  • nearest_neighbor(xy: tuple[float, float]) -> tuple[int, float, float] | None Returns the closest point to xy, or None if the tree is empty.

  • nearest_neighbors(xy: tuple[float, float], k: int) -> list[tuple[int, float, float]] Returns up to k nearest points to xy.

Geometric conventions

  • Rectangles are (min_x, min_y, max_x, max_y).
  • Containment rule is open on the min edge and closed on the max edge (x > min_x and x <= max_x and y > min_y and y <= max_y). This only matters for points exactly on edges. Decide your own tie-break if you care about boundaries.

Performance tips

  • Choose capacity so that leaves keep a small batch of points. Typical values are 8 to 64.
  • If your data is very skewed, set a max_depth to prevent degenerate chains.
  • For best runtime on your local dev build install with maturin develop --release.

Benchmarks

Generated with benchmarks/bench_plotly.py in this repo.

  • 100k points, 500 queries, capacity 20, max depth 10
  • Median over 3 runs per size

Total time Throughput

Example summary (PyQtree baseline) — numbers will vary by machine:

Library Build (s) Query (s) Total (s)
Brute force - 4.068 4.068
e-pyquadtree 0.447 1.951 2.398
PyQtree 0.686 0.685 1.371
quadtree-rs 0.038 0.285 0.323

FAQ

What happens if I insert the same id more than once? Allowed. For k-nearest, duplicates are de-duplicated by id. For range queries you will see every inserted point.

Can I store rectangles or circles? The core stores points. To index objects with extent, insert the representative point you choose. For rectangles, you can either insert their centers or build a separate AABB tree.

Threading The Python wrapper is a single QuadTree object with interior mutability handled in Rust. Use one tree per thread if you do heavy parallel inserts from Python.

License

MIT. See LICENSE.

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quadtree_rs-0.1.0.tar.gz (461.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

quadtree_rs-0.1.0-cp38-abi3-win_amd64.whl (140.1 kB view details)

Uploaded CPython 3.8+Windows x86-64

quadtree_rs-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (235.8 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

quadtree_rs-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (413.1 kB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file quadtree_rs-0.1.0.tar.gz.

File metadata

  • Download URL: quadtree_rs-0.1.0.tar.gz
  • Upload date:
  • Size: 461.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.9.4

File hashes

Hashes for quadtree_rs-0.1.0.tar.gz
Algorithm Hash digest
SHA256 90293de540f6eed307b3250e67c5f894bdd66ae35f41b35087422c847b653c47
MD5 0f2f9dcdbde84266ce3e1318f6ada383
BLAKE2b-256 b6c9f7639038e65481a2ba15a2ebfddeb02f7e3c7c77f9819b2a6968b74d2331

See more details on using hashes here.

File details

Details for the file quadtree_rs-0.1.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for quadtree_rs-0.1.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ffae92e7c07f5ff586741abb458b7f130a61f729df513da8c02b9309e4166f3d
MD5 13be121b4a599e1a7b3cafa80f1afb6d
BLAKE2b-256 e2556d8205fcf5c213f6f1ce22ac6c57fc22d79130bbcaab2c1d7059671719c9

See more details on using hashes here.

File details

Details for the file quadtree_rs-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for quadtree_rs-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 441165de3e41c38041025b1e22657310c3e6e0b85e70e4ef1899ae687df226bd
MD5 17dc3d0100bcf00b3c1069ab46c65c5c
BLAKE2b-256 8e5d80e25c108cc8f2703823a74c824400b4ad2e21d90901e6eaf15ae42fae36

See more details on using hashes here.

File details

Details for the file quadtree_rs-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for quadtree_rs-0.1.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 a8af28d1ea5c2d59c31e6cd4e684f32c50220dd92aead8de536a6b0524585a31
MD5 db93d0bc1ebd90c2099c8ca0e50b6c57
BLAKE2b-256 2a59b8113eddf06b549c22d0e0570e0def6a860eda331ec6aa2f15b429e4a441

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page