area.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  6. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
  12. #include <boost/concept_check.hpp>
  13. #include <boost/mpl/if.hpp>
  14. #include <boost/range/functions.hpp>
  15. #include <boost/range/metafunctions.hpp>
  16. #include <boost/variant/static_visitor.hpp>
  17. #include <boost/variant/apply_visitor.hpp>
  18. #include <boost/variant/variant_fwd.hpp>
  19. #include <boost/geometry/core/closure.hpp>
  20. #include <boost/geometry/core/exterior_ring.hpp>
  21. #include <boost/geometry/core/interior_rings.hpp>
  22. #include <boost/geometry/core/point_order.hpp>
  23. #include <boost/geometry/core/ring_type.hpp>
  24. #include <boost/geometry/geometries/concepts/check.hpp>
  25. #include <boost/geometry/algorithms/detail/calculate_null.hpp>
  26. #include <boost/geometry/algorithms/detail/calculate_sum.hpp>
  27. // #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
  28. #include <boost/geometry/strategies/area.hpp>
  29. #include <boost/geometry/strategies/default_area_result.hpp>
  30. #include <boost/geometry/strategies/concepts/area_concept.hpp>
  31. #include <boost/geometry/util/math.hpp>
  32. #include <boost/geometry/util/order_as_direction.hpp>
  33. #include <boost/geometry/views/closeable_view.hpp>
  34. #include <boost/geometry/views/reversible_view.hpp>
  35. namespace boost { namespace geometry
  36. {
  37. #ifndef DOXYGEN_NO_DETAIL
  38. namespace detail { namespace area
  39. {
  40. struct box_area
  41. {
  42. template <typename Box, typename Strategy>
  43. static inline typename coordinate_type<Box>::type
  44. apply(Box const& box, Strategy const&)
  45. {
  46. // Currently only works for 2D Cartesian boxes
  47. assert_dimension<Box, 2>();
  48. return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
  49. * (get<max_corner, 1>(box) - get<min_corner, 1>(box));
  50. }
  51. };
  52. template
  53. <
  54. iterate_direction Direction,
  55. closure_selector Closure
  56. >
  57. struct ring_area
  58. {
  59. template <typename Ring, typename Strategy>
  60. static inline typename Strategy::return_type
  61. apply(Ring const& ring, Strategy const& strategy)
  62. {
  63. BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
  64. assert_dimension<Ring, 2>();
  65. // Ignore warning (because using static method sometimes) on strategy
  66. boost::ignore_unused_variable_warning(strategy);
  67. // An open ring has at least three points,
  68. // A closed ring has at least four points,
  69. // if not, there is no (zero) area
  70. if (int(boost::size(ring))
  71. < core_detail::closure::minimum_ring_size<Closure>::value)
  72. {
  73. return typename Strategy::return_type();
  74. }
  75. typedef typename reversible_view<Ring const, Direction>::type rview_type;
  76. typedef typename closeable_view
  77. <
  78. rview_type const, Closure
  79. >::type view_type;
  80. typedef typename boost::range_iterator<view_type const>::type iterator_type;
  81. rview_type rview(ring);
  82. view_type view(rview);
  83. typename Strategy::state_type state;
  84. iterator_type it = boost::begin(view);
  85. iterator_type end = boost::end(view);
  86. for (iterator_type previous = it++;
  87. it != end;
  88. ++previous, ++it)
  89. {
  90. strategy.apply(*previous, *it, state);
  91. }
  92. return strategy.result(state);
  93. }
  94. };
  95. }} // namespace detail::area
  96. #endif // DOXYGEN_NO_DETAIL
  97. #ifndef DOXYGEN_NO_DISPATCH
  98. namespace dispatch
  99. {
  100. template
  101. <
  102. typename Geometry,
  103. typename Tag = typename tag<Geometry>::type
  104. >
  105. struct area : detail::calculate_null
  106. {
  107. template <typename Strategy>
  108. static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
  109. {
  110. return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
  111. }
  112. };
  113. template <typename Geometry>
  114. struct area<Geometry, box_tag> : detail::area::box_area
  115. {};
  116. template <typename Ring>
  117. struct area<Ring, ring_tag>
  118. : detail::area::ring_area
  119. <
  120. order_as_direction<geometry::point_order<Ring>::value>::value,
  121. geometry::closure<Ring>::value
  122. >
  123. {};
  124. template <typename Polygon>
  125. struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
  126. {
  127. template <typename Strategy>
  128. static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
  129. {
  130. return calculate_polygon_sum::apply<
  131. typename Strategy::return_type,
  132. detail::area::ring_area
  133. <
  134. order_as_direction<geometry::point_order<Polygon>::value>::value,
  135. geometry::closure<Polygon>::value
  136. >
  137. >(polygon, strategy);
  138. }
  139. };
  140. template <typename Geometry>
  141. struct devarianted_area
  142. {
  143. template <typename Strategy>
  144. static inline typename Strategy::return_type apply(Geometry const& geometry,
  145. Strategy const& strategy)
  146. {
  147. return area<Geometry>::apply(geometry, strategy);
  148. }
  149. };
  150. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  151. struct devarianted_area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  152. {
  153. template <typename Strategy>
  154. struct visitor: boost::static_visitor<typename Strategy::return_type>
  155. {
  156. Strategy const& m_strategy;
  157. visitor(Strategy const& strategy): m_strategy(strategy) {}
  158. template <typename Geometry>
  159. typename Strategy::return_type operator()(Geometry const& geometry) const
  160. {
  161. return devarianted_area<Geometry>::apply(geometry, m_strategy);
  162. }
  163. };
  164. template <typename Strategy>
  165. static inline typename Strategy::return_type
  166. apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
  167. Strategy const& strategy)
  168. {
  169. return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
  170. }
  171. };
  172. } // namespace dispatch
  173. #endif // DOXYGEN_NO_DISPATCH
  174. /*!
  175. \brief \brief_calc{area}
  176. \ingroup area
  177. \details \details_calc{area}. \details_default_strategy
  178. The area algorithm calculates the surface area of all geometries having a surface, namely
  179. box, polygon, ring, multipolygon. The units are the square of the units used for the points
  180. defining the surface. If subject geometry is defined in meters, then area is calculated
  181. in square meters.
  182. The area calculation can be done in all three common coordinate systems, Cartesian, Spherical
  183. and Geographic as well.
  184. \tparam Geometry \tparam_geometry
  185. \param geometry \param_geometry
  186. \return \return_calc{area}
  187. \qbk{[include reference/algorithms/area.qbk]}
  188. \qbk{[heading Examples]}
  189. \qbk{[area] [area_output]}
  190. */
  191. template <typename Geometry>
  192. inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
  193. {
  194. concept::check<Geometry const>();
  195. typedef typename point_type<Geometry>::type point_type;
  196. typedef typename strategy::area::services::default_strategy
  197. <
  198. typename cs_tag<point_type>::type,
  199. point_type
  200. >::type strategy_type;
  201. // detail::throw_on_empty_input(geometry);
  202. return dispatch::devarianted_area<Geometry>::apply(geometry, strategy_type());
  203. }
  204. /*!
  205. \brief \brief_calc{area} \brief_strategy
  206. \ingroup area
  207. \details \details_calc{area} \brief_strategy. \details_strategy_reasons
  208. \tparam Geometry \tparam_geometry
  209. \tparam Strategy \tparam_strategy{Area}
  210. \param geometry \param_geometry
  211. \param strategy \param_strategy{area}
  212. \return \return_calc{area}
  213. \qbk{distinguish,with strategy}
  214. \qbk{
  215. [include reference/algorithms/area.qbk]
  216. [heading Example]
  217. [area_with_strategy]
  218. [area_with_strategy_output]
  219. [heading Available Strategies]
  220. \* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
  221. \* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]
  222. }
  223. */
  224. template <typename Geometry, typename Strategy>
  225. inline typename Strategy::return_type area(
  226. Geometry const& geometry, Strategy const& strategy)
  227. {
  228. concept::check<Geometry const>();
  229. // detail::throw_on_empty_input(geometry);
  230. return dispatch::devarianted_area<Geometry>::apply(geometry, strategy);
  231. }
  232. }} // namespace boost::geometry
  233. #endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP