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.
The Boost Geometry library implements the OGC standard. From the intro
The library follows existing conventions:
- conventions from Boost
- conventions from the std library
- conventions and names from one of the OGC standards on geometry and, more specificly, from the OGC Simple Feature Specification
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)
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))");
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 thischeck
function doesn't report on that.