fastquadtree 1.5.0__cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.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.
@@ -0,0 +1,230 @@
1
+ # rect_quadtree.py
2
+ from __future__ import annotations
3
+
4
+ from typing import Any, Literal, SupportsFloat, Tuple, overload
5
+
6
+ from ._base_quadtree import Bounds, _BaseQuadTree
7
+ from ._item import Point, RectItem
8
+ from ._native import (
9
+ RectQuadTree as RectQuadTreeF32,
10
+ RectQuadTreeF64,
11
+ RectQuadTreeI32,
12
+ RectQuadTreeI64,
13
+ )
14
+
15
+ _IdRect = Tuple[int, SupportsFloat, SupportsFloat, SupportsFloat, SupportsFloat]
16
+
17
+ DTYPE_MAP = {
18
+ "f32": RectQuadTreeF32,
19
+ "f64": RectQuadTreeF64,
20
+ "i32": RectQuadTreeI32,
21
+ "i64": RectQuadTreeI64,
22
+ }
23
+
24
+
25
+ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
26
+ """
27
+ Rectangle version of the quadtree. All geometries are axis-aligned rectangles. (min_x, min_y, max_x, max_y)
28
+ High-level Python wrapper over the Rust quadtree engine.
29
+
30
+ Performance characteristics:
31
+ Inserts: average O(log n) <br>
32
+ Rect queries: average O(log n + k) where k is matches returned <br>
33
+ Nearest neighbor: average O(log n) <br>
34
+
35
+ Thread-safety:
36
+ Instances are not thread-safe. Use external synchronization if you
37
+ mutate the same tree from multiple threads.
38
+
39
+ Args:
40
+ bounds: World bounds as (min_x, min_y, max_x, max_y).
41
+ capacity: Max number of points per node before splitting.
42
+ max_depth: Optional max tree depth. If omitted, engine decides.
43
+ track_objects: Enable id <-> object mapping inside Python.
44
+ dtype: Data type for coordinates and ids in the native engine. Default is 'f32'. Options are 'f32', 'f64', 'i32', 'i64'.
45
+
46
+ Raises:
47
+ ValueError: If parameters are invalid or inserts are out of bounds.
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ bounds: Bounds,
53
+ capacity: int,
54
+ *,
55
+ max_depth: int | None = None,
56
+ track_objects: bool = False,
57
+ dtype: str = "f32",
58
+ ):
59
+ super().__init__(
60
+ bounds,
61
+ capacity,
62
+ max_depth=max_depth,
63
+ track_objects=track_objects,
64
+ dtype=dtype,
65
+ )
66
+
67
+ @overload
68
+ def query(
69
+ self, rect: Bounds, *, as_items: Literal[False] = ...
70
+ ) -> list[_IdRect]: ...
71
+ @overload
72
+ def query(self, rect: Bounds, *, as_items: Literal[True]) -> list[RectItem]: ...
73
+ def query(
74
+ self, rect: Bounds, *, as_items: bool = False
75
+ ) -> list[_IdRect] | list[RectItem]:
76
+ """
77
+ Query the tree for all items that intersect the given rectangle.
78
+
79
+ Args:
80
+ rect: Query rectangle as (min_x, min_y, max_x, max_y).
81
+ as_items: If True, return Item wrappers. If False, return raw tuples.
82
+
83
+ Returns:
84
+ If as_items is False: list of (id, x0, y0, x1, y1) tuples.
85
+ If as_items is True: list of Item objects.
86
+
87
+ Example:
88
+ ```python
89
+ results = rqt.query((10.0, 10.0, 20.0, 20.0), as_items=True)
90
+ for item in results:
91
+ print(f"Found rect id={item.id_} at {item.geom} with obj={item.obj}")
92
+ ```
93
+ """
94
+ if not as_items:
95
+ return self._native.query(rect)
96
+ if self._store is None:
97
+ raise ValueError("Cannot return results as items with track_objects=False")
98
+ return self._store.get_many_by_ids(self._native.query_ids(rect))
99
+
100
+ def query_np(self, rect: Bounds) -> tuple[Any, Any]:
101
+ """
102
+ Return all points inside an axis-aligned rectangle as NumPy arrays.
103
+ The first array is an array of IDs, and the second is a corresponding array of rectangle coordinates.
104
+
105
+ Requirements:
106
+ NumPy must be installed to use this method.
107
+
108
+ Args:
109
+ rect: Query rectangle as (min_x, min_y, max_x, max_y).
110
+
111
+ Returns:
112
+ Tuple of (ids, locations) where:
113
+ ids: NDArray[np.uint64] with shape (N,)
114
+ locations: NDArray[np.floating] with shape (N, 4)
115
+
116
+ Example:
117
+ ```python
118
+ ids, locations = rqt.query_np((10.0, 10.0, 20.0, 20.0))
119
+ for id_, (x0, y0, x1, y1) in zip(ids, locations):
120
+ print(f"Found rect id={id_} at ({x0}, {y0}, {x1}, {y1})")
121
+ ```
122
+ """
123
+
124
+ return self._native.query_np(rect)
125
+
126
+ @overload
127
+ def nearest_neighbor(
128
+ self, xy: Point, *, as_item: Literal[False] = ...
129
+ ) -> _IdRect | None: ...
130
+ @overload
131
+ def nearest_neighbor(
132
+ self, xy: Point, *, as_item: Literal[True]
133
+ ) -> RectItem | None: ...
134
+ def nearest_neighbor(
135
+ self, xy: Point, *, as_item: bool = False
136
+ ) -> RectItem | _IdRect | None:
137
+ """
138
+ Return the single nearest neighbor to the query point.
139
+ Utilizes euclidean distance to the nearest edge of rectangles.
140
+
141
+ Args:
142
+ xy: Query point (x, y).
143
+ as_item: If True, return Item. If False, return (id, x0, y0, x1, y1).
144
+
145
+ Returns:
146
+ The nearest neighbor or None if the tree is empty.
147
+
148
+ Example:
149
+ ```python
150
+ nn = rqt.nearest_neighbor((15.0, 15.0), as_item=True)
151
+ if nn is not None:
152
+ print(f"Nearest rect id={nn.id_} at {nn.geom} with obj={nn.obj}")
153
+ else:
154
+ print("No rectangles in the tree.")
155
+ ```
156
+ """
157
+ t = self._native.nearest_neighbor(xy)
158
+ if t is None or not as_item:
159
+ return t
160
+ if self._store is None:
161
+ raise ValueError("Cannot return result as item with track_objects=False")
162
+ id_, _x0, _y0, _x1, _y1 = t
163
+ it = self._store.by_id(id_)
164
+ if it is None:
165
+ raise RuntimeError("Internal error: missing tracked item")
166
+ return it
167
+
168
+ @overload
169
+ def nearest_neighbors(
170
+ self, xy: Point, k: int, *, as_items: Literal[False] = ...
171
+ ) -> list[_IdRect]: ...
172
+ @overload
173
+ def nearest_neighbors(
174
+ self, xy: Point, k: int, *, as_items: Literal[True]
175
+ ) -> list[RectItem]: ...
176
+ def nearest_neighbors(
177
+ self, xy: Point, k: int, *, as_items: bool = False
178
+ ) -> list[RectItem] | list[_IdRect]:
179
+ """
180
+ Return the k nearest neighbors to the query point in order of increasing distance.
181
+ Utilizes euclidean distance to the nearest edge of rectangles.
182
+
183
+ Args:
184
+ xy: Query point (x, y).
185
+ k: Number of neighbors to return.
186
+ as_items: If True, return Item wrappers. If False, return raw tuples.
187
+
188
+ Returns:
189
+ If as_items is False: list of (id, x0, y0, x1, y1) tuples. <br>
190
+ If as_items is True: list of Item objects. <br>
191
+
192
+ Example:
193
+ ```python
194
+ # Gets the 3 nearest rectangles to point (15.0, 15.0)
195
+ results = rqt.nearest_neighbors((15.0, 15.0), 3, as_items=True)
196
+ for item in results:
197
+ print(f"Found rect id={item.id_} at {item.geom} with obj={item.obj}")
198
+ ```
199
+ """
200
+ raw = self._native.nearest_neighbors(xy, k)
201
+ if not as_items:
202
+ return raw
203
+ if self._store is None:
204
+ raise ValueError("Cannot return results as items with track_objects=False")
205
+ out: list[RectItem] = []
206
+ for id_, _x0, _y0, _x1, _y1 in raw:
207
+ it = self._store.by_id(id_)
208
+ if it is None:
209
+ raise RuntimeError("Internal error: missing tracked item")
210
+ out.append(it)
211
+ return out
212
+
213
+ def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
214
+ """Create the native engine instance."""
215
+ rust_cls = DTYPE_MAP.get(self._dtype)
216
+ if rust_cls is None:
217
+ raise TypeError(f"Unsupported dtype: {self._dtype}")
218
+ return rust_cls(bounds, capacity, max_depth)
219
+
220
+ @classmethod
221
+ def _new_native_from_bytes(cls, data: bytes, dtype: str = "f32") -> Any:
222
+ """Create a new native engine instance from serialized bytes."""
223
+ rust_cls = DTYPE_MAP.get(dtype)
224
+ if rust_cls is None:
225
+ raise TypeError(f"Unsupported dtype: {dtype}")
226
+ return rust_cls.from_bytes(data)
227
+
228
+ @staticmethod
229
+ def _make_item(id_: int, geom: Bounds, obj: Any | None) -> RectItem:
230
+ return RectItem(id_, geom, obj)
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastquadtree
3
+ Version: 1.5.0
4
+ Classifier: Programming Language :: Python :: 3
5
+ Classifier: Programming Language :: Python :: 3 :: Only
6
+ Classifier: Programming Language :: Rust
7
+ Classifier: Programming Language :: Python :: Implementation :: CPython
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Topic :: Scientific/Engineering
10
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
11
+ Classifier: Topic :: Software Development :: Libraries
12
+ Classifier: Typing :: Typed
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Requires-Dist: ruff>=0.6.0 ; extra == 'dev'
15
+ Requires-Dist: pytest>=8.4.2 ; extra == 'dev'
16
+ Requires-Dist: pytest-cov>=7.0.0 ; extra == 'dev'
17
+ Requires-Dist: coverage>=7.5 ; extra == 'dev'
18
+ Requires-Dist: mypy>=1.10 ; extra == 'dev'
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'
27
+ Requires-Dist: pyqtree==1.0.0 ; extra == 'dev'
28
+ Requires-Dist: numpy ; extra == 'dev'
29
+ Requires-Dist: pre-commit ; extra == 'dev'
30
+ Provides-Extra: dev
31
+ License-File: LICENSE
32
+ Summary: Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
33
+ Keywords: quadtree,spatial-index,geometry,rust,pyo3,nearest-neighbor,k-nn
34
+ Author: Ethan Anderson
35
+ Requires-Python: >=3.9
36
+ Description-Content-Type: text/markdown
37
+ Project-URL: Homepage, https://github.com/Elan456/fastquadtree
38
+ Project-URL: Repository, https://github.com/Elan456/fastquadtree
39
+ Project-URL: Documentation, https://elan456.github.io/fastquadtree/
40
+ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
41
+
42
+ # fastquadtree
43
+
44
+ <img src="https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/interactive_v2_screenshot.png"
45
+ alt="Interactive Screenshot" align="right" width="420">
46
+
47
+ Rust-optimized quadtree with a clean Python API
48
+
49
+ 👉 **Check out the Docs:** https://elan456.github.io/fastquadtree/
50
+
51
+ [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
52
+ [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
53
+ [![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)
54
+ [![Build](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml/badge.svg)](https://github.com/Elan456/fastquadtree/actions/workflows/release.yml)
55
+ ![No runtime deps](https://img.shields.io/badge/deps-none-success)
56
+
57
+ [![PyO3](https://img.shields.io/badge/Rust-core%20via%20PyO3-orange)](https://pyo3.rs/)
58
+ [![maturin](https://img.shields.io/badge/Built%20with-maturin-1f6feb)](https://www.maturin.rs/)
59
+ [![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)
60
+
61
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen)](https://elan456.github.io/fastquadtree/)
62
+ [![Wheels](https://img.shields.io/pypi/wheel/fastquadtree.svg)](https://pypi.org/project/fastquadtree/#files)
63
+ [![Coverage](https://codecov.io/gh/Elan456/fastquadtree/branch/main/graph/badge.svg)](https://codecov.io/gh/Elan456/fastquadtree)
64
+ [![License: MIT](https://img.shields.io/pypi/l/fastquadtree.svg)](LICENSE)
65
+
66
+ <br clear="right"/>
67
+
68
+ ## Why use fastquadtree
69
+
70
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with **no external dependencies** and modern typing hints
71
+ - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
72
+ - Prebuilt wheels for Windows, macOS, and Linux
73
+ - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
74
+ - Fast KNN and range queries
75
+ - Optional object tracking for id ↔ object mapping
76
+ - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
77
+ - Support for multiple data types (f32, f64, i32, i64) for coordinates
78
+ - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
79
+ - Offers a drop-in [pyqtree shim](https://elan456.github.io/fastquadtree/benchmark/#pyqtree-drop-in-shim-performance-gains) that is 6.567x faster while keeping the same API
80
+
81
+ ----
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
+ ## Install
89
+ ```bash
90
+ pip install fastquadtree
91
+ ```
92
+
93
+ ```python
94
+ from fastquadtree import QuadTree # Point handling
95
+ from fastquadtree import RectQuadTree # Bounding box handling
96
+ from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (6.567x faster while keeping the same API)
97
+ ```
98
+
99
+ ## Benchmarks
100
+
101
+ fastquadtree **outperforms** all other quadtree Python packages, including the Rtree spatial index.
102
+
103
+ ### Library comparison
104
+
105
+ ![Total time](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_time.png)
106
+ ![Throughput](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/quadtree_bench_throughput.png)
107
+
108
+ ### Summary (largest dataset, PyQtree baseline)
109
+ - Points: **250,000**, Queries: **500**
110
+ - Fastest total: **fastquadtree** at **0.030 s**
111
+
112
+ | Library | Build (s) | Query (s) | Total (s) | Speed vs PyQtree |
113
+ |---|---:|---:|---:|---:|
114
+ | fastquadtree | 0.023 | 0.007 | 0.030 | 41.31× |
115
+ | Shapely STRtree | 0.094 | 0.049 | 0.143 | 8.67× |
116
+ | nontree-QuadTree | 0.448 | 0.475 | 0.924 | 1.34× |
117
+ | Rtree | 0.801 | 0.225 | 1.025 | 1.21× |
118
+ | e-pyquadtree | 0.666 | 0.451 | 1.117 | 1.11× |
119
+ | PyQtree | 1.066 | 0.175 | 1.241 | 1.00× |
120
+ | quads | 0.969 | 0.330 | 1.299 | 0.96× |
121
+
122
+ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) for details, including configurations, system info, and native vs shim benchmarks.
123
+
124
+ ## Quickstart
125
+ [See the quickstart guide](https://elan456.github.io/fastquadtree/quickstart/)
126
+
127
+ ## API
128
+
129
+ [See the full API](https://elan456.github.io/fastquadtree/api/quadtree/)
130
+
131
+ ### `QuadTree(bounds, capacity, max_depth=None, track_objects=False, start_id=1)`
132
+
133
+ * `bounds` — tuple `(min_x, min_y, max_x, max_y)` defines the 2D area covered by the quadtree
134
+ * `capacity` — max number of points kept in a leaf before splitting
135
+ * `max_depth` — optional depth cap. If omitted, the tree can keep splitting as needed
136
+ * `track_objects` — if `True`, the wrapper maintains an id → object map for convenience.
137
+ * `start_id` — starting value for auto-assigned ids
138
+
139
+ ### Key Methods
140
+
141
+ - `insert(xy, *, id=None, obj=None) -> int`
142
+
143
+ - `query(rect, *, as_items=False) -> list`
144
+
145
+ - `nearest_neighbor(xy, *, as_item=False) -> (id, x, y) | Item | None`
146
+
147
+ - `delete(id, xy) -> bool`
148
+
149
+ There are more methods and object tracking versions in the [docs](https://elan456.github.io/fastquadtree/api/quadtree/).
150
+
151
+ ### Geometric conventions
152
+
153
+ * Rectangles are `(min_x, min_y, max_x, max_y)`.
154
+ * Containment rule is closed on the min edge and open on the max edge
155
+ `(x >= min_x and x < max_x and y >= min_y and y < max_y)`.
156
+ This only matters for points exactly on edges.
157
+
158
+ ## Performance tips
159
+
160
+ * Choose `capacity` so that leaves keep a small batch of points. Typical values are 8 to 64.
161
+ * If your data is very skewed, set a `max_depth` to prevent long chains.
162
+ * For fastest local runs, use `maturin develop --release`.
163
+ * 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.
164
+ * Refer to the [Native vs Shim Benchmark](https://elan456.github.io/fastquadtree/benchmark/#native-vs-shim-benchmark) for overhead details.
165
+
166
+ ### Pygame Ball Pit Demo
167
+
168
+ ![Ballpit_Demo_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/ballpit.png)
169
+
170
+ A simple demo of moving objects with collision detection using **fastquadtree**.
171
+ You can toggle between quadtree mode and brute-force mode to see the performance difference.
172
+
173
+ See the [runnables guide](https://elan456.github.io/fastquadtree/runnables/) for setup instructions.
174
+
175
+ ## FAQ
176
+
177
+ **Can I delete items from the quadtree?**
178
+ 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.
179
+
180
+ **Can I store rectangles or circles?**
181
+ 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.
182
+
183
+ **Do I need NumPy installed?**
184
+ No, NumPy is a fully optional dependency. If you do have NumPy installed, you can use methods such as `query_np` and the NumPy array variant of `insert_many` for better performance. The Rust core is able to handle NumPy arrays faster than Python lists, so there's a lot of time savings in utilizing the NumPy functions. See the [Native vs Shim benchmark](https://elan456.github.io/fastquadtree/benchmark/#native-vs-shim) for details on how returing NumPy arrays can speed up queries.
185
+
186
+ **Does fastquadtree support multiprocessing?**
187
+ Yes, fastquadtree objects can be serialized to bytes using the `to_bytes()` method and deserialized back using `from_bytes()`. This allows you to share quadtree data across processes and even cache prebuilt trees to disk. See the [interactive v2 demo](https://github.com/Elan456/fastquadtree/blob/main/interactive/interactive_v2.py) for an example of saving and loading a quadtree.
188
+
189
+ ## License
190
+
191
+ MIT. See `LICENSE`.
192
+
193
+ ## Acknowledgments
194
+
195
+ * Python libraries compared: [PyQtree], [e-pyquadtree], [Rtree], [nontree], [quads], [Shapely]
196
+ * Built with [PyO3] and [maturin]
197
+
198
+ [PyQtree]: https://pypi.org/project/pyqtree/
199
+ [e-pyquadtree]: https://pypi.org/project/e-pyquadtree/
200
+ [PyO3]: https://pyo3.rs/
201
+ [maturin]: https://www.maturin.rs/
202
+ [Rtree]: https://pypi.org/project/Rtree/
203
+ [nontree]: https://pypi.org/project/nontree/
204
+ [quads]: https://pypi.org/project/quads/
205
+ [Shapely]: https://pypi.org/project/Shapely/
206
+
@@ -0,0 +1,13 @@
1
+ fastquadtree-1.5.0.dist-info/METADATA,sha256=F-qLCl6F_1h7um_sHBLFUvY8EzVgiVgq774oe6Sd8JU,10526
2
+ fastquadtree-1.5.0.dist-info/WHEEL,sha256=fqFHtOCr25M-h-Mnj-0-ZSwuoI9vJMsUUAJdvV4MPAM,145
3
+ fastquadtree-1.5.0.dist-info/licenses/LICENSE,sha256=pRuvcuqIMtEUBMgvP1Bc4fOHydzeuA61c6DQoQ1pb1w,1071
4
+ fastquadtree/__init__.py,sha256=rtkveNz7rScRasTRGu1yEqzeoJfLfreJNxg21orPL-U,195
5
+ fastquadtree/_base_quadtree.py,sha256=lnblGEYIIlB34rssfdRcfCdc0FI_tL7E8x0dbqhfPgI,17380
6
+ fastquadtree/_item.py,sha256=0ioI1mm-TUPzuAV8Y6t35IOV-R_pSiSMqQDyWAjb4zU,2468
7
+ fastquadtree/_native.abi3.so,sha256=a7aFvTIJcrzDDtT7Fu33FjPfvilo-uSYdkKhtm-ycc0,796648
8
+ fastquadtree/_obj_store.py,sha256=tY8siqTCjr1JK3rigtljDVVYbQmPDRs1m8iUCCBHMO0,6337
9
+ fastquadtree/point_quadtree.py,sha256=-3G_JgbyH8mFRV0bTFygI1mpb3F09v2gr1vqTm4hdUA,7167
10
+ fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fastquadtree/pyqtree.py,sha256=iAWAajViag4yTfiRXcGPha8bnNJOLRU7O9jdkjUeJKU,6450
12
+ fastquadtree/rect_quadtree.py,sha256=kTxMH7hQU5c4ocGkzLqd9w35IrUdbnkm1Hec1xjbyV8,8139
13
+ fastquadtree-1.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp38-abi3-manylinux_2_17_aarch64
5
+ Tag: cp38-abi3-manylinux2014_aarch64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ethan Anderson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.