rtree查不准因将经纬度当平面坐标处理,需投影转换或结合geohash;插多边形须用bounds提取MBR四元组并注意xy顺序;加速点查多边形需两层过滤;选型依场景:不规则形状用rtree,圆形邻域用geohash。
rtree 插入点坐标会查不准因为 rtree 本身不理解“经纬度”——它只认笛卡尔平面坐标。你传 (lat, lng) 进去,它就当是 (y, x) 处理;但球面距离在高纬度区严重压缩经度,导致 MBR(最小包围矩形)错位。常见错误现象:北京附近两个相距 200 米的点,在 rtree 查询中可能被判定为不相交,或把黑龙江的点误筛进广州范围。
正确做法必须统一坐标系:
pyproj 投影到局部平面坐标系,例如 EPSG:32650(UTM 50N);插入前先转换,查询时也转同一系geohash 或预计算 haversine 粗筛 + rtree 做二次加速(见下节)(lat, lng) 直接当 (minx, miny, maxx, maxy) 插进去——顺序反了、单位混了、曲率没校正rtree 插入多边形时为何返回空结果很多人把 GeoJSON 的 Polygon 坐标列表直接塞进 idx.insert(),结果查不到。原因: rtree 只索引 MBR(矩形框),不解析几何形状。它需要你显式提供四元组 (minx, miny, maxx, maxy),且这个矩形必须覆盖整个多边形。
实操要点:
立即学习“Python免费学习笔记(深入)”;
shapely.geometry.Polygon.bounds 提取多边形边界:minx, miny, maxx, maxy = poly.bounds
rtree 要求 (x_min, y_min, x_max, y_max),即 (lng_min, lat_min, lng_max, lat_max),不是 (lat, lng)
intersection() 判定“点在多边形内”——它只保证候选集不漏,但会多(MBR 包含但多边形不包含),必须用 shapely 或 matplotlib.path 做精确判断.bounds 仍返回外环矩形,不影响索引,但精确判断时需用 shapely 的 contains()
rtree 加速“点在哪个多边形里”查询暴力遍历每个 Polygon.contains(Point) 在 10 万个行政区划上会卡死。用 rtree 可把平均查询时间从秒级压到毫秒级,但关键在于两层过滤结构。
典型流程:
rtree 查所有 MBR 包含该点的多边形 ID 列表 —— list(idx.intersection((lng, lat, lng, lat)))
shapely.Polygon.contains(shapely.Point(lng, lat))
rtree 插入时用太松的 MBR(比如把全国省界都包进一个大框),会导致粗筛结果过多,精筛反而变慢rtree 每次重建索引开销大;静态数据(如行政区划)适合,动态围栏建议换 Redis + Geohashrtree 和 geohash 到底选哪个不是非此即彼,而是看场景。两者根本不是同一类工具:rtree 是内存内空间索引,支持任意形状相交/包含;geohash 是编码+前缀匹配,只适合“点附近 N 米”这种圆形区域查询。
选型依据:
rtree + 精确几何判断geohash 前缀查 + haversine 校验更快,但得接受边缘漏点风险geohash 快速捞出候选 POI,再用 rtree 判断它们是否在用户划定的服务多边形内rtree 需加载全部数据进内存;geohash 可存在 Redis 或 MySQL 前缀索引里,更适合服务化真正容易被忽略的是坐标系一致性——无论选哪个,lng/lat 的顺序、投影方式、半径单位(米还是度)、地球椭球模型(WGS84 还是 GCJ02),只要一处不统一会导致整套逻辑偏移几百米。