0
# Utilities and Support
1
2
Utility functions for library management, exception handling, coordinate format conversion, and supporting classes that enhance the Rtree functionality.
3
4
## Capabilities
5
6
### Library Management
7
8
Functions for loading and managing the underlying libspatialindex library.
9
10
```python { .api }
11
def load() -> ctypes.CDLL:
12
"""
13
Load the libspatialindex shared library.
14
15
Searches for the library in several locations:
16
- SPATIALINDEX_C_LIBRARY environment variable
17
- Package installation directory
18
- System library paths
19
- Conda environment paths (if applicable)
20
21
Returns:
22
ctypes.CDLL: Loaded shared library object
23
24
Raises:
25
OSError: If library cannot be found or loaded
26
"""
27
28
def get_include() -> str:
29
"""
30
Return the directory containing spatialindex header files.
31
32
Useful for building extensions or custom storage implementations.
33
Searches in:
34
- Package installation directory
35
- System include paths
36
- Conda environment paths
37
38
Returns:
39
str: Path to include directory or empty string if not found
40
"""
41
```
42
43
Usage example:
44
45
```python
46
from rtree import finder
47
48
# Load the library explicitly (usually done automatically)
49
try:
50
lib = finder.load()
51
print(f"Loaded library: {lib}")
52
except OSError as e:
53
print(f"Failed to load library: {e}")
54
55
# Get include directory for development
56
include_dir = finder.get_include()
57
if include_dir:
58
print(f"Headers available at: {include_dir}")
59
else:
60
print("Headers not found")
61
```
62
63
### Exception Handling
64
65
Exception classes for error handling in spatial indexing operations.
66
67
```python { .api }
68
class RTreeError(Exception):
69
"""
70
Main exception class for RTree-related errors.
71
72
Raised for various error conditions including:
73
- Invalid coordinate specifications
74
- Library initialization failures
75
- Storage or I/O errors
76
- Invalid property values
77
- Memory allocation errors
78
"""
79
pass
80
81
class InvalidHandleException(Exception):
82
"""
83
Exception raised when attempting to use a destroyed handle.
84
85
Handles become invalid after the associated index or property
86
object has been destroyed or closed.
87
"""
88
pass
89
```
90
91
Usage example:
92
93
```python
94
from rtree import index
95
from rtree.exceptions import RTreeError
96
97
try:
98
idx = index.Index()
99
# Invalid coordinates (min > max)
100
idx.insert(0, (1.0, 1.0, 0.0, 0.0))
101
except RTreeError as e:
102
print(f"Spatial index error: {e}")
103
104
try:
105
# Invalid property value
106
p = index.Property()
107
p.pagesize = -1000
108
except RTreeError as e:
109
print(f"Property error: {e}")
110
```
111
112
### Coordinate Format Conversion
113
114
Utility methods for converting between coordinate formats.
115
116
```python { .api }
117
@classmethod
118
def interleave(cls, deinterleaved: Sequence[float]) -> list[float]:
119
"""
120
Convert non-interleaved coordinates to interleaved format.
121
122
Parameters:
123
- deinterleaved (sequence): Coordinates in [minx, maxx, miny, maxy, ...] format
124
125
Returns:
126
list: Coordinates in [minx, miny, maxx, maxy, ...] format
127
128
Example:
129
[0, 2, 1, 3] -> [0, 1, 2, 3] # 2D case
130
"""
131
132
@classmethod
133
def deinterleave(cls, interleaved: Sequence[object]) -> list[object]:
134
"""
135
Convert interleaved coordinates to non-interleaved format.
136
137
Parameters:
138
- interleaved (sequence): Coordinates in [minx, miny, maxx, maxy, ...] format
139
140
Returns:
141
list: Coordinates in [minx, maxx, miny, maxy, ...] format
142
143
Example:
144
[0, 1, 2, 3] -> [0, 2, 1, 3] # 2D case
145
"""
146
```
147
148
Usage example:
149
150
```python
151
from rtree import index
152
153
# Convert coordinate formats
154
interleaved_coords = [0, 1, 2, 3] # minx, miny, maxx, maxy
155
non_interleaved = index.Index.deinterleave(interleaved_coords)
156
print(non_interleaved) # [0, 2, 1, 3] - minx, maxx, miny, maxy
157
158
# Convert back
159
back_to_interleaved = index.Index.interleave(non_interleaved)
160
print(back_to_interleaved) # [0, 1, 2, 3]
161
```
162
163
### Query Result Container
164
165
Container class for query results that provides access to item details.
166
167
```python { .api }
168
class Item:
169
"""
170
Container for index entries returned by query operations.
171
172
Automatically created when using objects=True in query methods.
173
Should not be instantiated directly.
174
"""
175
176
id: int
177
"""
178
Unique identifier of the index entry.
179
"""
180
181
object: object
182
"""
183
Python object stored with the entry (may be None).
184
"""
185
186
bounds: list[float]
187
"""
188
Bounding box coordinates in non-interleaved format.
189
Format: [minx, maxx, miny, maxy, minz, maxz, ...]
190
"""
191
192
@property
193
def bbox(self) -> list[float]:
194
"""
195
Bounding box coordinates in interleaved format.
196
197
Returns:
198
list: Coordinates in [minx, miny, maxx, maxy, ...] format
199
"""
200
201
def __lt__(self, other: Item) -> bool:
202
"""
203
Less than comparison based on item ID.
204
205
Parameters:
206
- other (Item): Another Item object
207
208
Returns:
209
bool: True if this item's ID is less than other's ID
210
"""
211
212
def __gt__(self, other: Item) -> bool:
213
"""
214
Greater than comparison based on item ID.
215
216
Parameters:
217
- other (Item): Another Item object
218
219
Returns:
220
bool: True if this item's ID is greater than other's ID
221
"""
222
```
223
224
Usage example:
225
226
```python
227
from rtree import index
228
229
idx = index.Index()
230
idx.insert(0, (0, 0, 1, 1), obj="Rectangle A")
231
idx.insert(1, (0.5, 0.5, 1.5, 1.5), obj="Rectangle B")
232
233
# Query returns Item objects
234
for item in idx.intersection((0, 0, 2, 2), objects=True):
235
print(f"ID: {item.id}")
236
print(f"Object: {item.object}")
237
print(f"Bounds (non-interleaved): {item.bounds}")
238
print(f"BBox (interleaved): {item.bbox}")
239
print("---")
240
241
# Items can be sorted by ID
242
items = list(idx.intersection((0, 0, 2, 2), objects=True))
243
items.sort() # Sorts by ID using __lt__
244
print([item.id for item in items]) # [0, 1]
245
```
246
247
### Internal Handle Classes
248
249
Low-level handle classes for advanced usage and custom storage implementations.
250
251
```python { .api }
252
class Handle:
253
"""
254
Base handle class for internal resource management.
255
256
Handles the lifecycle of underlying C library objects.
257
"""
258
259
def __init__(self, *args: Any, **kwargs: Any) -> None:
260
"""Initialize handle with C library resources."""
261
262
def destroy(self) -> None:
263
"""Destroy handle and free associated resources."""
264
265
@property
266
def _as_parameter_(self) -> ctypes.c_void_p:
267
"""Return handle as ctypes parameter for C library calls."""
268
269
class IndexHandle(Handle):
270
"""
271
Handle for spatial index objects.
272
273
Manages the connection to libspatialindex index instances.
274
"""
275
276
def flush(self) -> None:
277
"""Flush pending operations to storage."""
278
279
class IndexStreamHandle(IndexHandle):
280
"""
281
Handle for stream-based index operations.
282
283
Used during bulk loading from data streams.
284
"""
285
286
class IndexArrayHandle(IndexHandle):
287
"""
288
Handle for array-based bulk operations (optional).
289
290
Available when libspatialindex supports array operations.
291
"""
292
293
class PropertyHandle(Handle):
294
"""
295
Handle for property objects.
296
297
Manages property configuration in the C library.
298
"""
299
```
300
301
Note: Handle classes are primarily for internal use and custom storage implementations. Most users should not need to interact with them directly.
302
303
### Version Information
304
305
Access version information for the library and its components.
306
307
```python { .api }
308
__version__: str
309
"""Rtree Python package version string."""
310
311
__c_api_version__: bytes
312
"""libspatialindex C library version (as bytes)."""
313
314
major_version: int
315
"""Major version of libspatialindex C library."""
316
317
minor_version: int
318
"""Minor version of libspatialindex C library."""
319
320
patch_version: int
321
"""Patch version of libspatialindex C library."""
322
```
323
324
Usage example:
325
326
```python
327
from rtree import __version__
328
from rtree.index import __c_api_version__, major_version, minor_version, patch_version
329
330
print(f"Rtree Python version: {__version__}") # "1.4.1"
331
print(f"libspatialindex version: {__c_api_version__.decode('utf-8')}") # C library version
332
print(f"C library version components: {major_version}.{minor_version}.{patch_version}")
333
```
334
335
### Constants and Enumerations
336
337
Named constants for configuring index behavior.
338
339
```python { .api }
340
# Index Types
341
RT_RTree = 0 # Standard R-Tree
342
RT_MVRTree = 1 # Multi-Version R-Tree
343
RT_TPRTree = 2 # Time-Parameterized R-Tree
344
345
# Index Variants
346
RT_Linear = 0 # Linear splitting algorithm
347
RT_Quadratic = 1 # Quadratic splitting algorithm
348
RT_Star = 2 # R*-Tree splitting algorithm
349
350
# Storage Types
351
RT_Memory = 0 # Memory-based storage
352
RT_Disk = 1 # File-based storage
353
RT_Custom = 2 # Custom storage implementation
354
```
355
356
Usage example:
357
358
```python
359
from rtree import index
360
361
# Use constants for clarity
362
p = index.Property()
363
p.type = index.RT_RTree
364
p.variant = index.RT_Star
365
p.storage = index.RT_Memory
366
367
idx = index.Index(properties=p)
368
```
369
370
### Debug and Inspection Utilities
371
372
Tools for inspecting index state and debugging spatial operations.
373
374
```python { .api }
375
def get_coordinate_pointers(self, coordinates: Sequence[float]) -> tuple[float, float]:
376
"""
377
Convert coordinates to internal pointer format.
378
379
Parameters:
380
- coordinates (sequence): Spatial coordinates
381
382
Returns:
383
tuple: Internal coordinate representation
384
385
Note: Primarily for debugging and advanced use cases.
386
"""
387
```
388
389
### Serialization Support
390
391
Built-in serialization methods for index persistence.
392
393
```python { .api }
394
def dumps(self, obj: object) -> bytes:
395
"""
396
Serialize an object for storage (default: pickle).
397
398
Parameters:
399
- obj (object): Object to serialize
400
401
Returns:
402
bytes: Serialized object data
403
404
Note: Override this method to implement custom serialization.
405
"""
406
407
def loads(self, string: bytes) -> object:
408
"""
409
Deserialize an object from storage (default: pickle).
410
411
Parameters:
412
- string (bytes): Serialized object data
413
414
Returns:
415
object: Deserialized object
416
417
Note: Override this method to implement custom deserialization.
418
"""
419
```
420
421
### Error Checking Functions
422
423
Internal error checking utilities (primarily for development).
424
425
```python
426
# Internal error checking functions
427
def check_return(result, func, cargs): ...
428
def check_void(result, func, cargs): ...
429
def check_value(result, func, cargs): ...
430
```
431
432
Note: These are internal functions used by the library for C API error checking. They are not part of the public API but may be visible in advanced usage scenarios.
433
434
## Common Usage Patterns
435
436
### Robust Error Handling
437
```python
438
from rtree import index
439
from rtree.exceptions import RTreeError
440
441
def safe_spatial_operation():
442
try:
443
idx = index.Index()
444
idx.insert(0, (0, 0, 1, 1))
445
return list(idx.intersection((0, 0, 1, 1)))
446
except RTreeError as e:
447
print(f"Spatial index error: {e}")
448
return []
449
except Exception as e:
450
print(f"Unexpected error: {e}")
451
return []
452
```
453
454
### Library Validation
455
```python
456
from rtree import finder
457
458
def check_library_availability():
459
try:
460
lib = finder.load()
461
include_dir = finder.get_include()
462
463
print(f"✓ Library loaded successfully")
464
if include_dir:
465
print(f"✓ Headers available at: {include_dir}")
466
else:
467
print("⚠ Headers not found (development features limited)")
468
469
return True
470
except OSError as e:
471
print(f"✗ Library not available: {e}")
472
return False
473
```
474
475
### Coordinate Format Management
476
```python
477
from rtree import index
478
479
def normalize_coordinates(coords, target_format="interleaved"):
480
"""Convert coordinates to specified format."""
481
if target_format == "interleaved":
482
# Assume input is non-interleaved, convert to interleaved
483
return index.Index.interleave(coords)
484
else:
485
# Assume input is interleaved, convert to non-interleaved
486
return index.Index.deinterleave(coords)
487
488
# Usage
489
non_interleaved = [0, 2, 1, 3] # minx, maxx, miny, maxy
490
interleaved = normalize_coordinates(non_interleaved, "interleaved")
491
print(interleaved) # [0, 1, 2, 3] - minx, miny, maxx, maxy
492
```