Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
Project description
fastquadtree
Rust-optimized quadtree with a clean Python API
👉 Check out the Docs: https://elan456.github.io/fastquadtree/
Why use fastquadtree
- Clean Python API with no external dependencies and modern typing hints
- The fastest quadtree Python package (>10x faster than pyqtree)
- Prebuilt wheels for Windows, macOS, and Linux
- Support for inserting bounding boxes or points
- Fast KNN and range queries
- Optional object tracking for id ↔ object mapping
- Fast serialization to/from bytes
- 100% test coverage and CI on GitHub Actions
- Offers a drop-in pyqtree shim that is 6.567x faster while keeping the same API
Examples
See examples of how fastquadtree can be used in the runnables section.
Install
pip install fastquadtree
from fastquadtree import QuadTree # Point handling
from fastquadtree import RectQuadTree # Bounding box handling
from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (6.567x faster while keeping the same API)
Benchmarks
fastquadtree outperforms all other quadtree Python packages, including the Rtree spatial index.
Library comparison
Summary (largest dataset, PyQtree baseline)
- Points: 250,000, Queries: 500
- Fastest total: fastquadtree at 0.120 s
| Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
|---|---|---|---|---|
| fastquadtree | 0.031 | 0.089 | 0.120 | 14.64× |
| Shapely STRtree | 0.179 | 0.100 | 0.279 | 6.29× |
| nontree-QuadTree | 0.595 | 0.605 | 1.200 | 1.46× |
| Rtree | 0.961 | 0.300 | 1.261 | 1.39× |
| e-pyquadtree | 1.005 | 0.660 | 1.665 | 1.05× |
| PyQtree | 1.492 | 0.263 | 1.755 | 1.00× |
| quads | 1.407 | 0.484 | 1.890 | 0.93× |
See the benchmark section for details, including configurations, system info, and native vs shim benchmarks.
Quickstart
API
QuadTree(bounds, capacity, max_depth=None, track_objects=False, start_id=1)
bounds— tuple(min_x, min_y, max_x, max_y)defines the 2D area covered by the quadtreecapacity— max number of points kept in a leaf before splittingmax_depth— optional depth cap. If omitted, the tree can keep splitting as neededtrack_objects— ifTrue, the wrapper maintains an id → object map for convenience.start_id— starting value for auto-assigned ids
Key Methods
-
insert(xy, *, id=None, obj=None) -> int -
query(rect, *, as_items=False) -> list -
nearest_neighbor(xy, *, as_item=False) -> (id, x, y) | Item | None -
delete(id, xy) -> bool
There are more methods and object tracking versions in the docs.
Geometric conventions
- Rectangles are
(min_x, min_y, max_x, max_y). - Containment rule is closed on the min edge and open 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.
Performance tips
- Choose
capacityso that leaves keep a small batch of points. Typical values are 8 to 64. - If your data is very skewed, set a
max_depthto prevent long chains. - For fastest local runs, use
maturin develop --release. - The wrapper maintains an object map only if the quadtree was constructed with
track_objects=True. If you don't need it, leave it off for best performance. - Refer to the Native vs Shim Benchmark for overhead details.
Pygame Ball Pit Demo
A simple demo of moving objects with collision detection using fastquadtree. You can toggle between quadtree mode and brute-force mode to see the performance difference.
See the runnables guide for setup instructions.
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 delete items from the quadtree?
Yes! Use delete(id, xy) to remove specific items. You must provide both the ID and exact location for precise deletion. This handles cases where multiple items exist at the same location. If you're using track_objects=True, you can also use delete_by_object(obj) for convenient object-based deletion with O(1) lookup. The tree automatically merges nodes when item counts drop below capacity.
Can I store rectangles or circles?
Yes, you can store rectangles using the RectQuadTree class. Circles can be approximated with bounding boxes. See the RectQuadTree docs for details.
License
MIT. See LICENSE.
Acknowledgments
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastquadtree-1.2.3.tar.gz.
File metadata
- Download URL: fastquadtree-1.2.3.tar.gz
- Upload date:
- Size: 805.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b433050083784455933f53051682a9ceacd9a1003b4e508a1dbf7e1a862b2eca
|
|
| MD5 |
0cd147f80dd4773d59bc996124ba7cba
|
|
| BLAKE2b-256 |
1c5f7bc27828eddf670c983c912106f60a3ecd7c06feb65a85cffc1afff50c8f
|
File details
Details for the file fastquadtree-1.2.3-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: fastquadtree-1.2.3-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 174.2 kB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28c469c603c58dacda80c179a5b3b956cb73222811f5a14a92536bac29b91cbf
|
|
| MD5 |
33dc48569dd51065936b928d235fefc6
|
|
| BLAKE2b-256 |
b034796ba6ec7b87f69ad343925a6d687aa67f5f9dd8aedfd09178ab333ef22a
|
File details
Details for the file fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 275.1 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f4206b38a0428c1014dd039524b12225112d8f572a2c1a4c2c2c10508229c69
|
|
| MD5 |
3bce2e7dd505a248f4f1f78ffd33ac67
|
|
| BLAKE2b-256 |
4cb027466f942679f25027885863cb69fc221e3bfb7638535a412ef2a98dd838
|
File details
Details for the file fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.
File metadata
- Download URL: fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
- Upload date:
- Size: 299.5 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARMv7l
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f37b77eda6d858e09d6335bb78e2b0882cddff78119b124d8f2ab9c2578fe0c
|
|
| MD5 |
50463811960b2e91ec1f55b328f68409
|
|
| BLAKE2b-256 |
3e4e7aabc0ed8b59ac3b443863d01cc9a09bef39d35ce31585cbef20a5656f19
|
File details
Details for the file fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: fastquadtree-1.2.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 273.7 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f903b1c9db168d7650184c715ff8b637f277dc135db7521a735c06d9d46d324
|
|
| MD5 |
6c84d34ce11d5d605799d840cda27235
|
|
| BLAKE2b-256 |
2c83f543d304d5e7f2b57d095bdf5ab0c2b55d28f7c8573b11f8caa526002245
|
File details
Details for the file fastquadtree-1.2.3-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: fastquadtree-1.2.3-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 477.2 kB
- Tags: CPython 3.8+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fa383cc36140e49926dc7b1a341af8c5a26a330374c313583b3f98798ef87b2
|
|
| MD5 |
cb8da6f0fa2b57a829a69a6b7a9a1ede
|
|
| BLAKE2b-256 |
629ecf611a6c3f7fb459c58d86b91a80c94dd6338c56449447d5163db960f985
|