diff options
Diffstat (limited to 'boost/geometry/algorithms/area.hpp')
-rw-r--r-- | boost/geometry/algorithms/area.hpp | 182 |
1 files changed, 105 insertions, 77 deletions
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp index 8193200ab9..7377798719 100644 --- a/boost/geometry/algorithms/area.hpp +++ b/boost/geometry/algorithms/area.hpp @@ -18,18 +18,24 @@ #include <boost/mpl/if.hpp> #include <boost/range/functions.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/closure.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/point_order.hpp> +#include <boost/geometry/core/point_type.hpp> #include <boost/geometry/core/ring_type.hpp> +#include <boost/geometry/core/tags.hpp> #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/algorithms/detail/calculate_null.hpp> #include <boost/geometry/algorithms/detail/calculate_sum.hpp> // #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp> +#include <boost/geometry/algorithms/detail/multi_sum.hpp> #include <boost/geometry/strategies/area.hpp> #include <boost/geometry/strategies/default_area_result.hpp> @@ -49,41 +55,33 @@ namespace boost { namespace geometry namespace detail { namespace area { -template<typename Box, typename Strategy> struct box_area { - typedef typename coordinate_type<Box>::type return_type; - - static inline return_type apply(Box const& box, Strategy const&) + template <typename Box, typename Strategy> + static inline typename coordinate_type<Box>::type + apply(Box const& box, Strategy const&) { // Currently only works for 2D Cartesian boxes assert_dimension<Box, 2>(); - return_type const dx = get<max_corner, 0>(box) - - get<min_corner, 0>(box); - return_type const dy = get<max_corner, 1>(box) - - get<min_corner, 1>(box); - - return dx * dy; + return (get<max_corner, 0>(box) - get<min_corner, 0>(box)) + * (get<max_corner, 1>(box) - get<min_corner, 1>(box)); } }; template < - typename Ring, iterate_direction Direction, - closure_selector Closure, - typename Strategy + closure_selector Closure > struct ring_area { - BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) ); - - typedef typename Strategy::return_type type; - - static inline type apply(Ring const& ring, Strategy const& strategy) + template <typename Ring, typename Strategy> + static inline typename Strategy::return_type + apply(Ring const& ring, Strategy const& strategy) { + BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) ); assert_dimension<Ring, 2>(); // Ignore warning (because using static method sometimes) on strategy @@ -92,10 +90,10 @@ struct ring_area // An open ring has at least three points, // A closed ring has at least four points, // if not, there is no (zero) area - if (int(boost::size(ring)) + if (boost::size(ring) < core_detail::closure::minimum_ring_size<Closure>::value) { - return type(); + return typename Strategy::return_type(); } typedef typename reversible_view<Ring const, Direction>::type rview_type; @@ -136,77 +134,112 @@ namespace dispatch template < typename Geometry, - typename Strategy = typename strategy::area::services::default_strategy - < - typename cs_tag - < - typename point_type<Geometry>::type - >::type, - typename point_type<Geometry>::type - >::type, typename Tag = typename tag<Geometry>::type > -struct area - : detail::calculate_null - < - typename Strategy::return_type, - Geometry, - Strategy - > {}; +struct area : detail::calculate_null +{ + template <typename Strategy> + static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy) + { + return calculate_null::apply<typename Strategy::return_type>(geometry, strategy); + } +}; -template -< - typename Geometry, - typename Strategy -> -struct area<Geometry, Strategy, box_tag> - : detail::area::box_area<Geometry, Strategy> +template <typename Geometry> +struct area<Geometry, box_tag> : detail::area::box_area {}; -template -< - typename Ring, - typename Strategy -> -struct area<Ring, Strategy, ring_tag> +template <typename Ring> +struct area<Ring, ring_tag> : detail::area::ring_area < - Ring, order_as_direction<geometry::point_order<Ring>::value>::value, - geometry::closure<Ring>::value, - Strategy + geometry::closure<Ring>::value > {}; -template -< - typename Polygon, - typename Strategy -> -struct area<Polygon, Strategy, polygon_tag> - : detail::calculate_polygon_sum - < +template <typename Polygon> +struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum +{ + template <typename Strategy> + static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy) + { + return calculate_polygon_sum::apply< typename Strategy::return_type, - Polygon, - Strategy, detail::area::ring_area < - typename ring_type<Polygon const>::type, order_as_direction<geometry::point_order<Polygon>::value>::value, - geometry::closure<Polygon>::value, - Strategy + geometry::closure<Polygon>::value > - > -{}; + >(polygon, strategy); + } +}; + + +template <typename MultiGeometry> +struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum +{ + template <typename Strategy> + static inline typename Strategy::return_type + apply(MultiGeometry const& multi, Strategy const& strategy) + { + return multi_sum::apply + < + typename Strategy::return_type, + area<typename boost::range_value<MultiGeometry>::type> + >(multi, strategy); + } +}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH +namespace resolve_variant { + +template <typename Geometry> +struct area +{ + template <typename Strategy> + static inline typename Strategy::return_type apply(Geometry const& geometry, + Strategy const& strategy) + { + return dispatch::area<Geometry>::apply(geometry, strategy); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Strategy> + struct visitor: boost::static_visitor<typename Strategy::return_type> + { + Strategy const& m_strategy; + + visitor(Strategy const& strategy): m_strategy(strategy) {} + + template <typename Geometry> + typename Strategy::return_type operator()(Geometry const& geometry) const + { + return area<Geometry>::apply(geometry, m_strategy); + } + }; + + template <typename Strategy> + static inline typename Strategy::return_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{area} @@ -234,6 +267,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr { concept::check<Geometry const>(); + // TODO put this into a resolve_strategy stage + // (and take the return type from resolve_variant) typedef typename point_type<Geometry>::type point_type; typedef typename strategy::area::services::default_strategy < @@ -242,11 +277,8 @@ inline typename default_area_result<Geometry>::type area(Geometry const& geometr >::type strategy_type; // detail::throw_on_empty_input(geometry); - - return dispatch::area - < - Geometry - >::apply(geometry, strategy_type()); + + return resolve_variant::area<Geometry>::apply(geometry, strategy_type()); } /*! @@ -280,12 +312,8 @@ inline typename Strategy::return_type area( concept::check<Geometry const>(); // detail::throw_on_empty_input(geometry); - - return dispatch::area - < - Geometry, - Strategy - >::apply(geometry, strategy); + + return resolve_variant::area<Geometry>::apply(geometry, strategy); } |