fastquadtree 2.0.0__tar.gz → 2.0.2__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.
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/Cargo.lock +1 -1
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/Cargo.toml +1 -1
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/PKG-INFO +28 -18
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/README.md +27 -17
- fastquadtree-2.0.2/assets/quadtree_bench_throughput.png +0 -0
- fastquadtree-2.0.2/assets/quadtree_bench_time.png +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/engines.py +30 -5
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/plotting.py +29 -20
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/runner.py +1 -1
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/benchmark.md +17 -8
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/runnables.md +20 -3
- fastquadtree-2.0.2/examples/custom_id_example.py +31 -0
- fastquadtree-2.0.2/examples/object_tracking_example.py +30 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/interactive/ballpit.py +31 -15
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/__init__.py +10 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_base_quadtree.py +12 -1
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_item.py +4 -4
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/integration/test_public_api_contracts.py +4 -0
- fastquadtree-2.0.0/assets/quadtree_bench_throughput.png +0 -0
- fastquadtree-2.0.0/assets/quadtree_bench_time.png +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/.github/workflows/docs.yml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/.github/workflows/release.yml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/.github/workflows/test.yml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/.gitignore +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/.pre-commit-config.yaml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/LICENSE +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/assets/ballpit.png +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/assets/interactive_v2_rect_screenshot.png +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/assets/interactive_v2_screenshot.png +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/benchmark_native_vs_shim.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/benchmark_np_vs_list.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/benchmark_serialization_vs_rebuild.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/cross_library_bench.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/__init__.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/main.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/quadtree_bench/optimizer.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/requirements.txt +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/runner.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/benchmarks/system_info_collector.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/2.0_migration_guide.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/2.0_proposal.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/insert_result.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/item.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/point_item.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/pyqtree.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/quadtree.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/quadtree_objects.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/rect_item.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/rect_quadtree.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/api/rect_quadtree_objects.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/future_features.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/index.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/quickstart.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/rust_usage.md +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/docs/styles/overrides.css +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/interactive/interactive.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/interactive/interactive_v2.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/interactive/interactive_v2_rect.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/interactive/requirements.txt +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/mkdocs.yml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pyproject.toml +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pyrightconfig.json +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_base_quadtree_objects.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_common.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_insert_result.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/_obj_store.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/point_quadtree.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/point_quadtree_objects.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/py.typed +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/pyqtree.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/rect_quadtree.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/pysrc/fastquadtree/rect_quadtree_objects.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/src/geom.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/src/lib.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/src/quadtree.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/src/rect_quadtree.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/__init__.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/insertions.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/nearest_neighbor.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/query.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/rect_quadtree.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/rectangle_traversal.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/serialization.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_delete.rs +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/__init__.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_common_validation.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_insert_result_and_items.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_internal_edges.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_obj_store.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_serialization_container.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/conftest.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/integration/test_migration_breaks_and_safety.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_core.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_mutation.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_numpy.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_serialization.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points_objects/test_point_quadtree_objects_core.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points_objects/test_point_quadtree_objects_deletion_update.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points_objects/test_point_quadtree_objects_numpy.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points_objects/test_point_quadtree_objects_serialization.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_core.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_mutation.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_numpy.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_serialization.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects_objects/test_rect_quadtree_objects_core.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects_objects/test_rect_quadtree_objects_deletion_update.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects_objects/test_rect_quadtree_objects_numpy.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects_objects/test_rect_quadtree_objects_serialization.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/test_pyqtree_shim_compat.py +0 -0
- {fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/unconventional_bounds.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastquadtree
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
6
|
Classifier: Programming Language :: Rust
|
|
@@ -80,11 +80,6 @@ Rust-optimized quadtree with a clean Python API
|
|
|
80
80
|
|
|
81
81
|
----
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
## Examples
|
|
85
|
-
See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
|
|
86
|
-
|
|
87
|
-
|
|
88
83
|
## Install
|
|
89
84
|
```bash
|
|
90
85
|
pip install fastquadtree
|
|
@@ -98,6 +93,17 @@ from fastquadtree import RectQuadTreeObjects # Bounding box handling with objec
|
|
|
98
93
|
from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~6.5x faster while keeping the same API)
|
|
99
94
|
```
|
|
100
95
|
|
|
96
|
+
|
|
97
|
+
## Quickstart
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from fastquadtree import QuadTree
|
|
101
|
+
|
|
102
|
+
qt = QuadTree((0, 0, 1000, 1000), 16) # bounds and capacity
|
|
103
|
+
qt.insert((100, 200), id_=1) # insert point with ID 1
|
|
104
|
+
print(qt.query((0, 0, 500, 500))) # gets all points in that area: [(1, 100.0, 200.0)]
|
|
105
|
+
```
|
|
106
|
+
[See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/) or the [interactive demos](https://elan456.github.io/fastquadtree/runnables/) for more details.
|
|
101
107
|
## Benchmarks
|
|
102
108
|
|
|
103
109
|
fastquadtree **outperforms** all other quadtree Python packages, including the Rtree spatial index.
|
|
@@ -113,20 +119,23 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
|
|
|
113
119
|
|
|
114
120
|
| Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
|
|
115
121
|
|---|---:|---:|---:|---:|
|
|
116
|
-
| fastquadtree | 0.
|
|
117
|
-
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
| Rtree | 1.
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
122
|
+
| fastquadtree (np)[^fqtnp] | 0.057 | 0.021 | 0.078 | 54.45× |
|
|
123
|
+
| fastquadtree[^fqt] | 0.060 | 0.189 | 0.249 | 17.04× |
|
|
124
|
+
| Shapely STRtree[^npreturn] | 0.321 | 0.196 | 0.517 | 8.21× |
|
|
125
|
+
| fastquadtree (obj tracking)[^fqto] | 0.437 | 0.239 | 0.675 | 6.28× |
|
|
126
|
+
| Rtree | 1.796 | 0.561 | 2.357 | 1.80× |
|
|
127
|
+
| nontree-QuadTree | 1.275 | 1.272 | 2.547 | 1.67× |
|
|
128
|
+
| e-pyquadtree | 2.144 | 1.507 | 3.650 | 1.16× |
|
|
129
|
+
| quads | 3.001 | 1.171 | 4.172 | 1.02× |
|
|
130
|
+
| PyQtree | 3.677 | 0.565 | 4.242 | 1.00× |
|
|
131
|
+
|
|
132
|
+
[^fqtnp]: Uses `query_np` for Numpy array return values rather than Python lists.
|
|
133
|
+
[^fqt]: Uses standard `query` method returning Python lists.
|
|
134
|
+
[^npreturn]: Uses Shapely STRtree with Numpy array points and returns.
|
|
135
|
+
[^fqto]: Uses QuadTreeObjects with object association.
|
|
124
136
|
|
|
125
137
|
See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details, including configurations, system info, and native vs shim benchmarks.
|
|
126
138
|
|
|
127
|
-
## Quickstart
|
|
128
|
-
[See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
|
|
129
|
-
|
|
130
139
|
## API
|
|
131
140
|
|
|
132
141
|
[See the full API](https://elan456.github.io/fastquadtree/api/quadtree/)
|
|
@@ -170,7 +179,8 @@ For object tracking, use `QuadTreeObjects` instead. See the [docs](https://elan4
|
|
|
170
179
|

|
|
171
180
|
|
|
172
181
|
A simple demo of moving objects with collision detection using **fastquadtree**.
|
|
173
|
-
You can toggle between
|
|
182
|
+
You can toggle between fastquadtree, pyqtree, and brute-force mode to see the performance difference.
|
|
183
|
+
I typically see an FPS of ~70 with fastquadtree, ~25 with pyqtree, and <1 FPS with brute-force on my machine with 1500 balls.
|
|
174
184
|
|
|
175
185
|
See the [runnables guide](https://elan456.github.io/fastquadtree/runnables/) for setup instructions.
|
|
176
186
|
|
|
@@ -39,11 +39,6 @@ Rust-optimized quadtree with a clean Python API
|
|
|
39
39
|
|
|
40
40
|
----
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
## Examples
|
|
44
|
-
See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
|
|
45
|
-
|
|
46
|
-
|
|
47
42
|
## Install
|
|
48
43
|
```bash
|
|
49
44
|
pip install fastquadtree
|
|
@@ -57,6 +52,17 @@ from fastquadtree import RectQuadTreeObjects # Bounding box handling with objec
|
|
|
57
52
|
from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~6.5x faster while keeping the same API)
|
|
58
53
|
```
|
|
59
54
|
|
|
55
|
+
|
|
56
|
+
## Quickstart
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from fastquadtree import QuadTree
|
|
60
|
+
|
|
61
|
+
qt = QuadTree((0, 0, 1000, 1000), 16) # bounds and capacity
|
|
62
|
+
qt.insert((100, 200), id_=1) # insert point with ID 1
|
|
63
|
+
print(qt.query((0, 0, 500, 500))) # gets all points in that area: [(1, 100.0, 200.0)]
|
|
64
|
+
```
|
|
65
|
+
[See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/) or the [interactive demos](https://elan456.github.io/fastquadtree/runnables/) for more details.
|
|
60
66
|
## Benchmarks
|
|
61
67
|
|
|
62
68
|
fastquadtree **outperforms** all other quadtree Python packages, including the Rtree spatial index.
|
|
@@ -72,20 +78,23 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
|
|
|
72
78
|
|
|
73
79
|
| Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
|
|
74
80
|
|---|---:|---:|---:|---:|
|
|
75
|
-
| fastquadtree | 0.
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
| Rtree | 1.
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
81
|
+
| fastquadtree (np)[^fqtnp] | 0.057 | 0.021 | 0.078 | 54.45× |
|
|
82
|
+
| fastquadtree[^fqt] | 0.060 | 0.189 | 0.249 | 17.04× |
|
|
83
|
+
| Shapely STRtree[^npreturn] | 0.321 | 0.196 | 0.517 | 8.21× |
|
|
84
|
+
| fastquadtree (obj tracking)[^fqto] | 0.437 | 0.239 | 0.675 | 6.28× |
|
|
85
|
+
| Rtree | 1.796 | 0.561 | 2.357 | 1.80× |
|
|
86
|
+
| nontree-QuadTree | 1.275 | 1.272 | 2.547 | 1.67× |
|
|
87
|
+
| e-pyquadtree | 2.144 | 1.507 | 3.650 | 1.16× |
|
|
88
|
+
| quads | 3.001 | 1.171 | 4.172 | 1.02× |
|
|
89
|
+
| PyQtree | 3.677 | 0.565 | 4.242 | 1.00× |
|
|
90
|
+
|
|
91
|
+
[^fqtnp]: Uses `query_np` for Numpy array return values rather than Python lists.
|
|
92
|
+
[^fqt]: Uses standard `query` method returning Python lists.
|
|
93
|
+
[^npreturn]: Uses Shapely STRtree with Numpy array points and returns.
|
|
94
|
+
[^fqto]: Uses QuadTreeObjects with object association.
|
|
83
95
|
|
|
84
96
|
See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details, including configurations, system info, and native vs shim benchmarks.
|
|
85
97
|
|
|
86
|
-
## Quickstart
|
|
87
|
-
[See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
|
|
88
|
-
|
|
89
98
|
## API
|
|
90
99
|
|
|
91
100
|
[See the full API](https://elan456.github.io/fastquadtree/api/quadtree/)
|
|
@@ -129,7 +138,8 @@ For object tracking, use `QuadTreeObjects` instead. See the [docs](https://elan4
|
|
|
129
138
|

|
|
130
139
|
|
|
131
140
|
A simple demo of moving objects with collision detection using **fastquadtree**.
|
|
132
|
-
You can toggle between
|
|
141
|
+
You can toggle between fastquadtree, pyqtree, and brute-force mode to see the performance difference.
|
|
142
|
+
I typically see an FPS of ~70 with fastquadtree, ~25 with pyqtree, and <1 FPS with brute-force on my machine with 1500 balls.
|
|
133
143
|
|
|
134
144
|
See the [runnables guide](https://elan456.github.io/fastquadtree/runnables/) for setup instructions.
|
|
135
145
|
|
|
Binary file
|
|
Binary file
|
|
@@ -100,7 +100,7 @@ def _create_pyqtree_engine(
|
|
|
100
100
|
def _create_fastquadtree_np_engine(
|
|
101
101
|
bounds: Tuple[int, int, int, int], max_points: int, max_depth: int
|
|
102
102
|
) -> Engine:
|
|
103
|
-
"""Create engine adapter for fastquadtree."""
|
|
103
|
+
"""Create engine adapter for fastquadtree but queries are returned as numpy arrays instead of Python lists."""
|
|
104
104
|
|
|
105
105
|
def build(points):
|
|
106
106
|
qt = FQTQuadTree(bounds, max_points, max_depth=max_depth)
|
|
@@ -111,9 +111,31 @@ def _create_fastquadtree_np_engine(
|
|
|
111
111
|
for q in queries:
|
|
112
112
|
_ = qt.query_np(q)
|
|
113
113
|
|
|
114
|
+
return Engine(
|
|
115
|
+
"fastquadtree (np)",
|
|
116
|
+
"#e55100",
|
|
117
|
+
build,
|
|
118
|
+
query, # display name # color (orange)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _create_fastquadtree_engine(
|
|
123
|
+
bounds: Tuple[int, int, int, int], max_points: int, max_depth: int
|
|
124
|
+
) -> Engine:
|
|
125
|
+
"""Create engine adapter for fastquadtree."""
|
|
126
|
+
|
|
127
|
+
def build(points):
|
|
128
|
+
qt = FQTQuadTree(bounds, max_points, max_depth=max_depth)
|
|
129
|
+
qt.insert_many(points)
|
|
130
|
+
return qt
|
|
131
|
+
|
|
132
|
+
def query(qt, queries):
|
|
133
|
+
for q in queries:
|
|
134
|
+
_ = qt.query(q)
|
|
135
|
+
|
|
114
136
|
return Engine(
|
|
115
137
|
"fastquadtree",
|
|
116
|
-
"#
|
|
138
|
+
"#ff9500",
|
|
117
139
|
build,
|
|
118
140
|
query, # display name # color (orange)
|
|
119
141
|
)
|
|
@@ -134,8 +156,8 @@ def _create_fastquadtree_items_engine(
|
|
|
134
156
|
_ = qt.query(q)
|
|
135
157
|
|
|
136
158
|
return Engine(
|
|
137
|
-
"fastquadtree (
|
|
138
|
-
"#
|
|
159
|
+
"fastquadtree (objs)",
|
|
160
|
+
"#ffc107",
|
|
139
161
|
build,
|
|
140
162
|
query, # display name # color (orange)
|
|
141
163
|
)
|
|
@@ -314,7 +336,10 @@ def get_engines(
|
|
|
314
336
|
"""
|
|
315
337
|
# Always available engines
|
|
316
338
|
engines = {
|
|
317
|
-
"fastquadtree": _create_fastquadtree_np_engine(
|
|
339
|
+
"fastquadtree (np)": _create_fastquadtree_np_engine(
|
|
340
|
+
bounds, max_points, max_depth
|
|
341
|
+
),
|
|
342
|
+
"fastquadtree": _create_fastquadtree_engine(bounds, max_points, max_depth),
|
|
318
343
|
"fastquadtree (obj tracking)": _create_fastquadtree_items_engine(
|
|
319
344
|
bounds, max_points, max_depth
|
|
320
345
|
),
|
|
@@ -61,23 +61,27 @@ class PlotManager:
|
|
|
61
61
|
|
|
62
62
|
# Update layout
|
|
63
63
|
fig.update_layout(
|
|
64
|
-
title=
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
title={
|
|
65
|
+
"text": (
|
|
66
|
+
f"Tree build and query benchmarks "
|
|
67
|
+
f"(Max Depth {self.config.max_depth}, "
|
|
68
|
+
f"Capacity {self.config.max_points}, "
|
|
69
|
+
f"{self.config.repeats}x median, "
|
|
70
|
+
f"{self.config.n_queries} queries)"
|
|
71
|
+
),
|
|
72
|
+
"y": 0.98,
|
|
73
|
+
"x": 0.5,
|
|
74
|
+
"xanchor": "center",
|
|
75
|
+
},
|
|
71
76
|
template="plotly_dark",
|
|
72
77
|
legend={
|
|
73
|
-
"orientation": "
|
|
74
|
-
"
|
|
75
|
-
"xanchor": "
|
|
76
|
-
"
|
|
77
|
-
"yanchor": "
|
|
78
|
-
"y": 1,
|
|
78
|
+
"orientation": "h",
|
|
79
|
+
"x": 0.5,
|
|
80
|
+
"xanchor": "center",
|
|
81
|
+
"y": 1.12,
|
|
82
|
+
"yanchor": "bottom",
|
|
79
83
|
},
|
|
80
|
-
margin={"l": 40, "r": 20, "t":
|
|
84
|
+
margin={"l": 40, "r": 20, "t": 140, "b": 40}, # Increase top margin
|
|
81
85
|
height=520,
|
|
82
86
|
)
|
|
83
87
|
|
|
@@ -93,7 +97,7 @@ class PlotManager:
|
|
|
93
97
|
)
|
|
94
98
|
|
|
95
99
|
# Set logarithmic scale for query rate
|
|
96
|
-
fig.update_yaxes(type="log", row=1, col=2)
|
|
100
|
+
fig.update_yaxes(type="log", row=1, col=2, tickformat=".0s", dtick=0.25)
|
|
97
101
|
|
|
98
102
|
for name in list(self.results["query_rate"].keys()):
|
|
99
103
|
# Determine color
|
|
@@ -136,16 +140,21 @@ class PlotManager:
|
|
|
136
140
|
|
|
137
141
|
# Update layout
|
|
138
142
|
fig.update_layout(
|
|
139
|
-
title=
|
|
143
|
+
title={
|
|
144
|
+
"text": "Throughput",
|
|
145
|
+
"y": 0.98, # Push title to very top
|
|
146
|
+
"x": 0.5,
|
|
147
|
+
"xanchor": "center",
|
|
148
|
+
},
|
|
140
149
|
template="plotly_dark",
|
|
141
150
|
legend={
|
|
142
151
|
"orientation": "h",
|
|
143
|
-
"x": 0,
|
|
144
|
-
"xanchor": "
|
|
145
|
-
"y": 1.
|
|
152
|
+
"x": 0.5,
|
|
153
|
+
"xanchor": "center",
|
|
154
|
+
"y": 1.15, # Move legend higher
|
|
146
155
|
"yanchor": "bottom",
|
|
147
156
|
},
|
|
148
|
-
margin={"l": 60, "r": 40, "t":
|
|
157
|
+
margin={"l": 60, "r": 40, "t": 140, "b": 40}, # Increase top margin
|
|
149
158
|
height=480,
|
|
150
159
|
)
|
|
151
160
|
|
|
@@ -35,7 +35,7 @@ class BenchmarkConfig:
|
|
|
35
35
|
|
|
36
36
|
def __post_init__(self):
|
|
37
37
|
"""Generate experiment point sizes."""
|
|
38
|
-
self.experiments = [
|
|
38
|
+
self.experiments = [128000]
|
|
39
39
|
while self.experiments[-1] < self.max_experiment_points:
|
|
40
40
|
self.experiments.append(int(self.experiments[-1] * 2))
|
|
41
41
|
self.experiments[-1] = min(self.experiments[-1], self.max_experiment_points)
|
|
@@ -16,14 +16,23 @@ Quadtrees are the focus of the benchmark, but Rtrees are included for reference.
|
|
|
16
16
|
|
|
17
17
|
| Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
|
|
18
18
|
|---|---:|---:|---:|---:|
|
|
19
|
-
| fastquadtree | 0.
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
| Rtree | 1.
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
19
|
+
| fastquadtree (np)[^fqtnp] | 0.057 | 0.021 | 0.078 | 54.45× |
|
|
20
|
+
| fastquadtree[^fqt] | 0.060 | 0.189 | 0.249 | 17.04× |
|
|
21
|
+
| Shapely STRtree[^npreturn] | 0.321 | 0.196 | 0.517 | 8.21× |
|
|
22
|
+
| fastquadtree (obj tracking)[^fqto] | 0.437 | 0.239 | 0.675 | 6.28× |
|
|
23
|
+
| Rtree | 1.796 | 0.561 | 2.357 | 1.80× |
|
|
24
|
+
| nontree-QuadTree | 1.275 | 1.272 | 2.547 | 1.67× |
|
|
25
|
+
| e-pyquadtree | 2.144 | 1.507 | 3.650 | 1.16× |
|
|
26
|
+
| quads | 3.001 | 1.171 | 4.172 | 1.02× |
|
|
27
|
+
| PyQtree | 3.677 | 0.565 | 4.242 | 1.00× |
|
|
28
|
+
|
|
29
|
+
[^fqtnp]: Uses `query_np` for Numpy array return values rather than Python lists.
|
|
30
|
+
[^fqt]: Uses standard `query` method returning Python lists.
|
|
31
|
+
[^npreturn]: Uses Shapely STRtree with Numpy array points and returns.
|
|
32
|
+
[^fqto]: Uses QuadTreeObjects with object association.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
27
36
|
|
|
28
37
|
#### Benchmark Configuration
|
|
29
38
|
| Parameter | Value |
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
|
|
2
2
|
# Runnable Examples
|
|
3
3
|
|
|
4
|
+
After cloning the repository, you can run the following examples to see how fastquadtree works in practice.
|
|
5
|
+
|
|
6
|
+
## Environment Setup
|
|
7
|
+
|
|
8
|
+
### Clone the repo
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/Elan456/fastquadtree.git
|
|
11
|
+
cd fastquadtree
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Create and activate a virtual environment, install dependencies
|
|
15
|
+
This step can be skipped if you already have a suitable environment.
|
|
16
|
+
```bash
|
|
17
|
+
python -m venv .venv
|
|
18
|
+
source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
|
|
19
|
+
pip install -e .
|
|
20
|
+
maturin develop --release
|
|
21
|
+
pip install -r interactive/requirements.txt
|
|
22
|
+
```
|
|
23
|
+
|
|
4
24
|
## 1. Interactive demo
|
|
5
25
|
- Add and delete boids with mouse clicks
|
|
6
26
|
- Visualize KNN and range queries
|
|
@@ -10,7 +30,6 @@ You can see how the quadtree subdivides as you add points, and validate the accu
|
|
|
10
30
|
By pressing 1, you can visualize the KNN query for each boid.
|
|
11
31
|
|
|
12
32
|
```bash
|
|
13
|
-
pip install -r interactive/requirements.txt
|
|
14
33
|
python interactive/interactive_v2.py
|
|
15
34
|
```
|
|
16
35
|
|
|
@@ -24,7 +43,6 @@ If you are creating a game or simulation environment where entities have boundin
|
|
|
24
43
|
rectangular quadtree to quickly check which entities are intersecting with another.
|
|
25
44
|
|
|
26
45
|
```bash
|
|
27
|
-
pip install -r interactive/requirements.txt
|
|
28
46
|
python interactive/interactive_v2_rect.py
|
|
29
47
|
```
|
|
30
48
|
|
|
@@ -38,7 +56,6 @@ The ball pit demo shows how quadtrees offer massive performance improvements for
|
|
|
38
56
|
Rectangular queries are used to find potential collisions, and then precise circle-circle collision checks are performed.
|
|
39
57
|
|
|
40
58
|
```bash
|
|
41
|
-
pip install -r interactive/requirements.txt
|
|
42
59
|
python interactive/ball_pit.py
|
|
43
60
|
```
|
|
44
61
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from fastquadtree import QuadTree
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Person:
|
|
5
|
+
def __init__(self, x: float, y: float, name: str):
|
|
6
|
+
self.x = x
|
|
7
|
+
self.y = y
|
|
8
|
+
self.name = name
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
qt = QuadTree((0, 0, 1000, 1000), 16)
|
|
12
|
+
|
|
13
|
+
people = [
|
|
14
|
+
Person(100, 200, "Alice"),
|
|
15
|
+
Person(150, 250, "Bob"),
|
|
16
|
+
Person(300, 400, "Charlie"),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
for idx, person in enumerate(people):
|
|
20
|
+
qt.insert((person.x, person.y), id_=idx)
|
|
21
|
+
|
|
22
|
+
# Find people in a specific area
|
|
23
|
+
results = qt.query((90, 190, 200, 300))
|
|
24
|
+
for id_, x, y in results:
|
|
25
|
+
person = people[id_]
|
|
26
|
+
print(f"Found {person.name} at ({x}, {y})")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Output:
|
|
30
|
+
# Found Alice at (100.0, 200.0)
|
|
31
|
+
# Found Bob at (150.0, 250.0)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from fastquadtree import QuadTreeObjects
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Person:
|
|
5
|
+
def __init__(self, x: float, y: float, name: str):
|
|
6
|
+
self.x = x
|
|
7
|
+
self.y = y
|
|
8
|
+
self.name = name
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
qt = QuadTreeObjects((0, 0, 1000, 1000), 16)
|
|
12
|
+
|
|
13
|
+
people = [
|
|
14
|
+
Person(100, 200, "Alice"),
|
|
15
|
+
Person(150, 250, "Bob"),
|
|
16
|
+
Person(300, 400, "Charlie"),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
for person in people:
|
|
20
|
+
qt.insert((person.x, person.y), obj=person)
|
|
21
|
+
|
|
22
|
+
# Find people in a specific area
|
|
23
|
+
results = qt.query((90, 190, 200, 300))
|
|
24
|
+
for item in results:
|
|
25
|
+
print(f"Found {item.obj.name} at ({item.x}, {item.y})")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Output:
|
|
29
|
+
# Found Alice at (100, 200)
|
|
30
|
+
# Found Bob at (150, 250)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import math
|
|
2
2
|
import random
|
|
3
|
+
import time
|
|
3
4
|
from typing import Iterable, List, Set, Tuple
|
|
4
5
|
|
|
5
6
|
import pygame
|
|
6
7
|
from pyqtree import Index as PyQIndex
|
|
7
8
|
|
|
8
9
|
# Spatial backends -------------------------------------------------------------
|
|
9
|
-
from fastquadtree import
|
|
10
|
+
from fastquadtree import Quadtree
|
|
10
11
|
|
|
11
12
|
# ---------------------------- Ball object ---------------------------- #
|
|
12
13
|
|
|
@@ -130,23 +131,23 @@ class FastQTIndex(SpatialBase):
|
|
|
130
131
|
self.width = width
|
|
131
132
|
self.height = height
|
|
132
133
|
self.capacity = capacity
|
|
133
|
-
self.qt =
|
|
134
|
+
self.qt = Quadtree((0, 0, width, height), capacity)
|
|
134
135
|
|
|
135
136
|
def rebuild(self, balls: List[Ball], width: int, height: int) -> None:
|
|
136
137
|
if width != self.width or height != self.height:
|
|
137
138
|
self.width, self.height = width, height
|
|
138
|
-
self.qt
|
|
139
|
+
self.qt.clear()
|
|
139
140
|
else:
|
|
140
141
|
self.qt.clear()
|
|
141
|
-
for b in balls:
|
|
142
|
-
self.qt.insert((b.x, b.y), obj=b)
|
|
143
142
|
|
|
144
|
-
|
|
143
|
+
self.qt.insert_many([(b.x, b.y) for b in balls])
|
|
144
|
+
|
|
145
|
+
def neighbors(self, b: Ball, balls: List[Ball]) -> Iterable[Ball]:
|
|
145
146
|
r2 = 2 * b.r
|
|
146
147
|
min_x, min_y, max_x, max_y = b.x - r2, b.y - r2, b.x + r2, b.y + r2
|
|
147
148
|
neighbors = self.qt.query((min_x, min_y, max_x, max_y))
|
|
148
149
|
for it in neighbors:
|
|
149
|
-
other = it
|
|
150
|
+
other = balls[it[0]]
|
|
150
151
|
if other is not None and other is not b:
|
|
151
152
|
yield other
|
|
152
153
|
|
|
@@ -259,7 +260,7 @@ class BallPit:
|
|
|
259
260
|
def _backend(self) -> SpatialBase:
|
|
260
261
|
return self.backends[self.mode]
|
|
261
262
|
|
|
262
|
-
def update(self, dt: float):
|
|
263
|
+
def update(self, dt: float) -> tuple[float, float]:
|
|
263
264
|
# 1) Integrate motion
|
|
264
265
|
ax, ay = 0.0, 0.0
|
|
265
266
|
for b in self.balls:
|
|
@@ -268,13 +269,26 @@ class BallPit:
|
|
|
268
269
|
|
|
269
270
|
# 2) Rebuild spatial index
|
|
270
271
|
backend = self._backend()
|
|
272
|
+
start = time.perf_counter()
|
|
271
273
|
backend.rebuild(self.balls, self.width, self.height)
|
|
274
|
+
end = time.perf_counter()
|
|
275
|
+
|
|
276
|
+
tree_build_time = end - start
|
|
277
|
+
|
|
278
|
+
total_neighbor_collection_time = 0.0
|
|
272
279
|
|
|
273
280
|
# 3) Neighborhood checks with dedup on object id pairs
|
|
274
281
|
self.pair_checks = 0
|
|
275
282
|
processed: Set[Tuple[int, int]] = set()
|
|
276
283
|
for a in self.balls:
|
|
277
|
-
|
|
284
|
+
start = time.perf_counter()
|
|
285
|
+
if self.mode == "fastquadtree":
|
|
286
|
+
neighbors = backend.neighbors(a, self.balls) # type: ignore
|
|
287
|
+
else:
|
|
288
|
+
neighbors = backend.neighbors(a)
|
|
289
|
+
end = time.perf_counter()
|
|
290
|
+
total_neighbor_collection_time += end - start
|
|
291
|
+
for other in neighbors:
|
|
278
292
|
a_id = id(a)
|
|
279
293
|
o_id = id(other)
|
|
280
294
|
key = (a_id, o_id) if a_id < o_id else (o_id, a_id)
|
|
@@ -283,11 +297,11 @@ class BallPit:
|
|
|
283
297
|
processed.add(key)
|
|
284
298
|
self.pair_checks += 1
|
|
285
299
|
resolve_ball_ball(a, other)
|
|
300
|
+
return (total_neighbor_collection_time, tree_build_time)
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def draw(self, fps: float):
|
|
302
|
+
def draw(
|
|
303
|
+
self, fps: float, total_neighbor_collection_time: float, tree_build_time: float
|
|
304
|
+
):
|
|
291
305
|
for ball in self.balls:
|
|
292
306
|
ball.draw(self.screen)
|
|
293
307
|
|
|
@@ -295,6 +309,8 @@ class BallPit:
|
|
|
295
309
|
font = pygame.font.SysFont(None, 20)
|
|
296
310
|
hud_lines = [
|
|
297
311
|
f"FPS: {fps:.1f}",
|
|
312
|
+
f"Build time: {tree_build_time * 1000:.2f} ms",
|
|
313
|
+
f"Query time: {total_neighbor_collection_time * 1000:.2f} ms",
|
|
298
314
|
f"Mode: {self.mode} (Tab to cycle, 1/2/3 to select)",
|
|
299
315
|
f"Balls: {len(self.balls)}",
|
|
300
316
|
f"Pair checks this frame: {self.pair_checks}",
|
|
@@ -373,7 +389,7 @@ def main():
|
|
|
373
389
|
)
|
|
374
390
|
ball_pit.add_ball(x, y, radius=r, color=color)
|
|
375
391
|
|
|
376
|
-
ball_pit.update(dt)
|
|
392
|
+
stats = ball_pit.update(dt)
|
|
377
393
|
|
|
378
394
|
screen.fill((255, 255, 255))
|
|
379
395
|
fps = clock.get_fps()
|
|
@@ -387,7 +403,7 @@ def main():
|
|
|
387
403
|
+ fps
|
|
388
404
|
) / metrics[ball_pit.mode]["count"]
|
|
389
405
|
|
|
390
|
-
ball_pit.draw(fps)
|
|
406
|
+
ball_pit.draw(fps, stats[0], stats[1])
|
|
391
407
|
pygame.display.flip()
|
|
392
408
|
|
|
393
409
|
pygame.quit()
|
|
@@ -19,13 +19,23 @@ from .point_quadtree_objects import QuadTreeObjects
|
|
|
19
19
|
from .rect_quadtree import RectQuadTree
|
|
20
20
|
from .rect_quadtree_objects import RectQuadTreeObjects
|
|
21
21
|
|
|
22
|
+
# Allow lowercase version of quadtree for convenience
|
|
23
|
+
Quadtree = QuadTree
|
|
24
|
+
QuadtreeObjects = QuadTreeObjects
|
|
25
|
+
Rectquadtree = RectQuadTree
|
|
26
|
+
RectquadtreeObjects = RectQuadTreeObjects
|
|
27
|
+
|
|
22
28
|
__all__ = [
|
|
23
29
|
"InsertResult",
|
|
24
30
|
"Item",
|
|
25
31
|
"PointItem",
|
|
26
32
|
"QuadTree",
|
|
27
33
|
"QuadTreeObjects",
|
|
34
|
+
"Quadtree",
|
|
35
|
+
"QuadtreeObjects",
|
|
28
36
|
"RectItem",
|
|
29
37
|
"RectQuadTree",
|
|
30
38
|
"RectQuadTreeObjects",
|
|
39
|
+
"Rectquadtree",
|
|
40
|
+
"RectquadtreeObjects",
|
|
31
41
|
]
|
|
@@ -116,7 +116,8 @@ class _BaseQuadTree(Generic[G], ABC):
|
|
|
116
116
|
|
|
117
117
|
def insert_many(self, geoms: list[G]) -> InsertResult:
|
|
118
118
|
"""
|
|
119
|
-
Bulk insert geometries with auto-assigned contiguous IDs.
|
|
119
|
+
Bulk insert geometries with auto-assigned contiguous IDs. <br>
|
|
120
|
+
IDs start at 0 and increment by 1, so they will be aligned with the indexes of the input list if the tree started empty. <br>
|
|
120
121
|
|
|
121
122
|
Custom IDs are not supported for bulk insertion. Use single insert()
|
|
122
123
|
calls if you need custom IDs.
|
|
@@ -130,6 +131,16 @@ class _BaseQuadTree(Generic[G], ABC):
|
|
|
130
131
|
Raises:
|
|
131
132
|
TypeError: If geoms is a NumPy array (use insert_many_np instead).
|
|
132
133
|
ValueError: If any geometry is outside bounds.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
```python
|
|
137
|
+
# Point Quadtree Example:
|
|
138
|
+
|
|
139
|
+
points = [(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)]
|
|
140
|
+
qt = QuadTree(bounds=(0.0, 0.0, 10.0, 10.0), capacity=16)
|
|
141
|
+
result = qt.insert_many(points) # Each point's ID corresponds to its index in the points list
|
|
142
|
+
print(result) # InsertResult(count=3, start_id=0, end_id=2)
|
|
143
|
+
```
|
|
133
144
|
"""
|
|
134
145
|
if _is_np_array(geoms):
|
|
135
146
|
raise TypeError(
|
|
@@ -24,10 +24,10 @@ class Item(Generic[G]):
|
|
|
24
24
|
|
|
25
25
|
__slots__ = ("geom", "id_", "obj")
|
|
26
26
|
|
|
27
|
-
def __init__(self, id_: int, geom: G, obj: Any
|
|
27
|
+
def __init__(self, id_: int, geom: G, obj: Any = None):
|
|
28
28
|
self.id_: int = id_
|
|
29
29
|
self.geom: G = geom
|
|
30
|
-
self.obj: Any
|
|
30
|
+
self.obj: Any = obj
|
|
31
31
|
|
|
32
32
|
def to_dict(self) -> dict[str, Any]:
|
|
33
33
|
"""
|
|
@@ -76,7 +76,7 @@ class PointItem(Item[Point]):
|
|
|
76
76
|
|
|
77
77
|
__slots__ = ("x", "y")
|
|
78
78
|
|
|
79
|
-
def __init__(self, id_: int, geom: Point, obj: Any
|
|
79
|
+
def __init__(self, id_: int, geom: Point, obj: Any = None):
|
|
80
80
|
super().__init__(id_, geom, obj)
|
|
81
81
|
self.x, self.y = geom
|
|
82
82
|
|
|
@@ -100,6 +100,6 @@ class RectItem(Item[Bounds]):
|
|
|
100
100
|
|
|
101
101
|
__slots__ = ("max_x", "max_y", "min_x", "min_y")
|
|
102
102
|
|
|
103
|
-
def __init__(self, id_: int, geom: Bounds, obj: Any
|
|
103
|
+
def __init__(self, id_: int, geom: Bounds, obj: Any = None):
|
|
104
104
|
super().__init__(id_, geom, obj)
|
|
105
105
|
self.min_x, self.min_y, self.max_x, self.max_y = geom
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/integration/test_public_api_contracts.py
RENAMED
|
@@ -13,6 +13,10 @@ def test_public_api_all_exports():
|
|
|
13
13
|
"RectItem",
|
|
14
14
|
"RectQuadTree",
|
|
15
15
|
"RectQuadTreeObjects",
|
|
16
|
+
"Quadtree", # Lowercase added in 2.0.2
|
|
17
|
+
"QuadtreeObjects",
|
|
18
|
+
"Rectquadtree",
|
|
19
|
+
"RectquadtreeObjects",
|
|
16
20
|
]
|
|
17
21
|
assert sorted(fqt.__all__) == sorted(expected)
|
|
18
22
|
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_common_validation.py
RENAMED
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_insert_result_and_items.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/common/test_serialization_container.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_core.py
RENAMED
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_mutation.py
RENAMED
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/points/test_point_quadtree_numpy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_core.py
RENAMED
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_mutation.py
RENAMED
|
File without changes
|
{fastquadtree-2.0.0 → fastquadtree-2.0.2}/tests/test_python/rects/test_rect_quadtree_numpy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|