diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index 2bd097f13..1de639784 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -30,12 +30,17 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include + namespace boost { namespace geometry { @@ -229,6 +234,146 @@ struct simplify_insert #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy +{ + +struct simplify +{ + template + static inline void apply(Geometry const& geometry, + Geometry& out, + Distance const& max_distance, + Strategy const& strategy) + { + dispatch::simplify::apply(geometry, out, max_distance, strategy); + } + + template + static inline void apply(Geometry const& geometry, + Geometry& out, + Distance const& max_distance, + default_strategy) + { + typedef typename point_type::type point_type; + + typedef typename strategy::distance::services::default_strategy + < + segment_tag, point_type + >::type ds_strategy_type; + + typedef strategy::simplify::douglas_peucker + < + point_type, ds_strategy_type + > strategy_type; + + BOOST_CONCEPT_ASSERT( + (concept::SimplifyStrategy) + ); + + apply(geometry, out, max_distance, strategy_type()); + } +}; + +struct simplify_insert +{ + template + < + typename Geometry, + typename OutputIterator, + typename Distance, + typename Strategy + > + static inline void apply(Geometry const& geometry, + OutputIterator& out, + Distance const& max_distance, + Strategy const& strategy) + { + dispatch::simplify_insert::apply(geometry, out, max_distance, strategy); + } + + template + static inline void apply(Geometry const& geometry, + OutputIterator& out, + Distance const& max_distance, + default_strategy) + { + typedef typename point_type::type point_type; + + typedef typename strategy::distance::services::default_strategy + < + segment_tag, point_type + >::type ds_strategy_type; + + typedef strategy::simplify::douglas_peucker + < + point_type, ds_strategy_type + > strategy_type; + + BOOST_CONCEPT_ASSERT( + (concept::SimplifyStrategy) + ); + + apply(geometry, out, max_distance, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template +struct simplify +{ + template + static inline void apply(Geometry const& geometry, + Geometry& out, + Distance const& max_distance, + Strategy const& strategy) + { + resolve_strategy::simplify::apply(geometry, out, max_distance, strategy); + } +}; + +template +struct simplify > +{ + template + struct visitor: boost::static_visitor + { + Distance const& m_max_distance; + Strategy const& m_strategy; + + visitor(Distance const& max_distance, Strategy const& strategy) + : m_max_distance(max_distance) + , m_strategy(strategy) + {} + + template + void operator()(Geometry const& geometry, Geometry& out) const + { + simplify::apply(geometry, out, m_max_distance, m_strategy); + } + }; + + template + static inline void + apply(boost::variant const& geometry, + boost::variant& out, + Distance const& max_distance, + Strategy const& strategy) + { + boost::apply_visitor( + visitor(max_distance, strategy), + geometry, + out + ); + } +}; + +} // namespace resolve_variant + + /*! \brief Simplify a geometry using a specified strategy \ingroup simplify @@ -252,13 +397,9 @@ inline void simplify(Geometry const& geometry, Geometry& out, { concept::check(); - BOOST_CONCEPT_ASSERT( - (concept::SimplifyStrategy::type>) - ); - geometry::clear(out); - dispatch::simplify::apply(geometry, out, max_distance, strategy); + resolve_variant::simplify::apply(geometry, out, max_distance, strategy); } @@ -285,17 +426,8 @@ inline void simplify(Geometry const& geometry, Geometry& out, concept::check(); typedef typename point_type::type point_type; - typedef typename strategy::distance::services::default_strategy - < - segment_tag, point_type - >::type ds_strategy_type; - typedef strategy::simplify::douglas_peucker - < - point_type, ds_strategy_type - > strategy_type; - - simplify(geometry, out, max_distance, strategy_type()); + simplify(geometry, out, max_distance, default_strategy()); } @@ -321,14 +453,11 @@ namespace detail { namespace simplify */ template inline void simplify_insert(Geometry const& geometry, OutputIterator out, - Distance const& max_distance, Strategy const& strategy) + Distance const& max_distance, Strategy const& strategy) { concept::check(); - BOOST_CONCEPT_ASSERT( - (concept::SimplifyStrategy::type>) - ); - dispatch::simplify_insert::apply(geometry, out, max_distance, strategy); + resolve_strategy::simplify_insert::apply(geometry, out, max_distance, strategy); } /*! @@ -344,25 +473,13 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out, */ template inline void simplify_insert(Geometry const& geometry, OutputIterator out, - Distance const& max_distance) + Distance const& max_distance) { - typedef typename point_type::type point_type; - // Concept: output point type = point type of input geometry concept::check(); - concept::check(); + concept::check::type>(); - typedef typename strategy::distance::services::default_strategy - < - segment_tag, point_type - >::type ds_strategy_type; - - typedef strategy::simplify::douglas_peucker - < - point_type, ds_strategy_type - > strategy_type; - - dispatch::simplify_insert::apply(geometry, out, max_distance, strategy_type()); + simplify_insert(geometry, out, max_distance, default_strategy()); } }} // namespace detail::simplify diff --git a/test/algorithms/test_simplify.hpp b/test/algorithms/test_simplify.hpp index 0eda9b3b4..b3c64ba56 100644 --- a/test/algorithms/test_simplify.hpp +++ b/test/algorithms/test_simplify.hpp @@ -17,8 +17,8 @@ #include #include #include - #include +#include template struct test_inserter @@ -46,24 +46,43 @@ struct test_inserter template -void test_geometry(std::string const& wkt, std::string const& expected, double distance) +void check_geometry(Geometry const& geometry, + std::string const& expected, + double distance) { - Geometry geometry, simplified; - - // Generate polygon using only integer coordinates and obvious results - // Polygon is a hexagon, having one extra point (2,1) on a line which should be filtered out. - bg::read_wkt(wkt, geometry); + Geometry simplified; bg::simplify(geometry, simplified, distance); - { - std::ostringstream out; - out << std::setprecision(12) << bg::wkt(simplified); + std::ostringstream out; + out << std::setprecision(12) << bg::wkt(simplified); + BOOST_CHECK_EQUAL(out.str(), expected); +} - BOOST_CHECK_MESSAGE(out.str() == expected, - "simplify: " << bg::wkt(geometry) - << " expected " << expected - << " got " << out.str()); - } +template +void check_geometry(Geometry const& geometry, + std::string const& expected, + double distance, + Strategy const& strategy) +{ + Geometry simplified; + bg::simplify(geometry, simplified, distance, strategy); + + std::ostringstream out; + out << std::setprecision(12) << bg::wkt(simplified); + BOOST_CHECK_EQUAL(out.str(), expected); +} + +template +void test_geometry(std::string const& wkt, std::string const& expected, double distance) +{ + // Generate polygon using only integer coordinates and obvious results + // Polygon is a hexagon, having one extra point (2,1) on a line which should be filtered out. + Geometry geometry; + bg::read_wkt(wkt, geometry); + boost::variant v(geometry); + + check_geometry(geometry, expected, distance); + check_geometry(v, expected, distance); // Check using user-specified strategy typedef typename bg::point_type::type point_type; @@ -76,13 +95,9 @@ void test_geometry(std::string const& wkt, std::string const& expected, double d > simplify_strategy_type; BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy) ); - bg::simplify(geometry, simplified, distance, simplify_strategy_type()); - { - std::ostringstream out; - out << std::setprecision(12) << bg::wkt(simplified); - BOOST_CHECK_EQUAL(out.str(), expected); - } + check_geometry(geometry, expected, distance, simplify_strategy_type()); + check_geometry(v, expected, distance, simplify_strategy_type()); // Check inserter (if applicable) test_inserter