From dfc3785d486d003fb0faa2bc49b37be92b86d2ea Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 4 Apr 2014 16:16:43 +0300 Subject: [PATCH 01/17] [feature/is_simple] implement OGC is_simple test for points, segments, multi-points, linestrings and multi-linestrings --- .../geometry/algorithms/ogc/is_simple.hpp | 472 ++++++++++++++++++ test/algorithms/is_simple.cpp | 259 ++++++++++ 2 files changed, 731 insertions(+) create mode 100644 include/boost/geometry/algorithms/ogc/is_simple.hpp create mode 100644 test/algorithms/is_simple.cpp diff --git a/include/boost/geometry/algorithms/ogc/is_simple.hpp b/include/boost/geometry/algorithms/ogc/is_simple.hpp new file mode 100644 index 000000000..4b8660e49 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/is_simple.hpp @@ -0,0 +1,472 @@ +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry { namespace ogc +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +template ::type> +struct is_simple + : not_implemented +{}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + + +template +struct has_spikes; + +template +struct has_spikes +{ + static inline bool apply(Range const& range) + { + if ( boost::size(range) < 3 ) + { + return false; + } + + BOOST_AUTO_TPL(it1, boost::begin(range)); + BOOST_AUTO_TPL(it2, ++boost::begin(range)); + BOOST_AUTO_TPL(it3, ++(++boost::begin(range))); + + for (; it3 != boost::end(range); ++it1, ++it2, ++it3) + { + if ( geometry::detail::point_is_spike_or_equal(*it3, *it1, *it2) ) + { + return true; + } + } + + return false; + } +}; + + +template +struct has_spikes +{ + static inline bool apply(Range const& range) + { + typedef typename closeable_view::type ClosedRange; + + ClosedRange crange(const_cast(range)); + return has_spikes::apply(crange); + } + +}; + + +template +< + typename Geometry, + bool AllowEmpty = true, + typename Tag = typename tag::type +> +struct is_below_minimal_size +{ + static inline bool apply(Geometry const&) + { + return false; + } +}; + + +template +struct is_below_minimal_size +{ + static inline bool apply(Linestring const& linestring) + { + return boost::size(linestring) == 1; + } +}; + + + + + +template +struct is_simple_range +{ + static inline bool apply(Range const& range) + { + if ( is_below_minimal_size::apply(range) ) + { + return false; + } + + Range other(range); + geometry::unique(other); + + if ( boost::size(other) == 1 ) + { + return true; + } + + if ( has_spikes::value>::apply(other) ) + { + return false; + } + + return !geometry::intersects(other); + } +}; + + + +template +struct is_simple_polygon +{ + static inline bool apply(Polygon const& polygon) + { + typedef typename ring_type::type Ring; + + BOOST_AUTO_TPL(it, boost::begin(geometry::interior_rings(polygon))); + for (; it != boost::end(geometry::interior_rings(polygon)); ++it) + { + if ( !is_simple_range::apply(*it) ) + { + return false; + } + } + + return is_simple_range::apply(geometry::exterior_ring(polygon)); + } +}; + + +template +struct is_simple_multipoint +{ + static inline bool apply(MultiPoint const& multipoint) + { + if ( boost::size(multipoint) <= 1 ) + { + return true; + } + + MultiPoint mp(multipoint); + + typedef typename point_type::type Point; + + std::sort(boost::begin(mp), boost::end(mp), geometry::less()); + + geometry::equal_to equal; + + BOOST_AUTO_TPL(it_next, ++boost::begin(mp)); + BOOST_AUTO_TPL(it, boost::begin(mp)); + for (; it_next != boost::end(mp); ++it, ++it_next) + { + if ( equal(*it, *it_next) ) + { + return false; + } + } + return true; + } +}; + + +template +struct is_simple_multilinestring +{ + static inline bool apply(MultiLinestring const& multilinestring) + { + typedef typename boost::range_value::type Linestring; + typedef typename point_type::type Point; + + BOOST_AUTO_TPL(it, boost::begin(multilinestring)); + for (; it != boost::end(multilinestring); ++it) + { + if ( !dispatch::is_simple::apply(*it) ) + { + return false; + } + } + + + typedef geometry::detail::overlay::turn_info + < + Point + > turn_info; + + std::deque turns; + + typedef typename strategy_intersection + < + typename cs_tag::type, + MultiLinestring, + MultiLinestring, + Point + >::segment_intersection_strategy_type segment_intersection_strategy_type; + + typedef geometry::detail::overlay::get_turn_info + < + geometry::detail::disjoint::assign_disjoint_policy + > TurnPolicy; + + geometry::detail::self_get_turn_points::no_interrupt_policy + interrupt_policy; + + geometry::detail::self_get_turn_points::get_turns + < + TurnPolicy + >::apply(multilinestring, + geometry::detail::no_rescale_policy(), + turns, + interrupt_policy); + + std::cout << "turns:"; + for (typename std::deque::const_iterator tit = turns.begin(); + tit != turns.end(); ++tit) + { + std::cout << " " << geometry::dsv(tit->point); + } + std::cout << std::endl << std::endl; + + if ( turns.size() == 0 ) + { + return true; + } + + std::vector endpoints; + for (it = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) + { + BOOST_ASSERT ( boost::size(*it) != 1 ); + if ( boost::size(*it) != 0 ) + { + endpoints.push_back( *boost::begin(*it) ); + endpoints.push_back( *(--boost::end(*it)) ); + } + } + + + std::sort(endpoints.begin(), endpoints.end(), geometry::less()); + + std::cout << "endpoints: "; + for (typename std::vector::iterator pit = endpoints.begin(); + pit != endpoints.end(); ++pit) + { + std::cout << " " << geometry::dsv(*pit); + } + std::cout << std::endl << std::endl; + + for (typename std::deque::const_iterator tit = turns.begin(); + tit != turns.end(); ++tit) + { + Linestring const& ls1 = + *(boost::begin(multilinestring) + + tit->operations[0].seg_id.multi_index); + Linestring const& ls2 = + *(boost::begin(multilinestring) + + tit->operations[0].other_id.multi_index); + + if ( ( !geometry::equals(*boost::begin(ls1), tit->point) + && !geometry::equals(*--boost::end(ls1), tit->point) ) + || + ( !geometry::equals(*boost::begin(ls2), tit->point) + && !geometry::equals(*--boost::end(ls2), tit->point) ) + ) + { + return false; + } + } + return true; + } + +}; + + +template +struct is_simple_multigeometry +{ + static inline bool apply(MultiGeometry const& multigeometry) + { + typedef typename boost::range_value::type Geometry; + + BOOST_AUTO_TPL(it, boost::begin(multigeometry)); + for (; it != boost::end(multigeometry); ++it) + { + if ( !dispatch::is_simple::apply(*it) ) + { + return false; + } + } + + + if ( CheckIntersections ) + { + BOOST_AUTO_TPL(it1, boost::begin(multigeometry)); + it = it1; + for (; it != boost::end(multigeometry); ++it) + { + for (; it1 != boost::end(multigeometry); ++it1) + { + if ( geometry::intersects(*it, *it1) ) + { + return false; + } + } + } + } + return true; + } +}; + + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A point is always simple +template +struct is_simple +{ + static inline bool apply(Point const&) + { + return true; + } +}; + + +// A segment is always simple. +// A segment is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// Reference: OGC 06-103r4 (§6.1.6.1) +template +struct is_simple +{ + static inline bool apply(Segment const&) + { + return true; + } +}; + + +// A box is always simple +// A box is a Polygon, and it satisfies the conditions for Polygon validity. +// +// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) +template +struct is_simple +{ + static inline bool apply(Box const&) + { + return true; + } +}; + + +// A linestring is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// Reference: OGC 06-103r4 (§6.1.6.1) +template +struct is_simple + : detail::is_simple::is_simple_range +{}; + + +// A Ring is a Polygon. +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) +template +struct is_simple + : detail::is_simple::is_simple_range +{}; + + +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for validity of Polygons): OGC 06-103r4 (§6.1.11.1) +template +struct is_simple + : detail::is_simple::is_simple_polygon +{}; + + +// A MultiPoint is simple if no two Points in the MultiPoint are equal +// (have identical coordinate values in X and Y) +// +// Reference: OGC 06-103r4 (§6.1.5) +template +struct is_simple + : detail::is_simple::is_simple_multipoint +{}; + + +// A MultiLinestring is a MultiCurve +// A MultiCurve is simple if all of its elements are simple and the +// only intersections between any two elements occur at Points that +// are on the boundaries of both elements. +// +// Reference: OGC 06-103r4 (§6.1.8.1; Fig. 9) +template +struct is_simple + : detail::is_simple::is_simple_multilinestring +{}; + + +// Not clear what the definition is. +// Right now we check that each element is simple (in fact valid), and +// that the MultiPolygon is also valid. +// +// Reference (for validity of MultiPolygons): OGC 06-103r4 (§6.1.14) +template +struct is_simple + : detail::is_simple::is_simple_multigeometry +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +template +inline bool is_simple(Geometry const& g) +{ + return dispatch::is_simple::apply(g); +} + + + +}}} // namespace boost::geometry::ogc + + + +#endif // BOOST_GEOMETRY_MYSQL_ALGORITHMS_IS_SIMPLE_HPP diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp new file mode 100644 index 000000000..28e4fa9ce --- /dev/null +++ b/test/algorithms/is_simple.cpp @@ -0,0 +1,259 @@ +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_is_simple +#endif + +#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::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 +void test_simple(Geometry const& g, bool simple_geometry) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "======================================" << std::endl; +#endif + + bool simple = bg::ogc::is_simple(g); + BOOST_CHECK(simple == simple_geometry); + +#ifdef GEOMETRY_TEST_DEBUG + std::cout << "Geometry: " << bg::wkt(g) << std::endl; + std::cout << std::boolalpha; + std::cout << "is simple: " << simple << std::endl; + std::cout << "expected result: " << simple_geometry << std::endl; + std::cout << "======================================" << std::endl; + std::cout << std::endl << std::endl; + std::cout << std::noboolalpha; +#endif +} + +//=========================================================================== +//=========================================================================== +//=========================================================================== + +BOOST_AUTO_TEST_CASE( test_is_simple_point ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " IS_SIMPLE: POINT " << std::endl; + std::cout << "************************************" << std::endl; +#endif + + typedef point_type G; + + test_simple(from_wkt("POINT(0 0)"), true); +} + +BOOST_AUTO_TEST_CASE( test_is_simple_segment ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " IS_SIMPLE: SEGMENT " << std::endl; + std::cout << "************************************" << std::endl; +#endif + + typedef segment_type G; + + test_simple(make_segment(0, 0, 0, 0), true); + test_simple(make_segment(0, 0, 1, 0), true); +} + +BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " IS_SIMPLE: LINESTRING " << std::endl; + std::cout << "************************************" << std::endl; +#endif + + typedef linestring_type G; + + test_simple(from_wkt("LINESTRING()"), true); + test_simple(from_wkt("LINESTRING(0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,0 0)"), true); + test_simple(from_wkt("LINESTRING(0 0,1 2)"), true); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 10,0.5 -1)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 1,1 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 1,0.5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,0.5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,0.5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,1.5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,1.5 0,0.5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,0.5 0,2 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0.5 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0 0)"), true); + test_simple(from_wkt("LINESTRING(0 0,0 0,1 0,1 0,1 1,0 0)"), true); +} + + +BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) +{ + typedef multi_linestring_type G; + + test_simple(from_wkt("MULTILINESTRING()"), true); + test_simple(from_wkt("MULTILINESTRING(())"), true); + test_simple(from_wkt("MULTILINESTRING((),(),())"), true); + test_simple(from_wkt("MULTILINESTRING((),(0 1,1 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(0 1,1 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0),(1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(1 0,1 0))"), true); + + test_simple(from_wkt("MULTILINESTRING((0 0),(0 0))"), false); + + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ + (5 0,1 0,4 1))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ + (5 0,1 0,4 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))"), + false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0,2 0),(1 0,0 1))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0),(0 1,1 1))"), + true); + + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0),\ + (1 1,0 1,0.5,0.5))"), + false); +} + + + +#if 0 +BOOST_AUTO_TEST_CASE( test_is_simple_rest ) +{ + typedef multi_linestring_type mls; + typedef open_polygon_type op; + typedef closed_polygon_type cp; + typedef multi_point_type mpt; + typedef multi_polygon_type mpl; + + test_simple(from_wkt("MULTILINESTRING()"), true); + test_simple(from_wkt("MULTILINESTRING(())"), true); + test_simple(from_wkt("MULTILINESTRING((),(),())"), true); + test_simple(from_wkt("MULTILINESTRING((),(0 1,1 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0),(1 0))"), true); +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + // test_simple(from_wkt("MULTILINESTRING((0 0),(0 0))"), false); +#endif + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ + (5 0,1 0,4 1))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ + (5 0,1 0,4 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))"), + false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,2 0),(1 0,0 1))"), false); + + test_simple(from_wkt("POLYGON(())"), true); + test_simple(from_wkt("POLYGON((),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,1 0,1 1),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0))"), false); + test_simple(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 1))"), false); + test_simple(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 0))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1,1 0.5))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1))"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,2 1,2 2,1 3))"), true); + test_simple(from_wkt("POLYGON((0 0,2 0,4 1,1 0))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,3 1,-1 2,3 3,3 4,0 4))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,3 1,0 2,3 3,3 4,0 4))"), false); + test_simple(from_wkt("POLYGON((0 0,10 0,10 10,0 10),\ + (1 1,1 2,2 2,2 1))"), false); + + test_simple(from_wkt("POLYGON(())"), true); + test_simple(from_wkt("POLYGON((),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1,0 0),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,1 0,1 1,0 0),())"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,0 0))"), false); + test_simple(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 1,0 0))"), false); + test_simple(from_wkt("POLYGON((0 0,2 0,0.5 0,0.5 0,0 0))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1,1 0.5,0 0))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,1 1,0 0))"), true); + test_simple(from_wkt("POLYGON((0 0,1 0,2 1,2 2,1 3,0 0))"), true); + test_simple(from_wkt("POLYGON((0 0,2 0,4 1,1 0,0 0))"), false); + test_simple(from_wkt("POLYGON((0 0,1 0,3 1,-1 2,3 3,3 4,0 4,0 0))"), + false); + test_simple(from_wkt("POLYGON((0 0,1 0,3 1,0 2,3 3,3 4,0 4,0 0))"), + false); + test_simple(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_simple(from_wkt("MULTIPOINT()"), true); + test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,0 1)"), true); + test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,1 0,0 1)"), false); + + test_simple(from_wkt("MULTIPOLYGON()"), true); + test_simple(from_wkt("MULTIPOLYGON( ((),()) )"), true); + test_simple(from_wkt("MULTIPOLYGON( (()),(()) )"), true); + test_simple(from_wkt("MULTIPOLYGON( ((),()),(()) )"), true); + test_simple(from_wkt("MULTIPOLYGON( ((0 0),()),(()) )"), true); + test_simple(from_wkt("MULTIPOLYGON( ((0 0),()),((1 1)) )"), true); +#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS + // test_simple(from_wkt("MULTIPOLYGON( ((0 0),()),((0 0)) )"), false); +#endif + + test_simple(from_wkt("MULTIPOLYGON(((0 0,1 0,2 1,2 2,1 3)),\ + ((10 0,11 0,11 1)))"), true); + + test_simple(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_simple(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 From 029517cff8a5324607e0a2f447a73670f1df37e0 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 4 Apr 2014 16:18:38 +0300 Subject: [PATCH 02/17] [feature/is_simple] modify debug print-outs a bit --- test/algorithms/is_simple.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index 28e4fa9ce..2d680e406 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE( test_is_simple_point ) #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; - std::cout << " IS_SIMPLE: POINT " << std::endl; + std::cout << " is_simple: POINT " << std::endl; std::cout << "************************************" << std::endl; #endif @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE( test_is_simple_segment ) #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; - std::cout << " IS_SIMPLE: SEGMENT " << std::endl; + std::cout << " is_simple: SEGMENT " << std::endl; std::cout << "************************************" << std::endl; #endif @@ -110,7 +110,7 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) #ifdef GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl; std::cout << "************************************" << std::endl; - std::cout << " IS_SIMPLE: LINESTRING " << std::endl; + std::cout << " is_simple: LINESTRING " << std::endl; std::cout << "************************************" << std::endl; #endif @@ -136,6 +136,13 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) { +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " is_simple: MULTILINESTRING " << std::endl; + std::cout << "************************************" << std::endl; +#endif + typedef multi_linestring_type G; test_simple(from_wkt("MULTILINESTRING()"), true); From 7ac118882387180a40fd35b0c7cbd27da352b8e5 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Fri, 4 Apr 2014 16:24:06 +0300 Subject: [PATCH 03/17] [feature/is_simple] add test case for multi-points --- test/algorithms/is_simple.cpp | 44 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index 2d680e406..832e51e77 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -55,7 +55,7 @@ template void test_simple(Geometry const& g, bool simple_geometry) { #ifdef GEOMETRY_TEST_DEBUG - std::cout << "======================================" << std::endl; + std::cout << "=======" << std::endl; #endif bool simple = bg::ogc::is_simple(g); @@ -66,7 +66,7 @@ void test_simple(Geometry const& g, bool simple_geometry) std::cout << std::boolalpha; std::cout << "is simple: " << simple << std::endl; std::cout << "expected result: " << simple_geometry << std::endl; - std::cout << "======================================" << std::endl; + std::cout << "=======" << std::endl; std::cout << std::endl << std::endl; std::cout << std::noboolalpha; #endif @@ -133,6 +133,20 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) test_simple(from_wkt("LINESTRING(0 0,0 0,1 0,1 0,1 1,0 0)"), true); } +BOOST_AUTO_TEST_CASE( test_is_simple_multipoint ) +{ +#ifdef GEOMETRY_TEST_DEBUG + std::cout << std::endl << std::endl; + std::cout << "************************************" << std::endl; + std::cout << " is_simple: MULTIPOINT " << std::endl; + std::cout << "************************************" << std::endl; +#endif + typedef multi_point_type G; + + test_simple(from_wkt("MULTIPOINT()"), true); + test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,0 1)"), true); + test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,1 0,0 1)"), false); +} BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) { @@ -179,32 +193,10 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) #if 0 BOOST_AUTO_TEST_CASE( test_is_simple_rest ) { - typedef multi_linestring_type mls; typedef open_polygon_type op; typedef closed_polygon_type cp; - typedef multi_point_type mpt; typedef multi_polygon_type mpl; - test_simple(from_wkt("MULTILINESTRING()"), true); - test_simple(from_wkt("MULTILINESTRING(())"), true); - test_simple(from_wkt("MULTILINESTRING((),(),())"), true); - test_simple(from_wkt("MULTILINESTRING((),(0 1,1 0))"), true); - test_simple(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), true); - test_simple(from_wkt("MULTILINESTRING((0 0),(1 0))"), true); -#ifdef GEOMETRY_TEST_INCLUDE_FAILING_TESTS - // test_simple(from_wkt("MULTILINESTRING((0 0),(0 0))"), false); -#endif - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ - (5 0,1 0,4 1))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ - (5 0,1 0,4 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))"), - false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,2 0),(1 0,0 1))"), false); - test_simple(from_wkt("POLYGON(())"), true); test_simple(from_wkt("POLYGON((),())"), true); test_simple(from_wkt("POLYGON((0 0,1 0,1 1),())"), true); @@ -240,10 +232,6 @@ BOOST_AUTO_TEST_CASE( test_is_simple_rest ) (1 1,1 2,2 2,2 1,1 1))"), false); - test_simple(from_wkt("MULTIPOINT()"), true); - test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,0 1)"), true); - test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,1 0,0 1)"), false); - test_simple(from_wkt("MULTIPOLYGON()"), true); test_simple(from_wkt("MULTIPOLYGON( ((),()) )"), true); test_simple(from_wkt("MULTIPOLYGON( (()),(()) )"), true); From b4774ff964240f344dea56eb86d28c4c5a499366 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Mon, 28 Apr 2014 18:08:47 +0300 Subject: [PATCH 04/17] [is_valid] implementation of OGC's is_valid for pointlike and linear geometries; moved unit tests to test/algorithms/ogc directory; --- .../algorithms/ogc/detail/is_valid/box.hpp | 86 +++++ .../ogc/detail/is_valid/has_spikes.hpp | 146 ++++++++ .../ogc/detail/is_valid/linestring.hpp | 158 +++++++++ .../ogc/detail/is_valid/multi_range.hpp | 82 +++++ .../ogc/detail/is_valid/pointlike.hpp | 63 ++++ .../ogc/detail/is_valid/segment.hpp | 61 ++++ .../algorithms/ogc/dispatch/is_valid.hpp | 38 +++ .../geometry/algorithms/ogc/is_valid.hpp | 168 ++++++++++ test/algorithms/{ => ogc}/is_simple.cpp | 0 test/algorithms/ogc/is_valid.cpp | 312 ++++++++++++++++++ 10 files changed, 1114 insertions(+) create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp create mode 100644 include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp create mode 100644 include/boost/geometry/algorithms/ogc/is_valid.hpp rename test/algorithms/{ => ogc}/is_simple.cpp (100%) create mode 100644 test/algorithms/ogc/is_valid.cpp diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp new file mode 100644 index 000000000..696cf8095 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp @@ -0,0 +1,86 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +template +struct has_valid_corners +{ + static inline bool apply(Box const& box) + { + if ( geometry::get(box) + <= + geometry::get(box) ) + { + return false; + } + return has_valid_corners::apply(box); + } +}; + + +template +struct has_valid_corners +{ + static inline bool apply(Box const& box) + { + return true; + } +}; + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A box is always simple +// A box is a Polygon, and it satisfies the conditions for Polygon validity. +// +// The only thing we have to check is whether the max corner lies in +// the upper-right quadrant as defined by the min corner +// +// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) +template +struct is_valid + : detail::is_valid::has_valid_corners::value> +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp new file mode 100644 index 000000000..4c054a841 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp @@ -0,0 +1,146 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +template +struct equal_point +{ + Iterator m_it; + + equal_point(Iterator it) + : m_it(it) + {} + + template + inline bool operator()(Point const& p) const + { + return geometry::equals(p, *m_it); + } +}; + +template +struct not_equal_point +{ + Iterator m_it; + + not_equal_point(Iterator it) + : m_it(it) + {} + + template + inline bool operator()(Point const& p) const + { + return !geometry::equals(p, *m_it); + } +}; + + + +template +struct has_spikes +{ + static inline bool apply(Range const& range) + { + typedef typename boost::range_iterator::type iterator; + typedef typename boost::range_reverse_iterator + < + Range const + >::type reverse_iterator; + + typedef not_equal_point not_equal; + + BOOST_ASSERT( boost::size(range) > 2 ); + + iterator prev = boost::begin(range); + + iterator cur = std::find_if(prev, boost::end(range), not_equal(prev)); + BOOST_ASSERT( cur != boost::end(range) ); + + iterator next = std::find_if(cur, boost::end(range), not_equal(cur)); + BOOST_ASSERT( next != boost::end(range) ); + + while ( next != boost::end(range) ) + { + if ( geometry::detail::point_is_spike_or_equal(*prev, + *next, + *cur) ) + { + return true; + } + prev = cur; + cur = next; + next = std::find_if(cur, boost::end(range), not_equal(cur)); + } + + if ( geometry::equals(*boost::begin(range), *boost::rbegin(range)) ) + { + iterator cur = boost::begin(range); + reverse_iterator prev = + std::find_if(boost::rbegin(range), + boost::rend(range), + not_equal_point + < + reverse_iterator + >(boost::rbegin(range)) + ); + iterator next = std::find_if(cur, boost::end(range), not_equal(cur)); + return geometry::detail::point_is_spike_or_equal(*prev, + *next, + *cur); + } + + return false; + } +}; + + +template +struct has_spikes +{ + static inline bool apply(Range const& range) + { + typedef typename closeable_view::type ClosedRange; + + ClosedRange crange(const_cast(range)); + return has_spikes::apply(crange); + } + +}; + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp new file mode 100644 index 000000000..71933942f --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp @@ -0,0 +1,158 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP + +#include + +#include +#include + +#include +#include + +#include + +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +template +struct is_single_point +{ + static inline bool apply(Range const& range) + { + typedef typename boost::range_iterator::type iterator; + + BOOST_ASSERT( boost::size(range) > 1 ); + + return std::find_if(++boost::begin(range), + boost::end(range), + not_equal_point(boost::begin(range)) + ) + == boost::end(range); + } +}; + +template +struct has_three_distinct_points +{ + static inline bool apply(Range const& range) + { + typedef typename boost::range_iterator::type iterator; + + BOOST_ASSERT( boost::size(range) > 1 ); + + iterator it1 = + std::find_if(boost::begin(range), + boost::end(range), + not_equal_point(boost::begin(range))); + + BOOST_ASSERT( it1 != boost::end(range) ); + + iterator it2 = + std::find_if(it1, + boost::end(range), + not_equal_point(it1)); + + return it2 != boost::end(range) + && !geometry::equals(*boost::begin(range), *it2); + } +}; + + +template +struct is_valid_linestring +{ + static inline bool apply(Linestring const& linestring, + bool allow_spikes) + { + std::size_t linestring_size = boost::size(linestring); + + if ( linestring_size < 2 ) + { + // if it has zero or one points is cannot be valid + return false; + } + + if ( is_single_point::apply(linestring) ) + { + // if it is an one-point linestring its dimension is 0, + // so not valid + return false; + } + + BOOST_ASSERT( boost::size(linestring) > 1 ); + + if ( !has_three_distinct_points::apply(linestring) ) + { + return !geometry::equals(*boost::begin(linestring), + *--boost::end(linestring)); + } + + return allow_spikes || !has_spikes::apply(linestring); + } +}; + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A linestring is a curve. +// A curve is 1-dimensional so it has to have at least two distinct +// points. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// There is an open issue as to whether spikes are allowed for +// linestrings; here we pass this as an additional parameter: allow_spikes +// If allow_spikes is set to true, spikes are allowed, false otherwise. +// By default, spikes are disallowed +// +// Reference: OGC 06-103r4 (§6.1.6.1) +template +struct is_valid +{ + static inline bool apply(Linestring const& linestring, + bool allow_spikes = false) + { + return detail::is_valid::is_valid_linestring + < + Linestring + >::apply(linestring, allow_spikes); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp new file mode 100644 index 000000000..1248fc588 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp @@ -0,0 +1,82 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP + +#include + +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ +template +struct is_valid_multi_range +{ + template + static inline bool apply(RangeIterator first, RangeIterator beyond) + { + for (RangeIterator it = first; it != beyond; ++it) + { + if ( !dispatch::is_valid::apply(*it) ) + { + return false; + } + } + return true; + }; +}; + + +}} //namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A MultiLinestring is a MultiCurve +// A MultiCurve is simple if all of its elements are simple and the +// only intersections between any two elements occur at Points that +// are on the boundaries of both elements. +// +// Reference: OGC 06-103r4 (§6.1.8.1; Fig. 9) +template +struct is_valid +{ + static inline bool apply(MultiLinestring const& multilinestring) + { + return detail::is_valid::is_valid_multi_range + < + typename boost::range_value::type + >::apply(boost::begin(multilinestring), + boost::end(multilinestring)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp new file mode 100644 index 000000000..ea630f938 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp @@ -0,0 +1,63 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A point is always simple +template +struct is_valid +{ + static inline bool apply(Point const&) + { + return true; + } +}; + + + +// A MultiPoint is simple if no two Points in the MultiPoint are equal +// (have identical coordinate values in X and Y) +// +// Reference: OGC 06-103r4 (§6.1.5) +template +struct is_valid +{ + static inline bool apply(MultiPoint const& multipoint) + { + return boost::size(multipoint) > 0; + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp new file mode 100644 index 000000000..917b27c55 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp @@ -0,0 +1,61 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP + +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A segment is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// A curve is 1-dimensional, hence we have to check is the two +// endpoints of the segment coincide, since in this case it is +// 0-dimensional. +// +// Reference: OGC 06-103r4 (§6.1.6.1) +template +struct is_valid +{ + static inline bool apply(Segment const& segment) + { + typename point_type::type p[2]; + geometry::detail::assign_point_from_index<0>(segment, p[0]); + geometry::detail::assign_point_from_index<1>(segment, p[1]); + + return !geometry::equals(p[0], p[1]); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP diff --git a/include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp b/include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp new file mode 100644 index 000000000..c8f1680d4 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP + +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template ::type> +struct is_valid + : not_implemented +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP diff --git a/include/boost/geometry/algorithms/ogc/is_valid.hpp b/include/boost/geometry/algorithms/ogc/is_valid.hpp new file mode 100644 index 000000000..c4c18b838 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/is_valid.hpp @@ -0,0 +1,168 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + + + +template +struct is_valid_polygon +{ + static inline bool apply(Polygon const& polygon) + { + typedef typename ring_type::type ring_type; + + if ( !dispatch::is_valid::apply(exterior_ring(polygon)) ) + { + return false; + } + + if ( !is_valid_multi_range::apply + (boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon))) ) + { + return false; + } + + // MK::need check for self-intersection points; not done yet + return true; + } +}; + + + +template +struct is_valid_multipolygon +{ + static inline bool apply(MultiPolygon const& multipolygon) + { + typedef typename boost::range_value::type polygon_type; + + if ( !is_valid_multi_range + < + polygon_type + >::apply(boost::begin(multipolygon), + boost::end(multipolygon)) ) + { + return false; + } + + // MK::need to check that they are (almost) disjoint + return true; + } + +}; + + + +}} // namespace detail::is_valid +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// A Ring is a Polygon. +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) +template +struct is_valid +{ + static inline bool apply(Ring const& ring) + { + if ( boost::size(ring) < 3 ) + { + return false; + } + + if ( detail::is_valid::has_spikes::value>(ring) ) + { + return false; + } + + return !geometry::intersects(ring); + } +}; + + +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for validity of Polygons): OGC 06-103r4 (§6.1.11.1) +template +struct is_valid + : detail::is_valid::is_valid_polygon +{}; + + + +// Not clear what the definition is. +// Right now we check that each element is simple (in fact valid), and +// that the MultiPolygon is also valid. +// +// Reference (for validity of MultiPolygons): OGC 06-103r4 (§6.1.14) +template +struct is_valid + : detail::is_valid::is_valid_multipolygon +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +template +inline bool is_valid(Geometry const& g) +{ + return dispatch::is_valid::apply(g); +} + + + +}}} // namespace boost::geometry::ogc + + + +#endif // BOOST_GEOMETRY_MYSQL_ALGORITHMS_IS_VALID_HPP diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/ogc/is_simple.cpp similarity index 100% rename from test/algorithms/is_simple.cpp rename to test/algorithms/ogc/is_simple.cpp diff --git a/test/algorithms/ogc/is_valid.cpp b/test/algorithms/ogc/is_valid.cpp new file mode 100644 index 000000000..2a25d0244 --- /dev/null +++ b/test/algorithms/ogc/is_valid.cpp @@ -0,0 +1,312 @@ +#include + +#ifndef BOOST_TEST_MODULE +#define BOOST_TEST_MODULE test_is_valid +#endif + +#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::ogc::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()"), true); + + // 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 From 342d7d2a451c27bd96d570c525cd1988a5a41662 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 20:02:14 +0300 Subject: [PATCH 05/17] [test] add missing includes; fix wrong result with empty multilinestring --- test/algorithms/ogc/is_valid.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/algorithms/ogc/is_valid.cpp b/test/algorithms/ogc/is_valid.cpp index 2a25d0244..9be62cc4a 100644 --- a/test/algorithms/ogc/is_valid.cpp +++ b/test/algorithms/ogc/is_valid.cpp @@ -1,3 +1,12 @@ +// 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 @@ -7,7 +16,6 @@ #include - #include #include #include @@ -17,6 +25,11 @@ #include #include +#include +#include +#include +#include + #include namespace bg = ::boost::geometry; @@ -220,7 +233,7 @@ BOOST_AUTO_TEST_CASE( test_is_valid_multilinestring ) typedef multi_linestring_type G; // empty multilinestring - test_valid(from_wkt("MULTILINESTRING()"), true); + test_valid(from_wkt("MULTILINESTRING()"), false); // multilinestring with empty linestring(s) test_valid(from_wkt("MULTILINESTRING(())"), false); From 2b93a1e3903514e30cca9559f6e9b695f75849ca Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 20:03:12 +0300 Subject: [PATCH 06/17] [test][is_simple] more test cases for linear geometries; add missing includes; --- test/algorithms/ogc/is_simple.cpp | 116 ++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/test/algorithms/ogc/is_simple.cpp b/test/algorithms/ogc/is_simple.cpp index 832e51e77..92859b912 100644 --- a/test/algorithms/ogc/is_simple.cpp +++ b/test/algorithms/ogc/is_simple.cpp @@ -1,3 +1,12 @@ +// 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 @@ -7,7 +16,6 @@ #include - #include #include #include @@ -16,6 +24,12 @@ #include #include +#include +#include +#include +#include + +#include #include namespace bg = ::boost::geometry; @@ -64,6 +78,7 @@ void test_simple(Geometry const& g, bool simple_geometry) #ifdef GEOMETRY_TEST_DEBUG std::cout << "Geometry: " << bg::wkt(g) << std::endl; std::cout << std::boolalpha; + std::cout << "is valid : " << bg::ogc::is_valid(g) << std::endl; std::cout << "is simple: " << simple << std::endl; std::cout << "expected result: " << simple_geometry << std::endl; std::cout << "=======" << std::endl; @@ -101,7 +116,7 @@ BOOST_AUTO_TEST_CASE( test_is_simple_segment ) typedef segment_type G; - test_simple(make_segment(0, 0, 0, 0), true); + test_simple(make_segment(0, 0, 0, 0), false); test_simple(make_segment(0, 0, 1, 0), true); } @@ -116,21 +131,36 @@ BOOST_AUTO_TEST_CASE( test_is_simple_linestring ) typedef linestring_type G; - test_simple(from_wkt("LINESTRING()"), true); + // invalid linestrings + test_simple(from_wkt("LINESTRING()"), false); test_simple(from_wkt("LINESTRING(0 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,0 0)"), true); + test_simple(from_wkt("LINESTRING(0 0,0 0)"), false); + + // valid linestrings with multiple points + test_simple(from_wkt("LINESTRING(0 0,0 0,1 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,0 0,1 0,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,0 0,1 0,1 0,1 1,0 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,1 1,1 0,1 -1)"), false); + + // simple open linestrings test_simple(from_wkt("LINESTRING(0 0,1 2)"), true); + test_simple(from_wkt("LINESTRING(0 0,1 2,2 3)"), true); + + // simple closed linestrings + test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0 0)"), true); + test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0 1,0 0)"), true); + + // non-simple linestrings + test_simple(from_wkt("LINESTRING(0 0,1 0,0 0)"), false); test_simple(from_wkt("LINESTRING(0 0,1 0,2 10,0.5 -1)"), false); test_simple(from_wkt("LINESTRING(0 0,1 0,2 1,1 0)"), false); test_simple(from_wkt("LINESTRING(0 0,1 0,2 1,0.5 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,0.5 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,0.5 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,1.5 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,2 0,1.5 0,0.5 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,0.5 0,2 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0.5 0,0 0)"), false); - test_simple(from_wkt("LINESTRING(0 0,1 0,1 1,0 0)"), true); - test_simple(from_wkt("LINESTRING(0 0,0 0,1 0,1 0,1 1,0 0)"), true); + test_simple(from_wkt("LINESTRING(0 0,2 0,1 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,3 0,5 0,1 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,3 0,5 0,4 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,3 0,5 0,4 0,2 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,3 0,2 0,5 0)"), false); + test_simple(from_wkt("LINESTRING(0 0,2 0,2 2,1 0,0 0)"), false); } BOOST_AUTO_TEST_CASE( test_is_simple_multipoint ) @@ -143,7 +173,8 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multipoint ) #endif typedef multi_point_type G; - test_simple(from_wkt("MULTIPOINT()"), true); + test_simple(from_wkt("MULTIPOINT()"), false); + test_simple(from_wkt("MULTIPOINT(0 0)"), true); test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,0 1)"), true); test_simple(from_wkt("MULTIPOINT(0 0,1 0,1 1,1 0,0 1)"), false); } @@ -159,37 +190,66 @@ BOOST_AUTO_TEST_CASE( test_is_simple_multilinestring ) typedef multi_linestring_type G; - test_simple(from_wkt("MULTILINESTRING()"), true); - test_simple(from_wkt("MULTILINESTRING(())"), true); - test_simple(from_wkt("MULTILINESTRING((),(),())"), true); - test_simple(from_wkt("MULTILINESTRING((),(0 1,1 0))"), true); - test_simple(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(0 1,1 0))"), true); - test_simple(from_wkt("MULTILINESTRING((0 0),(1 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(1 0,1 0))"), true); + // empty multilinestring + test_simple(from_wkt("MULTILINESTRING()"), false); + // multilinestrings with empty linestrings + test_simple(from_wkt("MULTILINESTRING(())"), false); + test_simple(from_wkt("MULTILINESTRING((),(),())"), false); + test_simple(from_wkt("MULTILINESTRING((),(0 1,1 0))"), false); + + // multilinestrings with 1-point linestrings + test_simple(from_wkt("MULTILINESTRING((0 0),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0),(1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,0 0),(1 0,1 0))"), false); test_simple(from_wkt("MULTILINESTRING((0 0),(0 0))"), false); + // multilinestrings with linestrings with spikes test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ - (5 0,1 0,4 1))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),\ - (5 0,1 0,4 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0,1 0,4 1))"), + false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(5 0,1 0,4 0))"), + false); test_simple(from_wkt("MULTILINESTRING((0 0,1 0,0 0),(1 0,2 0))"), false); - test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), false); + + + // simple multilinestrings test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0))"), true); - test_simple(from_wkt("MULTILINESTRING((0 0,2 0),(1 0,0 1))"), false); test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0),(0 1,1 1))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0,2 2),(0 0,1 0,2 0,2 2))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0,2 2),(2 2,2 0,1 0,0 0))"), true); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0),(0 0,-1 0),\ + (1 0,2 0))"), + true); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0),(-1 0,0 0),\ + (2 0,1 0))"), + true); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,1 1,0 1,0 0),(-1 0,0 0))"), + true); + // non-simple multilinestrings + test_simple(from_wkt("MULTILINESTRING((0 0,2 2),(0 0,2 2))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,2 2),(2 2,0 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,2 2),\ + (0 0,1 0,1 1,2 0,2 2))"), + false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1,2 2),\ + (0 0,1 0,1 1,2 0,2 2))"), + false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1,2 2),(2 2,0 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(0 1,1 0))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,2 0),(1 0,0 1))"), false); test_simple(from_wkt("MULTILINESTRING((0 0,1 1),(1 1,1 0),\ (1 1,0 1,0.5,0.5))"), false); + test_simple(from_wkt("MULTILINESTRING((0 0,1 0,1 1,0 1,0 0),(1 0,1 -1))"), + false); } - #if 0 BOOST_AUTO_TEST_CASE( test_is_simple_rest ) { From dfa427e83a8bfc280adf7238fb48c27eb14204ee Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 20:04:35 +0300 Subject: [PATCH 07/17] [is_valid] fix includes --- .../geometry/algorithms/ogc/is_valid.hpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/include/boost/geometry/algorithms/ogc/is_valid.hpp b/include/boost/geometry/algorithms/ogc/is_valid.hpp index c4c18b838..c8159519b 100644 --- a/include/boost/geometry/algorithms/ogc/is_valid.hpp +++ b/include/boost/geometry/algorithms/ogc/is_valid.hpp @@ -10,17 +10,18 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP #define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP -#include -#include -#include -#include +#include + +#include +#include +#include +#include +#include +#include +#include + #include #include -#include -#include -#include -#include -#include #include @@ -29,6 +30,7 @@ #include #include #include +#include namespace boost { namespace geometry { namespace ogc From e68f3b512c479e494512e39d387ef2679f1c111e Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 20:05:16 +0300 Subject: [PATCH 08/17] [is_simple] update code; fix includes; --- .../geometry/algorithms/ogc/is_simple.hpp | 309 +++--------------- 1 file changed, 37 insertions(+), 272 deletions(-) diff --git a/include/boost/geometry/algorithms/ogc/is_simple.hpp b/include/boost/geometry/algorithms/ogc/is_simple.hpp index 4b8660e49..5817f0856 100644 --- a/include/boost/geometry/algorithms/ogc/is_simple.hpp +++ b/include/boost/geometry/algorithms/ogc/is_simple.hpp @@ -1,8 +1,37 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + #ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP #define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP -#include +#include + +#include + +#include +#include +#include + #include + +#include + +#include + +#include + +#include +#include + + + +// check includes below #include #include #include @@ -11,73 +40,19 @@ #include #include #include -#include + + + namespace boost { namespace geometry { namespace ogc { -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template ::type> -struct is_simple - : not_implemented -{}; - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace is_simple { - -template -struct has_spikes; - -template -struct has_spikes -{ - static inline bool apply(Range const& range) - { - if ( boost::size(range) < 3 ) - { - return false; - } - - BOOST_AUTO_TPL(it1, boost::begin(range)); - BOOST_AUTO_TPL(it2, ++boost::begin(range)); - BOOST_AUTO_TPL(it3, ++(++boost::begin(range))); - - for (; it3 != boost::end(range); ++it1, ++it2, ++it3) - { - if ( geometry::detail::point_is_spike_or_equal(*it3, *it1, *it2) ) - { - return true; - } - } - - return false; - } -}; - - -template -struct has_spikes -{ - static inline bool apply(Range const& range) - { - typedef typename closeable_view::type ClosedRange; - - ClosedRange crange(const_cast(range)); - return has_spikes::apply(crange); - } - -}; - - template < typename Geometry, @@ -106,35 +81,6 @@ struct is_below_minimal_size -template -struct is_simple_range -{ - static inline bool apply(Range const& range) - { - if ( is_below_minimal_size::apply(range) ) - { - return false; - } - - Range other(range); - geometry::unique(other); - - if ( boost::size(other) == 1 ) - { - return true; - } - - if ( has_spikes::value>::apply(other) ) - { - return false; - } - - return !geometry::intersects(other); - } -}; - - - template struct is_simple_polygon { @@ -156,147 +102,7 @@ struct is_simple_polygon }; -template -struct is_simple_multipoint -{ - static inline bool apply(MultiPoint const& multipoint) - { - if ( boost::size(multipoint) <= 1 ) - { - return true; - } - MultiPoint mp(multipoint); - - typedef typename point_type::type Point; - - std::sort(boost::begin(mp), boost::end(mp), geometry::less()); - - geometry::equal_to equal; - - BOOST_AUTO_TPL(it_next, ++boost::begin(mp)); - BOOST_AUTO_TPL(it, boost::begin(mp)); - for (; it_next != boost::end(mp); ++it, ++it_next) - { - if ( equal(*it, *it_next) ) - { - return false; - } - } - return true; - } -}; - - -template -struct is_simple_multilinestring -{ - static inline bool apply(MultiLinestring const& multilinestring) - { - typedef typename boost::range_value::type Linestring; - typedef typename point_type::type Point; - - BOOST_AUTO_TPL(it, boost::begin(multilinestring)); - for (; it != boost::end(multilinestring); ++it) - { - if ( !dispatch::is_simple::apply(*it) ) - { - return false; - } - } - - - typedef geometry::detail::overlay::turn_info - < - Point - > turn_info; - - std::deque turns; - - typedef typename strategy_intersection - < - typename cs_tag::type, - MultiLinestring, - MultiLinestring, - Point - >::segment_intersection_strategy_type segment_intersection_strategy_type; - - typedef geometry::detail::overlay::get_turn_info - < - geometry::detail::disjoint::assign_disjoint_policy - > TurnPolicy; - - geometry::detail::self_get_turn_points::no_interrupt_policy - interrupt_policy; - - geometry::detail::self_get_turn_points::get_turns - < - TurnPolicy - >::apply(multilinestring, - geometry::detail::no_rescale_policy(), - turns, - interrupt_policy); - - std::cout << "turns:"; - for (typename std::deque::const_iterator tit = turns.begin(); - tit != turns.end(); ++tit) - { - std::cout << " " << geometry::dsv(tit->point); - } - std::cout << std::endl << std::endl; - - if ( turns.size() == 0 ) - { - return true; - } - - std::vector endpoints; - for (it = boost::begin(multilinestring); - it != boost::end(multilinestring); ++it) - { - BOOST_ASSERT ( boost::size(*it) != 1 ); - if ( boost::size(*it) != 0 ) - { - endpoints.push_back( *boost::begin(*it) ); - endpoints.push_back( *(--boost::end(*it)) ); - } - } - - - std::sort(endpoints.begin(), endpoints.end(), geometry::less()); - - std::cout << "endpoints: "; - for (typename std::vector::iterator pit = endpoints.begin(); - pit != endpoints.end(); ++pit) - { - std::cout << " " << geometry::dsv(*pit); - } - std::cout << std::endl << std::endl; - - for (typename std::deque::const_iterator tit = turns.begin(); - tit != turns.end(); ++tit) - { - Linestring const& ls1 = - *(boost::begin(multilinestring) - + tit->operations[0].seg_id.multi_index); - Linestring const& ls2 = - *(boost::begin(multilinestring) - + tit->operations[0].other_id.multi_index); - - if ( ( !geometry::equals(*boost::begin(ls1), tit->point) - && !geometry::equals(*--boost::end(ls1), tit->point) ) - || - ( !geometry::equals(*boost::begin(ls2), tit->point) - && !geometry::equals(*--boost::end(ls2), tit->point) ) - ) - { - return false; - } - } - return true; - } - -}; template @@ -348,16 +154,6 @@ namespace dispatch { -// A point is always simple -template -struct is_simple -{ - static inline bool apply(Point const&) - { - return true; - } -}; - // A segment is always simple. // A segment is a curve. @@ -368,9 +164,9 @@ struct is_simple template struct is_simple { - static inline bool apply(Segment const&) + static inline bool apply(Segment const& segment) { - return true; + return dispatch::is_valid::apply(segment); } }; @@ -382,23 +178,13 @@ struct is_simple template struct is_simple { - static inline bool apply(Box const&) + static inline bool apply(Box const& box) { - return true; + return dispatch::is_valid::apply(box); } }; -// A linestring is a curve. -// A curve is simple if it does not pass through the same point twice, -// with the possible exception of its two endpoints -// -// Reference: OGC 06-103r4 (§6.1.6.1) -template -struct is_simple - : detail::is_simple::is_simple_range -{}; - // A Ring is a Polygon. // A Polygon is always a simple geometric object provided that it is valid. @@ -419,27 +205,6 @@ struct is_simple {}; -// A MultiPoint is simple if no two Points in the MultiPoint are equal -// (have identical coordinate values in X and Y) -// -// Reference: OGC 06-103r4 (§6.1.5) -template -struct is_simple - : detail::is_simple::is_simple_multipoint -{}; - - -// A MultiLinestring is a MultiCurve -// A MultiCurve is simple if all of its elements are simple and the -// only intersections between any two elements occur at Points that -// are on the boundaries of both elements. -// -// Reference: OGC 06-103r4 (§6.1.8.1; Fig. 9) -template -struct is_simple - : detail::is_simple::is_simple_multilinestring -{}; - // Not clear what the definition is. // Right now we check that each element is simple (in fact valid), and From d4c0f9d626430991f95f9000cc379fa66476c68b Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 20:05:57 +0300 Subject: [PATCH 09/17] [is_simple] basic dispatch for is_simple --- .../algorithms/ogc/dispatch/is_simple.hpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp diff --git a/include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp b/include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp new file mode 100644 index 000000000..c55a0b543 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp @@ -0,0 +1,38 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP + +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template ::type> +struct is_simple + : not_implemented +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP From 4e14afc71f8abc9e3f9b86df5cbe52a64e4f39ab Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Tue, 29 Apr 2014 23:00:38 +0300 Subject: [PATCH 10/17] [is_valid] fix wrong result for empty multi-geometries --- .../geometry/algorithms/ogc/detail/is_valid/multi_range.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp b/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp index 1248fc588..6da186f5b 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp +++ b/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp @@ -37,7 +37,7 @@ struct is_valid_multi_range return false; } } - return true; + return first != beyond; }; }; From a712981e28e2c6d21b1bfacb81c8d6e26b90500b Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 00:12:05 +0300 Subject: [PATCH 11/17] [is_simple] implementation of is_simple for pointlike and linear geometries --- .../ogc/detail/is_simple/has_duplicates.hpp | 66 ++++ .../ogc/detail/is_simple/linear.hpp | 309 ++++++++++++++++++ .../ogc/detail/is_simple/pointlike.hpp | 102 ++++++ 3 files changed, 477 insertions(+) create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp create mode 100644 include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp b/include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp new file mode 100644 index 000000000..b5711c340 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp @@ -0,0 +1,66 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP + +#include +#include + +#include + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + +template +struct has_duplicates +{ + static inline bool apply(Range const& range) + { + typedef typename boost::range_value::type point; + typedef typename boost::range_iterator::type iterator; + + BOOST_ASSERT( boost::size(range) > 0 ); + + if ( boost::size(range) == 1 ) + { + return false; + } + + geometry::equal_to equal; + + iterator it = boost::begin(range); + iterator next = ++boost::begin(range); + for (; next != boost::end(range); ++it, ++next) + { + if ( equal(*it, *next) ) + { + return true; + } + } + return false; + } +}; + + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + +}}} // namespace boost::geometry::ogc + + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp new file mode 100644 index 000000000..544bdabc6 --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp @@ -0,0 +1,309 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +struct is_simple_range +{ + static inline bool apply(Range const& range) + { + // the second argument to apply refers to spikes: + // spikes are disallowed + if ( !dispatch::is_valid::apply(range, false) ) + { + return false; + } + + if ( has_duplicates::apply(range) ) + { + return false; + } + + return !geometry::intersects(range); + } +}; + + + +template +struct is_simple_multi_range +{ + static inline bool apply(MultiRange const& multi_range) + { + typedef typename boost::range_value::type range; + typedef typename boost::range_iterator + < + MultiRange const + >::type iterator; + + if ( boost::size(multi_range) == 0 ) + { + return false; + } + + for (iterator it = boost::begin(multi_range); + it != boost::end(multi_range); ++it) + { + if ( !is_simple_range::apply(*it) ) + { + return false; + } + } + return true; + } +}; + + + +template +struct is_simple_multilinestring +{ + template + static inline bool check_turn(Turn const& turn, + Method method, + Operation operation) + { + return turn.method == method + && turn.operations[0].operation == operation + && turn.operations[1].operation == operation; + } + + template + static inline bool is_acceptable_turn(Turn const& turn) + { + return check_turn(turn, + geometry::detail::overlay::method_none, + geometry::detail::overlay::operation_continue) + || check_turn(turn, + geometry::detail::overlay::method_touch, + geometry::detail::overlay::operation_intersection) + || check_turn(turn, + geometry::detail::overlay::method_touch, + geometry::detail::overlay::operation_blocked) + ; + } + + template + static inline bool is_endpoint_of(Point const& point, + Linestring const& linestring) + { + BOOST_ASSERT( boost::size(linestring) > 1 ); + return geometry::equals(point, *boost::begin(linestring)) + || geometry::equals(point, *boost::rbegin(linestring)); + } + + template + static inline bool have_same_endpoints(Linestring1 const& ls1, + Linestring2 const& ls2) + { + return + (geometry::equals(*boost::begin(ls1), *boost::begin(ls2)) + && geometry::equals(*boost::rbegin(ls1), *boost::rbegin(ls2))) + || + (geometry::equals(*boost::begin(ls1), *boost::rbegin(ls2)) + && geometry::equals(*boost::rbegin(ls1), *boost::begin(ls2))) + ; + } + + + + + static inline bool apply(MultiLinestring const& multilinestring) + { + if ( !is_simple_multi_range::apply(multilinestring) ) + { + return false; + } + + typedef typename boost::range_value::type linestring; + typedef typename point_type::type point_type; + typedef point_type point; + + typedef geometry::detail::overlay::turn_info + < + point_type, + geometry::segment_ratio + < + typename geometry::coordinate_type::type + > + > turn_info; + + std::deque turns; + + typedef geometry::detail::overlay::get_turn_info + < + geometry::detail::disjoint::assign_disjoint_policy + > TurnPolicy; + + geometry::detail::self_get_turn_points::no_interrupt_policy + interrupt_policy; + + geometry::detail::self_get_turn_points::get_turns + < + TurnPolicy + >::apply(multilinestring, + geometry::detail::no_rescale_policy(), + turns, + interrupt_policy); + + std::cout << "turns:"; + for (typename std::deque::const_iterator tit = turns.begin(); + tit != turns.end(); ++tit) + { + std::cout << " [" << geometry::method_char(tit->method); + std::cout << "," << geometry::operation_char(tit->operations[0].operation); + std::cout << "/" << geometry::operation_char(tit->operations[1].operation); + std::cout << " " << geometry::dsv(tit->point); + std::cout << "] "; + } + std::cout << std::endl << std::endl; + + if ( turns.size() == 0 ) + { + return true; + } + +#ifdef GEOMETRY_TEST_DEBUG + std::vector endpoints; + typename boost::range_iterator::type it; + for (it = boost::begin(multilinestring); + it != boost::end(multilinestring); ++it) + { + BOOST_ASSERT ( boost::size(*it) != 1 ); + if ( boost::size(*it) != 0 ) + { + endpoints.push_back( *boost::begin(*it) ); + endpoints.push_back( *(--boost::end(*it)) ); + } + } + + + std::sort(endpoints.begin(), endpoints.end(), geometry::less()); + + std::cout << "endpoints: "; + for (typename std::vector::iterator pit = endpoints.begin(); + pit != endpoints.end(); ++pit) + { + std::cout << " " << geometry::dsv(*pit); + } + std::cout << std::endl << std::endl; +#endif + + for (typename std::deque::const_iterator tit = turns.begin(); + tit != turns.end(); ++tit) + { +#if 0 + if ( !is_acceptable_turn(*tit) ) + { + return false; + } +#endif + linestring const& ls1 = + *(boost::begin(multilinestring) + + tit->operations[0].seg_id.multi_index); + linestring const& ls2 = + *(boost::begin(multilinestring) + + tit->operations[0].other_id.multi_index); + + if ( !is_endpoint_of(tit->point, ls1) + || !is_endpoint_of(tit->point, ls2) ) + { + return false; + } + +#if 1 + if ( boost::size(ls1) == 2 + && boost::size(ls2) == 2 + && have_same_endpoints(ls1, ls2) ) + { + return false; + } +#endif + } + return true; + } + +}; + + + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A linestring is a curve. +// A curve is simple if it does not pass through the same point twice, +// with the possible exception of its two endpoints +// +// Reference: OGC 06-103r4 (§6.1.6.1) +template +struct is_simple + : detail::is_simple::is_simple_range +{}; + + +// A MultiLinestring is a MultiCurve +// A MultiCurve is simple if all of its elements are simple and the +// only intersections between any two elements occur at Points that +// are on the boundaries of both elements. +// +// Reference: OGC 06-103r4 (§6.1.8.1; Fig. 9) +template +struct is_simple + : detail::is_simple::is_simple_multilinestring +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp b/include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp new file mode 100644 index 000000000..e27d5d28c --- /dev/null +++ b/include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp @@ -0,0 +1,102 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace ogc +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_simple +{ + + +template +struct is_simple_multipoint +{ + static inline bool apply(MultiPoint const& multipoint) + { + typedef typename point_type::type Point; + typedef typename boost::range_iterator + < + MultiPoint const + >::type iterator; + + + if ( !dispatch::is_valid::apply(multipoint) ) + { + return false; + } + + MultiPoint mp(multipoint); + std::sort(boost::begin(mp), boost::end(mp), geometry::less()); + + return !has_duplicates::apply(mp); + } +}; + + +}} // namespace detail::is_simple +#endif // DOXYGEN_NO_DETAIL + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A point is always simple +template +struct is_simple +{ + static inline bool apply(Point const&) + { + return true; + } +}; + + + +// A MultiPoint is simple if no two Points in the MultiPoint are equal +// (have identical coordinate values in X and Y) +// +// Reference: OGC 06-103r4 (§6.1.5) +template +struct is_simple + : detail::is_simple::is_simple_multipoint +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}}} // namespace boost::geometry::ogc + + +#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP From c9e33bbd503126f3c12d0e97eed4bb92908bdd91 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 00:47:58 +0300 Subject: [PATCH 12/17] [is_simple] add missing includes; fix coding style; --- .../geometry/algorithms/ogc/detail/is_simple/linear.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp index 544bdabc6..1ff290f98 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp @@ -11,14 +11,17 @@ #define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP #include +#include #include #include #include +#include #include #include +#include #include #include @@ -171,14 +174,14 @@ struct is_simple_multilinestring typedef geometry::detail::overlay::get_turn_info < geometry::detail::disjoint::assign_disjoint_policy - > TurnPolicy; + > turn_policy; geometry::detail::self_get_turn_points::no_interrupt_policy interrupt_policy; geometry::detail::self_get_turn_points::get_turns < - TurnPolicy + turn_policy >::apply(multilinestring, geometry::detail::no_rescale_policy(), turns, From c5c22d720cf3b08dde94063f306d7e1521002d09 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 12:34:52 +0300 Subject: [PATCH 13/17] [is_valid / is_simple] move files one directory level up (ommit the ogc directory); move code one namespace up (ommit the ogc namespace); --- .../detail/is_simple/has_duplicates.hpp | 10 ++--- .../{ogc => }/detail/is_simple/linear.hpp | 40 +++++++++---------- .../{ogc => }/detail/is_simple/pointlike.hpp | 16 ++++---- .../{ogc => }/detail/is_valid/box.hpp | 12 +++--- .../{ogc => }/detail/is_valid/has_spikes.hpp | 14 +++---- .../{ogc => }/detail/is_valid/linestring.hpp | 14 +++---- .../{ogc => }/detail/is_valid/multi_range.hpp | 12 +++--- .../{ogc => }/detail/is_valid/pointlike.hpp | 12 +++--- .../{ogc => }/detail/is_valid/segment.hpp | 16 ++++---- .../{ogc => }/dispatch/is_simple.hpp | 10 ++--- .../{ogc => }/dispatch/is_valid.hpp | 10 ++--- .../algorithms/{ogc => }/is_simple.hpp | 20 +++++----- .../algorithms/{ogc => }/is_valid.hpp | 24 +++++------ test/algorithms/{ogc => }/is_simple.cpp | 8 ++-- test/algorithms/{ogc => }/is_valid.cpp | 4 +- 15 files changed, 110 insertions(+), 112 deletions(-) rename include/boost/geometry/algorithms/{ogc => }/detail/is_simple/has_duplicates.hpp (79%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_simple/linear.hpp (86%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_simple/pointlike.hpp (78%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/box.hpp (82%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/has_spikes.hpp (87%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/linestring.hpp (89%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/multi_range.hpp (82%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/pointlike.hpp (74%) rename include/boost/geometry/algorithms/{ogc => }/detail/is_valid/segment.hpp (70%) rename include/boost/geometry/algorithms/{ogc => }/dispatch/is_simple.hpp (69%) rename include/boost/geometry/algorithms/{ogc => }/dispatch/is_valid.hpp (69%) rename include/boost/geometry/algorithms/{ogc => }/is_simple.hpp (89%) rename include/boost/geometry/algorithms/{ogc => }/is_valid.hpp (82%) rename test/algorithms/{ogc => }/is_simple.cpp (98%) rename test/algorithms/{ogc => }/is_valid.cpp (99%) diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp b/include/boost/geometry/algorithms/detail/is_simple/has_duplicates.hpp similarity index 79% rename from include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp rename to include/boost/geometry/algorithms/detail/is_simple/has_duplicates.hpp index b5711c340..0e4f78a68 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_simple/has_duplicates.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/has_duplicates.hpp @@ -7,15 +7,15 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP #include #include #include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -59,8 +59,8 @@ struct has_duplicates #endif // DOXYGEN_NO_DETAIL -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_HAS_DUPLICATES_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp similarity index 86% rename from include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp rename to include/boost/geometry/algorithms/detail/is_simple/linear.hpp index 1ff290f98..68541d965 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_simple/linear.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/linear.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP #include #include @@ -23,10 +23,10 @@ #include #include -#include -#include +#include +#include -#include +#include #include #include @@ -34,7 +34,7 @@ #include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -113,14 +113,14 @@ struct is_simple_multilinestring static inline bool is_acceptable_turn(Turn const& turn) { return check_turn(turn, - geometry::detail::overlay::method_none, - geometry::detail::overlay::operation_continue) + detail::overlay::method_none, + detail::overlay::operation_continue) || check_turn(turn, - geometry::detail::overlay::method_touch, - geometry::detail::overlay::operation_intersection) + detail::overlay::method_touch, + detail::overlay::operation_intersection) || check_turn(turn, - geometry::detail::overlay::method_touch, - geometry::detail::overlay::operation_blocked) + detail::overlay::method_touch, + detail::overlay::operation_blocked) ; } @@ -160,7 +160,7 @@ struct is_simple_multilinestring typedef typename point_type::type point_type; typedef point_type point; - typedef geometry::detail::overlay::turn_info + typedef detail::overlay::turn_info < point_type, geometry::segment_ratio @@ -171,19 +171,19 @@ struct is_simple_multilinestring std::deque turns; - typedef geometry::detail::overlay::get_turn_info + typedef detail::overlay::get_turn_info < - geometry::detail::disjoint::assign_disjoint_policy + detail::disjoint::assign_disjoint_policy > turn_policy; - geometry::detail::self_get_turn_points::no_interrupt_policy + detail::self_get_turn_points::no_interrupt_policy interrupt_policy; - geometry::detail::self_get_turn_points::get_turns + detail::self_get_turn_points::get_turns < turn_policy >::apply(multilinestring, - geometry::detail::no_rescale_policy(), + detail::no_rescale_policy(), turns, interrupt_policy); @@ -306,7 +306,7 @@ struct is_simple #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_LINEAR_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_LINEAR_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp b/include/boost/geometry/algorithms/detail/is_simple/pointlike.hpp similarity index 78% rename from include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp rename to include/boost/geometry/algorithms/detail/is_simple/pointlike.hpp index e27d5d28c..fa5cf8c2b 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_simple/pointlike.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/pointlike.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_POINTLIKE_HPP #include @@ -20,13 +20,13 @@ #include -#include -#include +#include +#include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -96,7 +96,7 @@ struct is_simple #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_SIMPLE_POINTLIKE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_SIMPLE_POINTLIKE_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp b/include/boost/geometry/algorithms/detail/is_valid/box.hpp similarity index 82% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp rename to include/boost/geometry/algorithms/detail/is_valid/box.hpp index 696cf8095..488c8c6ca 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/box.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/box.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP #include @@ -16,10 +16,10 @@ #include #include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -80,7 +80,7 @@ struct is_valid -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_BOX_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_BOX_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp similarity index 87% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp rename to include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 4c054a841..6e5667e8d 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP #include @@ -23,7 +23,7 @@ #include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -113,9 +113,7 @@ struct has_spikes >(boost::rbegin(range)) ); iterator next = std::find_if(cur, boost::end(range), not_equal(cur)); - return geometry::detail::point_is_spike_or_equal(*prev, - *next, - *cur); + return detail::point_is_spike_or_equal(*prev, *next, *cur); } return false; @@ -140,7 +138,7 @@ struct has_spikes #endif // DOXYGEN_NO_DETAIL -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_HAS_SPIKES_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_HAS_SPIKES_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp b/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp similarity index 89% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp rename to include/boost/geometry/algorithms/detail/is_valid/linestring.hpp index 71933942f..e8410ca43 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINESTRING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINESTRING_HPP #include @@ -20,12 +20,12 @@ #include -#include +#include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL @@ -152,7 +152,7 @@ struct is_valid #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_LINESTRING_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINESTRING_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp b/include/boost/geometry/algorithms/detail/is_valid/multi_range.hpp similarity index 82% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp rename to include/boost/geometry/algorithms/detail/is_valid/multi_range.hpp index 6da186f5b..c8bad652f 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/multi_range.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/multi_range.hpp @@ -7,17 +7,17 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTI_RANGE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTI_RANGE_HPP #include #include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -76,7 +76,7 @@ struct is_valid #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_MULTI_RANGE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_MULTI_RANGE_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp b/include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp similarity index 74% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp rename to include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp index ea630f938..6cf0908dc 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/pointlike.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/pointlike.hpp @@ -7,18 +7,18 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP #include #include #include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -57,7 +57,7 @@ struct is_valid #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_POINTLIKE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POINTLIKE_HPP diff --git a/include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp similarity index 70% rename from include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp rename to include/boost/geometry/algorithms/detail/is_valid/segment.hpp index 917b27c55..ccbe49d4f 100644 --- a/include/boost/geometry/algorithms/ogc/detail/is_valid/segment.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/segment.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP #include #include @@ -16,10 +16,10 @@ #include #include -#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -43,8 +43,8 @@ struct is_valid static inline bool apply(Segment const& segment) { typename point_type::type p[2]; - geometry::detail::assign_point_from_index<0>(segment, p[0]); - geometry::detail::assign_point_from_index<1>(segment, p[1]); + detail::assign_point_from_index<0>(segment, p[0]); + detail::assign_point_from_index<1>(segment, p[1]); return !geometry::equals(p[0], p[1]); } @@ -55,7 +55,7 @@ struct is_valid #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DETAIL_IS_VALID_SEGMENT_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_SEGMENT_HPP diff --git a/include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp b/include/boost/geometry/algorithms/dispatch/is_simple.hpp similarity index 69% rename from include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp rename to include/boost/geometry/algorithms/dispatch/is_simple.hpp index c55a0b543..2ac92256b 100644 --- a/include/boost/geometry/algorithms/ogc/dispatch/is_simple.hpp +++ b/include/boost/geometry/algorithms/dispatch/is_simple.hpp @@ -7,15 +7,15 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP #include #include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DISPATCH @@ -33,6 +33,6 @@ struct is_simple #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_SIMPLE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_SIMPLE_HPP diff --git a/include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp b/include/boost/geometry/algorithms/dispatch/is_valid.hpp similarity index 69% rename from include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp rename to include/boost/geometry/algorithms/dispatch/is_valid.hpp index c8f1680d4..1d9834a4a 100644 --- a/include/boost/geometry/algorithms/ogc/dispatch/is_valid.hpp +++ b/include/boost/geometry/algorithms/dispatch/is_valid.hpp @@ -7,15 +7,15 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP #include #include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DISPATCH @@ -33,6 +33,6 @@ struct is_valid #endif // DOXYGEN_NO_DISPATCH -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_ALGORITHMS_OGC_DISPATCH_IS_VALID_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_IS_VALID_HPP diff --git a/include/boost/geometry/algorithms/ogc/is_simple.hpp b/include/boost/geometry/algorithms/is_simple.hpp similarity index 89% rename from include/boost/geometry/algorithms/ogc/is_simple.hpp rename to include/boost/geometry/algorithms/is_simple.hpp index 5817f0856..fbf355c96 100644 --- a/include/boost/geometry/algorithms/ogc/is_simple.hpp +++ b/include/boost/geometry/algorithms/is_simple.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_SIMPLE_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP +#define BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP #include @@ -20,14 +20,14 @@ #include -#include +#include -#include +#include -#include +#include -#include -#include +#include +#include @@ -44,7 +44,7 @@ -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -230,8 +230,8 @@ inline bool is_simple(Geometry const& g) -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_MYSQL_ALGORITHMS_IS_SIMPLE_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_IS_SIMPLE_HPP diff --git a/include/boost/geometry/algorithms/ogc/is_valid.hpp b/include/boost/geometry/algorithms/is_valid.hpp similarity index 82% rename from include/boost/geometry/algorithms/ogc/is_valid.hpp rename to include/boost/geometry/algorithms/is_valid.hpp index c8159519b..f12e3351f 100644 --- a/include/boost/geometry/algorithms/ogc/is_valid.hpp +++ b/include/boost/geometry/algorithms/is_valid.hpp @@ -7,8 +7,8 @@ // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html -#ifndef BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP -#define BOOST_GEOMETRY_ALGORITHMS_OGC_IS_VALID_HPP +#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP +#define BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP #include @@ -23,17 +23,17 @@ #include #include -#include +#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -namespace boost { namespace geometry { namespace ogc +namespace boost { namespace geometry { @@ -163,8 +163,8 @@ inline bool is_valid(Geometry const& g) -}}} // namespace boost::geometry::ogc +}} // namespace boost::geometry -#endif // BOOST_GEOMETRY_MYSQL_ALGORITHMS_IS_VALID_HPP +#endif // BOOST_GEOMETRY_ALGORITHMS_IS_VALID_HPP diff --git a/test/algorithms/ogc/is_simple.cpp b/test/algorithms/is_simple.cpp similarity index 98% rename from test/algorithms/ogc/is_simple.cpp rename to test/algorithms/is_simple.cpp index 92859b912..aa946d42e 100644 --- a/test/algorithms/ogc/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -29,8 +29,8 @@ #include #include -#include -#include +#include +#include namespace bg = ::boost::geometry; @@ -72,13 +72,13 @@ void test_simple(Geometry const& g, bool simple_geometry) std::cout << "=======" << std::endl; #endif - bool simple = bg::ogc::is_simple(g); + bool simple = bg::is_simple(g); BOOST_CHECK(simple == simple_geometry); #ifdef GEOMETRY_TEST_DEBUG std::cout << "Geometry: " << bg::wkt(g) << std::endl; std::cout << std::boolalpha; - std::cout << "is valid : " << bg::ogc::is_valid(g) << std::endl; + std::cout << "is valid : " << bg::is_valid(g) << std::endl; std::cout << "is simple: " << simple << std::endl; std::cout << "expected result: " << simple_geometry << std::endl; std::cout << "=======" << std::endl; diff --git a/test/algorithms/ogc/is_valid.cpp b/test/algorithms/is_valid.cpp similarity index 99% rename from test/algorithms/ogc/is_valid.cpp rename to test/algorithms/is_valid.cpp index 9be62cc4a..6328ebb45 100644 --- a/test/algorithms/ogc/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include namespace bg = ::boost::geometry; @@ -81,7 +81,7 @@ void test_valid(Geometry const& g, bool expected_result) std::cout << "=======" << std::endl; #endif - bool valid = bg::ogc::is_valid(g); + bool valid = bg::is_valid(g); BOOST_CHECK( valid == expected_result ); #ifdef GEOMETRY_TEST_DEBUG From 178696d511d5db7110f8fcd8e8817e3b82495d77 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 22:22:01 +0300 Subject: [PATCH 14/17] [is_valid] rename {not_}equal_point to {not_}equal_to and use point as the outer template parameter object instead of iterator --- .../algorithms/detail/is_valid/has_spikes.hpp | 68 +++++++++---------- .../algorithms/detail/is_valid/linestring.hpp | 9 +-- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp index 6e5667e8d..57cfe666e 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -31,35 +32,35 @@ namespace boost { namespace geometry namespace detail { namespace is_valid { -template -struct equal_point +template +struct equal_to { - Iterator m_it; + Point const& m_point; - equal_point(Iterator it) - : m_it(it) + equal_to(Point const& point) + : m_point(point) {} - template - inline bool operator()(Point const& p) const + template + inline bool operator()(OtherPoint const& other) const { - return geometry::equals(p, *m_it); + return geometry::equals(m_point, other); } }; -template -struct not_equal_point +template +struct not_equal_to { - Iterator m_it; + Point const& m_point; - not_equal_point(Iterator it) - : m_it(it) + not_equal_to(Point const& point) + : m_point(point) {} - template - inline bool operator()(Point const& p) const + template + inline bool operator()(OtherPoint const& other) const { - return !geometry::equals(p, *m_it); + return !geometry::equals(other, m_point); } }; @@ -70,22 +71,19 @@ struct has_spikes { static inline bool apply(Range const& range) { + typedef typename point_type::type point; typedef typename boost::range_iterator::type iterator; - typedef typename boost::range_reverse_iterator - < - Range const - >::type reverse_iterator; - typedef not_equal_point not_equal; + typedef not_equal_to not_equal; BOOST_ASSERT( boost::size(range) > 2 ); iterator prev = boost::begin(range); - iterator cur = std::find_if(prev, boost::end(range), not_equal(prev)); + iterator cur = std::find_if(prev, boost::end(range), not_equal(*prev)); BOOST_ASSERT( cur != boost::end(range) ); - iterator next = std::find_if(cur, boost::end(range), not_equal(cur)); + iterator next = std::find_if(cur, boost::end(range), not_equal(*cur)); BOOST_ASSERT( next != boost::end(range) ); while ( next != boost::end(range) ) @@ -98,21 +96,19 @@ struct has_spikes } prev = cur; cur = next; - next = std::find_if(cur, boost::end(range), not_equal(cur)); + next = std::find_if(cur, boost::end(range), not_equal(*cur)); } if ( geometry::equals(*boost::begin(range), *boost::rbegin(range)) ) { iterator cur = boost::begin(range); - reverse_iterator prev = - std::find_if(boost::rbegin(range), - boost::rend(range), - not_equal_point - < - reverse_iterator - >(boost::rbegin(range)) - ); - iterator next = std::find_if(cur, boost::end(range), not_equal(cur)); + typename boost::range_reverse_iterator + < + Range const + >::type prev = std::find_if(boost::rbegin(range), + boost::rend(range), + not_equal(*boost::rbegin(range))); + iterator next = std::find_if(cur, boost::end(range), not_equal(*cur)); return detail::point_is_spike_or_equal(*prev, *next, *cur); } @@ -126,10 +122,10 @@ struct has_spikes { static inline bool apply(Range const& range) { - typedef typename closeable_view::type ClosedRange; + typedef typename closeable_view::type closed_view_type; - ClosedRange crange(const_cast(range)); - return has_spikes::apply(crange); + closed_view_type closed_range(const_cast(range)); + return has_spikes::apply(closed_range); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp b/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp index e8410ca43..e458aefb2 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/linestring.hpp @@ -38,13 +38,13 @@ struct is_single_point { static inline bool apply(Range const& range) { - typedef typename boost::range_iterator::type iterator; + typedef typename point_type::type point; BOOST_ASSERT( boost::size(range) > 1 ); return std::find_if(++boost::begin(range), boost::end(range), - not_equal_point(boost::begin(range)) + not_equal_to(*boost::begin(range)) ) == boost::end(range); } @@ -55,6 +55,7 @@ struct has_three_distinct_points { static inline bool apply(Range const& range) { + typedef typename point_type::type point; typedef typename boost::range_iterator::type iterator; BOOST_ASSERT( boost::size(range) > 1 ); @@ -62,14 +63,14 @@ struct has_three_distinct_points iterator it1 = std::find_if(boost::begin(range), boost::end(range), - not_equal_point(boost::begin(range))); + not_equal_to(*boost::begin(range))); BOOST_ASSERT( it1 != boost::end(range) ); iterator it2 = std::find_if(it1, boost::end(range), - not_equal_point(it1)); + not_equal_to(*it1)); return it2 != boost::end(range) && !geometry::equals(*boost::begin(range), *it2); From a61be76a19ee647c98e44ca117384a8e7ec0a718 Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 22:25:10 +0300 Subject: [PATCH 15/17] [is_valid] file for polygon is_valid implementation (no code yet) --- .../algorithms/detail/is_valid/polygon.hpp | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/boost/geometry/algorithms/detail/is_valid/polygon.hpp diff --git a/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp new file mode 100644 index 000000000..6037d1609 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/is_valid/polygon.hpp @@ -0,0 +1,36 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + +}} // namespace dispatch +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_POLYGON_HPP From 6e384c3c5ed9a565d648077586e479b0e1576ccd Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 22:25:32 +0300 Subject: [PATCH 16/17] [is_valid] file for is_valid ring implementation (on-going) --- .../algorithms/detail/is_valid/ring.hpp | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 include/boost/geometry/algorithms/detail/is_valid/ring.hpp diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp new file mode 100644 index 000000000..fe69afb48 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -0,0 +1,172 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP + +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +// struct to check whether a ring is topologically closed +template +struct is_topologically_closed +{}; + +template +struct is_topologically_closed +{ + static inline bool apply(Ring const&) + { + return true; + } +}; + +template +struct is_topologically_closed +{ + static inline bool apply(Ring const& ring) + { + return geometry::equals(*boost::begin(ring), *boost::rbegin(ring)); + } +}; + + +// struct to check if the size is above the minimal one +// (3 for open, 4 for closed) +template +struct is_below_minimal_size +{}; + +template +struct is_below_minimal_size +{ + static inline bool apply(Ring const& ring) + { + return boost::size(ring) < 4; + } +}; + +template +struct is_below_minimal_size +{ + static inline bool apply(Ring const& ring) + { + return boost::size(ring) < 3; + } +}; + + + + + + +template +< + typename Ring, + order_selector PointOrder, + closure_selector Closure +> +struct is_valid_ring + : not_implemented +{}; + + +template +struct is_valid_ring +{ + static inline bool apply(Ring const& ring) + { + typedef typename reversible_view + < + Ring, iterate_reverse + >::type reversible_view_type; + + reversible_view_type reversed_ring(const_cast(ring)); + return is_valid_ring::apply(reversed_ring); + } +}; + +template +struct is_valid_ring +{ + static inline bool apply(Ring const& ring) + { + // return invalid if any of the following condition holds: + // (a) the ring's size is below the minimal one + // (b) the ring has less than three distinct points + // (c) the ring is not topologically closed + // (d) the ring has spikes + // + // Note: no need to check if the area is zero. If this is the + // case, then the ring must have at least two spikes, which is + // checked by condition (d). + if ( is_below_minimal_size::apply(ring) + || !has_three_distinct_points::apply(ring) + || !is_topologically_closed::apply(ring) + || has_spikes::apply(ring) ) + { + return false; + } + + // now call self turns to compute self intersections, if any, + // and analyze them + } +}; + + +}} // namespace dispatch +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A Ring is a Polygon. +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) +template +struct is_valid + : detail::is_valid::is_valid_ring + < + Ring, + point_order::value, + closure::value + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP From 7d2d0d916931cba993e5f6eb2e2f6d70f0591f1a Mon Sep 17 00:00:00 2001 From: Menelaos Karavelas Date: Wed, 30 Apr 2014 22:26:44 +0300 Subject: [PATCH 17/17] [is_valid] remove code for rings (moved to detail/is_valid/ring.hpp --- .../boost/geometry/algorithms/is_valid.hpp | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/include/boost/geometry/algorithms/is_valid.hpp b/include/boost/geometry/algorithms/is_valid.hpp index f12e3351f..3f0c457ec 100644 --- a/include/boost/geometry/algorithms/is_valid.hpp +++ b/include/boost/geometry/algorithms/is_valid.hpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace boost { namespace geometry @@ -105,30 +106,6 @@ namespace dispatch { -// A Ring is a Polygon. -// A Polygon is always a simple geometric object provided that it is valid. -// -// Reference (for polygon validity): OGC 06-103r4 (§6.1.11.1) -template -struct is_valid -{ - static inline bool apply(Ring const& ring) - { - if ( boost::size(ring) < 3 ) - { - return false; - } - - if ( detail::is_valid::has_spikes::value>(ring) ) - { - return false; - } - - return !geometry::intersects(ring); - } -}; - - // A Polygon is always a simple geometric object provided that it is valid. // // Reference (for validity of Polygons): OGC 06-103r4 (§6.1.11.1)