fastquadtree 1.1.2__cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl → 1.2.1__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.
Potentially problematic release.
This version of fastquadtree might be problematic. Click here for more details.
- fastquadtree/_base_quadtree.py +180 -1
- fastquadtree/_item.py +29 -0
- fastquadtree/_native.abi3.so +0 -0
- fastquadtree/_obj_store.py +39 -5
- fastquadtree/point_quadtree.py +26 -1
- fastquadtree/rect_quadtree.py +26 -1
- {fastquadtree-1.1.2.dist-info → fastquadtree-1.2.1.dist-info}/METADATA +2 -1
- fastquadtree-1.2.1.dist-info/RECORD +13 -0
- fastquadtree-1.1.2.dist-info/RECORD +0 -13
- {fastquadtree-1.1.2.dist-info → fastquadtree-1.2.1.dist-info}/WHEEL +0 -0
- {fastquadtree-1.1.2.dist-info → fastquadtree-1.2.1.dist-info}/licenses/LICENSE +0 -0
fastquadtree/_base_quadtree.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# _abc_quadtree.py
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
import pickle
|
|
4
5
|
from abc import ABC, abstractmethod
|
|
5
6
|
from typing import (
|
|
6
7
|
TYPE_CHECKING,
|
|
@@ -58,8 +59,9 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
58
59
|
def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
|
|
59
60
|
"""Create the native engine instance."""
|
|
60
61
|
|
|
62
|
+
@staticmethod
|
|
61
63
|
@abstractmethod
|
|
62
|
-
def _make_item(
|
|
64
|
+
def _make_item(id_: int, geom: G, obj: Any | None) -> ItemType:
|
|
63
65
|
"""Build an ItemType from id, geometry, and optional object."""
|
|
64
66
|
|
|
65
67
|
# ---- ctor ----
|
|
@@ -84,6 +86,91 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
84
86
|
self._next_id = 0
|
|
85
87
|
self._count = 0
|
|
86
88
|
|
|
89
|
+
# ---- serialization ----
|
|
90
|
+
|
|
91
|
+
def to_dict(self) -> dict[str, Any]:
|
|
92
|
+
"""
|
|
93
|
+
Serialize the quadtree to a dict suitable for JSON or other serialization.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Includes a binary 'core' key for the native engine state, plus other metadata such as bounds and capacity and the obj store if tracking is enabled.
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
```python
|
|
100
|
+
state = qt.to_dict()
|
|
101
|
+
assert "core" in state and "bounds" in state
|
|
102
|
+
```
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
core_bytes = self._native.to_bytes()
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"core": core_bytes,
|
|
109
|
+
"store": self._store.to_dict() if self._store is not None else None,
|
|
110
|
+
"bounds": self._bounds,
|
|
111
|
+
"capacity": self._capacity,
|
|
112
|
+
"max_depth": self._max_depth,
|
|
113
|
+
"track_objects": self._track_objects,
|
|
114
|
+
"next_id": self._next_id,
|
|
115
|
+
"count": self._count,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
def to_bytes(self) -> bytes:
|
|
119
|
+
"""
|
|
120
|
+
Serialize the quadtree to bytes.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Bytes representing the serialized quadtree. Can be saved as a file or loaded with `from_bytes()`.
|
|
124
|
+
|
|
125
|
+
Example:
|
|
126
|
+
```python
|
|
127
|
+
blob = qt.to_bytes()
|
|
128
|
+
with open("tree.fqt", "wb") as f:
|
|
129
|
+
f.write(blob)
|
|
130
|
+
```
|
|
131
|
+
"""
|
|
132
|
+
return pickle.dumps(self.to_dict())
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def from_bytes(cls, data: bytes) -> _BaseQuadTree[G, HitT, ItemType]:
|
|
136
|
+
"""
|
|
137
|
+
Deserialize a quadtree from bytes.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
data: Bytes representing the serialized quadtree from `to_bytes()`.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
A new quadtree instance with the same state as when serialized.
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
```python
|
|
147
|
+
blob = qt.to_bytes()
|
|
148
|
+
qt2 = type(qt).from_bytes(blob)
|
|
149
|
+
assert qt2.count_items() == qt.count_items()
|
|
150
|
+
```
|
|
151
|
+
"""
|
|
152
|
+
in_dict = pickle.loads(data)
|
|
153
|
+
core_bytes = in_dict["core"]
|
|
154
|
+
store_dict = in_dict["store"]
|
|
155
|
+
|
|
156
|
+
qt = cls.__new__(cls) # type: ignore[call-arg]
|
|
157
|
+
qt._native = cls._new_native_from_bytes(core_bytes)
|
|
158
|
+
|
|
159
|
+
if store_dict is not None:
|
|
160
|
+
qt._store = ObjStore.from_dict(store_dict, qt._make_item)
|
|
161
|
+
else:
|
|
162
|
+
qt._store = None
|
|
163
|
+
|
|
164
|
+
# Extract bounds, capacity, max_depth from native
|
|
165
|
+
qt._bounds = in_dict["bounds"]
|
|
166
|
+
qt._capacity = in_dict["capacity"]
|
|
167
|
+
qt._max_depth = in_dict["max_depth"]
|
|
168
|
+
qt._next_id = in_dict["next_id"]
|
|
169
|
+
qt._count = in_dict["count"]
|
|
170
|
+
qt._track_objects = in_dict["track_objects"]
|
|
171
|
+
|
|
172
|
+
return qt
|
|
173
|
+
|
|
87
174
|
# ---- internal helper ----
|
|
88
175
|
|
|
89
176
|
def _ids_to_objects(self, ids: Iterable[int]) -> list[Any]:
|
|
@@ -107,6 +194,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
107
194
|
|
|
108
195
|
Raises:
|
|
109
196
|
ValueError: If geometry is outside the tree bounds.
|
|
197
|
+
|
|
198
|
+
Example:
|
|
199
|
+
```python
|
|
200
|
+
id0 = point_qt.insert((10.0, 20.0)) # for point trees
|
|
201
|
+
id1 = rect_qt.insert((0.0, 0.0, 5.0, 5.0), obj="box") # for rect trees
|
|
202
|
+
assert isinstance(id0, int) and isinstance(id1, int)
|
|
203
|
+
```
|
|
110
204
|
"""
|
|
111
205
|
if self._store is not None:
|
|
112
206
|
# Reuse a dense free slot if available, else append
|
|
@@ -152,6 +246,17 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
152
246
|
|
|
153
247
|
Raises:
|
|
154
248
|
ValueError: If any geometry is outside bounds.
|
|
249
|
+
|
|
250
|
+
Example:
|
|
251
|
+
```python
|
|
252
|
+
n = qt.insert_many([(1.0, 1.0), (2.0, 2.0)])
|
|
253
|
+
assert n == 2
|
|
254
|
+
|
|
255
|
+
import numpy as np
|
|
256
|
+
arr = np.array([[3.0, 3.0], [4.0, 4.0]], dtype=np.float32)
|
|
257
|
+
n2 = qt.insert_many(arr)
|
|
258
|
+
assert n2 == 2
|
|
259
|
+
```
|
|
155
260
|
"""
|
|
156
261
|
if type(geoms) is list and len(geoms) == 0:
|
|
157
262
|
return 0
|
|
@@ -216,8 +321,19 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
216
321
|
"""
|
|
217
322
|
Delete an item by id and exact geometry.
|
|
218
323
|
|
|
324
|
+
Args:
|
|
325
|
+
id_: The id of the item to delete.
|
|
326
|
+
geom: The geometry of the item to delete.
|
|
327
|
+
|
|
219
328
|
Returns:
|
|
220
329
|
True if the item was found and deleted.
|
|
330
|
+
|
|
331
|
+
Example:
|
|
332
|
+
```python
|
|
333
|
+
i = qt.insert((1.0, 2.0))
|
|
334
|
+
ok = qt.delete(i, (1.0, 2.0))
|
|
335
|
+
assert ok is True
|
|
336
|
+
```
|
|
221
337
|
"""
|
|
222
338
|
deleted = self._native.delete(id_, geom)
|
|
223
339
|
if deleted:
|
|
@@ -230,6 +346,17 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
230
346
|
"""
|
|
231
347
|
Attach or replace the Python object for an existing id.
|
|
232
348
|
Tracking must be enabled.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
id_: The id of the item to attach the object to.
|
|
352
|
+
obj: The Python object to attach.
|
|
353
|
+
|
|
354
|
+
Example:
|
|
355
|
+
```python
|
|
356
|
+
i = qt.insert((2.0, 3.0), obj=None)
|
|
357
|
+
qt.attach(i, {"meta": 123})
|
|
358
|
+
assert qt.get(i) == {"meta": 123}
|
|
359
|
+
```
|
|
233
360
|
"""
|
|
234
361
|
if self._store is None:
|
|
235
362
|
raise ValueError("Cannot attach objects when track_objects=False")
|
|
@@ -242,6 +369,16 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
242
369
|
def delete_by_object(self, obj: Any) -> bool:
|
|
243
370
|
"""
|
|
244
371
|
Delete an item by Python object identity. Tracking must be enabled.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
obj: The Python object to delete.
|
|
375
|
+
|
|
376
|
+
Example:
|
|
377
|
+
```python
|
|
378
|
+
i = qt.insert((3.0, 4.0), obj="tag")
|
|
379
|
+
ok = qt.delete_by_object("tag")
|
|
380
|
+
assert ok is True
|
|
381
|
+
```
|
|
245
382
|
"""
|
|
246
383
|
if self._store is None:
|
|
247
384
|
raise ValueError("Cannot delete by object when track_objects=False")
|
|
@@ -256,6 +393,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
256
393
|
|
|
257
394
|
If tracking is enabled, the id -> object mapping is also cleared.
|
|
258
395
|
The ids are reset to start at zero again.
|
|
396
|
+
|
|
397
|
+
Example:
|
|
398
|
+
```python
|
|
399
|
+
_ = qt.insert((5.0, 6.0))
|
|
400
|
+
qt.clear()
|
|
401
|
+
assert qt.count_items() == 0 and len(qt) == 0
|
|
402
|
+
```
|
|
259
403
|
"""
|
|
260
404
|
self._native = self._new_native(self._bounds, self._capacity, self._max_depth)
|
|
261
405
|
self._count = 0
|
|
@@ -266,6 +410,14 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
266
410
|
def get_all_objects(self) -> list[Any]:
|
|
267
411
|
"""
|
|
268
412
|
Return all tracked Python objects in the tree.
|
|
413
|
+
|
|
414
|
+
Example:
|
|
415
|
+
```python
|
|
416
|
+
_ = qt.insert((7.0, 8.0), obj="a")
|
|
417
|
+
_ = qt.insert((9.0, 1.0), obj="b")
|
|
418
|
+
objs = qt.get_all_objects()
|
|
419
|
+
assert set(objs) == {"a", "b"}
|
|
420
|
+
```
|
|
269
421
|
"""
|
|
270
422
|
if self._store is None:
|
|
271
423
|
raise ValueError("Cannot get objects when track_objects=False")
|
|
@@ -274,6 +426,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
274
426
|
def get_all_items(self) -> list[ItemType]:
|
|
275
427
|
"""
|
|
276
428
|
Return all Item wrappers in the tree.
|
|
429
|
+
|
|
430
|
+
Example:
|
|
431
|
+
```python
|
|
432
|
+
_ = qt.insert((1.0, 1.0), obj=None)
|
|
433
|
+
items = qt.get_all_items()
|
|
434
|
+
assert hasattr(items[0], "id_") and hasattr(items[0], "geom")
|
|
435
|
+
```
|
|
277
436
|
"""
|
|
278
437
|
if self._store is None:
|
|
279
438
|
raise ValueError("Cannot get items when track_objects=False")
|
|
@@ -282,12 +441,25 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
282
441
|
def get_all_node_boundaries(self) -> list[Bounds]:
|
|
283
442
|
"""
|
|
284
443
|
Return all node boundaries in the tree. Useful for visualization.
|
|
444
|
+
|
|
445
|
+
Example:
|
|
446
|
+
```python
|
|
447
|
+
bounds = qt.get_all_node_boundaries()
|
|
448
|
+
assert isinstance(bounds, list)
|
|
449
|
+
```
|
|
285
450
|
"""
|
|
286
451
|
return self._native.get_all_node_boundaries()
|
|
287
452
|
|
|
288
453
|
def get(self, id_: int) -> Any | None:
|
|
289
454
|
"""
|
|
290
455
|
Return the object associated with id, if tracking is enabled.
|
|
456
|
+
|
|
457
|
+
Example:
|
|
458
|
+
```python
|
|
459
|
+
i = qt.insert((1.0, 2.0), obj={"k": "v"})
|
|
460
|
+
obj = qt.get(i)
|
|
461
|
+
assert obj == {"k": "v"}
|
|
462
|
+
```
|
|
291
463
|
"""
|
|
292
464
|
if self._store is None:
|
|
293
465
|
raise ValueError("Cannot get objects when track_objects=False")
|
|
@@ -297,6 +469,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
|
|
|
297
469
|
def count_items(self) -> int:
|
|
298
470
|
"""
|
|
299
471
|
Return the number of items currently in the tree (native count).
|
|
472
|
+
|
|
473
|
+
Example:
|
|
474
|
+
```python
|
|
475
|
+
before = qt.count_items()
|
|
476
|
+
_ = qt.insert((2.0, 2.0))
|
|
477
|
+
assert qt.count_items() == before + 1
|
|
478
|
+
```
|
|
300
479
|
"""
|
|
301
480
|
return self._native.count_items()
|
|
302
481
|
|
fastquadtree/_item.py
CHANGED
|
@@ -27,6 +27,35 @@ class Item:
|
|
|
27
27
|
self.geom: Point | Bounds = geom
|
|
28
28
|
self.obj: Any | None = obj
|
|
29
29
|
|
|
30
|
+
def to_dict(self) -> dict[str, Any]:
|
|
31
|
+
"""
|
|
32
|
+
Serialize the item to a dictionary.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
A dictionary with 'id', 'geom', and 'obj' keys.
|
|
36
|
+
"""
|
|
37
|
+
return {
|
|
38
|
+
"id": self.id_,
|
|
39
|
+
"geom": self.geom,
|
|
40
|
+
"obj": self.obj,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_dict(cls, data: dict[str, Any]) -> Item:
|
|
45
|
+
"""
|
|
46
|
+
Deserialize an item from a dictionary.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
data: A dictionary with 'id', 'geom', and 'obj' keys.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
An Item instance populated with the deserialized data.
|
|
53
|
+
"""
|
|
54
|
+
id_ = data["id"]
|
|
55
|
+
geom = data["geom"]
|
|
56
|
+
obj = data["obj"]
|
|
57
|
+
return cls(id_, geom, obj)
|
|
58
|
+
|
|
30
59
|
|
|
31
60
|
class PointItem(Item):
|
|
32
61
|
"""
|
fastquadtree/_native.abi3.so
CHANGED
|
Binary file
|
fastquadtree/_obj_store.py
CHANGED
|
@@ -35,11 +35,40 @@ class ObjStore(Generic[TItem]):
|
|
|
35
35
|
|
|
36
36
|
if items:
|
|
37
37
|
for it in items:
|
|
38
|
-
self.add(it)
|
|
38
|
+
self.add(it, handle_out_of_order=True)
|
|
39
|
+
|
|
40
|
+
# ---- Serialization ----
|
|
41
|
+
def to_dict(self) -> dict[str, Any]:
|
|
42
|
+
"""
|
|
43
|
+
Serialize to a dict suitable for JSON or other serialization.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
A dict with 'items' key containing list of serialized items.
|
|
47
|
+
"""
|
|
48
|
+
items = [it.to_dict() for it in self._arr if it is not None]
|
|
49
|
+
return {"items": items}
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def from_dict(cls, data: dict[str, Any], item_factory: Any) -> ObjStore[TItem]:
|
|
53
|
+
"""
|
|
54
|
+
Deserialize from a dict.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
data: A dict with 'items' key containing list of serialized items.
|
|
58
|
+
item_factory: A callable that takes (id, obj) and returns an Item.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
An ObjStore instance populated with the deserialized items.
|
|
62
|
+
"""
|
|
63
|
+
items = []
|
|
64
|
+
for item_data in data.get("items", []):
|
|
65
|
+
item = Item.from_dict(item_data)
|
|
66
|
+
items.append(item_factory(item.id_, item.geom, item.obj))
|
|
67
|
+
return cls(items)
|
|
39
68
|
|
|
40
69
|
# -------- core --------
|
|
41
70
|
|
|
42
|
-
def add(self, item: TItem) -> None:
|
|
71
|
+
def add(self, item: TItem, handle_out_of_order: bool = False) -> None:
|
|
43
72
|
"""
|
|
44
73
|
Insert or replace the mapping at item.id_. Reverse map updated so obj points to id.
|
|
45
74
|
"""
|
|
@@ -48,9 +77,14 @@ class ObjStore(Generic[TItem]):
|
|
|
48
77
|
|
|
49
78
|
# ids must be dense and assigned by the caller
|
|
50
79
|
if id_ > len(self._arr):
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
80
|
+
if not handle_out_of_order:
|
|
81
|
+
raise AssertionError(
|
|
82
|
+
"ObjStore.add received an out-of-order id, use alloc_id() to get the next available id"
|
|
83
|
+
)
|
|
84
|
+
# fill holes with None
|
|
85
|
+
while len(self._arr) < id_:
|
|
86
|
+
self._arr.append(None)
|
|
87
|
+
self._objs.append(None)
|
|
54
88
|
|
|
55
89
|
if id_ == len(self._arr):
|
|
56
90
|
# append
|
fastquadtree/point_quadtree.py
CHANGED
|
@@ -49,6 +49,18 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
|
|
|
49
49
|
track_objects=track_objects,
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
+
@classmethod
|
|
53
|
+
def from_bytes(cls, data: bytes) -> QuadTree:
|
|
54
|
+
"""
|
|
55
|
+
Create a QuadTree instance from serialized bytes.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
data: Serialized byte data from `to_bytes()`.
|
|
59
|
+
Returns:
|
|
60
|
+
A QuadTree instance.
|
|
61
|
+
"""
|
|
62
|
+
return super().from_bytes(data)
|
|
63
|
+
|
|
52
64
|
@overload
|
|
53
65
|
def query(
|
|
54
66
|
self, rect: Bounds, *, as_items: Literal[False] = ...
|
|
@@ -68,6 +80,13 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
|
|
|
68
80
|
Returns:
|
|
69
81
|
If as_items is False: list of (id, x, y) tuples.
|
|
70
82
|
If as_items is True: list of Item objects.
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
```python
|
|
86
|
+
results = qt.query((10.0, 10.0, 20.0, 20.0), as_items=True)
|
|
87
|
+
for item in results:
|
|
88
|
+
print(f"Found point id={item.id_} at {item.geom} with obj={item.obj}")
|
|
89
|
+
```
|
|
71
90
|
"""
|
|
72
91
|
if not as_items:
|
|
73
92
|
return self._native.query(rect)
|
|
@@ -145,5 +164,11 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
|
|
|
145
164
|
return _RustQuadTree(bounds, capacity)
|
|
146
165
|
return _RustQuadTree(bounds, capacity, max_depth=max_depth)
|
|
147
166
|
|
|
148
|
-
|
|
167
|
+
@classmethod
|
|
168
|
+
def _new_native_from_bytes(cls, data: bytes) -> Any:
|
|
169
|
+
"""Create a new native engine instance from serialized bytes."""
|
|
170
|
+
return _RustQuadTree.from_bytes(data)
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def _make_item(id_: int, geom: Point, obj: Any | None) -> PointItem:
|
|
149
174
|
return PointItem(id_, geom, obj)
|
fastquadtree/rect_quadtree.py
CHANGED
|
@@ -50,6 +50,18 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
|
|
|
50
50
|
track_objects=track_objects,
|
|
51
51
|
)
|
|
52
52
|
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_bytes(cls, data: bytes) -> RectQuadTree:
|
|
55
|
+
"""
|
|
56
|
+
Create a RectQuadTree instance from serialized bytes.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
data: Serialized byte data from `to_bytes()`.
|
|
60
|
+
Returns:
|
|
61
|
+
A RectQuadTree instance.
|
|
62
|
+
"""
|
|
63
|
+
return super().from_bytes(data)
|
|
64
|
+
|
|
53
65
|
@overload
|
|
54
66
|
def query(
|
|
55
67
|
self, rect: Bounds, *, as_items: Literal[False] = ...
|
|
@@ -69,6 +81,13 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
|
|
|
69
81
|
Returns:
|
|
70
82
|
If as_items is False: list of (id, x0, y0, x1, y1) tuples.
|
|
71
83
|
If as_items is True: list of Item objects.
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
```python
|
|
87
|
+
results = rqt.query((10.0, 10.0, 20.0, 20.0), as_items=True)
|
|
88
|
+
for item in results:
|
|
89
|
+
print(f"Found rect id={item.id_} at {item.geom} with obj={item.obj}")
|
|
90
|
+
```
|
|
72
91
|
"""
|
|
73
92
|
if not as_items:
|
|
74
93
|
return self._native.query(rect)
|
|
@@ -81,5 +100,11 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
|
|
|
81
100
|
return _RustRectQuadTree(bounds, capacity)
|
|
82
101
|
return _RustRectQuadTree(bounds, capacity, max_depth=max_depth)
|
|
83
102
|
|
|
84
|
-
|
|
103
|
+
@classmethod
|
|
104
|
+
def _new_native_from_bytes(cls, data: bytes) -> Any:
|
|
105
|
+
"""Create a new native engine instance from serialized bytes."""
|
|
106
|
+
return _RustRectQuadTree.from_bytes(data)
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def _make_item(id_: int, geom: Bounds, obj: Any | None) -> RectItem:
|
|
85
110
|
return RectItem(id_, geom, obj)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastquadtree
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
6
|
Classifier: Programming Language :: Rust
|
|
@@ -70,6 +70,7 @@ Rust-optimized quadtree with a clean Python API
|
|
|
70
70
|
- Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
|
|
71
71
|
- Fast KNN and range queries
|
|
72
72
|
- Optional object tracking for id ↔ object mapping
|
|
73
|
+
- Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
|
|
73
74
|
- [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
|
|
74
75
|
- 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
|
|
75
76
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
fastquadtree-1.2.1.dist-info/METADATA,sha256=IYzvJNOV07j4qtOFQqryt15YjrnuWrSjJpK0NUDe-1E,9614
|
|
2
|
+
fastquadtree-1.2.1.dist-info/WHEEL,sha256=cqfH6P_NujaeOc1olR46J5a7YgoxWJnrr5iZ1_DMqps,129
|
|
3
|
+
fastquadtree-1.2.1.dist-info/licenses/LICENSE,sha256=pRuvcuqIMtEUBMgvP1Bc4fOHydzeuA61c6DQoQ1pb1w,1071
|
|
4
|
+
fastquadtree/__init__.py,sha256=rtkveNz7rScRasTRGu1yEqzeoJfLfreJNxg21orPL-U,195
|
|
5
|
+
fastquadtree/_base_quadtree.py,sha256=NhUkMulVa2ItCtx5rEnE_asHY3aGN0XxG6m-AYJk7CE,15091
|
|
6
|
+
fastquadtree/_item.py,sha256=EDS3nJHdVtjDsuTqTZKGTZH8iWJIQ-TKxLXqvMScNPA,2405
|
|
7
|
+
fastquadtree/_native.abi3.so,sha256=KowjAh4FNt39FRoddwNjgcSWSG1tGRV7McT8WWRO8aE,540600
|
|
8
|
+
fastquadtree/_obj_store.py,sha256=HeYFGUPYhvxBzL7Js0g0jsIxflpZS6RsXNk50rGeNlA,6522
|
|
9
|
+
fastquadtree/point_quadtree.py,sha256=BM6mxw2pSmAKkOgXnosREfC6WOXCgEYNeQDlvnlEbKQ,5945
|
|
10
|
+
fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
fastquadtree/pyqtree.py,sha256=2Khh1gCPalD4z0gb3EmqtzMoga08E9BkB0j5bwkiRPU,6076
|
|
12
|
+
fastquadtree/rect_quadtree.py,sha256=82IygiEmJ4JdA6LBDXq288cs9VfS3LpdJdkjCPcYCKM,3807
|
|
13
|
+
fastquadtree-1.2.1.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
fastquadtree-1.1.2.dist-info/METADATA,sha256=Xuiwr9cpXZhCSt6P3e_kr6t4YWHD0PTszufwxLgmq74,9501
|
|
2
|
-
fastquadtree-1.1.2.dist-info/WHEEL,sha256=cqfH6P_NujaeOc1olR46J5a7YgoxWJnrr5iZ1_DMqps,129
|
|
3
|
-
fastquadtree-1.1.2.dist-info/licenses/LICENSE,sha256=pRuvcuqIMtEUBMgvP1Bc4fOHydzeuA61c6DQoQ1pb1w,1071
|
|
4
|
-
fastquadtree/__init__.py,sha256=rtkveNz7rScRasTRGu1yEqzeoJfLfreJNxg21orPL-U,195
|
|
5
|
-
fastquadtree/_base_quadtree.py,sha256=o5T0xqDM9i_JjpYF4U7VmLM0qUHkw0wr0bbRqb-CGt4,9901
|
|
6
|
-
fastquadtree/_item.py,sha256=LoTDr7zlsZyUrrKK6Ketzl5fxTcFF8YbcxEXbQ65st4,1679
|
|
7
|
-
fastquadtree/_native.abi3.so,sha256=C8MsshF2fjlaMGhJP6IkoP0D-7MFE6A1gKE6BkZttVE,508576
|
|
8
|
-
fastquadtree/_obj_store.py,sha256=vmhZGdzEoTQHvRbFjTne_0X2Z1l48SXyB6I9SAjjbiM,5267
|
|
9
|
-
fastquadtree/point_quadtree.py,sha256=Pz8ZS7N3kYSYJJYGa3ghKzy7d3JCA1dbi9nfEwwpF_k,5178
|
|
10
|
-
fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
fastquadtree/pyqtree.py,sha256=2Khh1gCPalD4z0gb3EmqtzMoga08E9BkB0j5bwkiRPU,6076
|
|
12
|
-
fastquadtree/rect_quadtree.py,sha256=7F-JceCHn5RLhztxSYCIJEZ_e2TV-NeobobbrdauJQA,3024
|
|
13
|
-
fastquadtree-1.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|