diff options
Diffstat (limited to 'boost/geometry/algorithms/perimeter.hpp')
-rw-r--r-- | boost/geometry/algorithms/perimeter.hpp | 192 |
1 files changed, 138 insertions, 54 deletions
diff --git a/boost/geometry/algorithms/perimeter.hpp b/boost/geometry/algorithms/perimeter.hpp index adeb0b05b0..0ec153c1f4 100644 --- a/boost/geometry/algorithms/perimeter.hpp +++ b/boost/geometry/algorithms/perimeter.hpp @@ -1,8 +1,13 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2012 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -14,16 +19,22 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP #define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP +#include <boost/range/metafunctions.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> -#include <boost/geometry/core/cs.hpp> -#include <boost/geometry/core/closure.hpp> -#include <boost/geometry/geometries/concepts/check.hpp> -#include <boost/geometry/strategies/default_length_result.hpp> #include <boost/geometry/algorithms/length.hpp> #include <boost/geometry/algorithms/detail/calculate_null.hpp> #include <boost/geometry/algorithms/detail/calculate_sum.hpp> +#include <boost/geometry/algorithms/detail/multi_sum.hpp> // #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp> - +#include <boost/geometry/core/cs.hpp> +#include <boost/geometry/core/closure.hpp> +#include <boost/geometry/core/tags.hpp> +#include <boost/geometry/geometries/concepts/check.hpp> +#include <boost/geometry/strategies/default_length_result.hpp> +#include <boost/geometry/strategies/default_strategy.hpp> namespace boost { namespace geometry { @@ -33,40 +44,59 @@ namespace dispatch { // Default perimeter is 0.0, specializations implement calculated values -template <typename Tag, typename Geometry, typename Strategy> +template <typename Geometry, typename Tag = typename tag<Geometry>::type> struct perimeter : detail::calculate_null - < - typename default_length_result<Geometry>::type, - Geometry, - Strategy - > -{}; +{ + typedef typename default_length_result<Geometry>::type return_type; + + template <typename Strategy> + static inline return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply<return_type>(geometry, strategy); + } +}; -template <typename Geometry, typename Strategy> -struct perimeter<ring_tag, Geometry, Strategy> +template <typename Geometry> +struct perimeter<Geometry, ring_tag> : detail::length::range_length < Geometry, - Strategy, closure<Geometry>::value > {}; -template <typename Polygon, typename Strategy> -struct perimeter<polygon_tag, Polygon, Strategy> - : detail::calculate_polygon_sum - < - typename default_length_result<Polygon>::type, - Polygon, - Strategy, - detail::length::range_length +template <typename Polygon> +struct perimeter<Polygon, polygon_tag> : detail::calculate_polygon_sum +{ + typedef typename default_length_result<Polygon>::type return_type; + typedef detail::length::range_length < typename ring_type<Polygon>::type, - Strategy, closure<Polygon>::value - > - > -{}; + > policy; + + template <typename Strategy> + static inline return_type apply(Polygon const& polygon, Strategy const& strategy) + { + return calculate_polygon_sum::apply<return_type, policy>(polygon, strategy); + } +}; + +template <typename MultiPolygon> +struct perimeter<MultiPolygon, multi_polygon_tag> : detail::multi_sum +{ + typedef typename default_length_result<MultiPolygon>::type return_type; + + template <typename Strategy> + static inline return_type apply(MultiPolygon const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + return_type, + perimeter<typename boost::range_value<MultiPolygon>::type> + >(multi, strategy); + } +}; // box,n-sphere: to be implemented @@ -75,6 +105,82 @@ struct perimeter<polygon_tag, Polygon, Strategy> #endif // DOXYGEN_NO_DISPATCH +namespace resolve_strategy { + +struct perimeter +{ + template <typename Geometry, typename Strategy> + static inline typename default_length_result<Geometry>::type + apply(Geometry const& geometry, Strategy const& strategy) + { + return dispatch::perimeter<Geometry>::apply(geometry, strategy); + } + + template <typename Geometry> + static inline typename default_length_result<Geometry>::type + apply(Geometry const& geometry, default_strategy) + { + typedef typename strategy::distance::services::default_strategy + < + point_tag, point_tag, typename point_type<Geometry>::type + >::type strategy_type; + + return dispatch::perimeter<Geometry>::apply(geometry, strategy_type()); + } +}; + +} // namespace resolve_strategy + + +namespace resolve_variant { + +template <typename Geometry> +struct perimeter +{ + template <typename Strategy> + static inline typename default_length_result<Geometry>::type + apply(Geometry const& geometry, Strategy const& strategy) + { + concept::check<Geometry const>(); + return resolve_strategy::perimeter::apply(geometry, strategy); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct perimeter<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + typedef typename default_length_result + < + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> + >::type result_type; + + template <typename Strategy> + struct visitor: boost::static_visitor<result_type> + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + + template <typename Geometry> + typename default_length_result<Geometry>::type + operator()(Geometry const& geometry) const + { + return perimeter<Geometry>::apply(geometry, m_strategy); + } + }; + + template <typename Strategy> + static inline result_type + apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + Strategy const& strategy) + { + return boost::apply_visitor(visitor<Strategy>(strategy), geometry); + } +}; + +} // namespace resolve_variant + + /*! \brief \brief_calc{perimeter} \ingroup perimeter @@ -90,22 +196,8 @@ template<typename Geometry> inline typename default_length_result<Geometry>::type perimeter( Geometry const& geometry) { - concept::check<Geometry const>(); - - typedef typename point_type<Geometry>::type point_type; - typedef typename strategy::distance::services::default_strategy - < - point_tag, point_type - >::type strategy_type; - // detail::throw_on_empty_input(geometry); - - return dispatch::perimeter - < - typename tag<Geometry>::type, - Geometry, - strategy_type - >::apply(geometry, strategy_type()); + return resolve_variant::perimeter<Geometry>::apply(geometry, default_strategy()); } /*! @@ -126,16 +218,8 @@ template<typename Geometry, typename Strategy> inline typename default_length_result<Geometry>::type perimeter( Geometry const& geometry, Strategy const& strategy) { - concept::check<Geometry const>(); - // detail::throw_on_empty_input(geometry); - - return dispatch::perimeter - < - typename tag<Geometry>::type, - Geometry, - Strategy - >::apply(geometry, strategy); + return resolve_variant::perimeter<Geometry>::apply(geometry, strategy); } }} // namespace boost::geometry |