fastquadtree 2.2.0__tar.gz → 2.4.0__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.
Files changed (117) hide show
  1. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/.pre-commit-config.yaml +1 -1
  2. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/Cargo.lock +82 -48
  3. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/Cargo.toml +3 -3
  4. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/LICENSE +1 -1
  5. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/PKG-INFO +7 -3
  6. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/README.md +6 -2
  7. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/benchmark_np_vs_list.py +6 -6
  8. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/2.0_migration_guide.md +3 -1
  9. fastquadtree-2.4.0/docs/api/pygame.md +8 -0
  10. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/benchmark.md +9 -9
  11. fastquadtree-2.4.0/docs/engine_defaults.md +73 -0
  12. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/index.md +2 -2
  13. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/quickstart.md +14 -7
  14. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/runnables.md +2 -2
  15. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/mkdocs.yml +1 -0
  16. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pyproject.toml +1 -1
  17. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_base_quadtree.py +42 -6
  18. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_base_quadtree_objects.py +41 -6
  19. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_common.py +41 -3
  20. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/point_quadtree.py +12 -3
  21. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/point_quadtree_objects.py +12 -3
  22. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/pygame.py +138 -73
  23. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/rect_quadtree.py +12 -3
  24. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/rect_quadtree_objects.py +12 -3
  25. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/src/geom.rs +6 -8
  26. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/src/lib.rs +26 -4
  27. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/src/quadtree.rs +40 -12
  28. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/src/rect_quadtree.rs +42 -14
  29. fastquadtree-2.4.0/src/serialization.rs +258 -0
  30. fastquadtree-2.4.0/tests/serialization.rs +151 -0
  31. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/common/test_internal_edges.py +26 -5
  32. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/integration/test_pygame_integration.py +59 -26
  33. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points/test_point_quadtree_serialization.py +53 -1
  34. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points_objects/test_point_quadtree_objects_serialization.py +27 -1
  35. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects/test_rect_quadtree_core.py +3 -3
  36. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects/test_rect_quadtree_serialization.py +34 -1
  37. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_core.py +3 -3
  38. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/test_pyqtree_shim_compat.py +3 -3
  39. fastquadtree-2.2.0/docs/api/pygame.md +0 -27
  40. fastquadtree-2.2.0/tests/serialization.rs +0 -63
  41. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/.github/workflows/docs.yml +0 -0
  42. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/.github/workflows/release.yml +0 -0
  43. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/.github/workflows/test.yml +0 -0
  44. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/.gitignore +0 -0
  45. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/ballpit.png +0 -0
  46. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/interactive_v2_rect_screenshot.png +0 -0
  47. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/interactive_v2_screenshot.png +0 -0
  48. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/pygame_sprites_demo.png +0 -0
  49. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/quadtree_bench_throughput.png +0 -0
  50. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/assets/quadtree_bench_time.png +0 -0
  51. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/benchmark_native_vs_shim.py +0 -0
  52. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/benchmark_serialization_vs_rebuild.py +0 -0
  53. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/cross_library_bench.py +0 -0
  54. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/__init__.py +0 -0
  55. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/engines.py +0 -0
  56. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/main.py +0 -0
  57. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/optimizer.py +0 -0
  58. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/plotting.py +0 -0
  59. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/quadtree_bench/runner.py +0 -0
  60. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/runner.py +0 -0
  61. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/benchmarks/system_info_collector.py +0 -0
  62. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/2.0_proposal.md +0 -0
  63. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/insert_result.md +0 -0
  64. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/item.md +0 -0
  65. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/point_item.md +0 -0
  66. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/pyqtree.md +0 -0
  67. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/quadtree.md +0 -0
  68. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/quadtree_objects.md +0 -0
  69. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/rect_item.md +0 -0
  70. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/rect_quadtree.md +0 -0
  71. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/api/rect_quadtree_objects.md +0 -0
  72. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/future_features.md +0 -0
  73. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/rust_usage.md +0 -0
  74. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/docs/styles/overrides.css +0 -0
  75. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/examples/custom_id_example.py +0 -0
  76. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/examples/object_tracking_example.py +0 -0
  77. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/interactive/ballpit.py +0 -0
  78. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/interactive/interactive.py +0 -0
  79. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/interactive/interactive_v2.py +0 -0
  80. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/interactive/interactive_v2_rect.py +0 -0
  81. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/interactive/pygame_sprites.py +0 -0
  82. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pyrightconfig.json +0 -0
  83. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/__init__.py +0 -0
  84. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_insert_result.py +0 -0
  85. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_item.py +0 -0
  86. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/_obj_store.py +0 -0
  87. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/py.typed +0 -0
  88. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/pysrc/fastquadtree/pyqtree.py +0 -0
  89. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/__init__.py +0 -0
  90. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/insertions.rs +0 -0
  91. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/nearest_neighbor.rs +0 -0
  92. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/query.rs +0 -0
  93. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/rect_quadtree.rs +0 -0
  94. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/rectangle_traversal.rs +0 -0
  95. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_delete.rs +0 -0
  96. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/__init__.py +0 -0
  97. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/common/test_common_validation.py +0 -0
  98. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/common/test_insert_result_and_items.py +0 -0
  99. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/common/test_obj_store.py +0 -0
  100. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/common/test_serialization_container.py +0 -0
  101. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/conftest.py +0 -0
  102. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/integration/test_migration_breaks_and_safety.py +0 -0
  103. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/integration/test_optional_pygame_dependency.py +0 -0
  104. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/integration/test_public_api_contracts.py +0 -0
  105. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points/test_point_quadtree_core.py +0 -0
  106. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points/test_point_quadtree_mutation.py +0 -0
  107. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points/test_point_quadtree_numpy.py +0 -0
  108. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points/test_point_quadtree_precision.py +0 -0
  109. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points_objects/test_point_quadtree_objects_core.py +0 -0
  110. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points_objects/test_point_quadtree_objects_deletion_update.py +0 -0
  111. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/points_objects/test_point_quadtree_objects_numpy.py +0 -0
  112. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects/test_rect_quadtree_mutation.py +0 -0
  113. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects/test_rect_quadtree_numpy.py +0 -0
  114. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_deletion_update.py +0 -0
  115. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_numpy.py +0 -0
  116. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_serialization.py +0 -0
  117. {fastquadtree-2.2.0 → fastquadtree-2.4.0}/tests/unconventional_bounds.rs +0 -0
@@ -1,7 +1,7 @@
1
1
  repos:
2
2
  # 0) Python linter and formatter: Ruff
3
3
  - repo: https://github.com/astral-sh/ruff-pre-commit
4
- rev: v0.6.9
4
+ rev: v0.15.15
5
5
  hooks:
6
6
  # Lint + autofix. If Ruff fixes something, the hook exits nonzero to force a re-run.
7
7
  - id: ruff
@@ -9,35 +9,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
9
9
  checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
10
10
 
11
11
  [[package]]
12
- name = "bincode"
13
- version = "2.0.1"
12
+ name = "darling"
13
+ version = "0.23.0"
14
14
  source = "registry+https://github.com/rust-lang/crates.io-index"
15
- checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
15
+ checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
16
16
  dependencies = [
17
- "bincode_derive",
18
- "serde",
19
- "unty",
17
+ "darling_core",
18
+ "darling_macro",
20
19
  ]
21
20
 
22
21
  [[package]]
23
- name = "bincode_derive"
24
- version = "2.0.1"
22
+ name = "darling_core"
23
+ version = "0.23.0"
25
24
  source = "registry+https://github.com/rust-lang/crates.io-index"
26
- checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
25
+ checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
27
26
  dependencies = [
28
- "virtue",
27
+ "ident_case",
28
+ "proc-macro2",
29
+ "quote",
30
+ "strsim",
31
+ "syn",
32
+ ]
33
+
34
+ [[package]]
35
+ name = "darling_macro"
36
+ version = "0.23.0"
37
+ source = "registry+https://github.com/rust-lang/crates.io-index"
38
+ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
39
+ dependencies = [
40
+ "darling_core",
41
+ "quote",
42
+ "syn",
29
43
  ]
30
44
 
31
45
  [[package]]
32
46
  name = "fastquadtree"
33
- version = "2.2.0"
47
+ version = "2.4.0"
34
48
  dependencies = [
35
- "bincode",
36
49
  "num-traits",
37
50
  "numpy",
38
51
  "pyo3",
39
- "serde",
40
52
  "smallvec",
53
+ "wincode",
41
54
  ]
42
55
 
43
56
  [[package]]
@@ -46,6 +59,12 @@ version = "0.5.0"
46
59
  source = "registry+https://github.com/rust-lang/crates.io-index"
47
60
  checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
48
61
 
62
+ [[package]]
63
+ name = "ident_case"
64
+ version = "1.0.1"
65
+ source = "registry+https://github.com/rust-lang/crates.io-index"
66
+ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
67
+
49
68
  [[package]]
50
69
  name = "libc"
51
70
  version = "0.2.186"
@@ -126,6 +145,12 @@ version = "1.21.4"
126
145
  source = "registry+https://github.com/rust-lang/crates.io-index"
127
146
  checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
128
147
 
148
+ [[package]]
149
+ name = "pastey"
150
+ version = "0.2.3"
151
+ source = "registry+https://github.com/rust-lang/crates.io-index"
152
+ checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
153
+
129
154
  [[package]]
130
155
  name = "portable-atomic"
131
156
  version = "1.13.1"
@@ -230,57 +255,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
230
255
  checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
231
256
 
232
257
  [[package]]
233
- name = "serde"
234
- version = "1.0.228"
258
+ name = "smallvec"
259
+ version = "1.15.1"
235
260
  source = "registry+https://github.com/rust-lang/crates.io-index"
236
- checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
237
- dependencies = [
238
- "serde_core",
239
- "serde_derive",
240
- ]
261
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
241
262
 
242
263
  [[package]]
243
- name = "serde_core"
244
- version = "1.0.228"
264
+ name = "strsim"
265
+ version = "0.11.1"
245
266
  source = "registry+https://github.com/rust-lang/crates.io-index"
246
- checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
247
- dependencies = [
248
- "serde_derive",
249
- ]
267
+ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
250
268
 
251
269
  [[package]]
252
- name = "serde_derive"
253
- version = "1.0.228"
270
+ name = "syn"
271
+ version = "2.0.117"
254
272
  source = "registry+https://github.com/rust-lang/crates.io-index"
255
- checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
273
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
256
274
  dependencies = [
257
275
  "proc-macro2",
258
276
  "quote",
259
- "syn",
277
+ "unicode-ident",
260
278
  ]
261
279
 
262
280
  [[package]]
263
- name = "smallvec"
264
- version = "1.15.1"
281
+ name = "target-lexicon"
282
+ version = "0.13.5"
265
283
  source = "registry+https://github.com/rust-lang/crates.io-index"
266
- checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
284
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
267
285
 
268
286
  [[package]]
269
- name = "syn"
270
- version = "2.0.117"
287
+ name = "thiserror"
288
+ version = "2.0.18"
271
289
  source = "registry+https://github.com/rust-lang/crates.io-index"
272
- checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
290
+ checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
273
291
  dependencies = [
274
- "proc-macro2",
275
- "quote",
276
- "unicode-ident",
292
+ "thiserror-impl",
277
293
  ]
278
294
 
279
295
  [[package]]
280
- name = "target-lexicon"
281
- version = "0.13.5"
296
+ name = "thiserror-impl"
297
+ version = "2.0.18"
282
298
  source = "registry+https://github.com/rust-lang/crates.io-index"
283
- checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
299
+ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
300
+ dependencies = [
301
+ "proc-macro2",
302
+ "quote",
303
+ "syn",
304
+ ]
284
305
 
285
306
  [[package]]
286
307
  name = "unicode-ident"
@@ -289,13 +310,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
289
310
  checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
290
311
 
291
312
  [[package]]
292
- name = "unty"
293
- version = "0.0.4"
313
+ name = "wincode"
314
+ version = "0.5.5"
294
315
  source = "registry+https://github.com/rust-lang/crates.io-index"
295
- checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
316
+ checksum = "66d967db7705dc29120bb6e8ce5b5a2e27734ed5976d1c904e95bd238d1c3c5a"
317
+ dependencies = [
318
+ "pastey",
319
+ "proc-macro2",
320
+ "quote",
321
+ "thiserror",
322
+ "wincode-derive",
323
+ ]
296
324
 
297
325
  [[package]]
298
- name = "virtue"
299
- version = "0.0.18"
326
+ name = "wincode-derive"
327
+ version = "0.4.6"
300
328
  source = "registry+https://github.com/rust-lang/crates.io-index"
301
- checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
329
+ checksum = "15ab90b719560d0fda79c74550ad1c948d17b118765942838055ebaf34d67071"
330
+ dependencies = [
331
+ "darling",
332
+ "proc-macro2",
333
+ "quote",
334
+ "syn",
335
+ ]
@@ -1,7 +1,8 @@
1
1
  [package]
2
2
  name = "fastquadtree"
3
- version = "2.2.0"
3
+ version = "2.4.0"
4
4
  edition = "2021"
5
+ rust-version = "1.89"
5
6
  readme = "README.md"
6
7
 
7
8
  [lib]
@@ -11,8 +12,7 @@ crate-type = ["rlib", "cdylib"]
11
12
  pyo3 = { version = "0.28", features = ["extension-module", "abi3-py39"] }
12
13
  smallvec = "1.15.1"
13
14
  numpy = "0.28"
14
- serde = { version = "1.0", features = ["derive"] }
15
- bincode = {version = "2.0.1", features = ["serde"]}
15
+ wincode = { version = "0.5.5", features = ["derive"] }
16
16
  num-traits = "0.2"
17
17
 
18
18
  [profile.release]
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Ethan Anderson
3
+ Copyright (c) 2025-2026 Ethan Anderson
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 2.2.0
3
+ Version: 2.4.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Python :: 3.9
@@ -62,6 +62,7 @@ Rust-optimized quadtree with a clean Python API
62
62
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
63
63
  - Fast KNN and range queries
64
64
  - Optional object tracking for id ↔ object mapping
65
+ - Mostly drop-in [pygame sprite-group integration](https://elan456.github.io/fastquadtree/api/pygame/) that adds automatic broadphase culling plus rect queries and k-NN over sprite rects
65
66
  - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
66
67
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
67
68
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -88,6 +89,7 @@ from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~10x faster whil
88
89
  | `QuadTreeObjects` | Points | Yes | Point indexing with attached Python objects. |
89
90
  | `RectQuadTreeObjects` | Bounding boxes | Yes | Rectangle indexing with attached objects. |
90
91
  | `fastquadtree.pyqtree.Index` | Bounding boxes | Yes | pyqtree-compatible API, much faster. |
92
+ | `fastquadtree.pygame.Group` | pygame sprites | Yes | Mostly drop-in `Group` with sprite queries. |
91
93
 
92
94
 
93
95
  ## Quickstart
@@ -171,7 +173,7 @@ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) f
171
173
 
172
174
  * `bounds` — tuple `(min_x, min_y, max_x, max_y)` defines the 2D area covered by the quadtree
173
175
  * `capacity` — max number of points kept in a leaf before splitting
174
- * `max_depth` — optional depth cap. If omitted, the tree can keep splitting as needed
176
+ * `max_depth` — optional depth cap. If omitted, uses the [engine default](https://elan456.github.io/fastquadtree/engine_defaults/#max-depth)
175
177
  * `dtype` — data type for coordinates, e.g., `"f32"`, `"f64"`, `"i32"`, `"i64"`
176
178
 
177
179
  ### Key Methods
@@ -233,7 +235,9 @@ qt.insert_many_np(points) # Use insert_many_np for NumPy arrays
233
235
  ```
234
236
 
235
237
  **Does fastquadtree support multiprocessing?**
236
- 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. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. 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, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
238
+ 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. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. Native decode uses a default preallocation limit of 67,108,864 bytes (64 MiB); if loading needs more than the configured bucket, `from_bytes()` fails with a `ValueError` unless you choose a larger allowed bucket or pass `disable_preallocation_limit=True` for trusted data. 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, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
239
+
240
+ Serialization uses the current fastquadtree binary format. Data serialized by bincode-backed fastquadtree releases, including v2.2 and earlier, is not loadable by newer wincode-backed releases.
237
241
 
238
242
  ## License
239
243
 
@@ -32,6 +32,7 @@ Rust-optimized quadtree with a clean Python API
32
32
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
33
33
  - Fast KNN and range queries
34
34
  - Optional object tracking for id ↔ object mapping
35
+ - Mostly drop-in [pygame sprite-group integration](https://elan456.github.io/fastquadtree/api/pygame/) that adds automatic broadphase culling plus rect queries and k-NN over sprite rects
35
36
  - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
36
37
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
37
38
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -58,6 +59,7 @@ from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~10x faster whil
58
59
  | `QuadTreeObjects` | Points | Yes | Point indexing with attached Python objects. |
59
60
  | `RectQuadTreeObjects` | Bounding boxes | Yes | Rectangle indexing with attached objects. |
60
61
  | `fastquadtree.pyqtree.Index` | Bounding boxes | Yes | pyqtree-compatible API, much faster. |
62
+ | `fastquadtree.pygame.Group` | pygame sprites | Yes | Mostly drop-in `Group` with sprite queries. |
61
63
 
62
64
 
63
65
  ## Quickstart
@@ -141,7 +143,7 @@ See the [benchmark section](https://elan456.github.io/fastquadtree/benchmark/) f
141
143
 
142
144
  * `bounds` — tuple `(min_x, min_y, max_x, max_y)` defines the 2D area covered by the quadtree
143
145
  * `capacity` — max number of points kept in a leaf before splitting
144
- * `max_depth` — optional depth cap. If omitted, the tree can keep splitting as needed
146
+ * `max_depth` — optional depth cap. If omitted, uses the [engine default](https://elan456.github.io/fastquadtree/engine_defaults/#max-depth)
145
147
  * `dtype` — data type for coordinates, e.g., `"f32"`, `"f64"`, `"i32"`, `"i64"`
146
148
 
147
149
  ### Key Methods
@@ -203,7 +205,9 @@ qt.insert_many_np(points) # Use insert_many_np for NumPy arrays
203
205
  ```
204
206
 
205
207
  **Does fastquadtree support multiprocessing?**
206
- 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. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. 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, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
208
+ 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. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. Native decode uses a default preallocation limit of 67,108,864 bytes (64 MiB); if loading needs more than the configured bucket, `from_bytes()` fails with a `ValueError` unless you choose a larger allowed bucket or pass `disable_preallocation_limit=True` for trusted data. 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, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
209
+
210
+ Serialization uses the current fastquadtree binary format. Data serialized by bincode-backed fastquadtree releases, including v2.2 and earlier, is not loadable by newer wincode-backed releases.
207
211
 
208
212
  ## License
209
213
 
@@ -38,9 +38,9 @@ def _build_tree_np(points_np: np.ndarray) -> float:
38
38
  # Direct NumPy path
39
39
  inserted = qt.insert_many_np(points_np)
40
40
  dt = now() - t0
41
- assert (
42
- inserted.count == points_np.shape[0]
43
- ), f"Inserted {inserted} != {points_np.shape[0]}"
41
+ assert inserted.count == points_np.shape[0], (
42
+ f"Inserted {inserted} != {points_np.shape[0]}"
43
+ )
44
44
  return dt
45
45
 
46
46
 
@@ -49,9 +49,9 @@ def _build_tree_list(points_list: list[tuple[float, float]]) -> float:
49
49
  qt = ShimQuadTree(BOUNDS, CAPACITY, max_depth=MAX_DEPTH)
50
50
  inserted = qt.insert_many(points_list)
51
51
  dt = now() - t0
52
- assert inserted.count == len(
53
- points_list
54
- ), f"Inserted {inserted} != {len(points_list)}"
52
+ assert inserted.count == len(points_list), (
53
+ f"Inserted {inserted} != {len(points_list)}"
54
+ )
55
55
  return dt
56
56
 
57
57
 
@@ -288,6 +288,8 @@ rqt_obj.update(id_, new_min_x, new_min_y, new_max_x, new_max_y)
288
288
 
289
289
  The serialization format has changed. **v1 serialized data cannot be loaded in v2.**
290
290
 
291
+ The native core codec changed again after v2.2 from bincode to wincode. Bincode-backed serialized data from fastquadtree v2.2 and earlier is not loadable by newer wincode-backed releases.
292
+
291
293
  ### Before (v1.x)
292
294
 
293
295
  ```python
@@ -455,4 +457,4 @@ from fastquadtree import (
455
457
  PointItem,
456
458
  RectItem,
457
459
  )
458
- ```
460
+ ```
@@ -0,0 +1,8 @@
1
+ # fastquadtree.pygame
2
+
3
+ !!! note "Optional dependency"
4
+ Core `fastquadtree` APIs do not require pygame. This page documents the
5
+ optional `fastquadtree.pygame` integration, which requires pygame or a
6
+ compatible package such as `pygame-ce` when imported at runtime.
7
+
8
+ ::: fastquadtree.pygame
@@ -132,22 +132,22 @@ If your data is already in a NumPy array, using the `insert_many_np` method dire
132
132
 
133
133
  | Variant | Mean (s) | Stdev (s) |
134
134
  |---|---:|---:|
135
- | Serialize to bytes | 0.021356 | 0.000937 |
136
- | Rebuild from points | 0.106783 | 0.011430 |
137
- | Rebuild from bytes | 0.021754 | 0.001687 |
138
- | Rebuild from file | 0.024887 | 0.001846 |
135
+ | Serialize to bytes | 0.011789 | 0.000617 |
136
+ | Rebuild from points | 0.088791 | 0.001616 |
137
+ | Rebuild from bytes | 0.007105 | 0.000137 |
138
+ | Rebuild from file | 0.012052 | 0.000442 |
139
139
 
140
140
  ### Summary
141
141
 
142
- - Rebuild from bytes is **4.908747x** faster than reinserting points.
143
- - Rebuild from file is **4.290712x** faster than reinserting points.
144
- - Serialized blob size is **13,770,328 bytes**.
142
+ - Rebuild from bytes is **12.497145x** faster than reinserting points.
143
+ - Rebuild from file is **7.367322x** faster than reinserting points.
144
+ - Serialized blob size is **18,104,173 bytes**.
145
145
 
146
146
  ----------------
147
147
 
148
148
  ## System Info
149
- - **OS**: CachyOS 6.18.5-2-cachyos x86_64
150
- - **Python**: CPython 3.14.2
149
+ - **OS**: CachyOS 7.0.10-1-cachyos x86_64
150
+ - **Python**: CPython 3.14.5
151
151
  - **CPU**: AMD Ryzen 7 3700X 8-Core Processor (16 threads)
152
152
  - **Memory**: 31.3 GB
153
153
  - **GPU**: NVIDIA GeForce RTX 5070 (11.9 GB)
@@ -0,0 +1,73 @@
1
+ # Engine Defaults
2
+
3
+ ## max_depth {#max-depth}
4
+
5
+ When `max_depth=None`, the native Python APIs use a dtype-specific engine
6
+ default. These defaults apply to `QuadTree`, `RectQuadTree`,
7
+ `QuadTreeObjects`, `RectQuadTreeObjects`, and the `fastquadtree.pygame`
8
+ integration when `max_depth` is omitted.
9
+
10
+ | dtype | Engine default `max_depth` |
11
+ |---|---:|
12
+ | `f32` | 24 |
13
+ | `f64` | 53 |
14
+ | `i32` | 32 |
15
+ | `i64` | 64 |
16
+
17
+ Use `get_inner_max_depth()` on a constructed tree to inspect the resolved
18
+ engine value.
19
+
20
+ ### Why These Values?
21
+
22
+ Infinite subdivision was the default behavior prior to version 1.4.3. With
23
+ infinite subdivision, inserting two points at the same location could keep
24
+ splitting forever and eventually exhaust memory, as seen in
25
+ [issue #10](https://github.com/Elan456/fastquadtree/issues/10). The engine
26
+ default now caps subdivision before it can become unbounded.
27
+
28
+ One alternative would be for the engine to check for duplicate coordinates
29
+ before splitting. However, doing so would add work to each insert and make
30
+ splitting behavior harder to define for cells that contain a mixture of
31
+ duplicate and nearby non-duplicate points. Letting duplicated points create a
32
+ depth of 24 or 53 in some parts of the tree can also hurt traversal time, so the
33
+ default is a compromise rather than a perfect answer for every workload.
34
+
35
+ The default caps are based on a practical starting point for each dtype. Each
36
+ quadtree level halves a node's width and height:
37
+
38
+ ```text
39
+ cell_width_at_depth_d = world_width / 2^d
40
+ cell_height_at_depth_d = world_height / 2^d
41
+ ```
42
+
43
+ The chosen defaults are roughly aligned with the binary precision available for
44
+ each coordinate type:
45
+
46
+ - `f32` uses 24 because single-precision floats have about 24 bits of
47
+ significand precision.
48
+ - `f64` uses 53 because double-precision floats have about 53 bits of
49
+ significand precision.
50
+ - `i32` uses 32 and `i64` uses 64 because integer coordinates cannot provide
51
+ more distinct binary subdivision steps than their bit width.
52
+
53
+ These values are safety defaults, not hard limits on useful subdivision. World
54
+ size and data distribution still matter. For example, with `f32` and a world
55
+ width of `1_000_000_000`, depth 24 still leaves cells about 60 units wide:
56
+
57
+ ```text
58
+ 1_000_000_000 / 2^24 ~= 59.6
59
+ ```
60
+
61
+ If most of your points are clustered near the origin and you need to separate
62
+ features smaller than that, more than 24 splits can still be meaningful. In that
63
+ case, pass an explicit `max_depth` larger than the engine default.
64
+
65
+ For `i32` and `i64`, there is generally no situation where you would need more
66
+ than 32 and 64 subdivisions, respectively.
67
+
68
+ The defaults are intended to be a relatively safe starting point. Use tighter
69
+ world bounds, coordinate normalization, or an explicit `max_depth` when your
70
+ world is very large compared with the area where points actually cluster.
71
+
72
+ For best performance, choose a `max_depth` that keeps leaf cells near the scale
73
+ of your typical queries and data spacing.
@@ -41,7 +41,7 @@
41
41
  - Support for [inserting bounding boxes](api/rect_quadtree.md) or points
42
42
  - Fast KNN and range queries
43
43
  - Optional object tracking for id ↔ object mapping
44
- - Drop-in [pygame sprite-group integration](api/pygame.md) that adds automatic broadphase culling for faster collision detection (depending on workload)
44
+ - Mostly drop-in [pygame sprite-group integration](api/pygame.md) that adds automatic broadphase culling plus rect queries and k-NN over sprite rects
45
45
  - Fast [serialization](benchmark.md#serialization-vs-rebuild) to/from bytes
46
46
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
47
47
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -63,5 +63,5 @@ from fastquadtree import RectQuadTree # Bounding box handling
63
63
  from fastquadtree import QuadTreeObjects # Point handling with object tracking
64
64
  from fastquadtree import RectQuadTreeObjects # Bounding box handling with object tracking
65
65
  from fastquadtree.pyqtree import Index # Drop-in replacement for pyqtree (~10x faster while keeping the same API)
66
- from fastquadtree.pygame import Group # Drop-in replacement for pygame.sprite.Group with quadtree indexing (pygame install required)
66
+ from fastquadtree.pygame import Group # Mostly drop-in pygame Group with quadtree queries (pygame install required)
67
67
  ```
@@ -103,15 +103,16 @@ Tip: Use `QuadTree` instead of `QuadTreeObjects` for max speed when you do not n
103
103
 
104
104
  ---
105
105
 
106
- ## Pygame sprite groups
106
+ ## Pygame sprite groups and spatial queries
107
107
 
108
- The optional `fastquadtree.pygame` module provides a mostly drop-in
109
- `pygame.sprite.Group` replacement plus collision helpers shaped like pygame's
110
- own `spritecollide(...)` APIs. It indexes sprite `rect` bounds to give you
111
- automatic broadphase culling for collision queries and viewport culling.
108
+ The optional `fastquadtree.pygame` module provides a pygame sprite group backed
109
+ by `RectQuadTreeObjects`. It supports normal sprite-group operations, collision
110
+ helpers shaped like pygame's own `spritecollide(...)` APIs, and direct spatial
111
+ queries such as rectangle queries and k-nearest-neighbor search over sprite
112
+ `rect` bounds.
112
113
 
113
114
  This is most useful when you have many static or mostly stable sprites and each
114
- query touches only a small part of the world. The tradeoff is tree maintenance:
115
+ query touches only a small part of the world. The tradeoff is index maintenance:
115
116
  moving indexed sprites need `Group.update(...)` or `Group.sync(...)` so the
116
117
  index reflects their current rects. If most sprites move every frame, create the
117
118
  group with `rebuild_on_update=True` to rebuild the index after each
@@ -124,14 +125,20 @@ import fastquadtree.pygame as fpygame
124
125
  world_bounds = (0, 0, 2000, 2000)
125
126
  blocks = fpygame.Group(bounds=world_bounds)
126
127
  blocks.add(block_sprites)
128
+ blocks.add(enemy_sprite)
127
129
 
128
130
  # Collision helper with the same shape as pygame.sprite.spritecollide.
129
131
  hits = fpygame.spritecollide(player, blocks, dokill=False)
130
132
 
131
133
  # Rectangle queries can use pygame.Rect or (min_x, min_y, max_x, max_y) bounds.
132
- visible = blocks.query_rect(camera_rect, sync=False)
134
+ visible = blocks.query(camera_rect, sync=False)
133
135
  for sprite in visible:
134
136
  screen.blit(sprite.image, sprite.rect.move(-camera_x, -camera_y))
137
+
138
+ # Direct spatial queries return sprites.
139
+ nearest = blocks.nearest_neighbors(player.rect.center, k=5)
140
+ for sprite in nearest:
141
+ print(sprite)
135
142
  ```
136
143
 
137
144
  pygame is not a required dependency for core `fastquadtree`; install a
@@ -62,7 +62,7 @@ uv run python interactive/ballpit.py
62
62
  ![Ballpit_Demo_Screenshot](https://raw.githubusercontent.com/Elan456/fastquadtree/main/assets/ballpit.png)
63
63
 
64
64
  ## 3. Pygame sprite group comparison
65
- - Compare `pygame.sprite.Group` with the mostly drop-in `fastquadtree.pygame.Group`
65
+ - Compare `pygame.sprite.Group` with the quadtree-backed `fastquadtree.pygame.Group`
66
66
  - Press `G` to switch group backends while the demo is running
67
67
  - Uses the fastquadtree-backed group for automatic broadphase culling
68
68
 
@@ -70,7 +70,7 @@ This demo creates many static block sprites and a moving player. Player
70
70
  collision uses the normal `spritecollide(...)` flow for both backends. Viewport
71
71
  culling asks "which blocks intersect the camera rect?" The pygame backend
72
72
  answers by scanning every block, while the fastquadtree backend can answer the
73
- same rectangle query through `Group.query_rect(...)`.
73
+ same rectangle query through `Group.query(...)`.
74
74
 
75
75
  The performance tradeoff is tree maintenance. The demo uses static blocks, so
76
76
  the fastquadtree group can reuse its index frame after frame. If most indexed
@@ -87,6 +87,7 @@ nav:
87
87
  - Benchmark: benchmark.md
88
88
  - Future Features: future_features.md
89
89
  - Rust Usage: rust_usage.md
90
+ - Engine Defaults: engine_defaults.md
90
91
  - API:
91
92
  - QuadTree: api/quadtree.md
92
93
  - RectQuadTree: api/rect_quadtree.md
@@ -53,7 +53,7 @@ compatibility = "manylinux_2_28"
53
53
  # uv sync will install the "dev" group by default.
54
54
  [dependency-groups]
55
55
  dev = [ # Testing and build dependencies
56
- "ruff>=0.6.0",
56
+ "ruff>=0.15.15",
57
57
  "pytest>=8.4.2",
58
58
  "pytest-cov>=7.0.0",
59
59
  "coverage>=7.5",