Skip to main content

Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.

Project description

fastquadtree

Interactive Screenshot

Rust-optimized quadtree with a clean Python API

👉 Check out the Docs: https://elan456.github.io/fastquadtree/

PyPI Python versions Downloads Build No runtime deps

PyO3 maturin Ruff

Docs Wheels Coverage License: MIT


Why use fastquadtree

  • Just pip install: prebuilt wheels for Windows, macOS, and Linux (no Rust or compiler needed)
  • The fastest quadtree Python package (>10x faster than pyqtree)
  • Clean Python API with no external dependencies and modern typing hints
  • Support for inserting bounding boxes or points
  • Fast KNN and range queries
  • Optional object tracking for id ↔ object mapping
  • Fast serialization to/from bytes
  • Support for multiple data types (f32, f64, i32, i64) for coordinates
  • 100% test coverage and CI on GitHub Actions
  • Offers a drop-in pyqtree shim that is ~6.5x faster while keeping the same API

Install

pip install fastquadtree
from fastquadtree import QuadTree  # Point handling
from fastquadtree import RectQuadTree  # Bounding box handling
from fastquadtree import QuadTreeObjects  # Point handling with object tracking
from fastquadtree import RectQuadTreeObjects  # Bounding box handling with object tracking
from fastquadtree.pyqtree import Index  # Drop-in pyqtree shim (~6.5x faster while keeping the same API)

Quickstart

from fastquadtree import QuadTree

qt = QuadTree((0, 0, 1000, 1000), 16)  # bounds and capacity
qt.insert((100, 200), id_=1)  # insert point with ID 1
print(qt.query((0, 0, 500, 500)))  # gets all points in that area: [(1, 100.0, 200.0)]

See the quickstart guide or the interactive demos for more details.

Benchmarks

fastquadtree outperforms all other quadtree Python packages, including the Rtree spatial index.

Library comparison

Total time Throughput

Summary (largest dataset, PyQtree baseline)

  • Points: 500,000, Queries: 500
  • Fastest total: fastquadtree at 0.067 s
Library Build (s) Query (s) Total (s) Speed vs PyQtree
fastquadtree (np)[^fqtnp] 0.057 0.021 0.078 54.45×
fastquadtree[^fqt] 0.060 0.189 0.249 17.04×
Shapely STRtree[^npreturn] 0.321 0.196 0.517 8.21×
fastquadtree (obj tracking)[^fqto] 0.437 0.239 0.675 6.28×
Rtree 1.796 0.561 2.357 1.80×
nontree-QuadTree 1.275 1.272 2.547 1.67×
e-pyquadtree 2.144 1.507 3.650 1.16×
quads 3.001 1.171 4.172 1.02×
PyQtree 3.677 0.565 4.242 1.00×

[^fqtnp]: Uses query_np for Numpy array return values rather than Python lists.
[^fqt]: Uses standard query method returning Python lists.
[^npreturn]: Uses Shapely STRtree with Numpy array points and returns.
[^fqto]: Uses QuadTreeObjects with object association.

See the benchmark section for details, including configurations, system info, and native vs shim benchmarks.

API

See the full API

QuadTree(bounds, capacity, max_depth=None, dtype="f32")

  • bounds — tuple (min_x, min_y, max_x, max_y) defines the 2D area covered by the quadtree
  • capacity — max number of points kept in a leaf before splitting
  • max_depth — optional depth cap. If omitted, the tree can keep splitting as needed
  • dtype — data type for coordinates, e.g., "f32", "f64", "i32", "i64"

Key Methods

  • insert(xy, id_=None) -> int

  • query(rect) -> list[tuple[int, float, float]]

  • nearest_neighbor(xy) -> tuple[int, float, float] | None

  • delete(id, x, y) -> bool

For object tracking, use QuadTreeObjects instead. See the docs for more methods.

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 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 long chains.
  • For fastest local runs, use maturin develop --release.
  • Use QuadTree when you only need spatial indexing. Use QuadTreeObjects when you need to store Python objects with your points.
  • Refer to the Native vs Shim Benchmark for overhead details.

Pygame Ball Pit Demo

Ballpit_Demo_Screenshot

A simple demo of moving objects with collision detection using fastquadtree. You can toggle between fastquadtree, pyqtree, and brute-force mode to see the performance difference. I typically see an FPS of ~70 with fastquadtree, ~25 with pyqtree, and <1 FPS with brute-force on my machine with 1500 balls.

See the runnables guide for setup instructions.

FAQ

Can I delete items from the quadtree? Yes! Use delete(id, x, y) 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 QuadTreeObjects, 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.

Do I need NumPy installed? No, NumPy is a fully optional dependency. If you do have NumPy installed, you can use methods such as query_np and insert_many_np for better performance. Note that insert_many raises TypeError on NumPy input—you must use insert_many_np explicitly for NumPy arrays. The Rust core is able to handle NumPy arrays faster than Python lists, so there's a lot of time savings in utilizing the NumPy functions. See the Native vs Shim benchmark for details on how returing NumPy arrays can speed up queries.

# Using Python lists
qt.insert_many([(10, 20), (30, 40), (50, 60)])

# Using NumPy arrays (requires NumPy)
import numpy as np
points = np.array([[10, 20], [30, 40], [50, 60]])
qt.insert_many_np(points)  # Use insert_many_np for NumPy arrays

Does fastquadtree support multiprocessing? Yes, fastquadtree objects can be serialized to bytes using the to_bytes() method and deserialized back using from_bytes(). This allows you to share quadtree data across processes and even cache prebuilt trees to disk. When using QuadTreeObjects or RectQuadTreeObjects, you must pass include_objects=True to to_bytes() to serialize Python objects, and allow_objects=True to from_bytes() when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. See the interactive v2 demo for an example of saving and loading a quadtree, and the QuadTreeObjects API docs for full details on the serialization methods.

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

fastquadtree-2.0.2.tar.gz (837.6 kB view details)

Uploaded Source

Built Distributions

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

fastquadtree-2.0.2-cp38-abi3-win_amd64.whl (302.8 kB view details)

Uploaded CPython 3.8+Windows x86-64

fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (414.8 kB view details)

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

fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (442.4 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARMv7l

fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (403.6 kB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

fastquadtree-2.0.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (717.7 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 fastquadtree-2.0.2.tar.gz.

File metadata

  • Download URL: fastquadtree-2.0.2.tar.gz
  • Upload date:
  • Size: 837.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.10.2

File hashes

Hashes for fastquadtree-2.0.2.tar.gz
Algorithm Hash digest
SHA256 38be2f3f0c73232966f508a3df40c641782fa125af734dd2f7f0d152c6890505
MD5 6595a592bdb56bb5a9bb122d82a384fd
BLAKE2b-256 3e5908f75e6fbefe4698789074a30d4a3aff60aec07077c46032feab9c781fff

See more details on using hashes here.

File details

Details for the file fastquadtree-2.0.2-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for fastquadtree-2.0.2-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7effd5de2492838d38ed0196e7a5e01cb1555dca5d98290f496a8c295d7c7d23
MD5 ba1c31ec7644dc73fb929a5b6b7fa138
BLAKE2b-256 fff3850e2165c85b580e7c8721d790970a1fa993c7edc03a623a680dee41bdca

See more details on using hashes here.

File details

Details for the file fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 63c1fef10071377a22b251460d535a4e7d881e4bc81231bbb8d4589754d79d5a
MD5 46cbdcc448b19129a8e9e8df5ead3f08
BLAKE2b-256 e3b01c272364cbba97118b16d1dbd1ac782249d26dca1ee9a9059104820fe7bc

See more details on using hashes here.

File details

Details for the file fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 9a4d9b37755a9ec7aec6f7bd3a4bf338b2016214c602d9c86a7a535e45825591
MD5 fa40f87ba5c2e7be680b453cac09453b
BLAKE2b-256 c11747a18aca48d83ed6d87afcde7edcf6f0a08143ff8dfe124d80a0a8129aee

See more details on using hashes here.

File details

Details for the file fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for fastquadtree-2.0.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 789b8c5303efb461d2a96c3b34821388bddd725c09242b2b5b4d0f6b48c21a62
MD5 98cbd1b49019762e98d3db3f36807e74
BLAKE2b-256 f06577b3c6fdfdb9196157b461cbe0e3bef71016d11a3dd28cfadb65b5785247

See more details on using hashes here.

File details

Details for the file fastquadtree-2.0.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for fastquadtree-2.0.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 78d3960f343fc768d04f4f4cbeb60370d7fd674930c55f2fdfe91f37992d72cd
MD5 f85d866b4e78c8ddfe12cab0d4d614f2
BLAKE2b-256 fff92e9d077b1f9768770190ea2b9aa675bcfffc434d2725f092c409b18d12f9

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