fastquadtree 0.6.1__cp38-abi3-win_amd64.whl → 0.8.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 0.6.1
3
+ Version: 0.8.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Rust
@@ -12,11 +12,18 @@ Classifier: Topic :: Software Development :: Libraries
12
12
  Classifier: Typing :: Typed
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Requires-Dist: ruff>=0.6.0 ; extra == 'dev'
15
- Requires-Dist: pytest>=7.0 ; extra == 'dev'
16
- Requires-Dist: pytest-cov>=4.1 ; extra == 'dev'
15
+ Requires-Dist: pytest>=8.4.2 ; extra == 'dev'
16
+ Requires-Dist: pytest-cov>=7.0.0 ; extra == 'dev'
17
17
  Requires-Dist: coverage>=7.5 ; extra == 'dev'
18
18
  Requires-Dist: mypy>=1.10 ; extra == 'dev'
19
19
  Requires-Dist: build>=1.2.1 ; extra == 'dev'
20
+ Requires-Dist: mkdocs>=1.6 ; extra == 'dev'
21
+ Requires-Dist: mkdocs-material ; extra == 'dev'
22
+ Requires-Dist: mkdocstrings[python] ; extra == 'dev'
23
+ Requires-Dist: mkdocs-autorefs ; extra == 'dev'
24
+ Requires-Dist: mkdocs-git-revision-date-localized-plugin ; extra == 'dev'
25
+ Requires-Dist: mkdocs-minify-plugin ; extra == 'dev'
26
+ Requires-Dist: maturin>=1.5 ; extra == 'dev'
20
27
  Provides-Extra: dev
21
28
  License-File: LICENSE
22
29
  Summary: Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
@@ -26,10 +33,12 @@ Requires-Python: >=3.8
26
33
  Description-Content-Type: text/markdown
27
34
  Project-URL: Homepage, https://github.com/Elan456/fastquadtree
28
35
  Project-URL: Repository, https://github.com/Elan456/fastquadtree
36
+ Project-URL: Documentation, https://elan456.github.io/fastquadtree/
29
37
  Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
30
38
 
31
39
  # fastquadtree
32
40
 
41
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
33
42
  [![PyPI version](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
34
43
  [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
35
44
  [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
@@ -37,7 +46,7 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
37
46
 
38
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)
39
48
 
40
- [![Build](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml/badge.svg)](https://github.com/Elan456/fastquadtree/actions/workflows/ci.yml)
49
+ [![Build](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml/badge.svg)](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml)
41
50
  [![Codecov](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
42
51
 
43
52
  [![Rust core via PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
@@ -51,6 +60,8 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
51
60
 
52
61
  Rust-optimized quadtree with a simple Python API.
53
62
 
63
+ 👉 **Docs:** https://elan456.github.io/fastquadtree/
64
+
54
65
  - Python package: **`fastquadtree`**
55
66
  - Python ≥ 3.8
56
67
  - Import path: `from fastquadtree import QuadTree`
@@ -66,7 +77,6 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
66
77
 
67
78
  ### Summary (largest dataset, PyQtree baseline)
68
79
  - Points: **250,000**, Queries: **500**
69
- --------------------
70
80
  - Fastest total: **fastquadtree** at **0.120 s**
71
81
 
72
82
  | Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
@@ -79,7 +89,7 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
79
89
  | PyQtree | 1.492 | 0.263 | 1.755 | 1.00× |
80
90
  | quads | 1.407 | 0.484 | 1.890 | 0.93× |
81
91
 
82
- #### Benchmark Configuration
92
+ ### Benchmark Configuration
83
93
  | Parameter | Value |
84
94
  |---|---:|
85
95
  | Bounds | (0, 0, 1000, 1000) |
@@ -87,11 +97,13 @@ fastquadtree **outperforms** all other quadtree Python packages, including the R
87
97
  | Max depth | 16 |
88
98
  | Queries per experiment | 500 |
89
99
 
100
+ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details.
101
+
90
102
  ## Install
91
103
 
92
104
  ```bash
93
105
  pip install fastquadtree
94
- ````
106
+ ```
95
107
 
96
108
  If you are developing locally:
97
109
 
@@ -101,76 +113,12 @@ maturin develop --release
101
113
  ```
102
114
 
103
115
  ## Quickstart
104
-
105
- ```python
106
- from fastquadtree import QuadTree
107
-
108
- # Bounds are (min_x, min_y, max_x, max_y)
109
- qt = QuadTree(bounds=(0, 0, 1000, 1000), capacity=20) # max_depth is optional
110
-
111
- # Insert points with auto ids
112
- id1 = qt.insert((10, 10))
113
- id2 = qt.insert((200, 300))
114
- id3 = qt.insert((999, 500), id=42) # you can supply your own id
115
-
116
- # Axis-aligned rectangle query
117
- hits = qt.query((0, 0, 250, 350)) # returns [(id, x, y), ...] by default
118
- print(hits) # e.g. [(1, 10.0, 10.0), (2, 200.0, 300.0)]
119
-
120
- # Nearest neighbor
121
- best = qt.nearest_neighbor((210, 310)) # -> (id, x, y) or None
122
- print(best)
123
-
124
- # k-nearest neighbors
125
- top3 = qt.nearest_neighbors((210, 310), 3)
126
- print(top3) # list of up to 3 (id, x, y) tuples
127
-
128
- # Delete items by ID and location
129
- deleted = qt.delete(id2, (200, 300)) # True if found and deleted
130
- print(f"Deleted: {deleted}")
131
- print(f"Remaining items: {qt.count_items()}")
132
-
133
- # For object tracking with track_objects=True
134
- qt_tracked = QuadTree((0, 0, 1000, 1000), capacity=4, track_objects=True)
135
- player1 = {"name": "Alice", "score": 100}
136
- player2 = {"name": "Bob", "score": 200}
137
-
138
- id1 = qt_tracked.insert((50, 50), obj=player1)
139
- id2 = qt_tracked.insert((150, 150), obj=player2)
140
-
141
- # Delete by object reference (O(1) lookup!)
142
- deleted = qt_tracked.delete_by_object(player1)
143
- print(f"Deleted player: {deleted}") # True
144
- ```
145
-
146
- ### Working with Python objects
147
-
148
- You can keep the tree pure and manage your own id → object map, or let the wrapper manage it.
149
-
150
- **Wrapper Managed Objects**
151
-
152
- ```python
153
- from fastquadtree import QuadTree
154
-
155
- qt = QuadTree((0, 0, 1000, 1000), capacity=16, track_objects=True)
156
-
157
- # Store the object alongside the point
158
- qt.insert((25, 40), obj={"name": "apple"})
159
-
160
- # Ask for Item objects within a bounding box
161
- items = qt.query((0, 0, 100, 100), as_items=True)
162
- for it in items:
163
- print(it.id, it.x, it.y, it.obj)
164
- ```
165
-
166
- You can also attach or replace an object later:
167
-
168
- ```python
169
- qt.attach(123, my_object) # binds object to id 123
170
- ```
116
+ [See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
171
117
 
172
118
  ## API
173
119
 
120
+ [See the full API](https://elan456.github.io/fastquadtree/api/quadtree/)
121
+
174
122
  ### `QuadTree(bounds, capacity, max_depth=None, track_objects=False, start_id=1)`
175
123
 
176
124
  * `bounds` — tuple `(min_x, min_y, max_x, max_y)` defines the 2D area covered by the quadtree
@@ -179,36 +127,17 @@ qt.attach(123, my_object) # binds object to id 123
179
127
  * `track_objects` — if `True`, the wrapper maintains an id → object map for convenience.
180
128
  * `start_id` — starting value for auto-assigned ids
181
129
 
182
- ### Core Methods
183
-
184
- Full docs are in the docstrings of the [Python Shim](pysrc/fastquadtree/__init__.py)
130
+ ### Key Methods
185
131
 
186
132
  - `insert(xy, *, id=None, obj=None) -> int`
187
133
 
188
- - `insert_many_points(points) -> int`
189
-
190
134
  - `query(rect, *, as_items=False) -> list`
191
135
 
192
136
  - `nearest_neighbor(xy, *, as_item=False) -> (id, x, y) | Item | None`
193
137
 
194
- - `nearest_neighbors(xy, k, *, as_items=False) -> list`
195
-
196
138
  - `delete(id, xy) -> bool`
197
139
 
198
- - `delete_by_object(obj) -> bool (requires track_objects=True)`
199
-
200
- - `attach(id, obj) -> None (requires track_objects=True)`
201
-
202
- - `count_items() -> int`
203
-
204
- - `get(id) -> object | None`
205
-
206
- - `get_all_rectangles() -> list[tuple] (for visualization)`
207
-
208
- ### `Item` (returned when `as_items=True`)
209
-
210
- * Attributes: `id`, `x`, `y`, and a lazy `obj` property
211
- * Accessing `obj` performs a dictionary lookup only if tracking is enabled
140
+ There are more methods and object tracking versions in the [docs](https://elan456.github.io/fastquadtree/api/quadtree/).
212
141
 
213
142
  ### Geometric conventions
214
143
 
@@ -222,52 +151,17 @@ Full docs are in the docstrings of the [Python Shim](pysrc/fastquadtree/__init__
222
151
  * Choose `capacity` so that leaves keep a small batch of points. Typical values are 8 to 64.
223
152
  * If your data is very skewed, set a `max_depth` to prevent long chains.
224
153
  * For fastest local runs, use `maturin develop --release`.
225
- * The wrapper keeps Python overhead low: raw tuple results by default, `Item` wrappers only when requested.
226
-
227
-
228
- ### Native vs Shim Benchmark
229
-
230
- **Setup**
231
- - Points: 500,000
232
- - Queries: 500
233
- - Repeats: 5
234
-
235
- **Timing (seconds)**
154
+ * The wrapper maintains an object map only if the quadtree was constructed with `track_objects=True`. If you don't need it, leave it off for best performance.
155
+ * Refer to the [Native vs Shim Benchmark](https://elan456.github.io/fastquadtree/benchmark/#native-vs-shim-benchmark) for overhead details.
236
156
 
237
- | Variant | Build | Query | Total |
238
- |---|---:|---:|---:|
239
- | Native | 0.483 | 4.380 | 4.863 |
240
- | Shim (no map) | 0.668 | 4.167 | 4.835 |
241
- | Shim (track+objs) | 1.153 | 4.458 | 5.610 |
157
+ ### Pygame Ball Pit Demo
242
158
 
243
- **Overhead vs Native**
159
+ ![Ballpit_Demo_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/ballpit.png)
244
160
 
245
- - No map: build 1.38x, query 0.95x, total 0.99x
246
- - Track + objs: build 2.39x, query 1.02x, total 1.15x
161
+ A simple demo of moving objects with collision detection using **fastquadtree**.
162
+ You can toggle between quadtree mode and brute-force mode to see the performance difference.
247
163
 
248
- ### Run benchmarks
249
- To run the benchmarks yourself, first install the dependencies:
250
-
251
- ```bash
252
- pip install -r benchmarks/requirements.txt
253
- ```
254
-
255
- Then run:
256
-
257
- ```bash
258
- python benchmarks/cross_library_bench.py
259
- python benchmarks/benchmark_native_vs_shim.py
260
- ```
261
-
262
- ## Run Visualizer
263
- A visualizer is included to help you understand how the quadtree subdivides space.
264
-
265
- ```bash
266
- pip install -r interactive/requirements.txt
267
- python interactive/interactive_v2.py
268
- ```
269
-
270
- Check the CLI arguments for the cross-library benchmark in `benchmarks/quadtree_bench/main.py`.
164
+ See the [runnables guide](https://elan456.github.io/fastquadtree/runnables/) for setup instructions.
271
165
 
272
166
  ## FAQ
273
167
 
@@ -278,10 +172,7 @@ Allowed. For k-nearest, duplicates are de-duplicated by id. For range queries yo
278
172
  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.
279
173
 
280
174
  **Can I store rectangles or circles?**
281
- 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.
282
-
283
- **Threading**
284
- Use one tree per thread if you need heavy parallel inserts from Python.
175
+ Yes, you can store rectangles using the `RectQuadTree` class. Circles can be approximated with bounding boxes. See the [RectQuadTree docs](https://elan456.github.io/fastquadtree/api/rect_quadtree/) for details.
285
176
 
286
177
  ## License
287
178
 
@@ -0,0 +1,12 @@
1
+ fastquadtree-0.8.0.dist-info/METADATA,sha256=CK8OPp9c36mESYvCPafheE8Rdt9oVbtuJOoDJjvXiRw,8632
2
+ fastquadtree-0.8.0.dist-info/WHEEL,sha256=CG8OzNtm0LMpJ2zhrjswlO8N-965OeMLklsQAG-nMvQ,94
3
+ fastquadtree-0.8.0.dist-info/licenses/LICENSE,sha256=46IVFhoCIwMo-ocq4olyEB1eBvvtaKic5yGLeKXnDuc,1092
4
+ fastquadtree/__init__.py,sha256=jy7uimnd7QDllmNOgnRByKom1aONIKOWhCvCJxndsnM,200
5
+ fastquadtree/_base_quadtree.py,sha256=sfHAvKsWbrBX6RSUNi32Lh0fxCu8D6hAnyp1-SJj0Ok,8676
6
+ fastquadtree/_bimap.py,sha256=oNvJOk-BjYLo6aNJnG0i3uEQCq8FsUTGRE6c6_kVC2c,3439
7
+ fastquadtree/_item.py,sha256=cXiKXCjCfOWK19LUbxnzvAx6xffejd3F1axxYR9SMeM,1400
8
+ fastquadtree/_native.pyd,sha256=wr7KjDtXszGOlm8GvAkKjeZugzOq_o23lbqV-D8_6Ko,271360
9
+ fastquadtree/point_quadtree.py,sha256=Xs2Igat4ekewnMd2wHVYu0pm7f7duvLdEcm_DUrO2B4,5744
10
+ fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fastquadtree/rect_quadtree.py,sha256=_t3RVZYSSxZatGCtv4G9Cokn6mJ8BMDsmWHAo7fsAaE,3569
12
+ fastquadtree-0.8.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.9.5)
2
+ Generator: maturin (1.9.6)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp38-abi3-win_amd64
fastquadtree/__init__.pyi DELETED
@@ -1,70 +0,0 @@
1
- from typing import (
2
- Any,
3
- Iterable,
4
- Literal as _Literal, # avoid polluting public namespace
5
- overload,
6
- )
7
-
8
- Bounds = tuple[float, float, float, float]
9
- Point = tuple[float, float]
10
-
11
- class Item:
12
- id_: int
13
- x: float
14
- y: float
15
- obj: Any | None
16
-
17
- class QuadTree:
18
- # Expose the raw native class for power users
19
- NativeQuadTree: type
20
-
21
- def __init__(
22
- self,
23
- bounds: Bounds,
24
- capacity: int,
25
- *,
26
- max_depth: int | None = None,
27
- track_objects: bool = False,
28
- start_id: int = 1,
29
- ) -> None: ...
30
-
31
- # Inserts
32
- def insert(self, xy: Point, *, id_: int | None = ..., obj: Any = ...) -> int: ...
33
- def insert_many_points(self, points: Iterable[Point]) -> int: ...
34
- def attach(self, id_: int, obj: Any) -> None: ...
35
-
36
- # Deletions
37
- def delete(self, id_: int, xy: Point) -> bool: ...
38
- def delete_by_object(self, obj: Any) -> bool: ...
39
-
40
- # Queries
41
- @overload
42
- def query(
43
- self, rect: Bounds, *, as_items: _Literal[False] = ...
44
- ) -> list[tuple[int, float, float]]: ...
45
- @overload
46
- def query(self, rect: Bounds, *, as_items: _Literal[True]) -> list[Item]: ...
47
- @overload
48
- def nearest_neighbor(
49
- self, xy: Point, *, as_item: _Literal[False] = ...
50
- ) -> tuple[int, float, float] | None: ...
51
- @overload
52
- def nearest_neighbor(
53
- self, xy: Point, *, as_item: _Literal[True]
54
- ) -> Item | None: ...
55
- @overload
56
- def nearest_neighbors(
57
- self, xy: Point, k: int, *, as_items: _Literal[False] = ...
58
- ) -> list[tuple[int, float, float]]: ...
59
- @overload
60
- def nearest_neighbors(
61
- self, xy: Point, k: int, *, as_items: _Literal[True]
62
- ) -> list[Item]: ...
63
-
64
- # Misc
65
- def get(self, id_: int) -> Any | None: ...
66
- def get_all_rectangles(self) -> list[Bounds]: ...
67
- def get_all_objects(self) -> list[Any]: ...
68
- def get_all_items(self) -> list[Item]: ...
69
- def count_items(self) -> int: ...
70
- def __len__(self) -> int: ...
@@ -1,10 +0,0 @@
1
- fastquadtree-0.6.1.dist-info/METADATA,sha256=H8lkeuXlgH2BCxZSzEvFAKnLANM4H52NG78hT7AObUk,10746
2
- fastquadtree-0.6.1.dist-info/WHEEL,sha256=F7HFsRl56IeLjGhxiHeG3IpurHNaGNHQJeIy7gdwTO4,94
3
- fastquadtree-0.6.1.dist-info/licenses/LICENSE,sha256=46IVFhoCIwMo-ocq4olyEB1eBvvtaKic5yGLeKXnDuc,1092
4
- fastquadtree/__init__.py,sha256=o7zH6lOu2lTxMafl9FNVZiecM0KVxqhC3FNSRbpaaqY,12435
5
- fastquadtree/__init__.pyi,sha256=_HGJ9lpIZ9-JTSfMKSn8aif_tu60m2vgOXR4d0uXnRY,2062
6
- fastquadtree/_bimap.py,sha256=SPFFw9hWAVRKZVXyDGYFFNw4MLV8qUlOq8gDbLcTqkg,3402
7
- fastquadtree/_item.py,sha256=p-ymnE9S-c8Lc00KhNKN9Pt4bd05nZ6g-DB8q8D9zYk,533
8
- fastquadtree/_native.pyd,sha256=OHlc3FG-kZbjt2YW2QM9I809C1FRQlV6RQXcPcQLNhM,254464
9
- fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- fastquadtree-0.6.1.dist-info/RECORD,,