1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- #ifndef BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
- #define BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
- #include <cstddef>
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- #include <iostream>
- #endif
- #include <set>
- #include <vector>
- #include <boost/core/addressof.hpp>
- #include <boost/range/begin.hpp>
- #include <boost/range/end.hpp>
- #include <boost/range/size.hpp>
- #include <boost/range/value_type.hpp>
- #include <boost/geometry/algorithms/area.hpp>
- #include <boost/geometry/algorithms/clear.hpp>
- #include <boost/geometry/algorithms/convert.hpp>
- #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
- #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
- #include <boost/geometry/algorithms/detail/visit.hpp>
- #include <boost/geometry/algorithms/not_implemented.hpp>
- #include <boost/geometry/algorithms/is_empty.hpp>
- #include <boost/geometry/algorithms/perimeter.hpp>
- #include <boost/geometry/core/cs.hpp>
- #include <boost/geometry/core/closure.hpp>
- #include <boost/geometry/core/exterior_ring.hpp>
- #include <boost/geometry/core/interior_rings.hpp>
- #include <boost/geometry/core/mutable_range.hpp>
- #include <boost/geometry/core/tags.hpp>
- #include <boost/geometry/core/visit.hpp>
- #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
- #include <boost/geometry/geometries/concepts/check.hpp>
- #include <boost/geometry/strategies/default_strategy.hpp>
- #include <boost/geometry/strategies/detail.hpp>
- #include <boost/geometry/strategies/distance/comparable.hpp>
- #include <boost/geometry/strategies/simplify/cartesian.hpp>
- #include <boost/geometry/strategies/simplify/geographic.hpp>
- #include <boost/geometry/strategies/simplify/spherical.hpp>
- #include <boost/geometry/util/type_traits_std.hpp>
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- #include <boost/geometry/io/dsv/write.hpp>
- #endif
- namespace boost { namespace geometry
- {
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail { namespace simplify
- {
- template <typename Point>
- struct douglas_peucker_point
- {
- typedef Point point_type;
- Point const* p;
- bool included;
- inline douglas_peucker_point(Point const& ap)
- : p(boost::addressof(ap))
- , included(false)
- {}
- };
- class douglas_peucker
- {
- template <typename Iterator, typename Distance, typename PSDistanceStrategy>
- static inline void consider(Iterator begin,
- Iterator end,
- Distance const& max_dist,
- int& n,
- PSDistanceStrategy const& ps_distance_strategy)
- {
- typedef typename std::iterator_traits<Iterator>::value_type::point_type point_type;
- typedef decltype(ps_distance_strategy.apply(std::declval<point_type>(),
- std::declval<point_type>(), std::declval<point_type>())) distance_type;
- std::size_t size = end - begin;
-
-
- if (size <= 2)
- {
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- if (begin != end)
- {
- std::cout << "ignore between " << dsv(*(begin->p))
- << " and " << dsv(*((end - 1)->p))
- << " size=" << size << std::endl;
- }
- std::cout << "return because size=" << size << std::endl;
- #endif
- return;
- }
- Iterator last = end - 1;
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- std::cout << "find between " << dsv(*(begin->p))
- << " and " << dsv(*(last->p))
- << " size=" << size << std::endl;
- #endif
-
-
- distance_type md(-1.0);
- Iterator candidate = end;
- for (Iterator it = begin + 1; it != last; ++it)
- {
- distance_type dist = ps_distance_strategy.apply(*(it->p), *(begin->p), *(last->p));
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- std::cout << "consider " << dsv(*(it->p))
- << " at " << double(dist)
- << ((dist > max_dist) ? " maybe" : " no")
- << std::endl;
- #endif
- if (md < dist)
- {
- md = dist;
- candidate = it;
- }
- }
-
-
- if (max_dist < md && candidate != end)
- {
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- std::cout << "use " << dsv(candidate->p) << std::endl;
- #endif
- candidate->included = true;
- n++;
- consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
- consider(candidate, end, max_dist, n, ps_distance_strategy);
- }
- }
- template
- <
- typename Range, typename OutputIterator, typename Distance,
- typename PSDistanceStrategy
- >
- static inline OutputIterator apply_(Range const& range,
- OutputIterator out,
- Distance const& max_distance,
- PSDistanceStrategy const& ps_distance_strategy)
- {
- #ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
- std::cout << "max distance: " << max_distance
- << std::endl << std::endl;
- #endif
- typedef typename boost::range_value<Range>::type point_type;
- typedef douglas_peucker_point<point_type> dp_point_type;
-
- std::vector<dp_point_type> ref_candidates(boost::begin(range),
- boost::end(range));
-
-
- int n = 2;
- ref_candidates.front().included = true;
- ref_candidates.back().included = true;
-
-
- consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n,
- ps_distance_strategy);
-
- for (auto it = boost::begin(ref_candidates); it != boost::end(ref_candidates); ++it)
- {
- if (it->included)
- {
-
-
-
- *out = *(it->p);
- ++out;
- }
- }
- return out;
- }
- public:
- template <typename Range, typename OutputIterator, typename Distance, typename Strategies>
- static inline OutputIterator apply(Range const& range,
- OutputIterator out,
- Distance const& max_distance,
- Strategies const& strategies)
- {
- typedef typename boost::range_value<Range>::type point_type;
- typedef decltype(strategies.distance(detail::dummy_point(), detail::dummy_segment())) distance_strategy_type;
- typedef typename strategy::distance::services::comparable_type
- <
- distance_strategy_type
- >::type comparable_distance_strategy_type;
- comparable_distance_strategy_type cstrategy = strategy::distance::services::get_comparable
- <
- distance_strategy_type
- >::apply(strategies.distance(detail::dummy_point(), detail::dummy_segment()));
- return apply_(range, out,
- strategy::distance::services::result_from_distance
- <
- comparable_distance_strategy_type, point_type, point_type
- >::apply(cstrategy, max_distance),
- cstrategy);
- }
- };
- template <typename Range, typename Strategies>
- inline bool is_degenerate(Range const& range, Strategies const& strategies)
- {
- return boost::size(range) == 2
- && detail::equals::equals_point_point(geometry::range::front(range),
- geometry::range::back(range),
- strategies);
- }
- struct simplify_range_insert
- {
- template
- <
- typename Range, typename OutputIterator, typename Distance,
- typename Impl, typename Strategies
- >
- static inline void apply(Range const& range, OutputIterator out,
- Distance const& max_distance,
- Impl const& impl,
- Strategies const& strategies)
- {
- if (is_degenerate(range, strategies))
- {
- std::copy(boost::begin(range), boost::begin(range) + 1, out);
- }
- else if (boost::size(range) <= 2 || max_distance < 0)
- {
- std::copy(boost::begin(range), boost::end(range), out);
- }
- else
- {
- impl.apply(range, out, max_distance, strategies);
- }
- }
- };
- struct simplify_copy_assign
- {
- template
- <
- typename In, typename Out, typename Distance,
- typename Impl, typename Strategies
- >
- static inline void apply(In const& in, Out& out,
- Distance const& ,
- Impl const& ,
- Strategies const& )
- {
- out = in;
- }
- };
- struct simplify_copy
- {
- template
- <
- typename RangeIn, typename RangeOut, typename Distance,
- typename Impl, typename Strategies
- >
- static inline void apply(RangeIn const& range, RangeOut& out,
- Distance const& ,
- Impl const& ,
- Strategies const& )
- {
- std::copy(boost::begin(range), boost::end(range),
- geometry::range::back_inserter(out));
- }
- };
- template <std::size_t MinimumToUseStrategy>
- struct simplify_range
- {
- template
- <
- typename RangeIn, typename RangeOut, typename Distance,
- typename Impl, typename Strategies
- >
- static inline void apply(RangeIn const& range, RangeOut& out,
- Distance const& max_distance,
- Impl const& impl,
- Strategies const& strategies)
- {
-
-
-
-
- if (boost::size(range) <= MinimumToUseStrategy || max_distance < 0)
- {
- simplify_copy::apply(range, out, max_distance, impl, strategies);
- }
- else
- {
- simplify_range_insert::apply(range, geometry::range::back_inserter(out),
- max_distance, impl, strategies);
- }
-
-
- if (is_degenerate(out, strategies))
- {
- range::resize(out, 1);
- }
- }
- };
- struct simplify_ring
- {
- private :
- template <typename Area>
- static inline int area_sign(Area const& area)
- {
- return area > 0 ? 1 : area < 0 ? -1 : 0;
- }
- template <typename Ring, typename Strategies>
- static std::size_t get_opposite(std::size_t index, Ring const& ring,
- Strategies const& strategies)
- {
-
- auto const cdistance_strategy = strategies::distance::detail::make_comparable(strategies)
- .distance(detail::dummy_point(), detail::dummy_point());
- using point_type = typename geometry::point_type<Ring>::type;
- using cdistance_type = decltype(cdistance_strategy.apply(
- std::declval<point_type>(), std::declval<point_type>()));
-
-
- cdistance_type max_cdistance(-1);
- point_type const& point = range::at(ring, index);
- std::size_t i = 0;
- for (auto it = boost::begin(ring); it != boost::end(ring); ++it, ++i)
- {
- cdistance_type const cdistance = cdistance_strategy.apply(*it, point);
- if (cdistance > max_cdistance)
- {
- max_cdistance = cdistance;
- index = i;
- }
- }
- return index;
- }
- public :
- template
- <
- typename RingIn, typename RingOut,
- typename Distance, typename Impl, typename Strategies
- >
- static inline void apply(RingIn const& ring, RingOut& out, Distance const& max_distance,
- Impl const& impl, Strategies const& strategies)
- {
- std::size_t const size = boost::size(ring);
- if (size == 0)
- {
- return;
- }
- bool const is_closed_in = geometry::closure<RingIn>::value == closed;
- bool const is_closed_out = geometry::closure<RingOut>::value == closed;
- bool const is_clockwise_in = geometry::point_order<RingIn>::value == clockwise;
- bool const is_clockwise_out = geometry::point_order<RingOut>::value == clockwise;
-
- int const input_sign = area_sign(geometry::area(ring, strategies));
- std::set<std::size_t> visited_indexes;
-
-
-
- typedef typename geometry::point_type<RingIn>::type point_type;
- std::vector<point_type> rotated;
- rotated.reserve(size + 1);
-
- std::size_t index = 0;
-
- for (std::size_t iteration = 0; iteration < 4u; iteration++)
- {
-
-
-
-
-
-
-
-
-
-
-
- switch (iteration)
- {
- case 1 : index = (index + size / 4) % size; break;
- case 2 : index = (index + size / 8) % size; break;
- case 3 : index = (index + size / 4) % size; break;
- }
- index = get_opposite(index, ring, strategies);
- if (visited_indexes.count(index) > 0)
- {
-
- continue;
- }
-
- auto rot_end = boost::end(ring);
- std::size_t rot_index = index;
- if (BOOST_GEOMETRY_CONDITION(is_closed_in) && size > 1)
- {
- --rot_end;
- if (rot_index == size - 1) { rot_index = 0; }
- }
- std::rotate_copy(boost::begin(ring), range::pos(ring, rot_index),
- rot_end, std::back_inserter(rotated));
-
- rotated.push_back(range::at(ring, rot_index));
- simplify_range<0>::apply(rotated, out, max_distance, impl, strategies);
-
- if (BOOST_GEOMETRY_CONDITION(! is_closed_out) && boost::size(out) > 1)
- {
- range::pop_back(out);
- }
-
-
-
- int const output_sign = area_sign(geometry::area(out, strategies));
- if (output_sign == input_sign)
- {
-
-
-
- return;
- }
-
-
- geometry::clear(out);
- if (iteration == 0
- && geometry::perimeter(ring, strategies) < 3 * max_distance)
- {
-
-
- return;
- }
-
- visited_indexes.insert(index);
- rotated.clear();
- }
- if (BOOST_GEOMETRY_CONDITION(is_clockwise_in != is_clockwise_out))
- {
- std::reverse(boost::begin(out), boost::end(out));
- }
- }
- };
- struct simplify_polygon
- {
- private:
- template
- <
- typename IteratorIn,
- typename InteriorRingsOut,
- typename Distance,
- typename Impl,
- typename Strategies
- >
- static inline void iterate(IteratorIn begin, IteratorIn end,
- InteriorRingsOut& interior_rings_out,
- Distance const& max_distance,
- Impl const& impl, Strategies const& strategies)
- {
- typedef typename boost::range_value<InteriorRingsOut>::type single_type;
- for (IteratorIn it = begin; it != end; ++it)
- {
- single_type out;
- simplify_ring::apply(*it, out, max_distance, impl, strategies);
- if (! geometry::is_empty(out))
- {
- range::push_back(interior_rings_out, std::move(out));
- }
- }
- }
- template
- <
- typename InteriorRingsIn,
- typename InteriorRingsOut,
- typename Distance,
- typename Impl,
- typename Strategies
- >
- static inline void apply_interior_rings(InteriorRingsIn const& interior_rings_in,
- InteriorRingsOut& interior_rings_out,
- Distance const& max_distance,
- Impl const& impl, Strategies const& strategies)
- {
- range::clear(interior_rings_out);
- iterate(boost::begin(interior_rings_in), boost::end(interior_rings_in),
- interior_rings_out,
- max_distance,
- impl, strategies);
- }
- public:
- template
- <
- typename PolygonIn, typename PolygonOut,
- typename Distance, typename Impl, typename Strategies
- >
- static inline void apply(PolygonIn const& poly_in, PolygonOut& poly_out,
- Distance const& max_distance,
- Impl const& impl, Strategies const& strategies)
- {
-
-
-
- simplify_ring::apply(exterior_ring(poly_in), exterior_ring(poly_out),
- max_distance, impl, strategies);
- apply_interior_rings(interior_rings(poly_in), interior_rings(poly_out),
- max_distance, impl, strategies);
- }
- };
- template<typename Policy>
- struct simplify_multi
- {
- template
- <
- typename MultiGeometryIn, typename MultiGeometryOut,
- typename Distance, typename Impl, typename Strategies
- >
- static inline void apply(MultiGeometryIn const& multi, MultiGeometryOut& out,
- Distance const& max_distance,
- Impl const& impl, Strategies const& strategies)
- {
- range::clear(out);
- using single_type = typename boost::range_value<MultiGeometryOut>::type;
- for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
- {
- single_type single_out;
- Policy::apply(*it, single_out, max_distance, impl, strategies);
- if (! geometry::is_empty(single_out))
- {
- range::push_back(out, std::move(single_out));
- }
- }
- }
- };
- template <typename Geometry>
- struct has_same_tag_as
- {
- template <typename OtherGeometry>
- struct pred
- : std::is_same
- <
- typename geometry::tag<Geometry>::type,
- typename geometry::tag<OtherGeometry>::type
- >
- {};
- };
- template <typename StaticGeometryIn, typename DynamicGeometryOut>
- struct static_geometry_type
- {
- using type = typename util::sequence_find_if
- <
- typename traits::geometry_types<DynamicGeometryOut>::type,
- detail::simplify::has_same_tag_as<StaticGeometryIn>::template pred
- >::type;
- BOOST_GEOMETRY_STATIC_ASSERT(
- (! std::is_void<type>::value),
- "Unable to find corresponding geometry in GeometryOut",
- StaticGeometryIn, DynamicGeometryOut);
- };
- }}
- #endif
- #ifndef DOXYGEN_NO_DISPATCH
- namespace dispatch
- {
- template
- <
- typename GeometryIn,
- typename GeometryOut,
- typename TagIn = typename tag<GeometryIn>::type,
- typename TagOut = typename tag<GeometryOut>::type
- >
- struct simplify: not_implemented<TagIn, TagOut>
- {};
- template <typename PointIn, typename PointOut>
- struct simplify<PointIn, PointOut, point_tag, point_tag>
- {
- template <typename Distance, typename Impl, typename Strategy>
- static inline void apply(PointIn const& point, PointOut& out, Distance const& ,
- Impl const& , Strategy const& )
- {
- geometry::convert(point, out);
- }
- };
- template <typename SegmentIn, typename SegmentOut>
- struct simplify<SegmentIn, SegmentOut, segment_tag, segment_tag>
- : detail::simplify::simplify_copy_assign
- {};
- template <typename BoxIn, typename BoxOut>
- struct simplify<BoxIn, BoxOut, box_tag, box_tag>
- : detail::simplify::simplify_copy_assign
- {};
- template <typename LinestringIn, typename LinestringOut>
- struct simplify<LinestringIn, LinestringOut, linestring_tag, linestring_tag>
- : detail::simplify::simplify_range<2>
- {};
- template <typename RingIn, typename RingOut>
- struct simplify<RingIn, RingOut, ring_tag, ring_tag>
- : detail::simplify::simplify_ring
- {};
- template <typename PolygonIn, typename PolygonOut>
- struct simplify<PolygonIn, PolygonOut, polygon_tag, polygon_tag>
- : detail::simplify::simplify_polygon
- {};
- template <typename MultiPointIn, typename MultiPointOut>
- struct simplify<MultiPointIn, MultiPointOut, multi_point_tag, multi_point_tag>
- : detail::simplify::simplify_copy
- {};
- template <typename MultiLinestringIn, typename MultiLinestringOut>
- struct simplify<MultiLinestringIn, MultiLinestringOut, multi_linestring_tag, multi_linestring_tag>
- : detail::simplify::simplify_multi<detail::simplify::simplify_range<2> >
- {};
- template <typename MultiPolygonIn, typename MultiPolygonOut>
- struct simplify<MultiPolygonIn, MultiPolygonOut, multi_polygon_tag, multi_polygon_tag>
- : detail::simplify::simplify_multi<detail::simplify::simplify_polygon>
- {};
- template
- <
- typename Geometry,
- typename Tag = typename tag<Geometry>::type
- >
- struct simplify_insert: not_implemented<Tag>
- {};
- template <typename Linestring>
- struct simplify_insert<Linestring, linestring_tag>
- : detail::simplify::simplify_range_insert
- {};
- template <typename Ring>
- struct simplify_insert<Ring, ring_tag>
- : detail::simplify::simplify_range_insert
- {};
- }
- #endif
- namespace resolve_strategy
- {
- template
- <
- typename Strategies,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
- >
- struct simplify
- {
- template <typename GeometryIn, typename GeometryOut, typename Distance>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- Strategies const& strategies)
- {
- dispatch::simplify
- <
- GeometryIn, GeometryOut
- >::apply(geometry, out, max_distance,
- detail::simplify::douglas_peucker(),
- strategies);
- }
- };
- template <typename Strategy>
- struct simplify<Strategy, false>
- {
- template <typename GeometryIn, typename GeometryOut, typename Distance>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- Strategy const& strategy)
- {
- using strategies::simplify::services::strategy_converter;
- simplify
- <
- decltype(strategy_converter<Strategy>::get(strategy))
- >::apply(geometry, out, max_distance,
- strategy_converter<Strategy>::get(strategy));
- }
- };
- template <>
- struct simplify<default_strategy, false>
- {
- template <typename GeometryIn, typename GeometryOut, typename Distance>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- default_strategy)
- {
-
- using cs_tag1_t = typename geometry::cs_tag<GeometryIn>::type;
- using cs_tag2_t = typename geometry::cs_tag<GeometryOut>::type;
- BOOST_GEOMETRY_STATIC_ASSERT(
- (std::is_same<cs_tag1_t, cs_tag2_t>::value),
- "Incompatible coordinate systems",
- cs_tag1_t, cs_tag2_t);
- typedef typename strategies::simplify::services::default_strategy
- <
- GeometryIn
- >::type strategy_type;
- simplify
- <
- strategy_type
- >::apply(geometry, out, max_distance, strategy_type());
- }
- };
- template
- <
- typename Strategies,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
- >
- struct simplify_insert
- {
- template<typename Geometry, typename OutputIterator, typename Distance>
- static inline void apply(Geometry const& geometry,
- OutputIterator& out,
- Distance const& max_distance,
- Strategies const& strategies)
- {
- dispatch::simplify_insert
- <
- Geometry
- >::apply(geometry, out, max_distance,
- detail::simplify::douglas_peucker(),
- strategies);
- }
- };
- template <typename Strategy>
- struct simplify_insert<Strategy, false>
- {
- template<typename Geometry, typename OutputIterator, typename Distance>
- static inline void apply(Geometry const& geometry,
- OutputIterator& out,
- Distance const& max_distance,
- Strategy const& strategy)
- {
- using strategies::simplify::services::strategy_converter;
- simplify_insert
- <
- decltype(strategy_converter<Strategy>::get(strategy))
- >::apply(geometry, out, max_distance,
- strategy_converter<Strategy>::get(strategy));
- }
- };
- template <>
- struct simplify_insert<default_strategy, false>
- {
- template <typename Geometry, typename OutputIterator, typename Distance>
- static inline void apply(Geometry const& geometry,
- OutputIterator& out,
- Distance const& max_distance,
- default_strategy)
- {
- typedef typename strategies::simplify::services::default_strategy
- <
- Geometry
- >::type strategy_type;
- simplify_insert
- <
- strategy_type
- >::apply(geometry, out, max_distance, strategy_type());
- }
- };
- }
- namespace resolve_dynamic {
- template
- <
- typename GeometryIn, typename GeometryOut,
- typename TagIn = typename tag<GeometryIn>::type,
- typename TagOut = typename tag<GeometryOut>::type
- >
- struct simplify
- {
- template <typename Distance, typename Strategy>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- Strategy const& strategy)
- {
- resolve_strategy::simplify<Strategy>::apply(geometry, out, max_distance, strategy);
- }
- };
- template <typename GeometryIn, typename GeometryOut>
- struct simplify<GeometryIn, GeometryOut, dynamic_geometry_tag, dynamic_geometry_tag>
- {
- template <typename Distance, typename Strategy>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- Strategy const& strategy)
- {
- traits::visit<GeometryIn>::apply([&](auto const& g)
- {
- using geom_t = util::remove_cref_t<decltype(g)>;
- using detail::simplify::static_geometry_type;
- using geom_out_t = typename static_geometry_type<geom_t, GeometryOut>::type;
- geom_out_t o;
- simplify<geom_t, geom_out_t>::apply(g, o, max_distance, strategy);
- out = std::move(o);
- }, geometry);
- }
- };
- template <typename GeometryIn, typename GeometryOut>
- struct simplify<GeometryIn, GeometryOut, geometry_collection_tag, geometry_collection_tag>
- {
- template <typename Distance, typename Strategy>
- static inline void apply(GeometryIn const& geometry,
- GeometryOut& out,
- Distance const& max_distance,
- Strategy const& strategy)
- {
- detail::visit_breadth_first([&](auto const& g)
- {
- using geom_t = util::remove_cref_t<decltype(g)>;
- using detail::simplify::static_geometry_type;
- using geom_out_t = typename static_geometry_type<geom_t, GeometryOut>::type;
- geom_out_t o;
- simplify<geom_t, geom_out_t>::apply(g, o, max_distance, strategy);
- traits::emplace_back<GeometryOut>::apply(out, std::move(o));
- return true;
- }, geometry);
- }
- };
- }
- template<typename Geometry, typename GeometryOut, typename Distance, typename Strategy>
- inline void simplify(Geometry const& geometry, GeometryOut& out,
- Distance const& max_distance, Strategy const& strategy)
- {
- concepts::check<Geometry const>();
- concepts::check<GeometryOut>();
- geometry::clear(out);
- resolve_dynamic::simplify<Geometry, GeometryOut>::apply(geometry, out, max_distance, strategy);
- }
- template<typename Geometry, typename GeometryOut, typename Distance>
- inline void simplify(Geometry const& geometry, GeometryOut& out,
- Distance const& max_distance)
- {
- concepts::check<Geometry const>();
- concepts::check<GeometryOut>();
- geometry::simplify(geometry, out, max_distance, default_strategy());
- }
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail { namespace simplify
- {
- template<typename Geometry, typename OutputIterator, typename Distance, typename Strategy>
- inline void simplify_insert(Geometry const& geometry, OutputIterator out,
- Distance const& max_distance, Strategy const& strategy)
- {
- concepts::check<Geometry const>();
- resolve_strategy::simplify_insert<Strategy>::apply(geometry, out, max_distance, strategy);
- }
- template<typename Geometry, typename OutputIterator, typename Distance>
- inline void simplify_insert(Geometry const& geometry, OutputIterator out,
- Distance const& max_distance)
- {
-
- concepts::check<Geometry const>();
- concepts::check<typename point_type<Geometry>::type>();
- simplify_insert(geometry, out, max_distance, default_strategy());
- }
- }}
- #endif
- }}
- #endif
|