fastquadtree 1.2.0__tar.gz → 1.2.3__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.

Potentially problematic release.


This version of fastquadtree might be problematic. Click here for more details.

Files changed (77) hide show
  1. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/.github/workflows/release.yml +1 -1
  2. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/Cargo.lock +1 -1
  3. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/Cargo.toml +1 -1
  4. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/PKG-INFO +5 -4
  5. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/README.md +3 -2
  6. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/future_features.md +26 -10
  7. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/mkdocs.yml +8 -5
  8. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pyproject.toml +1 -1
  9. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/_base_quadtree.py +119 -1
  10. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/point_quadtree.py +7 -12
  11. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/rect_quadtree.py +7 -12
  12. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/.github/workflows/docs.yml +0 -0
  13. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/.gitignore +0 -0
  14. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/.pre-commit-config.yaml +0 -0
  15. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/LICENSE +0 -0
  16. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/assets/ballpit.png +0 -0
  17. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/assets/interactive_v2_rect_screenshot.png +0 -0
  18. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/assets/interactive_v2_screenshot.png +0 -0
  19. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/assets/quadtree_bench_throughput.png +0 -0
  20. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/assets/quadtree_bench_time.png +0 -0
  21. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/benchmark_native_vs_shim.py +0 -0
  22. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/benchmark_np_vs_list.py +0 -0
  23. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/benchmark_serialization_vs_rebuild.py +0 -0
  24. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/cross_library_bench.py +0 -0
  25. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/quadtree_bench/__init__.py +0 -0
  26. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/quadtree_bench/engines.py +0 -0
  27. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/quadtree_bench/main.py +0 -0
  28. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/quadtree_bench/plotting.py +0 -0
  29. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/quadtree_bench/runner.py +0 -0
  30. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/requirements.txt +0 -0
  31. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/runner.py +0 -0
  32. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/benchmarks/system_info_collector.py +0 -0
  33. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/api/point_item.md +0 -0
  34. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/api/pyqtree.md +0 -0
  35. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/api/quadtree.md +0 -0
  36. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/api/rect_item.md +0 -0
  37. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/api/rect_quadtree.md +0 -0
  38. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/benchmark.md +0 -0
  39. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/index.md +0 -0
  40. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/quickstart.md +0 -0
  41. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/runnables.md +0 -0
  42. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/docs/styles/overrides.css +0 -0
  43. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/interactive/ballpit.py +0 -0
  44. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/interactive/interactive.py +0 -0
  45. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/interactive/interactive_v2.py +0 -0
  46. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/interactive/interactive_v2_rect.py +0 -0
  47. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/interactive/requirements.txt +0 -0
  48. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/__init__.py +0 -0
  49. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/_item.py +0 -0
  50. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/_obj_store.py +0 -0
  51. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/py.typed +0 -0
  52. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/pysrc/fastquadtree/pyqtree.py +0 -0
  53. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/src/geom.rs +0 -0
  54. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/src/lib.rs +0 -0
  55. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/src/quadtree.rs +0 -0
  56. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/src/rect_quadtree.rs +0 -0
  57. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/insertions.rs +0 -0
  58. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/nearest_neighbor.rs +0 -0
  59. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/query.rs +0 -0
  60. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/rect_quadtree.rs +0 -0
  61. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/rectangle_traversal.rs +0 -0
  62. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/serialization.rs +0 -0
  63. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_base_quadtree.py +0 -0
  64. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_clear.py +0 -0
  65. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_delete.rs +0 -0
  66. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_delete_by_object.py +0 -0
  67. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_delete_python.py +0 -0
  68. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_insert_many_numpy.py +0 -0
  69. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_obj_store.py +0 -0
  70. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_point_quadtree_nn_runtime.py +0 -0
  71. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_pyqtree_shim_compat.py +0 -0
  72. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_python.py +0 -0
  73. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_rect_quadtree.py +0 -0
  74. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_serialization.py +0 -0
  75. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_unconventional_bounds.py +0 -0
  76. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/test_wrapper_edges.py +0 -0
  77. {fastquadtree-1.2.0 → fastquadtree-1.2.3}/tests/unconventional_bounds.rs +0 -0
@@ -16,7 +16,7 @@ jobs:
16
16
  - name: Set up Python
17
17
  uses: actions/setup-python@v5
18
18
  with:
19
- python-version: "3.10"
19
+ python-version: "3.9"
20
20
 
21
21
  - name: Create venv for maturin develop
22
22
  run: python -m venv .venv
@@ -30,7 +30,7 @@ dependencies = [
30
30
 
31
31
  [[package]]
32
32
  name = "fastquadtree"
33
- version = "1.2.0"
33
+ version = "1.2.3"
34
34
  dependencies = [
35
35
  "bincode",
36
36
  "numpy",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "fastquadtree"
3
- version = "1.2.0"
3
+ version = "1.2.3"
4
4
  edition = "2021"
5
5
  readme = "README.md"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 1.2.0
3
+ Version: 1.2.3
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Rust
@@ -31,7 +31,7 @@ License-File: LICENSE
31
31
  Summary: Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
32
32
  Keywords: quadtree,spatial-index,geometry,rust,pyo3,nearest-neighbor,k-nn
33
33
  Author: Ethan Anderson
34
- Requires-Python: >=3.8
34
+ Requires-Python: >=3.9
35
35
  Description-Content-Type: text/markdown
36
36
  Project-URL: Homepage, https://github.com/Elan456/fastquadtree
37
37
  Project-URL: Repository, https://github.com/Elan456/fastquadtree
@@ -45,6 +45,8 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
45
45
 
46
46
  Rust-optimized quadtree with a clean Python API
47
47
 
48
+ 👉 **Check out the Docs:** https://elan456.github.io/fastquadtree/
49
+
48
50
  [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
49
51
  [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
50
52
  [![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)
@@ -64,7 +66,7 @@ Rust-optimized quadtree with a clean Python API
64
66
 
65
67
  ## Why use fastquadtree
66
68
 
67
- - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with no external dependencies and modern typing hints
69
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with **no external dependencies** and modern typing hints
68
70
  - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
69
71
  - Prebuilt wheels for Windows, macOS, and Linux
70
72
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
@@ -76,7 +78,6 @@ Rust-optimized quadtree with a clean Python API
76
78
 
77
79
  ----
78
80
 
79
- 👉 **Docs:** https://elan456.github.io/fastquadtree/
80
81
 
81
82
  ## Examples
82
83
  See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
@@ -5,6 +5,8 @@
5
5
 
6
6
  Rust-optimized quadtree with a clean Python API
7
7
 
8
+ 👉 **Check out the Docs:** https://elan456.github.io/fastquadtree/
9
+
8
10
  [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
9
11
  [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
10
12
  [![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)
@@ -24,7 +26,7 @@ Rust-optimized quadtree with a clean Python API
24
26
 
25
27
  ## Why use fastquadtree
26
28
 
27
- - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with no external dependencies and modern typing hints
29
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with **no external dependencies** and modern typing hints
28
30
  - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
29
31
  - Prebuilt wheels for Windows, macOS, and Linux
30
32
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
@@ -36,7 +38,6 @@ Rust-optimized quadtree with a clean Python API
36
38
 
37
39
  ----
38
40
 
39
- 👉 **Docs:** https://elan456.github.io/fastquadtree/
40
41
 
41
42
  ## Examples
42
43
  See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
@@ -5,26 +5,42 @@ If you really want any of these features, please let us know by opening an issue
5
5
 
6
6
  If you have any suggestions or would like to contribute, please feel free to open an issue or a pull request.
7
7
 
8
- ## Planned Features
8
+ The features will likely be implemented in the order they are listed below, but this is not guaranteed.
9
9
 
10
- ### 1. [COMPLETE] Quadtree serialization
10
+ ## 🚧 Planned Features
11
11
 
12
- By serializing the quadtree, we can save its state to a file and load it later. This will allow us to persist the quadtree structure and data across sessions. For example, you could pre build a quadtree with all the walls in your video game level, serialize it to a file, and then load it when the game starts. This will heavily reduce the game load time since you won't have to rebuild the quadtree from scratch every time.
12
+ ### 1. Configurable Quadtree Coordinate Type
13
13
 
14
- ### 2. Circle support
14
+ Currently, the point quadtree only uses f32 for point coordinates, limiting precision in favor of better performance.
15
+ To make the quadtree more flexible, we could allow users to specify the coordinate type (e.g., f64, i32, etc.) when creating a quadtree.
16
+ The f32 will remain the default, but users will be able to specify a different type if needed.
15
17
 
16
- Currently, we support points and rectangles in two separate quadtrees.
17
- For example, in the ball-pit demo, we use a point quadtree, but then query a larger area to account for the radius of the balls.
18
- With a circle quadtree, we could directly insert circles and perform circle-circle collision detection.
18
+ If the type cannot be made truly generic, then only the following types would be supported: f32, f64, i32, i64
19
19
 
20
- ### 3. KNN with criteria function
20
+ ### 2. KNN with criteria function
21
21
 
22
22
  Currently, KNN only supports finding the nearest neighbors based on euclidean distance.
23
23
  By adding a criteria function, we could allow users to define custom criteria for finding neighbors by passing a function that
24
24
  takes in a point and returns a score. The KNN algorithm would then use this score to determine the nearest neighbors.
25
25
 
26
- ### 4. KNN in rectangle quadtree
26
+ ### 3. KNN in rectangle quadtree
27
27
 
28
28
  Currently, KNN is only supported in the point quadtree. By adding KNN support to the rectangle quadtree, we could allow users to find the nearest rectangles to a given point. This would be to the nearest edge of the rectangle, adding complexity to the algorithm.
29
29
  However, it will allow for really quick collision detection between a point and a set of rectangles as the point can just do
30
- robust-collision handling with the nearest rectangles.
30
+ robust-collision handling with the nearest rectangles.
31
+
32
+ ### 4. Circle support
33
+
34
+ Currently, we support points and rectangles in two separate quadtrees.
35
+ For example, in the ball-pit demo, we use a point quadtree, but then query a larger area to account for the radius of the balls.
36
+ With a circle quadtree, we could directly insert circles and perform circle-circle collision detection.
37
+
38
+ A good alternative is to use the rectangle quadtree and insert the minimum bounding rectangles of the circles.
39
+
40
+ ## ✅ Completed Planned Features
41
+
42
+ Once a feature from above is completed, it will be moved to this section.
43
+
44
+ ### Quadtree serialization
45
+
46
+ By serializing the quadtree, we can save its state to a file and load it later. This will allow us to persist the quadtree structure and data across sessions. For example, you could pre build a quadtree with all the walls in your video game level, serialize it to a file, and then load it when the game starts. This will heavily reduce the game load time since you won't have to rebuild the quadtree from scratch every time.
@@ -12,10 +12,12 @@ theme:
12
12
  - navigation.tracking
13
13
  - navigation.indexes
14
14
  - content.code.copy
15
- - toc.integrate
15
+ - toc.follow
16
16
  - search.suggest
17
17
  - search.highlight
18
18
  - content.tooltips
19
+ - navigation.footer
20
+ - navigation.top
19
21
  palette:
20
22
  - scheme: slate
21
23
  primary: indigo
@@ -37,13 +39,14 @@ plugins:
37
39
  options:
38
40
  docstring_style: google
39
41
  merge_init_into_class: true
40
- show_source: true
42
+ show_source: false
41
43
  show_root_heading: false
42
44
  show_signature: true
43
45
  show_if_no_docstring: true
44
- separate_signature: true
45
- line_length: 88
46
- heading_level: 2
46
+ separate_signature: false
47
+ line_length: 100
48
+ heading_level: 3
49
+ members_order: source
47
50
  filters: # Exclude __slots__ and __len__ and anything with a single underscore prefix (don't filter insert_many even though it has a single underscore)
48
51
  - "!__slots__"
49
52
  - "!__len__"
@@ -8,7 +8,7 @@ name = "fastquadtree"
8
8
  dynamic = ["version"]
9
9
  description = "Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search."
10
10
  readme = { file = "README.md", content-type = "text/markdown" }
11
- requires-python = ">=3.8"
11
+ requires-python = ">=3.9"
12
12
  dependencies = [] # No runtime dependencies
13
13
  license = { file = "LICENSE" }
14
14
  authors = [{ name = "Ethan Anderson" }]
@@ -18,6 +18,8 @@ from ._item import Item # base class for PointItem and RectItem
18
18
  from ._obj_store import ObjStore
19
19
 
20
20
  if TYPE_CHECKING:
21
+ from typing import Self # Only in Python 3.11+
22
+
21
23
  from numpy.typing import NDArray
22
24
 
23
25
  Bounds = Tuple[float, float, float, float]
@@ -59,6 +61,10 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
59
61
  def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
60
62
  """Create the native engine instance."""
61
63
 
64
+ @classmethod
65
+ def _new_native_from_bytes(cls, data: bytes) -> Any:
66
+ """Create the native engine instance from serialized bytes."""
67
+
62
68
  @staticmethod
63
69
  @abstractmethod
64
70
  def _make_item(id_: int, geom: G, obj: Any | None) -> ItemType:
@@ -94,6 +100,12 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
94
100
 
95
101
  Returns:
96
102
  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.
103
+
104
+ Example:
105
+ ```python
106
+ state = qt.to_dict()
107
+ assert "core" in state and "bounds" in state
108
+ ```
97
109
  """
98
110
 
99
111
  core_bytes = self._native.to_bytes()
@@ -115,11 +127,18 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
115
127
 
116
128
  Returns:
117
129
  Bytes representing the serialized quadtree. Can be saved as a file or loaded with `from_bytes()`.
130
+
131
+ Example:
132
+ ```python
133
+ blob = qt.to_bytes()
134
+ with open("tree.fqt", "wb") as f:
135
+ f.write(blob)
136
+ ```
118
137
  """
119
138
  return pickle.dumps(self.to_dict())
120
139
 
121
140
  @classmethod
122
- def from_bytes(cls, data: bytes) -> _BaseQuadTree[G, HitT, ItemType]:
141
+ def from_bytes(cls, data: bytes) -> Self:
123
142
  """
124
143
  Deserialize a quadtree from bytes.
125
144
 
@@ -128,6 +147,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
128
147
 
129
148
  Returns:
130
149
  A new quadtree instance with the same state as when serialized.
150
+
151
+ Example:
152
+ ```python
153
+ blob = qt.to_bytes()
154
+ qt2 = type(qt).from_bytes(blob)
155
+ assert qt2.count_items() == qt.count_items()
156
+ ```
131
157
  """
132
158
  in_dict = pickle.loads(data)
133
159
  core_bytes = in_dict["core"]
@@ -174,6 +200,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
174
200
 
175
201
  Raises:
176
202
  ValueError: If geometry is outside the tree bounds.
203
+
204
+ Example:
205
+ ```python
206
+ id0 = point_qt.insert((10.0, 20.0)) # for point trees
207
+ id1 = rect_qt.insert((0.0, 0.0, 5.0, 5.0), obj="box") # for rect trees
208
+ assert isinstance(id0, int) and isinstance(id1, int)
209
+ ```
177
210
  """
178
211
  if self._store is not None:
179
212
  # Reuse a dense free slot if available, else append
@@ -219,6 +252,17 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
219
252
 
220
253
  Raises:
221
254
  ValueError: If any geometry is outside bounds.
255
+
256
+ Example:
257
+ ```python
258
+ n = qt.insert_many([(1.0, 1.0), (2.0, 2.0)])
259
+ assert n == 2
260
+
261
+ import numpy as np
262
+ arr = np.array([[3.0, 3.0], [4.0, 4.0]], dtype=np.float32)
263
+ n2 = qt.insert_many(arr)
264
+ assert n2 == 2
265
+ ```
222
266
  """
223
267
  if type(geoms) is list and len(geoms) == 0:
224
268
  return 0
@@ -283,8 +327,19 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
283
327
  """
284
328
  Delete an item by id and exact geometry.
285
329
 
330
+ Args:
331
+ id_: The id of the item to delete.
332
+ geom: The geometry of the item to delete.
333
+
286
334
  Returns:
287
335
  True if the item was found and deleted.
336
+
337
+ Example:
338
+ ```python
339
+ i = qt.insert((1.0, 2.0))
340
+ ok = qt.delete(i, (1.0, 2.0))
341
+ assert ok is True
342
+ ```
288
343
  """
289
344
  deleted = self._native.delete(id_, geom)
290
345
  if deleted:
@@ -297,6 +352,17 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
297
352
  """
298
353
  Attach or replace the Python object for an existing id.
299
354
  Tracking must be enabled.
355
+
356
+ Args:
357
+ id_: The id of the item to attach the object to.
358
+ obj: The Python object to attach.
359
+
360
+ Example:
361
+ ```python
362
+ i = qt.insert((2.0, 3.0), obj=None)
363
+ qt.attach(i, {"meta": 123})
364
+ assert qt.get(i) == {"meta": 123}
365
+ ```
300
366
  """
301
367
  if self._store is None:
302
368
  raise ValueError("Cannot attach objects when track_objects=False")
@@ -309,6 +375,16 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
309
375
  def delete_by_object(self, obj: Any) -> bool:
310
376
  """
311
377
  Delete an item by Python object identity. Tracking must be enabled.
378
+
379
+ Args:
380
+ obj: The Python object to delete.
381
+
382
+ Example:
383
+ ```python
384
+ i = qt.insert((3.0, 4.0), obj="tag")
385
+ ok = qt.delete_by_object("tag")
386
+ assert ok is True
387
+ ```
312
388
  """
313
389
  if self._store is None:
314
390
  raise ValueError("Cannot delete by object when track_objects=False")
@@ -323,6 +399,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
323
399
 
324
400
  If tracking is enabled, the id -> object mapping is also cleared.
325
401
  The ids are reset to start at zero again.
402
+
403
+ Example:
404
+ ```python
405
+ _ = qt.insert((5.0, 6.0))
406
+ qt.clear()
407
+ assert qt.count_items() == 0 and len(qt) == 0
408
+ ```
326
409
  """
327
410
  self._native = self._new_native(self._bounds, self._capacity, self._max_depth)
328
411
  self._count = 0
@@ -333,6 +416,14 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
333
416
  def get_all_objects(self) -> list[Any]:
334
417
  """
335
418
  Return all tracked Python objects in the tree.
419
+
420
+ Example:
421
+ ```python
422
+ _ = qt.insert((7.0, 8.0), obj="a")
423
+ _ = qt.insert((9.0, 1.0), obj="b")
424
+ objs = qt.get_all_objects()
425
+ assert set(objs) == {"a", "b"}
426
+ ```
336
427
  """
337
428
  if self._store is None:
338
429
  raise ValueError("Cannot get objects when track_objects=False")
@@ -341,6 +432,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
341
432
  def get_all_items(self) -> list[ItemType]:
342
433
  """
343
434
  Return all Item wrappers in the tree.
435
+
436
+ Example:
437
+ ```python
438
+ _ = qt.insert((1.0, 1.0), obj=None)
439
+ items = qt.get_all_items()
440
+ assert hasattr(items[0], "id_") and hasattr(items[0], "geom")
441
+ ```
344
442
  """
345
443
  if self._store is None:
346
444
  raise ValueError("Cannot get items when track_objects=False")
@@ -349,12 +447,25 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
349
447
  def get_all_node_boundaries(self) -> list[Bounds]:
350
448
  """
351
449
  Return all node boundaries in the tree. Useful for visualization.
450
+
451
+ Example:
452
+ ```python
453
+ bounds = qt.get_all_node_boundaries()
454
+ assert isinstance(bounds, list)
455
+ ```
352
456
  """
353
457
  return self._native.get_all_node_boundaries()
354
458
 
355
459
  def get(self, id_: int) -> Any | None:
356
460
  """
357
461
  Return the object associated with id, if tracking is enabled.
462
+
463
+ Example:
464
+ ```python
465
+ i = qt.insert((1.0, 2.0), obj={"k": "v"})
466
+ obj = qt.get(i)
467
+ assert obj == {"k": "v"}
468
+ ```
358
469
  """
359
470
  if self._store is None:
360
471
  raise ValueError("Cannot get objects when track_objects=False")
@@ -364,6 +475,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
364
475
  def count_items(self) -> int:
365
476
  """
366
477
  Return the number of items currently in the tree (native count).
478
+
479
+ Example:
480
+ ```python
481
+ before = qt.count_items()
482
+ _ = qt.insert((2.0, 2.0))
483
+ assert qt.count_items() == before + 1
484
+ ```
367
485
  """
368
486
  return self._native.count_items()
369
487
 
@@ -49,18 +49,6 @@ 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
-
64
52
  @overload
65
53
  def query(
66
54
  self, rect: Bounds, *, as_items: Literal[False] = ...
@@ -80,6 +68,13 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
80
68
  Returns:
81
69
  If as_items is False: list of (id, x, y) tuples.
82
70
  If as_items is True: list of Item objects.
71
+
72
+ Example:
73
+ ```python
74
+ results = qt.query((10.0, 10.0, 20.0, 20.0), as_items=True)
75
+ for item in results:
76
+ print(f"Found point id={item.id_} at {item.geom} with obj={item.obj}")
77
+ ```
83
78
  """
84
79
  if not as_items:
85
80
  return self._native.query(rect)
@@ -50,18 +50,6 @@ 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
-
65
53
  @overload
66
54
  def query(
67
55
  self, rect: Bounds, *, as_items: Literal[False] = ...
@@ -81,6 +69,13 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
81
69
  Returns:
82
70
  If as_items is False: list of (id, x0, y0, x1, y1) tuples.
83
71
  If as_items is True: list of Item objects.
72
+
73
+ Example:
74
+ ```python
75
+ results = rqt.query((10.0, 10.0, 20.0, 20.0), as_items=True)
76
+ for item in results:
77
+ print(f"Found rect id={item.id_} at {item.geom} with obj={item.obj}")
78
+ ```
84
79
  """
85
80
  if not as_items:
86
81
  return self._native.query(rect)
File without changes
File without changes
File without changes
File without changes
File without changes