Ruben
Ruben

Reputation: 21

Dataset of invalid geometries in boost::geometry

Exists a dataset of all posible invalid geometries using c++ and boost::geometry libraries? or at least polygon coordinates of that invalid geomtries that i can to translate to boost::geometry Example: Selfintersection, etc I would like to test my application with a least all posibles invalid geometries. Something like this:

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

but with more test cases with inners and outer polygons.

Upvotes: 0

Views: 862

Answers (2)

Wouter van Kleunen
Wouter van Kleunen

Reputation: 81

I have created a library 'boost_geometry_make_valid' which allows correcting the errors described in this dataset:

https://github.com/kleunen/boost_geometry_make_valid

I use the dataset now for testing, the library is able to correct all the mentioned failures. Most important, remove self-intersection from polygons.

Upvotes: 5

sehe
sehe

Reputation: 393064

The Boost Geometry library implements the OGC standard. From the intro

The library follows existing conventions:

So the list that you used is relevant.

Besides, you can use the is_valid function with a reason parameter to interrogate the library about your geometry. I have several examples on this site showing how to do that. (Note: Not all constraints might be validatable)

Your Samples, Live

Let's adopt the outer ring orientation from the samples (not the BG default):

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>;

Let's create a generalized checker:

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";
    }
}

And run it for all the test cases:

//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))");

Output

Live On Coliru

Prints

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))

Note: the bg::correct might in cases correct /part/ of the problem, but leave other issues, and this check function doesn't report on that.

Upvotes: 2

Related Questions