如何用Boost C++查找与带孔多边形外环相交且不在孔内的RTree元素?
解决Boost RTree中带孔多边形的元素筛选问题
首先,咱们来拆解一下你遇到的编译错误原因:你的RTree索引元素是Boost2dBox类型,而你尝试用bgi::within(pHole)(其中pHole是Boost2dRing)来查询完全在孔内的元素时,Boost Geometry没有为Box和Ring这对几何类型提供默认的within判断策略,所以触发了模板断言失败,导致编译报错。
接下来给你一套可行的实现思路,分步骤来:
核心思路
先获取所有与外环相交的元素,再从这些元素中排除完全包含在任意一个孔内的元素。因为直接用RTree查询孔内元素的方式不支持Box+Ring组合,所以我们换个方式:先拿到相交的候选集,再逐个检查元素是否在孔内(用支持Box+Polygon的within判断)。
具体实现步骤
1. 正确构造单个孔的多边形
单独的Ring作为几何对象,Boost对它的within支持有限,所以我们需要把每个孔的Ring包装成一个Polygon,并且修正环的方向(Boost要求外环顺时针、内环逆时针,否则空间判断会出错):
// 假设你的孔Ring是pHole,类型为Boost2dRing Boost2dPolygon holePolygon; // 把孔的Ring作为这个Polygon的"外环"(代表孔的范围) holePolygon.outer() = pHole; // 修正环的方向,确保符合Boost的空间判断规则 bg::correct(holePolygon);
2. 获取与外环相交的候选元素(你已实现的部分,补充细节)
建议把外环也包装成Polygon并修正方向,避免潜在的判断误差:
// 构造外环Polygon Boost2dPolygon outerPoly; outerPoly.outer() = p; // p是你的外环Ring bg::correct(outerPoly); std::vector<YourElementType> candidates; m_RTree.query(bgi::intersects(outerPoly), std::back_inserter(candidates));
3. 过滤掉完全包含在孔内的元素
遍历所有候选元素,逐个检查是否存在于任意一个孔的Polygon内部,保留不在孔内的元素:
std::vector<YourElementType> finalResults; // 假设你有多个孔,存在holesPolygons列表中(每个元素是孔的Polygon) for (const auto& elem : candidates) { bool isInsideAnyHole = false; // 遍历每个孔 for (const auto& holePoly : holesPolygons) { // 判断元素的Box是否完全在孔Polygon内部 // 假设elem的几何部分是elem.box,类型为Boost2dBox if (bg::within(elem.box, holePoly)) { isInsideAnyHole = true; break; } } // 不在任何孔内则加入最终结果 if (!isInsideAnyHole) { finalResults.push_back(elem); } }
关键注意事项
- 环的方向修正:一定要调用
bg::correct()来修正多边形的环方向,否则within、intersects等空间判断函数会返回错误结果。 - 性能优化:如果候选集或孔的数量极大,可以考虑给孔的Polygon建立临时RTree来加速判断,但大多数场景下,内存中遍历过滤已经足够高效。
- 替代方案说明:之所以不用RTree直接查询孔内元素,是因为Boost RTree的
bgi::within谓词需要对应的策略支持,而Box和Ring的组合没有默认实现,但Box和Polygon的组合是原生支持的,所以"先查相交+内存过滤"是最直接的解决方案。
内容的提问来源于stack exchange,提问作者tonipozo
相关产品推荐
相关产品推荐

