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