如何判断线段A->B是否位于多边形内且不触碰墙体?
解决Boost Geometry中判断线段完全位于多边形内部时返回错误的问题
问题背景
需求为判断由Point A、Point B构成的线段A->B是否满足以下任一条件:
- 不与多边形C的墙体相交
- 完全位于多边形C内部
现有代码对跨通道的线段(如POINT(2.5 3.25)至POINT(3 3.625)的线段)能正确返回true,但完全位于多边形内部的线段会错误返回false。
目标多边形
POLYGON((2 2,2 3.5,4 3.5,4 2,2 3.5,2 5.5,5 5.5,5 3.5,4 2,4 3.5,5 3.5,5 5.5,7.5 5.5,7.5 2,2 2))
通道信息
Passage: POINT(2.5 3.5) POINT(3 3.5) Passage: POINT(4.25 3.5) POINT(4.75 3.5) Passage: POINT(4 2.5) POINT(4 3) Passage: POINT(5 4) POINT(5 5)
错误原因分析
当前代码else分支使用的DE-9IM掩码"T*F**F***"不符合需求。该掩码仅要求线段与多边形内部有交集、与外部无交集,但未覆盖线段完全位于多边形内部的所有场景,导致判断逻辑失效。
解决方案
核心修正:替换内部判断逻辑
放弃手动编写DE-9IM掩码,改用Boost Geometry提供的covered_by或within函数,这两个函数更直观且能准确判断线段与多边形的包含关系:
bg::covered_by(AB, wall):判断线段完全位于多边形内部包括边界bg::within(AB, wall):判断线段严格位于多边形内部不接触边界
同时需要修正多边形拓扑,输入的多边形存在重复顶点,需调用bg::correct确保其有效性。
完整修正代码
#include <boost/geometry.hpp> #include <boost/geometry/geometries/segment.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/geometries/point_xy.hpp> #include <boost/geometry/geometries/linestring.hpp> namespace bg = boost::geometry; namespace bgm = boost::geometry::model; typedef bgm::d2::point_xy<double> Point; typedef bgm::polygon<Point> Polygon; typedef boost::geometry::model::segment<Point> Segment; int main() { Polygon wall; // 读取多边形并修正拓扑 bg::read_wkt("POLYGON((2 2,2 3.5,4 3.5,4 2,2 3.5,2 5.5,5 5.5,5 3.5,4 2,4 3.5,5 3.5,5 5.5,7.5 5.5,7.5 2,2 2))", wall); bg::correct(wall); // 去除重复顶点,确保多边形拓扑有效 Polygon passage; // 此处根据通道信息初始化passage多边形... Point start(2.5, 3.25); Point end(3, 3.625); boost::geometry::model::linestring<Point> AB{start, end}; bool isPassable = false; bool intersecting = bg::intersects(AB, wall); if (intersecting) { for (int i = 0; i < passage.outer().size(); i += 2) { Point p1 = passage.outer()[i]; Point p2 = passage.outer()[i + 1]; Segment passageSegment(p1, p2); Segment testSegment(start, end); if (bg::intersects(passageSegment, testSegment)) { isPassable = true; break; } } } else { // 替换为covered_by判断线段完全在多边形内(含边界) isPassable = bg::covered_by(AB, wall); // 若需严格内部(不含边界),则替换为: // isPassable = bg::within(AB, wall); } return 0; }
额外注意事项
- 多边形有效性:必须调用
bg::correct处理输入多边形,否则重复顶点可能导致几何判断异常。 - 通道多边形构建:确保
passage多边形正确包含所有通道线段,避免遍历过程中出现索引越界或逻辑错误。
内容的提问来源于stack exchange,提问作者canersevdiceginibekleyenoglu
相关产品推荐
相关产品推荐

