fastquadtree 0.8.1__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/.github/workflows/release.yml +1 -1
  2. fastquadtree-0.9.1/Cargo.lock +170 -0
  3. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/Cargo.toml +2 -2
  4. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/PKG-INFO +38 -37
  5. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/README.md +36 -36
  6. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/benchmark_native_vs_shim.py +50 -5
  7. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/benchmark.md +1 -1
  8. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/index.md +15 -5
  9. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/runnables.md +10 -0
  10. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/mkdocs.yml +1 -1
  11. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pyproject.toml +1 -0
  12. fastquadtree-0.9.1/pysrc/fastquadtree/pyqtree.py +131 -0
  13. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/src/lib.rs +4 -2
  14. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/src/rect_quadtree.rs +24 -29
  15. fastquadtree-0.9.1/tests/test_pyqtree_shim_compat.py +154 -0
  16. fastquadtree-0.8.1/Cargo.lock +0 -296
  17. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/.github/workflows/docs.yml +0 -0
  18. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/.gitignore +0 -0
  19. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/.pre-commit-config.yaml +0 -0
  20. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/LICENSE +0 -0
  21. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/assets/ballpit.png +0 -0
  22. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/assets/interactive_v2_rect_screenshot.png +0 -0
  23. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/assets/interactive_v2_screenshot.png +0 -0
  24. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/assets/quadtree_bench_throughput.png +0 -0
  25. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/assets/quadtree_bench_time.png +0 -0
  26. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/cross_library_bench.py +0 -0
  27. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/quadtree_bench/__init__.py +0 -0
  28. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/quadtree_bench/engines.py +0 -0
  29. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/quadtree_bench/main.py +0 -0
  30. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/quadtree_bench/plotting.py +0 -0
  31. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/quadtree_bench/runner.py +0 -0
  32. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/requirements.txt +0 -0
  33. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/runner.py +0 -0
  34. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/benchmarks/system_info_collector.py +0 -0
  35. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/api/point_item.md +0 -0
  36. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/api/quadtree.md +0 -0
  37. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/api/rect_item.md +0 -0
  38. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/api/rect_quadtree.md +0 -0
  39. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/docs/quickstart.md +0 -0
  40. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/interactive/ballpit.py +0 -0
  41. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/interactive/interactive.py +0 -0
  42. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/interactive/interactive_v2.py +0 -0
  43. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/interactive/interactive_v2_rect.py +0 -0
  44. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/interactive/requirements.txt +0 -0
  45. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/__init__.py +0 -0
  46. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/_base_quadtree.py +0 -0
  47. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/_bimap.py +0 -0
  48. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/_item.py +0 -0
  49. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/point_quadtree.py +0 -0
  50. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/py.typed +0 -0
  51. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/pysrc/fastquadtree/rect_quadtree.py +0 -0
  52. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/src/geom.rs +0 -0
  53. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/src/quadtree.rs +0 -0
  54. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/insertions.rs +0 -0
  55. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/nearest_neighbor.rs +0 -0
  56. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/query.rs +0 -0
  57. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/rect_quadtree.rs +0 -0
  58. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/rectangle_traversal.rs +0 -0
  59. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_bimap.py +0 -0
  60. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_clear.py +0 -0
  61. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_delete.rs +0 -0
  62. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_delete_by_object.py +0 -0
  63. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_delete_python.py +0 -0
  64. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_python.py +0 -0
  65. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_rect_quadtree.py +0 -0
  66. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_unconventional_bounds.py +0 -0
  67. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/test_wrapper_edges.py +0 -0
  68. {fastquadtree-0.8.1 → fastquadtree-0.9.1}/tests/unconventional_bounds.rs +0 -0
@@ -31,7 +31,7 @@ jobs:
31
31
  - name: Install Python test deps into .venv
32
32
  run: |
33
33
  . .venv/bin/activate
34
- pip install -U pip pytest pytest-cov
34
+ pip install -e '.[dev]'
35
35
 
36
36
  - name: Run Python tests
37
37
  run: |
@@ -0,0 +1,170 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "autocfg"
7
+ version = "1.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
10
+
11
+ [[package]]
12
+ name = "fastquadtree"
13
+ version = "0.9.1"
14
+ dependencies = [
15
+ "pyo3",
16
+ "smallvec",
17
+ ]
18
+
19
+ [[package]]
20
+ name = "heck"
21
+ version = "0.5.0"
22
+ source = "registry+https://github.com/rust-lang/crates.io-index"
23
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
24
+
25
+ [[package]]
26
+ name = "indoc"
27
+ version = "2.0.6"
28
+ source = "registry+https://github.com/rust-lang/crates.io-index"
29
+ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
30
+
31
+ [[package]]
32
+ name = "libc"
33
+ version = "0.2.175"
34
+ source = "registry+https://github.com/rust-lang/crates.io-index"
35
+ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
36
+
37
+ [[package]]
38
+ name = "memoffset"
39
+ version = "0.9.1"
40
+ source = "registry+https://github.com/rust-lang/crates.io-index"
41
+ checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
42
+ dependencies = [
43
+ "autocfg",
44
+ ]
45
+
46
+ [[package]]
47
+ name = "once_cell"
48
+ version = "1.21.3"
49
+ source = "registry+https://github.com/rust-lang/crates.io-index"
50
+ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
51
+
52
+ [[package]]
53
+ name = "portable-atomic"
54
+ version = "1.11.1"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
57
+
58
+ [[package]]
59
+ name = "proc-macro2"
60
+ version = "1.0.101"
61
+ source = "registry+https://github.com/rust-lang/crates.io-index"
62
+ checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
63
+ dependencies = [
64
+ "unicode-ident",
65
+ ]
66
+
67
+ [[package]]
68
+ name = "pyo3"
69
+ version = "0.26.0"
70
+ source = "registry+https://github.com/rust-lang/crates.io-index"
71
+ checksum = "7ba0117f4212101ee6544044dae45abe1083d30ce7b29c4b5cbdfa2354e07383"
72
+ dependencies = [
73
+ "indoc",
74
+ "libc",
75
+ "memoffset",
76
+ "once_cell",
77
+ "portable-atomic",
78
+ "pyo3-build-config",
79
+ "pyo3-ffi",
80
+ "pyo3-macros",
81
+ "unindent",
82
+ ]
83
+
84
+ [[package]]
85
+ name = "pyo3-build-config"
86
+ version = "0.26.0"
87
+ source = "registry+https://github.com/rust-lang/crates.io-index"
88
+ checksum = "4fc6ddaf24947d12a9aa31ac65431fb1b851b8f4365426e182901eabfb87df5f"
89
+ dependencies = [
90
+ "target-lexicon",
91
+ ]
92
+
93
+ [[package]]
94
+ name = "pyo3-ffi"
95
+ version = "0.26.0"
96
+ source = "registry+https://github.com/rust-lang/crates.io-index"
97
+ checksum = "025474d3928738efb38ac36d4744a74a400c901c7596199e20e45d98eb194105"
98
+ dependencies = [
99
+ "libc",
100
+ "pyo3-build-config",
101
+ ]
102
+
103
+ [[package]]
104
+ name = "pyo3-macros"
105
+ version = "0.26.0"
106
+ source = "registry+https://github.com/rust-lang/crates.io-index"
107
+ checksum = "2e64eb489f22fe1c95911b77c44cc41e7c19f3082fc81cce90f657cdc42ffded"
108
+ dependencies = [
109
+ "proc-macro2",
110
+ "pyo3-macros-backend",
111
+ "quote",
112
+ "syn",
113
+ ]
114
+
115
+ [[package]]
116
+ name = "pyo3-macros-backend"
117
+ version = "0.26.0"
118
+ source = "registry+https://github.com/rust-lang/crates.io-index"
119
+ checksum = "100246c0ecf400b475341b8455a9213344569af29a3c841d29270e53102e0fcf"
120
+ dependencies = [
121
+ "heck",
122
+ "proc-macro2",
123
+ "pyo3-build-config",
124
+ "quote",
125
+ "syn",
126
+ ]
127
+
128
+ [[package]]
129
+ name = "quote"
130
+ version = "1.0.40"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
133
+ dependencies = [
134
+ "proc-macro2",
135
+ ]
136
+
137
+ [[package]]
138
+ name = "smallvec"
139
+ version = "1.15.1"
140
+ source = "registry+https://github.com/rust-lang/crates.io-index"
141
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
142
+
143
+ [[package]]
144
+ name = "syn"
145
+ version = "2.0.106"
146
+ source = "registry+https://github.com/rust-lang/crates.io-index"
147
+ checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
148
+ dependencies = [
149
+ "proc-macro2",
150
+ "quote",
151
+ "unicode-ident",
152
+ ]
153
+
154
+ [[package]]
155
+ name = "target-lexicon"
156
+ version = "0.13.3"
157
+ source = "registry+https://github.com/rust-lang/crates.io-index"
158
+ checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
159
+
160
+ [[package]]
161
+ name = "unicode-ident"
162
+ version = "1.0.19"
163
+ source = "registry+https://github.com/rust-lang/crates.io-index"
164
+ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
165
+
166
+ [[package]]
167
+ name = "unindent"
168
+ version = "0.2.4"
169
+ source = "registry+https://github.com/rust-lang/crates.io-index"
170
+ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fastquadtree"
3
- version = "0.8.1"
3
+ version = "0.9.1"
4
4
  edition = "2021"
5
5
  readme = "README.md"
6
6
 
@@ -8,7 +8,7 @@ readme = "README.md"
8
8
  crate-type = ["rlib", "cdylib"]
9
9
 
10
10
  [dependencies]
11
- pyo3 = { version = "0.21", features = ["extension-module", "abi3-py38"] }
11
+ pyo3 = { version = "0.26", features = ["extension-module", "abi3-py38"] }
12
12
  smallvec = "1.15.1"
13
13
 
14
14
  [profile.release]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 0.8.1
3
+ Version: 0.9.1
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Rust
@@ -24,6 +24,7 @@ Requires-Dist: mkdocs-autorefs ; extra == 'dev'
24
24
  Requires-Dist: mkdocs-git-revision-date-localized-plugin ; extra == 'dev'
25
25
  Requires-Dist: mkdocs-minify-plugin ; extra == 'dev'
26
26
  Requires-Dist: maturin>=1.5 ; extra == 'dev'
27
+ Requires-Dist: pyqtree==1.0.0 ; extra == 'dev'
27
28
  Provides-Extra: dev
28
29
  License-File: LICENSE
29
30
  Summary: Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
@@ -38,33 +39,54 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
38
39
 
39
40
  # fastquadtree
40
41
 
41
- [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
42
- [![PyPI version](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
43
- [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
44
- [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
45
- [![License: MIT](https://img.shields.io/pypi/l/fastquadtree.svg)](LICENSE)
42
+ <img src="https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png"
43
+ alt="Interactive Screenshot" align="right" width="420">
46
44
 
47
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/fastquadtree?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=BLUE&left_text=Total+Downloads)](https://pepy.tech/projects/fastquadtree)
45
+ Rust-optimized quadtree with a clean Python API
48
46
 
47
+ [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
48
+ [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
49
+ [![Downloads](https://static.pepy.tech/personalized-badge/fastquadtree?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=BLUE&left_text=Total%20Downloads)](https://pepy.tech/projects/fastquadtree)
49
50
  [![Build](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml/badge.svg)](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml)
50
- [![Codecov](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
51
51
 
52
- [![Rust core via PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
53
- [![Built with maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
52
+ [![PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
53
+ [![maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
54
54
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
55
55
 
56
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
57
+ [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
58
+ [![Coverage](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
59
+ [![License: MIT](https://img.shields.io/pypi/l/fastquadtree.svg)](LICENSE)
56
60
 
61
+ <br clear="right"/>
57
62
 
58
- ![Interactive_V2_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png)
63
+ ## Why use fastquadtree
59
64
 
65
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with modern typing hints
66
+ - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
67
+ - Prebuilt wheels for Windows, macOS, and Linux
68
+ - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
69
+ - Fast KNN and range queries
70
+ - Optional object tracking for id ↔ object mapping
71
+ - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
60
72
 
61
- Rust-optimized quadtree with a simple Python API.
73
+ ----
62
74
 
63
75
  👉 **Docs:** https://elan456.github.io/fastquadtree/
64
76
 
65
- - Python package: **`fastquadtree`**
66
- - Python 3.8
67
- - Import path: `from fastquadtree import QuadTree`
77
+ ## Examples
78
+ See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
79
+
80
+
81
+ ## Install
82
+ ```bash
83
+ pip install fastquadtree
84
+ ```
85
+
86
+ ```python
87
+ from fastquadtree import QuadTree # Point handling
88
+ from fastquadtree import RectQuadTree # Bounding box handling
89
+ ```
68
90
 
69
91
  ## Benchmarks
70
92
 
@@ -89,28 +111,7 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
89
111
  | PyQtree | 1.492 | 0.263 | 1.755 | 1.00× |
90
112
  | quads | 1.407 | 0.484 | 1.890 | 0.93× |
91
113
 
92
- ### Benchmark Configuration
93
- | Parameter | Value |
94
- |---|---:|
95
- | Bounds | (0, 0, 1000, 1000) |
96
- | Max points per node | 128 |
97
- | Max depth | 16 |
98
- | Queries per experiment | 500 |
99
-
100
- See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details.
101
-
102
- ## Install
103
-
104
- ```bash
105
- pip install fastquadtree
106
- ```
107
-
108
- If you are developing locally:
109
-
110
- ```bash
111
- # optimized dev install
112
- maturin develop --release
113
- ```
114
+ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details, including configurations, system info, and native vs shim benchmarks.
114
115
 
115
116
  ## Quickstart
116
117
  [See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
@@ -1,32 +1,53 @@
1
1
  # fastquadtree
2
2
 
3
- [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
4
- [![PyPI version](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
5
- [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
6
- [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
7
- [![License: MIT](https://img.shields.io/pypi/l/fastquadtree.svg)](LICENSE)
3
+ <img src="https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png"
4
+ alt="Interactive Screenshot" align="right" width="420">
8
5
 
9
- [![PyPI Downloads](https://static.pepy.tech/personalized-badge/fastquadtree?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=BLUE&left_text=Total+Downloads)](https://pepy.tech/projects/fastquadtree)
6
+ Rust-optimized quadtree with a clean Python API
10
7
 
8
+ [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
9
+ [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
10
+ [![Downloads](https://static.pepy.tech/personalized-badge/fastquadtree?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=BLUE&left_text=Total%20Downloads)](https://pepy.tech/projects/fastquadtree)
11
11
  [![Build](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml/badge.svg)](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml)
12
- [![Codecov](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
13
12
 
14
- [![Rust core via PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
15
- [![Built with maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
13
+ [![PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
14
+ [![maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
16
15
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
17
16
 
17
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
18
+ [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
19
+ [![Coverage](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
20
+ [![License: MIT](https://img.shields.io/pypi/l/fastquadtree.svg)](LICENSE)
18
21
 
22
+ <br clear="right"/>
19
23
 
20
- ![Interactive_V2_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png)
24
+ ## Why use fastquadtree
21
25
 
26
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with modern typing hints
27
+ - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
28
+ - Prebuilt wheels for Windows, macOS, and Linux
29
+ - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
30
+ - Fast KNN and range queries
31
+ - Optional object tracking for id ↔ object mapping
32
+ - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
22
33
 
23
- Rust-optimized quadtree with a simple Python API.
34
+ ----
24
35
 
25
36
  👉 **Docs:** https://elan456.github.io/fastquadtree/
26
37
 
27
- - Python package: **`fastquadtree`**
28
- - Python 3.8
29
- - Import path: `from fastquadtree import QuadTree`
38
+ ## Examples
39
+ See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
40
+
41
+
42
+ ## Install
43
+ ```bash
44
+ pip install fastquadtree
45
+ ```
46
+
47
+ ```python
48
+ from fastquadtree import QuadTree # Point handling
49
+ from fastquadtree import RectQuadTree # Bounding box handling
50
+ ```
30
51
 
31
52
  ## Benchmarks
32
53
 
@@ -51,28 +72,7 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
51
72
  | PyQtree | 1.492 | 0.263 | 1.755 | 1.00× |
52
73
  | quads | 1.407 | 0.484 | 1.890 | 0.93× |
53
74
 
54
- ### Benchmark Configuration
55
- | Parameter | Value |
56
- |---|---:|
57
- | Bounds | (0, 0, 1000, 1000) |
58
- | Max points per node | 128 |
59
- | Max depth | 16 |
60
- | Queries per experiment | 500 |
61
-
62
- See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details.
63
-
64
- ## Install
65
-
66
- ```bash
67
- pip install fastquadtree
68
- ```
69
-
70
- If you are developing locally:
71
-
72
- ```bash
73
- # optimized dev install
74
- maturin develop --release
75
- ```
75
+ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details, including configurations, system info, and native vs shim benchmarks.
76
76
 
77
77
  ## Quickstart
78
78
  [See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
@@ -7,14 +7,16 @@ import random
7
7
  import statistics as stats
8
8
  from time import perf_counter as now
9
9
 
10
+ from pyqtree import Index as PyQTreeIndex
10
11
  from system_info_collector import collect_system_info, format_system_info_markdown_lite
11
12
  from tqdm import tqdm
12
13
 
13
14
  from fastquadtree import QuadTree as ShimQuadTree
14
15
  from fastquadtree._native import QuadTree as NativeQuadTree
16
+ from fastquadtree.pyqtree import Index as FQTIndex
15
17
 
16
18
  BOUNDS = (0.0, 0.0, 1000.0, 1000.0)
17
- CAPACITY = 20
19
+ CAPACITY = 64
18
20
  MAX_DEPTH = 10
19
21
  SEED = 42
20
22
 
@@ -69,6 +71,30 @@ def bench_shim(points, queries, *, track_objects: bool, with_objs: bool):
69
71
  return t_build, t_query
70
72
 
71
73
 
74
+ def bench_pyqtree(points, queries, fqt: bool):
75
+ """
76
+ Benchmarks the pyqtree compatibility shim vs the original pyqtree.
77
+
78
+ Set fqt to True to use the shim, False to use the original pyqtree.
79
+ """
80
+ t0 = now()
81
+ qt = (
82
+ FQTIndex(bbox=BOUNDS, max_items=CAPACITY, max_depth=MAX_DEPTH)
83
+ if fqt
84
+ else PyQTreeIndex(bbox=BOUNDS, max_items=CAPACITY, max_depth=MAX_DEPTH)
85
+ )
86
+ for i, p in enumerate(points):
87
+ box = (p[0], p[1], p[0], p[1])
88
+ qt.insert(i, box)
89
+ t_build = now() - t0
90
+
91
+ t0 = now()
92
+ for q in queries:
93
+ _ = qt.intersect(q)
94
+ t_query = now() - t0
95
+ return t_build, t_query
96
+
97
+
72
98
  def median_times(fn, points, queries, repeats: int, desc: str = "Running"):
73
99
  """Run benchmark multiple times and return median times."""
74
100
  builds, queries_t = [], []
@@ -119,14 +145,28 @@ def main():
119
145
  points,
120
146
  queries,
121
147
  args.repeats,
122
- desc="Shim (no map)",
148
+ desc="Shim (no tracking)",
123
149
  )
124
150
  s_build_map, s_query_map = median_times(
125
151
  lambda pts, qs: bench_shim(pts, qs, track_objects=True, with_objs=True),
126
152
  points,
127
153
  queries,
128
154
  args.repeats,
129
- desc="Shim (track+objs)",
155
+ desc="Shim (tracking)",
156
+ )
157
+ p_build, p_query = median_times(
158
+ lambda pts, qs: bench_pyqtree(pts, qs, fqt=False),
159
+ points,
160
+ queries,
161
+ args.repeats,
162
+ desc="pyqtree (original)",
163
+ )
164
+ fqt_build, fqt_query = median_times(
165
+ lambda pts, qs: bench_pyqtree(pts, qs, fqt=True),
166
+ points,
167
+ queries,
168
+ args.repeats,
169
+ desc="pyqtree (FQT shim)",
130
170
  )
131
171
  print()
132
172
 
@@ -146,14 +186,19 @@ def main():
146
186
  | Variant | Build | Query | Total |
147
187
  |---|---:|---:|---:|
148
188
  | Native | {fmt(n_build)} | {fmt(n_query)} | {fmt(n_build + n_query)} |
149
- | Shim (no map) | {fmt(s_build_no_map)} | {fmt(s_query_no_map)} | {fmt(s_build_no_map + s_query_no_map)} |
150
- | Shim (track+objs) | {fmt(s_build_map)} | {fmt(s_query_map)} | {fmt(s_build_map + s_query_map)} |
189
+ | Shim (no tracking) | {fmt(s_build_no_map)} | {fmt(s_query_no_map)} | {fmt(s_build_no_map + s_query_no_map)} |
190
+ | Shim (tracking) | {fmt(s_build_map)} | {fmt(s_query_map)} | {fmt(s_build_map + s_query_map)} |
191
+ | pyqtree (fastquadtree) | {fmt(fqt_build)} | {fmt(fqt_query)} | {fmt(fqt_build + fqt_query)} |
192
+ | pyqtree (original) | {fmt(p_build)} | {fmt(p_query)} | {fmt(p_build + p_query)} |
151
193
 
152
194
  ### Summary
153
195
 
154
196
  Using the shim with object tracking increases build time by {fmt(s_build_map / n_build)}x and query time by {fmt(s_query_map / n_query)}x.
155
197
  **Total slowdown = {fmt((s_build_map + s_query_map) / (n_build + n_query))}x.**
156
198
 
199
+ If you directly replace pyqtree with the drop-in `fastquadtree.pyqtree.Index` shim, you get a build time of {fmt(fqt_build)}s and query time of {fmt(fqt_query)}s.
200
+ This is a total speedup of {fmt((p_build + p_query) / (fqt_build + fqt_query))}x compared to the original pyqtree and requires no code changes.
201
+
157
202
  Adding the object map only impacts the build time, not the query time.
158
203
  """
159
204
  print(md.strip())
@@ -17,7 +17,7 @@ Quadtrees are the focus of the benchmark, but Rtrees are included for reference.
17
17
 
18
18
  | Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
19
19
  |---|---:|---:|---:|---:|
20
- | fastquadtree | 0.031 | 0.089 | 0.120 | 14.64× |
20
+ | **fastquadtree** | 0.031 | 0.089 | 0.120 | **14.64×** |
21
21
  | Shapely STRtree | 0.179 | 0.100 | 0.279 | 6.29× |
22
22
  | nontree-QuadTree | 0.595 | 0.605 | 1.200 | 1.46× |
23
23
  | Rtree | 0.961 | 0.300 | 1.261 | 1.39× |
@@ -35,15 +35,25 @@
35
35
 
36
36
  ## Why use fastquadtree
37
37
 
38
- - Simple Python API you can teach in one review
39
- - Fast inserts and queries on hundreds of thousands of points
38
+ - Clean [Python API](api/quadtree.md) with modern typing hints
39
+ - The fastest quadtree Python package ([>10x faster](benchmark.md) than pyqtree)
40
+ - Prebuilt wheels for Windows, macOS, and Linux
41
+ - Support for [inserting bounding boxes](api/rect_quadtree.md) or points
42
+ - Fast KNN and range queries
40
43
  - Optional object tracking for id ↔ object mapping
41
- - Clean integrations for range queries and nearest neighbors
42
- - Support for inserting bounding boxes or points
44
+ - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
45
+
46
+ ## Examples
47
+ See examples of how fastquadtree can be used in the [runnables](runnables.md) section.
48
+
43
49
 
44
50
  ## Install
45
51
  ```bash
46
52
  pip install fastquadtree
47
53
  ```
48
54
 
49
- **Look at the nav panel for quick start guides and API docs**
55
+ ```python
56
+ from fastquadtree import QuadTree # Point handling
57
+ from fastquadtree import RectQuadTree # Bounding box handling
58
+ from fastquadtree.pyqtree import Index # Drop-in replacement for pyqtree
59
+ ```
@@ -5,6 +5,10 @@
5
5
  - Add and delete boids with mouse clicks
6
6
  - Visualize KNN and range queries
7
7
 
8
+ The interactive demo is a great way to see how fastquadtree works in practice.
9
+ You can see how the quadtree subdivides as you add points, and validate the accuracy of the queries visually.
10
+ By pressing 1, you can visualize the KNN query for each boid.
11
+
8
12
  ```bash
9
13
  pip install -r interactive/requirements.txt
10
14
  python interactive/interactive_v2.py
@@ -16,6 +20,9 @@ python interactive/interactive_v2.py
16
20
  - Similar to the above demo, but uses rectangles instead of points
17
21
  - If the rectangles intersect at all with the query area, they will be highlighted in red
18
22
 
23
+ If you are creating a game or simulation environment where entities have bounding boxes, you can use the
24
+ rectangular quadtree to quickly check which entities are intersecting with another.
25
+
19
26
  ```bash
20
27
  pip install -r interactive/requirements.txt
21
28
  python interactive/interactive_v2_rect.py
@@ -27,6 +34,9 @@ python interactive/interactive_v2_rect.py
27
34
  - Spawn balls in a pit with physics-based collisions
28
35
  - Easily switch between brute force and quadtree collision detection to see the performance difference
29
36
 
37
+ The ball pit demo shows how quadtrees offer massive performance improvements for collision detection.
38
+ Rectangular queries are used to find potential collisions, and then precise circle-circle collision checks are performed.
39
+
30
40
  ```bash
31
41
  pip install -r interactive/requirements.txt
32
42
  python interactive/ball_pit.py
@@ -18,7 +18,7 @@ theme:
18
18
  palette:
19
19
  - scheme: slate
20
20
  primary: indigo
21
- accent: indigo
21
+ accent: deep orange
22
22
 
23
23
  plugins:
24
24
  - search
@@ -77,6 +77,7 @@ dev = [
77
77
  "mkdocs-git-revision-date-localized-plugin",
78
78
  "mkdocs-minify-plugin",
79
79
  "maturin>=1.5", # build Rust wheels
80
+ "pyqtree==1.0.0", # for comparison in tests
80
81
  ]
81
82
 
82
83
  [tool.ruff]