1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // This file was modified by Oracle on 2017.
8 // Modifications copyright (c) 2017 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
18 #ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
19 #define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
21 #include <boost/concept_check.hpp>
22 #include <boost/mpl/if.hpp>
23 #include <boost/range/functions.hpp>
24 #include <boost/range/metafunctions.hpp>
26 #include <boost/variant/apply_visitor.hpp>
27 #include <boost/variant/static_visitor.hpp>
28 #include <boost/variant/variant_fwd.hpp>
30 #include <boost/geometry/core/closure.hpp>
31 #include <boost/geometry/core/exterior_ring.hpp>
32 #include <boost/geometry/core/interior_rings.hpp>
33 #include <boost/geometry/core/point_order.hpp>
34 #include <boost/geometry/core/point_type.hpp>
35 #include <boost/geometry/core/ring_type.hpp>
36 #include <boost/geometry/core/tags.hpp>
38 #include <boost/geometry/geometries/concepts/check.hpp>
40 #include <boost/geometry/algorithms/detail/calculate_null.hpp>
41 #include <boost/geometry/algorithms/detail/calculate_sum.hpp>
42 // #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
43 #include <boost/geometry/algorithms/detail/multi_sum.hpp>
45 #include <boost/geometry/strategies/area.hpp>
46 #include <boost/geometry/strategies/default_area_result.hpp>
48 #include <boost/geometry/strategies/concepts/area_concept.hpp>
50 #include <boost/geometry/util/math.hpp>
51 #include <boost/geometry/util/order_as_direction.hpp>
52 #include <boost/geometry/views/closeable_view.hpp>
53 #include <boost/geometry/views/reversible_view.hpp>
56 namespace boost { namespace geometry
59 #ifndef DOXYGEN_NO_DETAIL
60 namespace detail { namespace area
65 template <typename Box, typename Strategy>
66 static inline typename coordinate_type<Box>::type
67 apply(Box const& box, Strategy const&)
69 // Currently only works for 2D Cartesian boxes
70 assert_dimension<Box, 2>();
72 return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
73 * (get<max_corner, 1>(box) - get<min_corner, 1>(box));
80 iterate_direction Direction,
81 closure_selector Closure
85 template <typename Ring, typename Strategy>
86 static inline typename Strategy::return_type
87 apply(Ring const& ring, Strategy const& strategy)
89 BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy<Strategy>) );
90 assert_dimension<Ring, 2>();
92 // Ignore warning (because using static method sometimes) on strategy
93 boost::ignore_unused_variable_warning(strategy);
95 // An open ring has at least three points,
96 // A closed ring has at least four points,
97 // if not, there is no (zero) area
99 < core_detail::closure::minimum_ring_size<Closure>::value)
101 return typename Strategy::return_type();
104 typedef typename reversible_view<Ring const, Direction>::type rview_type;
105 typedef typename closeable_view
107 rview_type const, Closure
109 typedef typename boost::range_iterator<view_type const>::type iterator_type;
111 rview_type rview(ring);
112 view_type view(rview);
113 typename Strategy::state_type state;
114 iterator_type it = boost::begin(view);
115 iterator_type end = boost::end(view);
117 for (iterator_type previous = it++;
121 strategy.apply(*previous, *it, state);
124 return strategy.result(state);
129 }} // namespace detail::area
132 #endif // DOXYGEN_NO_DETAIL
135 #ifndef DOXYGEN_NO_DISPATCH
142 typename Tag = typename tag<Geometry>::type
144 struct area : detail::calculate_null
146 template <typename Strategy>
147 static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
149 return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
154 template <typename Geometry>
155 struct area<Geometry, box_tag> : detail::area::box_area
159 template <typename Ring>
160 struct area<Ring, ring_tag>
161 : detail::area::ring_area
163 order_as_direction<geometry::point_order<Ring>::value>::value,
164 geometry::closure<Ring>::value
169 template <typename Polygon>
170 struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
172 template <typename Strategy>
173 static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
175 return calculate_polygon_sum::apply<
176 typename Strategy::return_type,
177 detail::area::ring_area
179 order_as_direction<geometry::point_order<Polygon>::value>::value,
180 geometry::closure<Polygon>::value
182 >(polygon, strategy);
187 template <typename MultiGeometry>
188 struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
190 template <typename Strategy>
191 static inline typename Strategy::return_type
192 apply(MultiGeometry const& multi, Strategy const& strategy)
194 return multi_sum::apply
196 typename Strategy::return_type,
197 area<typename boost::range_value<MultiGeometry>::type>
203 } // namespace dispatch
204 #endif // DOXYGEN_NO_DISPATCH
207 namespace resolve_variant {
209 template <typename Geometry>
212 template <typename Strategy>
213 static inline typename Strategy::return_type apply(Geometry const& geometry,
214 Strategy const& strategy)
216 return dispatch::area<Geometry>::apply(geometry, strategy);
220 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
221 struct area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
223 template <typename Strategy>
224 struct visitor: boost::static_visitor<typename Strategy::return_type>
226 Strategy const& m_strategy;
228 visitor(Strategy const& strategy): m_strategy(strategy) {}
230 template <typename Geometry>
231 typename Strategy::return_type operator()(Geometry const& geometry) const
233 return area<Geometry>::apply(geometry, m_strategy);
237 template <typename Strategy>
238 static inline typename Strategy::return_type
239 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
240 Strategy const& strategy)
242 return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
246 } // namespace resolve_variant
250 \brief \brief_calc{area}
252 \details \details_calc{area}. \details_default_strategy
254 The area algorithm calculates the surface area of all geometries having a surface, namely
255 box, polygon, ring, multipolygon. The units are the square of the units used for the points
256 defining the surface. If subject geometry is defined in meters, then area is calculated
259 The area calculation can be done in all three common coordinate systems, Cartesian, Spherical
260 and Geographic as well.
262 \tparam Geometry \tparam_geometry
263 \param geometry \param_geometry
264 \return \return_calc{area}
266 \qbk{[include reference/algorithms/area.qbk]}
267 \qbk{[heading Examples]}
268 \qbk{[area] [area_output]}
270 template <typename Geometry>
271 inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
273 concepts::check<Geometry const>();
275 // TODO put this into a resolve_strategy stage
276 // (and take the return type from resolve_variant)
277 typedef typename point_type<Geometry>::type point_type;
278 typedef typename strategy::area::services::default_strategy
280 typename cs_tag<point_type>::type,
282 >::type strategy_type;
284 // detail::throw_on_empty_input(geometry);
286 return resolve_variant::area<Geometry>::apply(geometry, strategy_type());
290 \brief \brief_calc{area} \brief_strategy
292 \details \details_calc{area} \brief_strategy. \details_strategy_reasons
293 \tparam Geometry \tparam_geometry
294 \tparam Strategy \tparam_strategy{Area}
295 \param geometry \param_geometry
296 \param strategy \param_strategy{area}
297 \return \return_calc{area}
299 \qbk{distinguish,with strategy}
302 [include reference/algorithms/area.qbk]
306 [area_with_strategy_output]
308 [heading Available Strategies]
309 \* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
310 \* [link geometry.reference.strategies.strategy_area_spherical Spherical]
311 [/link geometry.reference.strategies.strategy_area_geographic Geographic]
314 template <typename Geometry, typename Strategy>
315 inline typename Strategy::return_type area(
316 Geometry const& geometry, Strategy const& strategy)
318 concepts::check<Geometry const>();
320 // detail::throw_on_empty_input(geometry);
322 return resolve_variant::area<Geometry>::apply(geometry, strategy);
326 }} // namespace boost::geometry
329 #endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP