// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2014, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle #include #ifndef BOOST_TEST_MODULE #define BOOST_TEST_MODULE test_is_valid #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace bg = ::boost::geometry; typedef bg::model::point point_type; typedef bg::model::segment segment_type; typedef bg::model::box box_type; typedef bg::model::linestring linestring_type; typedef bg::model::multi_linestring multi_linestring_type; // ccw open and closed polygons typedef bg::model::polygon open_polygon_type; typedef bg::model::polygon closed_polygon_type; // multi-geometries typedef bg::model::multi_point multi_point_type; typedef bg::model::multi_polygon multi_polygon_type; template Geometry from_wkt(std::string const& wkt) { Geometry g; bg::read_wkt(wkt, g); return g; } template Segment make_segment(double x1, double y1, double x2, double y2) { typename boost::geometry::point_type::type p(x1, y1), q(x2, y2); return Segment(p, q); } template Box make_box(double x1, double y1, double x2, double y2) { typename boost::geometry::point_type::type p(x1, y1), q(x2, y2); return Box(p, q); } template void test_valid(Geometry const& g, bool expected_result) { #ifdef GEOMETRY_TEST_DEBUG std::cout << "=======" << std::endl; #endif bool valid = bg::is_valid(g); BOOST_CHECK( valid == expected_result ); #ifdef GEOMETRY_TEST_DEBUG std::cout << "Geometry: " << bg::wkt(g) << std::endl; std::cout << std::boolalpha; std::cout << "is valid:? " << valid << std::endl; std::cout << "expected result: " << expected_result << std::endl; std::cout << "=======" << std::endl; std::cout << std::endl << std::endl; std::cout << std::noboolalpha; #endif } //=========================================================================== //=========================================================================== //=========================================================================== BOOST_AUTO_TEST_CASE( test_is_valid_point ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: POINT " << std::endl; std::cout << "************************************" << std::endl; #endif typedef point_type G; test_valid(from_wkt("POINT(0 0)"), true); } BOOST_AUTO_TEST_CASE( test_is_valid_segment ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: SEGMENT " << std::endl; std::cout << "************************************" << std::endl; #endif typedef segment_type G; test_valid(make_segment(0, 0, 0, 0), false); test_valid(make_segment(0, 0, 1, 0), true); } BOOST_AUTO_TEST_CASE( test_is_valid_box ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: BOX " << std::endl; std::cout << "************************************" << std::endl; #endif typedef box_type G; // boxes where the max corner and below and/or to the left of min corner test_valid(make_box(0, 0, -1, 0), false); test_valid(make_box(0, 0, 0, -1), false); test_valid(make_box(0, 0, -1, -1), false); // boxes of zero area; they are not 2-dimensional, so invalid test_valid(make_box(0, 0, 0, 0), false); test_valid(make_box(0, 0, 1, 0), false); test_valid(make_box(0, 0, 0, 1), false); test_valid(make_box(0, 0, 1, 1), true); } BOOST_AUTO_TEST_CASE( test_is_valid_linestring ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: LINESTRING " << std::endl; std::cout << "************************************" << std::endl; #endif typedef linestring_type G; // empty linestring test_valid(from_wkt("LINESTRING()"), false); // 1-point linestrings test_valid(from_wkt("LINESTRING(0 0)"), false); test_valid(from_wkt("LINESTRING(0 0,0 0)"), false); test_valid(from_wkt("LINESTRING(0 0,0 0,0 0)"), false); // 2-point linestrings test_valid(from_wkt("LINESTRING(0 0,1 2)"), true); test_valid(from_wkt("LINESTRING(0 0,1 2,1 2)"), true); test_valid(from_wkt("LINESTRING(0 0,0 0,1 2,1 2)"), true); test_valid(from_wkt("LINESTRING(0 0,0 0,0 0,1 2,1 2)"), true); // 3-point linestrings test_valid(from_wkt("LINESTRING(0 0,1 0,2 10)"), true); test_valid(from_wkt("LINESTRING(0 0,1 0,2 10,0 0)"), true); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0)"), true); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0,4 0)"), true); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0,4 0,3 0)"), true); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0,4 0,-1 0)"), true); test_valid(from_wkt("LINESTRING(0 0,1 0,1 1,-1 1,-1 0,0 0)"), true); // should this be valid? we have two overlapping segments test_valid(from_wkt("LINESTRING(0 0,1 0,1 1,-1 1,-1 0,0.5 0)"), true); // linestrings with spikes static const bool accept_spikes = false; test_valid(from_wkt("LINESTRING(0 0,1 2,0 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,1 2,1 2,0 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,0 0,1 2,1 2,0 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,0 0,0 0,1 2,1 2,0 0,0 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,10 0,5 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0,0 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,10 0,10 10,5 0,4 0,6 0)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,1 0,1 1,5 5,4 4)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,1 0,1 1,5 5,4 4,6 6)"), accept_spikes); test_valid(from_wkt("LINESTRING(0 0,1 0,1 1,5 5,4 4,4 0)"), accept_spikes); } BOOST_AUTO_TEST_CASE( test_is_valid_multipoint ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: MULTIPOINT " << std::endl; std::cout << "************************************" << std::endl; #endif typedef multi_point_type G; test_valid(from_wkt("MULTIPOINT()"), false); test_valid(from_wkt("MULTIPOINT(0 0,0 0)"), true); test_valid(from_wkt("MULTIPOINT(0 0,1 0,1 1,0 1)"), true); test_valid(from_wkt("MULTIPOINT(0 0,1 0,1 1,1 0,0 1)"), true); } BOOST_AUTO_TEST_CASE( test_is_valid_multilinestring ) { #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; std::cout << " is_valid: MULTILINESTRING " << std::endl; std::cout << "************************************" << std::endl; #endif typedef multi_linestring_type G; // empty multilinestring test_valid(from_wkt("MULTILINESTRING()"), false); // multilinestring with empty linestring(s) test_valid(from_wkt("MULTILINESTRING(())"), false); test_valid(from_wkt("MULTILINESTRING((),(),())"), false); test_valid(from_wkt("MULTILINESTRING((),(0 1,1 0))"), false); // multilinestring with invalid linestrings test_valid(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0,0 0),(0 1,1 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0),(1 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0,0 0),(1 0,1 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0),(0 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0))"), false); test_valid(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0,1 0,4 1))"), false); test_valid(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))"), false); // valid multilinestrings test_valid(from_wkt("MULTILINESTRING((0 0,1 0,2 0),(5 0,1 0,4 1))"), true); test_valid(from_wkt("MULTILINESTRING((0 0,1 0,2 0),(1 0,2 0))"), true); test_valid(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), true); test_valid(from_wkt("MULTILINESTRING((0 0,1 1,2 2),(0 1,1 0,2 2))"), true); } #if 0 BOOST_AUTO_TEST_CASE( test_is_valid_rest ) { typedef open_polygon_type op; typedef closed_polygon_type cp; typedef multi_polygon_type mpl; test_valid(from_wkt("POLYGON(())"), true); test_valid(from_wkt("POLYGON((),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0,1 1),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0,1 0,1 1),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0))"), false); test_valid(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 1))"), false); test_valid(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,1 1,1 0.5))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,1 1))"), true); test_valid(from_wkt("POLYGON((0 0,1 0,2 1,2 2,1 3))"), true); test_valid(from_wkt("POLYGON((0 0,2 0,4 1,1 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,3 1,-1 2,3 3,3 4,0 4))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,3 1,0 2,3 3,3 4,0 4))"), false); test_valid(from_wkt("POLYGON((0 0,10 0,10 10,0 10),\ (1 1,1 2,2 2,2 1))"), false); test_valid(from_wkt("POLYGON(())"), true); test_valid(from_wkt("POLYGON((),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0,1 1,0 0),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0,1 0,1 1,0 0),())"), true); test_valid(from_wkt("POLYGON((0 0,1 0,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 1,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 0,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,1 1,1 0.5,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,1 1,0 0))"), true); test_valid(from_wkt("POLYGON((0 0,1 0,2 1,2 2,1 3,0 0))"), true); test_valid(from_wkt("POLYGON((0 0,2 0,4 1,1 0,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,3 1,-1 2,3 3,3 4,0 4,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,1 0,3 1,0 2,3 3,3 4,0 4,0 0))"), false); test_valid(from_wkt("POLYGON((0 0,10 0,10 10,0 10,0 0),\ (1 1,1 2,2 2,2 1,1 1))"), false); test_valid(from_wkt("MULTIPOLYGON()"), true); test_valid(from_wkt("MULTIPOLYGON( ((),()) )"), true); test_valid(from_wkt("MULTIPOLYGON( (()),(()) )"), true); test_valid(from_wkt("MULTIPOLYGON( ((),()),(()) )"), true); test_valid(from_wkt("MULTIPOLYGON( ((0 0),()),(()) )"), true); test_valid(from_wkt("MULTIPOLYGON( ((0 0),()),((1 1)) )"), true); #ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS // test_valid(from_wkt("MULTIPOLYGON( ((0 0),()),((0 0)) )"), false); #endif test_valid(from_wkt("MULTIPOLYGON(((0 0,1 0,2 1,2 2,1 3)),\ ((10 0,11 0,11 1)))"), true); test_valid(from_wkt("MULTIPOLYGON(((0 0,1 0,1 0,2 1,2 2,1 3)),\ ((10 0,11 0,11 1,11 1)))"), true); test_valid(from_wkt("MULTIPOLYGON(((0 0,1 0,3 1,0 2,3 3,3 4,0 4)),\ ((10 0,11 0,11 1)))"), false); } #endif