rtree - 基本使用记录


代码调用

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:对象ID
    • object:存储的Python对象
    • bbox:边界框(交错的坐标顺序)
    • bounds:原始边界坐标

4. RtreeContainer 类(专用容器)
  • 特点
    • 继承自 Index
    • 自动管理对象ID(使用 id(obj)
    • 支持直接存储Python对象
  • 特殊方法
    • __contains__(obj):检查对象是否存在
    • __iter__():迭代所有对象

二、设计思路

1. 分层架构
应用程序
RtreeContainer/Index
索引核心
libspatialindex C库
磁盘/内存存储

2. 关键设计
  • 多索引类型支持
    • R-tree:静态空间索引
    • MVR-tree:移动对象索引
    • TPR-tree:轨迹预测索引
  • 灵活存储
    • 内存存储(RT_Memory)
    • 磁盘存储(RT_Disk)
    • 自定义存储(RT_Custom)
  • 序列化扩展
    • 默认使用 pickle
    • 可通过子类覆盖 dumps()/loads() 实现自定义序列化(如JSON)

3. 性能优化
  • 批量加载:通过 streamarrays 参数高效初始化
  • 交错坐标:优化坐标存储格式减少计算
  • 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>]

总结

该库实现了高性能空间索引功能:

  1. 核心优势
    • 支持三种空间索引类型
    • 灵活的内存/磁盘存储
    • 直接集成C库保障性能
  2. 使用场景
    • GIS地理查询
    • 移动对象轨迹跟踪
    • 游戏/仿真空间索引
  3. 注意事项
    • 严格依赖 libspatialindex >= 1.8.5
    • TPR-tree需要完整参数(位置+速度+时间)
    • 坐标顺序需与 interleaved 设置一致

通过 RtreeContainer 类可简化Python对象存储,而底层 Index 类提供更精细的控制能力。


2025-08-04(一)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EAI工程笔记

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值