Boost Geometry RTree的overlaps查询异常问题求助
overlaps与intersects的OGC标准语义 你遇到的问题完全是对Boost Geometry空间谓词语义的理解偏差,和地理坐标系的特性直接相关,但绝非RTree或函数实现的bug——核心问题是你需要的是intersects谓词,而非overlaps。
先明确两个谓词的核心区别(遵循OGC标准)
Boost Geometry的空间谓词严格按照Open Geospatial Consortium的定义实现:
intersects:只要两个几何体存在任何形式的交集(包含一个完全包裹另一个、边界接触、部分重叠),就返回true。这正是你想要的“检查是否存在重叠/包含/接触”的逻辑。overlaps:仅当两个几何体的交集维度与自身维度相同,且彼此都不包含对方时才返回true。简单说就是“部分重叠但互不包含”——如果一个几何体完全包含另一个,overlaps会直接返回false。
结合你的测试用例分析异常原因
第一个Assert的部分异常:
新包围盒{1, 2.75}, {2, 9}与第三个已存在的包围盒{1, 4}, {2, 9}是包含关系(新盒完全包裹旧盒),因此overlaps返回false,RTree查询不会返回这个旧盒;但新盒与第一个旧盒{1, 1}, {3, 3}是部分重叠且互不包含,所以overlaps返回true,查询到该条目,因此Assert::IsFalse生效。第二个Assert的完全失效:
新包围盒{1, 4}, {3.5, 9}与第三个旧盒{1, 4}, {2, 9}同样是包含关系(新盒包裹旧盒),overlaps返回false,RTree查询无结果,导致新盒被插入,Assert::IsFalse失败。
解决方案:替换为intersects谓词
把查询时的boost::geometry::index::overlaps(box)替换为boost::geometry::index::intersects(box)即可,修改后的TestAddTreeEntry函数如下:
bool TestAddTreeEntry(RTree& tree, uint64_t index, RTreeBox box) { if (!boost::geometry::is_valid(box)) { boost::geometry::correct(box); } std::vector<RTreeEntry> query_results; // 替换为符合需求的intersects谓词 tree.query(boost::geometry::index::intersects(box), std::back_inserter(query_results)); if (query_results.size() > 0) { return false; } tree.insert(std::make_pair(box, index)); return true; }
额外地理坐标系提示
你使用的boost::geometry::cs::geographic是球面坐标系,这里的box代表经纬度范围框(球面矩形区域),Boost Geometry会正确处理球面逻辑下的空间关系判断,只要用对谓词就不会有问题。
内容的提问来源于stack exchange,提问作者Crispy

