文章目录
代码调用
def test_rtree():
r0 = (0, 0, 5, 5)
r1 = (5, 5, 10, 10)
r2 = (10, 10, 15, 15)
idx.insert(0, r0)
idx.insert(1, r1)
idx.insert(2, r2)
# 查找某个范围内的对象个数
count = idx.count((0, 0, 10, 10)) # 3
count = idx.count((0, 0, 9, 9)) # 2
print('-- count : ', count )
# 叶子结点 (id, child_ids, bounds)
print('-- leaves : ', idx.leaves()) # [(0, [0, 1, 2], [0.0, 0.0, 15.0, 15.0])]
# 最近邻搜索
nearest = list(idx.nearest((5, 15, 10, 20), num_results=2)) # [2, 1]
nearest = list(idx.nearest((11, 11, 15, 13), num_results=2)) # [2, 1]
print('-- nearest : ', nearest )
# num_result=0 和 num_result=1 等同, num_result=-1,-2... 的时候全部的点都会列出来
# 查找所有交集对象
hits = list(idx.intersection((6, 6, 8, 11))) # [1]
hits = list(idx.intersection((6, 6, 11, 11))) # [1, 2]
# 返回ID列表
# list(idx.intersection((0,0,10,10))) → [4321, 4322]
# # 返回对象(带边界信息)
# list(idx.intersection(..., objects=True)) → [<Item object>]
# # 返回原始对象(最快)
hits = list(idx.intersection((6, 6, 11, 11), objects="raw")) # [None, None] # [42, "text"]
hits = list(idx.intersection((5, 5, 11, 11), objects="raw")) # [None, None, None]
print('-- hits : ', hits )
# 和矩形 (0,0,4,4) 有交集对象(即使一个点)
in_window = list(idx.intersection((0, 0, 4, 4), objects=False)) # [0]
in_window = list(idx.intersection((0, 0, 10, 10), objects=False)) # [0, 1, 2]
in_window = list(idx.intersection((0, 0, 9, 9), objects=False)) # [0, 1]
print('-- in_window : ', in_window )
# 检测两个矩形是否相交
r3 = (4, 4, 8, 8)
intersects = any(idx.intersection(r3, objects=[r0, r1, r2])) # True
intersects = any(idx.intersection(r3, objects=[r0])) # True
print('-- intersects : ', intersects )
intersects = any(idx.intersection(r3, objects=[r2])) #
print('-- intersects : ', intersects )
for item in idx.intersection(r3, objects=True): # 返回生成器
print(item.bounds) # (xmin, xmax, ymin, ymax)
# [0.0, 5.0, 0.0, 5.0] | [5.0, 10.0, 5.0, 10.0]
for item in idx.intersection(r3, objects=False): # 返回 id
print(item) # 0, 1
源码分析 - 主要类和功能概览
该源代码实现了一个基于 R-tree 的空间索引库,支持三种树类型(R-tree、MVR-tree、TPR-tree)。以下是核心组件:
一、核心类说明
1. Index
类(主索引类)
- 功能:实现空间索引(R-tree/MVR-tree/TPR-tree)
- 关键属性:
interleaved
:坐标顺序(True: [xmin, ymin, xmax, ymax] / False: [xmin, xmax, ymin, ymax])properties
:索引配置(通过Property
类设置)
- 核心方法:
insert(id, coordinates, obj)
:插入空间对象- TPR-tree 需额外提供速度向量和时间
delete(id, coordinates)
:删除对象intersection(coordinates)
:区域查询(返回相交对象)nearest(coordinates, num_results)
:最近邻查询count(coordinates)
:统计区域内的对象数量leaves()
:获取所有叶子节点信息
2. Property
类(索引配置)
- 功能:配置索引行为
- 关键配置项:
type = RT_RTree # 索引类型(R-tree/MVR-tree/TPR-tree)
variant = RT_Star # 分裂算法(Linear/Quadratic/Star)
dimension = 2 # 空间维度
storage = RT_Memory # 存储类型(内存/磁盘/自定义)
pagesize = 4096 # 磁盘页大小
overwrite = False # 是否覆盖现有文件
3. Item
类(查询结果容器)
- 功能:封装查询结果
- 属性:
id
:对象IDobject
:存储的Python对象bbox
:边界框(交错的坐标顺序)bounds
:原始边界坐标
4. RtreeContainer
类(专用容器)
- 特点:
- 继承自
Index
- 自动管理对象ID(使用
id(obj)
) - 支持直接存储Python对象
- 继承自
- 特殊方法:
__contains__(obj)
:检查对象是否存在__iter__()
:迭代所有对象
二、设计思路
1. 分层架构
2. 关键设计
- 多索引类型支持:
- R-tree:静态空间索引
- MVR-tree:移动对象索引
- TPR-tree:轨迹预测索引
- 灵活存储:
- 内存存储(RT_Memory)
- 磁盘存储(RT_Disk)
- 自定义存储(RT_Custom)
- 序列化扩展:
- 默认使用
pickle
- 可通过子类覆盖
dumps()/loads()
实现自定义序列化(如JSON)
- 默认使用
3. 性能优化
- 批量加载:通过
stream
或arrays
参数高效初始化 - 交错坐标:优化坐标存储格式减少计算
- C扩展集成:通过
ctypes
调用libspatialindex
三、使用注意事项
1. 重要约束
# 版本依赖
if (major, minor, patch) < (1, 8, 5):
raise Exception("需要 libspatialindex >= 1.8.5")
# TPR-tree 特殊要求
if properties.type == RT_TPRTree:
insert(id, (坐标, 速度, 时间), obj)
2. 坐标处理
- 默认顺序:
interleaved=True
([xmin, ymin, xmax, ymax]) - 非交错顺序:
interleaved=False
([xmin, xmax, ymin, ymax]) - 错误示例:
# 错误:最小值 > 最大值
idx.insert(1, (50, 40, 30, 20)) # 抛出 RTreeError
3. 查询模式
# 返回ID列表
list(idx.intersection((0,0,10,10))) → [4321, 4322]
# 返回对象(带边界信息)
list(idx.intersection(..., objects=True)) → [<Item object>]
# 返回原始对象(最快)
list(idx.intersection(..., objects="raw")) → [42, "text"]
4. 自定义存储
实现 ICustomStorage
接口:
class MyStorage(ICustomStorage):
def create(self, ...): ...
def storeByteArray(self, page, data): ...
# 需实现6个回调方法
5. 容器专用类
# 创建容器
idx = RtreeContainer()
# 直接存储对象
idx.insert(my_obj, (xmin, ymin, xmax, ymax))
# 查询时返回对象
list(idx.intersection(bbox)) → [my_obj1, my_obj2]
四、典型使用示例
1. 基本索引操作
p = Property(type=RT_RTree, dimension=2)
idx = Index(properties=p)
# 插入对象
idx.insert(1, (34.5, 26.7, 49.3, 41.7), obj="对象1")
# 区域查询
hits = idx.intersection((0,0,60,60), objects="raw")
# 返回: ["对象1"]
2. TPR-tree 使用
p = Property(type=RT_TPRTree)
idx = Index(properties=p)
# 插入移动对象(位置+速度+时间)
idx.insert(1,
((34.5, 26.7, 49.3, 41.7), # 位置
(0.5, 2.0, 1.5, 2.5), # 速度
3.0), # 时间
obj="移动车辆")
3. 容器专用接口
idx = RtreeContainer()
class Road:
def __init__(self, coords):
self.coords = coords
road = Road((34.5, 26.7, 49.3, 41.7))
idx.insert(road, road.coords)
# 查询并直接获取对象
list(idx.nearest((35,27), bbox=False)) → [<Road object>]
总结
该库实现了高性能空间索引功能:
- 核心优势:
- 支持三种空间索引类型
- 灵活的内存/磁盘存储
- 直接集成C库保障性能
- 使用场景:
- GIS地理查询
- 移动对象轨迹跟踪
- 游戏/仿真空间索引
- 注意事项:
- 严格依赖
libspatialindex >= 1.8.5
- TPR-tree需要完整参数(位置+速度+时间)
- 坐标顺序需与
interleaved
设置一致
- 严格依赖
通过 RtreeContainer
类可简化Python对象存储,而底层 Index
类提供更精细的控制能力。
2025-08-04(一)