0
# Advanced Features
1
2
Advanced spatial indexing capabilities that extend beyond basic CRUD operations. These features provide high-performance bulk operations, custom storage implementations, temporal indexing, and set operations between indexes.
3
4
## Capabilities
5
6
### Bulk Operations with NumPy
7
8
High-performance bulk queries using NumPy arrays for processing multiple spatial queries efficiently.
9
10
```python { .api }
11
def intersection_v(self, mins, maxs):
12
"""
13
Bulk intersection query for multiple bounding boxes.
14
15
Parameters:
16
- mins (array-like): Minimum coordinates for each query box
17
- maxs (array-like): Maximum coordinates for each query box
18
19
Returns:
20
tuple: (ids, counts) where:
21
- ids: Flattened array of all intersecting item IDs
22
- counts: Array of intersection counts for each query box
23
"""
24
25
def nearest_v(self, mins, maxs, *, num_results=1, max_dists=None, strict=False, return_max_dists=False):
26
"""
27
Bulk k-nearest neighbor query for multiple bounding boxes.
28
29
Parameters:
30
- mins (array-like): Minimum coordinates for each query box
31
- maxs (array-like): Maximum coordinates for each query box
32
- num_results (int): Number of nearest neighbors to find per query
33
- max_dists (array-like, optional): Maximum search distances
34
- strict (bool): Strict distance checking
35
- return_max_dists (bool): Return maximum distances found
36
37
Returns:
38
tuple: (ids, counts) or (ids, counts, distances) if return_max_dists=True
39
"""
40
```
41
42
Usage example:
43
44
```python
45
import numpy as np
46
from rtree import index
47
48
# Create index with sample data
49
idx = index.Index()
50
for i in range(100):
51
x, y = i % 10, i // 10
52
idx.insert(i, (x, y, x+1, y+1))
53
54
# Bulk intersection queries
55
query_mins = np.array([[0, 0], [2, 2], [5, 5]])
56
query_maxs = np.array([[1, 1], [3, 3], [6, 6]])
57
58
ids, counts = idx.intersection_v(query_mins, query_maxs)
59
print(f"Found {len(ids)} total intersections")
60
print(f"Per-query counts: {counts}")
61
62
# Bulk nearest neighbor queries
63
nearest_ids, nearest_counts = idx.nearest_v(query_mins, query_maxs, num_results=3)
64
print(f"Found {len(nearest_ids)} nearest neighbors")
65
```
66
67
### Custom Storage Implementation
68
69
Implement custom storage backends for specialized use cases like ZODB integration or custom persistence layers.
70
71
```python { .api }
72
class ICustomStorage:
73
"""
74
Interface for custom storage implementations.
75
76
Must implement all abstract methods for data persistence.
77
"""
78
79
def create(self, name): ...
80
def destroy(self, name): ...
81
def open(self, name): ...
82
def close(self): ...
83
def flush(self): ...
84
def read(self, page, length): ...
85
def write(self, page, data): ...
86
def delete(self, page): ...
87
88
class CustomStorageBase(ICustomStorage):
89
"""
90
Base class for custom storage with default implementations.
91
92
Provides basic structure that can be extended for specific storage needs.
93
"""
94
95
class CustomStorage(ICustomStorage):
96
"""
97
Template custom storage implementation.
98
99
Example implementation showing the storage interface pattern.
100
"""
101
```
102
103
Usage example:
104
105
```python
106
from rtree import index
107
108
class MemoryStorage(index.CustomStorageBase):
109
def __init__(self):
110
self._data = {}
111
self._next_page = 0
112
113
def create(self, name):
114
self._data = {}
115
return 0
116
117
def write(self, page, data):
118
self._data[page] = data
119
return len(data)
120
121
def read(self, page, length):
122
return self._data.get(page, b'')
123
124
# Use custom storage
125
storage = MemoryStorage()
126
idx = index.Index(storage=storage)
127
```
128
129
### TPR-Tree Temporal Indexing
130
131
Support for Time-Parameterized R-Trees (TPR-Tree) that handle moving objects with temporal queries.
132
133
```python { .api }
134
class Property:
135
tpr_horizon: float
136
"""
137
Time horizon for TPR-Tree temporal queries.
138
139
Sets the time window for trajectory prediction.
140
"""
141
```
142
143
TPR-Tree indexes use specialized coordinate formats that include velocity information:
144
145
```python
146
from rtree import index
147
148
# Configure for TPR-Tree
149
p = index.Property()
150
p.type = index.RT_TPRTree
151
p.tpr_horizon = 100.0
152
153
tpr_idx = index.Index(properties=p)
154
155
# Insert moving object: ((position_bounds), (velocity_bounds), time)
156
tpr_idx.insert(0, ((0, 0, 1, 1), (0.1, 0.1, 0.1, 0.1), 0.0))
157
```
158
159
### Set Operations
160
161
Perform set operations between spatial indexes to combine or compare their contents.
162
163
```python { .api }
164
def __and__(self, other: Index) -> Index:
165
"""
166
Intersection of two indexes - items present in both indexes.
167
168
Parameters:
169
- other (Index): Another spatial index
170
171
Returns:
172
Index: New index containing items in both indexes
173
"""
174
175
def __or__(self, other: Index) -> Index:
176
"""
177
Union of two indexes - items present in either index.
178
179
Parameters:
180
- other (Index): Another spatial index
181
182
Returns:
183
Index: New index containing items from both indexes
184
"""
185
```
186
187
Usage example:
188
189
```python
190
from rtree import index
191
192
# Create two indexes
193
idx1 = index.Index()
194
idx1.insert(0, (0, 0, 1, 1))
195
idx1.insert(1, (1, 1, 2, 2))
196
197
idx2 = index.Index()
198
idx2.insert(1, (1, 1, 2, 2)) # Overlapping item
199
idx2.insert(2, (2, 2, 3, 3))
200
201
# Set operations
202
intersection_idx = idx1 & idx2 # Items in both
203
union_idx = idx1 | idx2 # Items in either
204
205
print(len(intersection_idx)) # 1
206
print(len(union_idx)) # 3
207
```
208
209
### Advanced Index Properties
210
211
Configure specialized index behaviors and performance characteristics.
212
213
```python { .api }
214
class Property:
215
near_minimum_overlap_factor: int
216
"""
217
Factor for near minimum overlap splitting in R*-Tree.
218
"""
219
220
split_distribution_factor: float
221
"""
222
Distribution factor for node splitting algorithms.
223
"""
224
225
reinsert_factor: float
226
"""
227
Reinsertion factor for R*-Tree forced reinsertion.
228
"""
229
230
tight_mbr: bool
231
"""
232
Use tight minimum bounding rectangles.
233
"""
234
235
buffering_capacity: int
236
"""
237
Buffer capacity for batched operations.
238
"""
239
240
point_pool_capacity: int
241
"""
242
Capacity of the point object pool.
243
"""
244
245
region_pool_capacity: int
246
"""
247
Capacity of the region object pool.
248
"""
249
```
250
251
### Stream-Based Bulk Loading
252
253
Load large datasets efficiently using stream-based bulk loading.
254
255
```python { .api }
256
def __init__(self, stream, **kwargs):
257
"""
258
Create index from a stream of data for efficient bulk loading.
259
260
Parameters:
261
- stream (iterable): Stream of (id, coordinates, object) tuples
262
263
Stream format:
264
- Regular R-Tree: (id, coordinates, object)
265
- TPR-Tree: (id, ((pos_coords), (vel_coords), time), object)
266
"""
267
```
268
269
Usage example:
270
271
```python
272
from rtree import index
273
274
def data_stream():
275
"""Generator that yields spatial data."""
276
for i in range(10000):
277
x, y = i % 100, i // 100
278
yield (i, (x, y, x+1, y+1), f"Object {i}")
279
280
# Bulk load from stream - more efficient than individual inserts
281
idx = index.Index(data_stream())
282
print(f"Bulk loaded {len(idx)} items")
283
```
284
285
### Serialization and Persistence
286
287
Control object serialization for stored data and index persistence.
288
289
```python { .api }
290
def dumps(self, obj: object) -> bytes:
291
"""
292
Serialize an object for storage in the index.
293
294
Parameters:
295
- obj (object): Object to serialize
296
297
Returns:
298
bytes: Serialized object data
299
300
Note:
301
Default implementation uses pickle. Override for custom serialization.
302
"""
303
304
def loads(self, string: bytes) -> object:
305
"""
306
Deserialize an object from index storage.
307
308
Parameters:
309
- string (bytes): Serialized object data
310
311
Returns:
312
object: Deserialized object
313
314
Note:
315
Default implementation uses pickle. Override for custom deserialization.
316
"""
317
318
def __getstate__(self) -> dict[str, Any]:
319
"""
320
Get state for pickle serialization of the index itself.
321
322
Returns:
323
dict: Index state for serialization
324
"""
325
326
def __setstate__(self, state: dict[str, Any]) -> None:
327
"""
328
Restore index state from pickle deserialization.
329
330
Parameters:
331
- state (dict): Index state from serialization
332
"""
333
```
334
335
Usage example with custom serialization:
336
337
```python
338
import json
339
from rtree import index
340
341
class JSONIndex(index.Index):
342
def dumps(self, obj):
343
return json.dumps(obj).encode('utf-8')
344
345
def loads(self, data):
346
return json.loads(data.decode('utf-8'))
347
348
# Use custom serialization
349
json_idx = JSONIndex()
350
json_idx.insert(0, (0, 0, 1, 1), obj={"name": "Building", "floors": 5})
351
352
# Objects are serialized as JSON instead of pickle
353
for item in json_idx.intersection((0, 0, 1, 1), objects=True):
354
print(item.object) # {"name": "Building", "floors": 5}
355
```
356
357
### Leaf Node Access
358
359
Access detailed information about index leaf nodes for advanced analysis.
360
361
```python { .api }
362
def leaves(self):
363
"""
364
Get information about leaf nodes in the index.
365
366
Returns:
367
Generator yielding leaf node information including:
368
- Node IDs
369
- Child item IDs
370
- Node bounding boxes
371
"""
372
```
373
374
Usage example:
375
376
```python
377
from rtree import index
378
379
idx = index.Index()
380
for i in range(10):
381
idx.insert(i, (i, i, i+1, i+1))
382
383
# Examine leaf structure
384
leaf_info = list(idx.leaves())
385
print(f"Index has {len(leaf_info)} leaf nodes")
386
```
387
388
### Result Set Control
389
390
Control query result pagination and limits.
391
392
```python { .api }
393
@property
394
def result_limit(self) -> int:
395
"""
396
Get/set the maximum number of results returned by queries.
397
398
Returns:
399
int: Current result limit
400
"""
401
402
@property
403
def result_offset(self) -> int:
404
"""
405
Get/set the offset for query results (pagination).
406
407
Returns:
408
int: Current result offset
409
"""
410
```
411
412
Usage example:
413
414
```python
415
from rtree import index
416
417
idx = index.Index()
418
for i in range(100):
419
idx.insert(i, (0, 0, 10, 10)) # All overlap
420
421
# Paginate results
422
idx.result_limit = 10
423
idx.result_offset = 20
424
425
hits = list(idx.intersection((0, 0, 10, 10)))
426
print(f"Got {len(hits)} results (page 3)") # Results 20-29
427
```
428
429
### Object-Oriented Container
430
431
Alternative object-oriented interface that automatically manages object-coordinate associations.
432
433
```python { .api }
434
class RtreeContainer:
435
"""
436
Object-oriented spatial container that automatically manages coordinate relationships.
437
438
Unlike the Index class which requires separate ID and coordinate management,
439
RtreeContainer directly stores objects and automatically handles coordinate associations.
440
"""
441
442
def __init__(self, *args: Any, **kwargs: Any) -> None:
443
"""
444
Create a new spatial container.
445
446
Parameters:
447
Same as Index constructor (properties, storage, etc.)
448
"""
449
450
def insert(self, obj: object, coordinates: Any) -> None:
451
"""
452
Insert an object with its spatial coordinates.
453
454
Parameters:
455
- obj (object): Object to store
456
- coordinates (sequence): Spatial coordinates
457
"""
458
459
def delete(self, obj: object, coordinates: Any) -> None:
460
"""
461
Delete an object from the container.
462
463
Parameters:
464
- obj (object): Object to remove
465
- coordinates (sequence): Object's coordinates
466
"""
467
468
def intersection(self, coordinates: Any, bbox: bool = False) -> Iterator[object | Item]:
469
"""
470
Find objects that intersect with coordinates.
471
472
Parameters:
473
- coordinates (sequence): Query bounds
474
- bbox (bool): Return Item objects with bounding boxes
475
476
Returns:
477
Iterator of objects or Item objects
478
"""
479
480
def nearest(self, coordinates: Any, num_results: int = 1, bbox: bool = True) -> Iterator[object | Item]:
481
"""
482
Find nearest objects to coordinates.
483
484
Parameters:
485
- coordinates (sequence): Query point
486
- num_results (int): Number of results
487
- bbox (bool): Return Item objects with bounding boxes
488
489
Returns:
490
Iterator of objects or Item objects
491
"""
492
493
def __contains__(self, obj: object) -> bool:
494
"""Check if object is in container."""
495
496
def __len__(self) -> int:
497
"""Get number of objects in container."""
498
499
def __iter__(self) -> Iterator[object]:
500
"""Iterate over all objects in container."""
501
```
502
503
Usage example:
504
505
```python
506
from rtree import index
507
508
# Create object-oriented container
509
container = index.RtreeContainer()
510
511
# Insert objects directly
512
buildings = [
513
{"name": "City Hall", "type": "government"},
514
{"name": "Library", "type": "public"},
515
{"name": "Mall", "type": "commercial"}
516
]
517
518
container.insert(buildings[0], (100, 100, 150, 150))
519
container.insert(buildings[1], (200, 200, 250, 250))
520
container.insert(buildings[2], (120, 120, 180, 180))
521
522
# Query for objects
523
for building in container.intersection((110, 110, 160, 160)):
524
print(f"Found: {building['name']}")
525
526
# Check membership
527
print(buildings[0] in container) # True
528
529
# Iterate over all objects
530
for building in container:
531
print(building['name'])
532
```