【问题标题】:Dataset of invalid geometries in boost::geometryboost::geometry 中无效几何的数据集
【发布时间】:2018-04-18 14:17:44
【问题描述】:

是否存在使用 c++ 和 boost::geometry 库的所有可能无效几何的数据集?或者至少我可以转换为 boost::geometry 的无效几何的多边形坐标 示例:自相交等 我想用至少所有可能的无效几何图形来测试我的应用程序。 像这样的:

https://knowledge.safe.com/articles/21674/invalid-ogc-geometry-examples.html

但有更多带有内部和外部多边形的测试用例。

【问题讨论】:

    标签: c++ boost geometry boost-geometry


    【解决方案1】:

    Boost Geometry 库实现了 OGC 标准。来自intro

    该库遵循现有约定:

    所以你使用的列表是相关的。

    此外,您可以使用带有reason 参数的is_valid 函数来询问有关几何图形的库。我在这个网站上有几个例子展示了如何做到这一点。 (注意:并非所有约束都可能是可验证的)

    您的样品,现场直播

    让我们采用样本中的外环方向(不是 BG 默认值):

    namespace bg = boost::geometry;
    using pt    = bg::model::d2::point_xy<double>;
    using poly  = bg::model::polygon<pt, false>;
    using multi = bg::model::multi_polygon<poly>;
    

    让我们创建一个通用检查器:

    template <typename Geo = poly> void check(std::string wkt) {
        Geo g;
        bg::read_wkt(wkt, g);
        std::string reason;
        bool ok = bg::is_valid(g, reason);
        std::cout << "Valid: " << std::boolalpha << ok << " (" << reason << ")\n";
    
        bg::correct(g);
        if (bg::is_valid(g, reason)) {
            std::cout << "Autocorrected: " << bg::wkt(g) << "\n";
        }
    }
    

    并为所有测试用例运行它:

    //Hole Outside Shell
    check("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))");
    //Nested Holes
    check("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (2 2, 2 8, 8 8, 8 2, 2 2), (3 3, 3 7, 7 7, 7 3, 3 3))");
    //Disconnected Interior
    check("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (5 0, 10 5, 5 10, 0 5, 5 0))");
    //Self Intersection
    check("POLYGON((0 0, 10 10, 0 10, 10 0, 0 0))");
    //Ring Self Intersection
    check("POLYGON((5 0, 10 0, 10 10, 0 10, 0 0, 5 0, 3 3, 5 6, 7 3, 5 0))");
    //Nested Shells
    check<multi>("MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)),(( 2 2, 8 2, 8 8, 2 8, 2 2)))");
    //Duplicated Rings
    check<multi>("MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)),((0 0, 10 0, 10 10, 0 10, 0 0)))");
    //Too Few Points
    check("POLYGON((2 2, 8 2))");
    //Invalid Coordinate
    check("POLYGON((NaN 3, 3 4, 4 4, 4 3, 3 3))");
    //Ring Not Closed
    check("POLYGON((0 0, 0 10, 10 10, 10 0))");
    

    输出

    Live On Coliru

    打印

    Valid: false (Geometry has interior rings defined outside the outer boundary)
    Valid: false (Geometry has nested interior rings)
    Valid: false (Geometry has wrong orientation)
    Valid: false (Geometry has wrong orientation)
    Valid: false (Geometry has invalid self-intersections. A self-intersection point was found at (5, 0); method: t; operations: i/i; segment IDs {source, multi, ring, segment}: {0, -1, -1, 4}/{0, -1, -1, 8})
    Valid: false (Multi-polygon has intersecting interiors)
    Valid: false (Geometry has invalid self-intersections. A self-intersection point was found at (10, 0); method: e; operations: c/c; segment IDs {source, multi, ring, segment}: {0, 0, -1, 0}/{0, 1, -1, 0})
    Valid: false (Geometry has too few points)
    Valid: false (Geometry has point(s) with invalid coordinate(s))
    Valid: false (Geometry is defined as closed but is open)
    Autocorrected: POLYGON((0 0,10 0,10 10,0 10,0 0))
    

    注意:bg::correct 在某些情况下可能会纠正/部分/问题,但会留下其他问题,并且此check 函数不会报告该问题。

    【讨论】:

      【解决方案2】:

      我创建了一个库“boost_geometry_make_valid”,它允许纠正此数据集中描述的错误:

      https://github.com/kleunen/boost_geometry_make_valid

      我现在使用数据集进行测试,该库能够纠正所有提到的故障。最重要的是,从多边形中移除自相交。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-25
        相关资源
        最近更新 更多