Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@16: // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. Chris@16: // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. Chris@16: Chris@16: // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library Chris@16: // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP Chris@16: #define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: // #include Chris@101: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: namespace detail { namespace area Chris@16: { Chris@16: Chris@16: struct box_area Chris@16: { Chris@16: template Chris@16: static inline typename coordinate_type::type Chris@16: apply(Box const& box, Strategy const&) Chris@16: { Chris@16: // Currently only works for 2D Cartesian boxes Chris@16: assert_dimension(); Chris@16: Chris@16: return (get(box) - get(box)) Chris@16: * (get(box) - get(box)); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: < Chris@16: iterate_direction Direction, Chris@16: closure_selector Closure Chris@16: > Chris@16: struct ring_area Chris@16: { Chris@16: template Chris@16: static inline typename Strategy::return_type Chris@16: apply(Ring const& ring, Strategy const& strategy) Chris@16: { Chris@16: BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy) ); Chris@16: assert_dimension(); Chris@16: Chris@16: // Ignore warning (because using static method sometimes) on strategy Chris@16: boost::ignore_unused_variable_warning(strategy); Chris@16: Chris@16: // An open ring has at least three points, Chris@16: // A closed ring has at least four points, Chris@16: // if not, there is no (zero) area Chris@101: if (boost::size(ring) Chris@16: < core_detail::closure::minimum_ring_size::value) Chris@16: { Chris@16: return typename Strategy::return_type(); Chris@16: } Chris@16: Chris@16: typedef typename reversible_view::type rview_type; Chris@16: typedef typename closeable_view Chris@16: < Chris@16: rview_type const, Closure Chris@16: >::type view_type; Chris@16: typedef typename boost::range_iterator::type iterator_type; Chris@16: Chris@16: rview_type rview(ring); Chris@16: view_type view(rview); Chris@16: typename Strategy::state_type state; Chris@16: iterator_type it = boost::begin(view); Chris@16: iterator_type end = boost::end(view); Chris@16: Chris@16: for (iterator_type previous = it++; Chris@16: it != end; Chris@16: ++previous, ++it) Chris@16: { Chris@16: strategy.apply(*previous, *it, state); Chris@16: } Chris@16: Chris@16: return strategy.result(state); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: }} // namespace detail::area Chris@16: Chris@16: Chris@16: #endif // DOXYGEN_NO_DETAIL Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DISPATCH Chris@16: namespace dispatch Chris@16: { Chris@16: Chris@16: template Chris@16: < Chris@16: typename Geometry, Chris@16: typename Tag = typename tag::type Chris@16: > Chris@16: struct area : detail::calculate_null Chris@16: { Chris@16: template Chris@16: static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy) Chris@16: { Chris@16: return calculate_null::apply(geometry, strategy); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct area : detail::area::box_area Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct area Chris@16: : detail::area::ring_area Chris@16: < Chris@16: order_as_direction::value>::value, Chris@16: geometry::closure::value Chris@16: > Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct area : detail::calculate_polygon_sum Chris@16: { Chris@16: template Chris@16: static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy) Chris@16: { Chris@16: return calculate_polygon_sum::apply< Chris@16: typename Strategy::return_type, Chris@16: detail::area::ring_area Chris@16: < Chris@16: order_as_direction::value>::value, Chris@16: geometry::closure::value Chris@16: > Chris@16: >(polygon, strategy); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@101: template Chris@101: struct area : detail::multi_sum Chris@101: { Chris@101: template Chris@101: static inline typename Strategy::return_type Chris@101: apply(MultiGeometry const& multi, Strategy const& strategy) Chris@101: { Chris@101: return multi_sum::apply Chris@101: < Chris@101: typename Strategy::return_type, Chris@101: area::type> Chris@101: >(multi, strategy); Chris@101: } Chris@101: }; Chris@101: Chris@101: Chris@101: } // namespace dispatch Chris@101: #endif // DOXYGEN_NO_DISPATCH Chris@101: Chris@101: Chris@101: namespace resolve_variant { Chris@101: Chris@16: template Chris@101: struct area Chris@16: { Chris@16: template Chris@16: static inline typename Strategy::return_type apply(Geometry const& geometry, Chris@16: Strategy const& strategy) Chris@16: { Chris@101: return dispatch::area::apply(geometry, strategy); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@101: struct area > Chris@16: { Chris@16: template Chris@16: struct visitor: boost::static_visitor Chris@16: { Chris@16: Strategy const& m_strategy; Chris@16: Chris@16: visitor(Strategy const& strategy): m_strategy(strategy) {} Chris@16: Chris@16: template Chris@16: typename Strategy::return_type operator()(Geometry const& geometry) const Chris@16: { Chris@101: return area::apply(geometry, m_strategy); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: static inline typename Strategy::return_type Chris@16: apply(boost::variant const& geometry, Chris@16: Strategy const& strategy) Chris@16: { Chris@16: return boost::apply_visitor(visitor(strategy), geometry); Chris@16: } Chris@16: }; Chris@16: Chris@101: } // namespace resolve_variant Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief \brief_calc{area} Chris@16: \ingroup area Chris@16: \details \details_calc{area}. \details_default_strategy Chris@16: Chris@16: The area algorithm calculates the surface area of all geometries having a surface, namely Chris@16: box, polygon, ring, multipolygon. The units are the square of the units used for the points Chris@16: defining the surface. If subject geometry is defined in meters, then area is calculated Chris@16: in square meters. Chris@16: Chris@16: The area calculation can be done in all three common coordinate systems, Cartesian, Spherical Chris@16: and Geographic as well. Chris@16: Chris@16: \tparam Geometry \tparam_geometry Chris@16: \param geometry \param_geometry Chris@16: \return \return_calc{area} Chris@16: Chris@16: \qbk{[include reference/algorithms/area.qbk]} Chris@16: \qbk{[heading Examples]} Chris@16: \qbk{[area] [area_output]} Chris@16: */ Chris@16: template Chris@16: inline typename default_area_result::type area(Geometry const& geometry) Chris@16: { Chris@16: concept::check(); Chris@16: Chris@101: // TODO put this into a resolve_strategy stage Chris@101: // (and take the return type from resolve_variant) Chris@16: typedef typename point_type::type point_type; Chris@16: typedef typename strategy::area::services::default_strategy Chris@16: < Chris@16: typename cs_tag::type, Chris@16: point_type Chris@16: >::type strategy_type; Chris@16: Chris@16: // detail::throw_on_empty_input(geometry); Chris@101: Chris@101: return resolve_variant::area::apply(geometry, strategy_type()); Chris@16: } Chris@16: Chris@16: /*! Chris@16: \brief \brief_calc{area} \brief_strategy Chris@16: \ingroup area Chris@16: \details \details_calc{area} \brief_strategy. \details_strategy_reasons Chris@16: \tparam Geometry \tparam_geometry Chris@16: \tparam Strategy \tparam_strategy{Area} Chris@16: \param geometry \param_geometry Chris@16: \param strategy \param_strategy{area} Chris@16: \return \return_calc{area} Chris@16: Chris@16: \qbk{distinguish,with strategy} Chris@16: Chris@16: \qbk{ Chris@16: [include reference/algorithms/area.qbk] Chris@16: Chris@16: [heading Example] Chris@16: [area_with_strategy] Chris@16: [area_with_strategy_output] Chris@16: Chris@16: [heading Available Strategies] Chris@16: \* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)] Chris@16: \* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)] Chris@16: } Chris@16: */ Chris@16: template Chris@16: inline typename Strategy::return_type area( Chris@16: Geometry const& geometry, Strategy const& strategy) Chris@16: { Chris@16: concept::check(); Chris@16: Chris@16: // detail::throw_on_empty_input(geometry); Chris@101: Chris@101: return resolve_variant::area::apply(geometry, strategy); Chris@16: } Chris@16: Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: Chris@16: #endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP