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
  • Mostly drop-in pygame sprite-group integration that adds automatic broadphase culling for faster collision detection (depending on workload)
  • 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 ~10x faster while keeping the same API

Install

pip install fastquadtree
from fastquadtree import QuadTree # Or any of the other classes mentioned below
from fastquadtree.pyqtree import Index  # Drop-in pyqtree shim (~10x faster while keeping the same API)

Which class should I use?

Class Stores Object tracking Best when
QuadTree Points No Fast point indexing with IDs only.
RectQuadTree Bounding boxes No Fast rectangle overlap queries.
QuadTreeObjects Points Yes Point indexing with attached Python objects.
RectQuadTreeObjects Bounding boxes Yes Rectangle indexing with attached objects.
fastquadtree.pyqtree.Index Bounding boxes Yes pyqtree-compatible API, much faster.
fastquadtree.pygame.Group pygame sprites Yes Mostly drop-in replacement for pygame.sprite.Group with quadtree indexing for faster collision detection.

Quickstart

1. Point indexing (QuadTree)

from fastquadtree import QuadTree

qt = QuadTree((0.0, 0.0, 1000.0, 1000.0), capacity=16)

# Insert points with explicit IDs (or omit id_ for auto IDs)
qt.insert((100.0, 200.0), id_=1)
qt.insert((120.0, 260.0), id_=2)
qt.insert((700.0, 800.0), id_=3)

# Range query returns (id, x, y)
hits = qt.query((0.0, 0.0, 500.0, 500.0))
print(hits)  # [(1, 100.0, 200.0), (2, 120.0, 260.0)]

2. Object tracking (QuadTreeObjects)

from fastquadtree import QuadTreeObjects

qto = QuadTreeObjects((0.0, 0.0, 1000.0, 1000.0), capacity=16)

player = {"name": "player-1", "team": "blue"}
enemy = {"name": "enemy-9", "team": "red"}

qto.insert((100.0, 200.0), obj=player)
qto.insert((130.0, 220.0), obj=enemy)

# Query returns PointItem objects with id_, x, y, geom, and obj
for item in qto.query((0.0, 0.0, 300.0, 300.0)):
    print(item.id_, item.x, item.y, item.obj["name"]) # 0 100.0 200.0 player-1
                                                      # 1 130.0 220.0 enemy-9

# Remove entries by object identity
qto.delete_by_object(player)  # returns 1 (number of items deleted)

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 (PyQtree baseline, sorted by total time)

  • Points: 500,000, Queries: 500
Library Build (s) Query (s) Total (s) Speed vs PyQtree
fastquadtree (np)1 0.052 0.017 0.068 42.52×
fastquadtree2 0.054 0.231 0.285 10.20×
Shapely STRtree3 0.200 0.110 0.309 9.40×
fastquadtree (obj tracking)4 0.263 0.093 0.356 8.17×
nontree-QuadTree 0.826 0.844 1.670 1.74×
Rtree 1.805 0.546 2.351 1.24×
e-pyquadtree 1.530 0.941 2.471 1.18×
quads 1.907 0.759 2.667 1.09×
PyQtree 2.495 0.414 2.909 1.00×

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. Native decode uses a default preallocation limit of 67,108,864 bytes (64 MiB); if loading needs more than the configured bucket, from_bytes() fails with a ValueError unless you choose a larger allowed bucket or pass disable_preallocation_limit=True for trusted data. 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.

Serialization uses the current fastquadtree binary format. Data serialized by bincode-backed fastquadtree releases, including v2.2 and earlier, is not loadable by newer wincode-backed releases.

License

MIT. See LICENSE.

Acknowledgments

  1. Uses query_np for Numpy array return values rather than Python lists.

  2. Uses standard query method returning Python lists.

  3. Uses Shapely STRtree with Numpy array points and returns.

  4. Uses QuadTreeObjects with object association.

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.3.0.tar.gz (946.3 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.3.0-cp39-abi3-win_amd64.whl (317.4 kB view details)

Uploaded CPython 3.9+Windows x86-64

fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_x86_64.whl (469.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64

fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_armv7l.whl (502.3 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARMv7l

fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_aarch64.whl (454.8 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

fastquadtree-2.3.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (813.5 kB view details)

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

File details

Details for the file fastquadtree-2.3.0.tar.gz.

File metadata

  • Download URL: fastquadtree-2.3.0.tar.gz
  • Upload date:
  • Size: 946.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0.tar.gz
Algorithm Hash digest
SHA256 9e677ac4751387c11cb1fec8030fd5c88edfa77c41b597b7475704d042e20f30
MD5 e083c8fd4b32ef19ea33ba19b4e9f355
BLAKE2b-256 fd907ec091fd1574a5c496ab05afebbe519fdf818ee05075878711be81f071fd

See more details on using hashes here.

File details

Details for the file fastquadtree-2.3.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: fastquadtree-2.3.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 317.4 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7e45e57cee4a6cd5691c0c0d2881ed55149703b4f3eb695ce8bbaf33b7588f6d
MD5 c9312e49e513ee244625c8fe6d597937
BLAKE2b-256 ca7c97cb834ca09af60e07b4d77eb0b3b6635e4889d1c8fce56a8c6ee78cfb45

See more details on using hashes here.

File details

Details for the file fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 469.9 kB
  • Tags: CPython 3.9+, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0d87076936d8c2fa7e9a266f5ecd94d7df951623e21ce5e18f8ee35e5f2a4ee5
MD5 fb87ea980e4a12831c7bfc9a173482f5
BLAKE2b-256 95920bd197c1380dcfc38dfedcb0a0d1a0657f2391bf604b29a7d92d2ef76c0c

See more details on using hashes here.

File details

Details for the file fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_armv7l.whl.

File metadata

  • Download URL: fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_armv7l.whl
  • Upload date:
  • Size: 502.3 kB
  • Tags: CPython 3.9+, manylinux: glibc 2.28+ ARMv7l
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_armv7l.whl
Algorithm Hash digest
SHA256 250f41307715b1a0927db044b82696b21bd023e9457af2cc23012021dbe883e8
MD5 49590525a0da533f37b87a96e58e9581
BLAKE2b-256 4a250fb48eba2307777afc3fa0971ac9eb7e134fa4a3f0ef3acfc7b749c27a33

See more details on using hashes here.

File details

Details for the file fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

  • Download URL: fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_aarch64.whl
  • Upload date:
  • Size: 454.8 kB
  • Tags: CPython 3.9+, manylinux: glibc 2.28+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 4a74737651ac216aa5c7824cbd246cbdb132a0ecadfa3fc207234f8ff64a8ba5
MD5 af55a0215d20770ef9b576a558615cbe
BLAKE2b-256 29ecdd14873e7cdac73ec6834460446f4ecb878d10804602ff970fc36034ec95

See more details on using hashes here.

File details

Details for the file fastquadtree-2.3.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

  • Download URL: fastquadtree-2.3.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
  • Upload date:
  • Size: 813.5 kB
  • Tags: CPython 3.9+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastquadtree-2.3.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 7ce5c358a67919b2481d4e68b648aecce3580f41a35cba5a08edb71ad0f2f65e
MD5 55f3e0de294d13be016c1768c71e20f7
BLAKE2b-256 8a6f3389a78edafff0182edbf1502b65a2af870ca6997aa573b94ebc8de62b97

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