fastquadtree 0.4.1__cp38-abi3-win_amd64.whl → 0.5.0__cp38-abi3-win_amd64.whl

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/_bimap.py CHANGED
@@ -80,11 +80,11 @@ class BiMap:
80
80
  """
81
81
  removed = None
82
82
  # Remove by id first
83
- if self._id_to_item.get(item.id) is item:
84
- removed = self._id_to_item.pop(item.id)
83
+ removed = self._id_to_item.pop(item.id)
84
+
85
85
  # Remove by obj side
86
86
  obj = item.obj
87
- if obj is not None and self._objid_to_item.get(id(obj)) is item:
87
+ if obj is not None:
88
88
  self._objid_to_item.pop(id(obj), None)
89
89
  removed = removed or item
90
90
  return removed
fastquadtree/_native.pyd CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Rust
@@ -37,7 +37,6 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
37
37
  [![Rust core via PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
38
38
  [![Built with maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
39
39
  [![Code style: Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
40
- [![Type checking: mypy](https://img.shields.io/badge/type%20checking-mypy-2a6db2)](http://mypy-lang.org/)
41
40
 
42
41
 
43
42
  ![Interactive_V2_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png)
@@ -49,6 +48,29 @@ Rust-optimized quadtree with a simple Python API.
49
48
  - Python ≥ 3.8
50
49
  - Import path: `from fastquadtree import QuadTree`
51
50
 
51
+ ## Benchmarks
52
+
53
+ fastquadtree **outperforms** all other quadtree Python packages, including the Rtree spatial index.
54
+
55
+ ### Library comparison
56
+
57
+ ![Total time](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_time.png)
58
+ ![Throughput](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_throughput.png)
59
+
60
+ ### Summary (largest dataset, PyQtree baseline)
61
+ - Points: **500,000**, Queries: **500**
62
+ --------------------
63
+ - Fastest total: **fastquadtree** at **1.591 s**
64
+
65
+ | Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
66
+ |---|---:|---:|---:|---:|
67
+ | fastquadtree | 0.165 | 1.427 | 1.591 | 5.09× |
68
+ | Rtree | 1.320 | 2.369 | 3.688 | 2.20× |
69
+ | PyQtree | 2.687 | 5.415 | 8.102 | 1.00× |
70
+ | nontree-QuadTree | 1.284 | 9.891 | 11.175 | 0.73× |
71
+ | quads | 2.346 | 10.129 | 12.475 | 0.65× |
72
+ | e-pyquadtree | 1.795 | 11.855 | 13.650 | 0.59× |
73
+
52
74
  ## Install
53
75
 
54
76
  ```bash
@@ -109,25 +131,7 @@ print(f"Deleted player: {deleted}") # True
109
131
 
110
132
  You can keep the tree pure and manage your own id → object map, or let the wrapper manage it.
111
133
 
112
- **Option A: Manage your own map**
113
-
114
- ```python
115
- from fastquadtree import QuadTree
116
-
117
- qt = QuadTree((0, 0, 1000, 1000), capacity=16)
118
- objects: dict[int, object] = {}
119
-
120
- def add(obj) -> int:
121
- obj_id = qt.insert(obj.position) # auto id
122
- objects[obj_id] = obj
123
- return obj_id
124
-
125
- # Later, resolve ids back to objects
126
- ids = [obj_id for (obj_id, x, y) in qt.query((100, 100, 300, 300))]
127
- selected = [objects[i] for i in ids]
128
- ```
129
-
130
- **Option B: Ask the wrapper to track objects**
134
+ **Wrapper Managed Objects**
131
135
 
132
136
  ```python
133
137
  from fastquadtree import QuadTree
@@ -137,7 +141,7 @@ qt = QuadTree((0, 0, 1000, 1000), capacity=16, track_objects=True)
137
141
  # Store the object alongside the point
138
142
  qt.insert((25, 40), obj={"name": "apple"})
139
143
 
140
- # Ask for Item objects so you can access .obj lazily
144
+ # Ask for Item objects within a bounding box
141
145
  items = qt.query((0, 0, 100, 100), as_items=True)
142
146
  for it in items:
143
147
  print(it.id, it.x, it.y, it.obj)
@@ -151,7 +155,7 @@ qt.attach(123, my_object) # binds object to id 123
151
155
 
152
156
  ## API
153
157
 
154
- ### `QuadTree(bounds, capacity, *, max_depth=None, track_objects=False, start_id=1)`
158
+ ### `QuadTree(bounds, capacity, max_depth=None, track_objects=False, start_id=1)`
155
159
 
156
160
  * `bounds` — tuple `(min_x, min_y, max_x, max_y)` defines the 2D area covered by the quadtree
157
161
  * `capacity` — max number of points kept in a leaf before splitting
@@ -204,30 +208,8 @@ Full docs are in the docstrings of the [Python Shim](pysrc/fastquadtree/__init__
204
208
  * For fastest local runs, use `maturin develop --release`.
205
209
  * The wrapper keeps Python overhead low: raw tuple results by default, `Item` wrappers only when requested.
206
210
 
207
- ## Benchmarks
208
-
209
- fastquadtree outperforms all other quadtree python packages (at least all the ones I could find and install via pip.)
210
-
211
- ### Library comparison
212
-
213
- ![Total time](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_time.png)
214
- ![Throughput](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_throughput.png)
215
-
216
- ### Summary (largest dataset, PyQtree baseline)
217
- - Points: **500,000**, Queries: **500**
218
- - Fastest total: **fastquadtree** at **2.207 s**
219
-
220
- | Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
221
- |---|---:|---:|---:|---:|
222
- | fastquadtree | 0.321 | 1.885 | 2.207 | 4.27× |
223
- | Rtree | 1.718 | 4.376 | 6.095 | 1.55× |
224
- | nontree-QuadTree | 1.617 | 7.643 | 9.260 | 1.02× |
225
- | PyQtree | 4.349 | 5.082 | 9.431 | 1.00× |
226
- | quads | 3.874 | 9.058 | 12.932 | 0.73× |
227
- | e-pyquadtree | 2.732 | 10.598 | 13.330 | 0.71× |
228
- | Brute force | 0.019 | 19.986 | 20.005 | 0.47× |
229
211
 
230
- ### Native vs Shim
212
+ ### Native vs Shim Benchmark
231
213
 
232
214
  **Setup**
233
215
  - Points: 500,000
@@ -277,7 +259,7 @@ Check the CLI arguments for the cross-library benchmark in `benchmarks/quadtree_
277
259
  Allowed. For k-nearest, duplicates are de-duplicated by id. For range queries you will see every inserted point.
278
260
 
279
261
  **Can I delete items from the quadtree?**
280
- Yes! Use `delete(id, xy)` to remove specific items. You must provide both the ID and exact location for precise deletion. This handles cases where multiple items exist at the same location. If you're using `track_objects=True`, you can also use `delete_by_object(obj, xy)` for convenient object-based deletion with O(1) lookup. The tree automatically merges nodes when item counts drop below capacity.
262
+ Yes! Use `delete(id, xy)` to remove specific items. You must provide both the ID and exact location for precise deletion. This handles cases where multiple items exist at the same location. If you're using `track_objects=True`, you can also use `delete_by_object(obj)` for convenient object-based deletion with O(1) lookup. The tree automatically merges nodes when item counts drop below capacity.
281
263
 
282
264
  **Can I store rectangles or circles?**
283
265
  The core stores points. To index objects with extent, insert whatever representative point you choose. For rectangles you can insert centers or build an AABB tree separately.
@@ -0,0 +1,10 @@
1
+ fastquadtree-0.5.0.dist-info/METADATA,sha256=7TPGeXEmmg20TEZc2Wx3gAiGMzdTuklhapwtEbn8IrQ,10119
2
+ fastquadtree-0.5.0.dist-info/WHEEL,sha256=7bfl5v0wbVhXZba613g0x-n2obNNfpQuN8I1cQ4oaU8,94
3
+ fastquadtree-0.5.0.dist-info/licenses/LICENSE,sha256=46IVFhoCIwMo-ocq4olyEB1eBvvtaKic5yGLeKXnDuc,1092
4
+ fastquadtree/__init__.py,sha256=rqttCrFBaqMjD7BDZlcwkU9eeOQh2gzRi81xKHHLwLk,12652
5
+ fastquadtree/__init__.pyi,sha256=4lKaqtnvylRzhj322ue_y_DO_xxrkzOzjpYnH5SN1Fg,2166
6
+ fastquadtree/_bimap.py,sha256=zMp20NJkvVuO3jn2OeVApf7j4siBI4r2kU6SHyb7EZE,3428
7
+ fastquadtree/_item.py,sha256=imyiwnbmY21mHsOvNqB4j-TsOPpAmsvb38LKxEL8q4o,526
8
+ fastquadtree/_native.pyd,sha256=84XbRhl0Lj2ofRahwDK4Pjw_JiXvOVHfEFGD8hHbbJ0,247808
9
+ fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ fastquadtree-0.5.0.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- fastquadtree-0.4.1.dist-info/METADATA,sha256=AilnbTzmPbAZVi-TgkxosNYrsHaeRyp3rqiWhPR7sQ0,10735
2
- fastquadtree-0.4.1.dist-info/WHEEL,sha256=7bfl5v0wbVhXZba613g0x-n2obNNfpQuN8I1cQ4oaU8,94
3
- fastquadtree-0.4.1.dist-info/licenses/LICENSE,sha256=46IVFhoCIwMo-ocq4olyEB1eBvvtaKic5yGLeKXnDuc,1092
4
- fastquadtree/__init__.py,sha256=rqttCrFBaqMjD7BDZlcwkU9eeOQh2gzRi81xKHHLwLk,12652
5
- fastquadtree/__init__.pyi,sha256=4lKaqtnvylRzhj322ue_y_DO_xxrkzOzjpYnH5SN1Fg,2166
6
- fastquadtree/_bimap.py,sha256=TWiI6ZSsF-g-agFIkgbXmoN2FRi4ksLvqtG6Zbd_gY0,3526
7
- fastquadtree/_item.py,sha256=imyiwnbmY21mHsOvNqB4j-TsOPpAmsvb38LKxEL8q4o,526
8
- fastquadtree/_native.pyd,sha256=jObtZvUYzlmgy-rs0NUWuTw_TvZDidMirwgDG4XviuY,309248
9
- fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- fastquadtree-0.4.1.dist-info/RECORD,,