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