area.hpp 10 KB

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