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