]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/strategies/geographic/area.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / strategies / geographic / area.hpp
CommitLineData
b32b8144
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
11fdf7f2
TL
3// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
4
5// Copyright (c) 2016-2018 Oracle and/or its affiliates.
b32b8144
FG
6// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
7// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8
9// Use, modification and distribution is subject to the Boost Software License,
10// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11// http://www.boost.org/LICENSE_1_0.txt)
12
13#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
14#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP
15
16
11fdf7f2 17#include <boost/geometry/srs/spheroid.hpp>
b32b8144
FG
18
19#include <boost/geometry/formulas/area_formulas.hpp>
20#include <boost/geometry/formulas/authalic_radius_sqr.hpp>
21#include <boost/geometry/formulas/eccentricity_sqr.hpp>
22
92f5a8d4 23#include <boost/geometry/strategies/area.hpp>
b32b8144
FG
24#include <boost/geometry/strategies/geographic/parameters.hpp>
25
26
27namespace boost { namespace geometry
28{
29
30namespace strategy { namespace area
31{
32
33/*!
34\brief Geographic area calculation
35\ingroup strategies
36\details Geographic area calculation by trapezoidal rule plus integral
37 approximation that gives the ellipsoidal correction
b32b8144
FG
38\tparam FormulaPolicy Formula used to calculate azimuths
39\tparam SeriesOrder The order of approximation of the geodesic integral
40\tparam Spheroid The spheroid model
41\tparam CalculationType \tparam_calculation
42\author See
43- Danielsen JS, The area under the geodesic. Surv Rev 30(232): 61–66, 1989
44- Charles F.F Karney, Algorithms for geodesics, 2011 https://arxiv.org/pdf/1109.4448.pdf
45
46\qbk{
47[heading See also]
11fdf7f2
TL
48\* [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
49\* [link geometry.reference.srs.srs_spheroid srs::spheroid]
b32b8144
FG
50}
51*/
52template
53<
b32b8144
FG
54 typename FormulaPolicy = strategy::andoyer,
55 std::size_t SeriesOrder = strategy::default_order<FormulaPolicy>::value,
56 typename Spheroid = srs::spheroid<double>,
57 typename CalculationType = void
58>
59class geographic
60{
61 // Switch between two kinds of approximation(series in eps and n v.s.series in k ^ 2 and e'^2)
62 static const bool ExpandEpsN = true;
63 // LongSegment Enables special handling of long segments
64 static const bool LongSegment = false;
65
66 //Select default types in case they are not set
67
11fdf7f2
TL
68public:
69 template <typename Geometry>
70 struct result_type
71 : strategy::area::detail::result_type
b32b8144 72 <
11fdf7f2
TL
73 Geometry,
74 CalculationType
75 >
76 {};
b32b8144
FG
77
78protected :
79 struct spheroid_constants
80 {
11fdf7f2
TL
81 typedef typename boost::mpl::if_c
82 <
83 boost::is_void<CalculationType>::value,
84 typename geometry::radius_type<Spheroid>::type,
85 CalculationType
86 >::type calc_t;
87
b32b8144 88 Spheroid m_spheroid;
11fdf7f2
TL
89 calc_t const m_a2; // squared equatorial radius
90 calc_t const m_e2; // squared eccentricity
91 calc_t const m_ep2; // squared second eccentricity
92 calc_t const m_ep; // second eccentricity
93 calc_t const m_c2; // squared authalic radius
b32b8144
FG
94
95 inline spheroid_constants(Spheroid const& spheroid)
96 : m_spheroid(spheroid)
97 , m_a2(math::sqr(get_radius<0>(spheroid)))
11fdf7f2
TL
98 , m_e2(formula::eccentricity_sqr<calc_t>(spheroid))
99 , m_ep2(m_e2 / (calc_t(1.0) - m_e2))
b32b8144
FG
100 , m_ep(math::sqrt(m_ep2))
101 , m_c2(formula_dispatch::authalic_radius_sqr
102 <
11fdf7f2 103 calc_t, Spheroid, srs_spheroid_tag
b32b8144
FG
104 >::apply(m_a2, m_e2))
105 {}
106 };
107
11fdf7f2
TL
108public:
109 template <typename Geometry>
110 class state
b32b8144 111 {
11fdf7f2 112 friend class geographic;
b32b8144 113
11fdf7f2 114 typedef typename result_type<Geometry>::type return_type;
b32b8144 115
11fdf7f2
TL
116 public:
117 inline state()
b32b8144
FG
118 : m_excess_sum(0)
119 , m_correction_sum(0)
120 , m_crosses_prime_meridian(0)
121 {}
11fdf7f2
TL
122
123 private:
124 inline return_type area(spheroid_constants const& spheroid_const) const
b32b8144 125 {
11fdf7f2 126 return_type result;
b32b8144 127
11fdf7f2 128 return_type sum = spheroid_const.m_c2 * m_excess_sum
b32b8144
FG
129 + spheroid_const.m_e2 * spheroid_const.m_a2 * m_correction_sum;
130
131 // If encircles some pole
132 if (m_crosses_prime_meridian % 2 == 1)
133 {
134 std::size_t times_crosses_prime_meridian
135 = 1 + (m_crosses_prime_meridian / 2);
136
11fdf7f2
TL
137 result = return_type(2.0)
138 * geometry::math::pi<return_type>()
b32b8144 139 * spheroid_const.m_c2
11fdf7f2 140 * return_type(times_crosses_prime_meridian)
b32b8144
FG
141 - geometry::math::abs(sum);
142
11fdf7f2 143 if (geometry::math::sign<return_type>(sum) == 1)
b32b8144
FG
144 {
145 result = - result;
146 }
147
148 }
149 else
150 {
151 result = sum;
152 }
153
154 return result;
155 }
11fdf7f2
TL
156
157 return_type m_excess_sum;
158 return_type m_correction_sum;
159
160 // Keep track if encircles some pole
161 std::size_t m_crosses_prime_meridian;
b32b8144
FG
162 };
163
164public :
b32b8144
FG
165 explicit inline geographic(Spheroid const& spheroid = Spheroid())
166 : m_spheroid_constants(spheroid)
167 {}
168
11fdf7f2 169 template <typename PointOfSegment, typename Geometry>
b32b8144
FG
170 inline void apply(PointOfSegment const& p1,
171 PointOfSegment const& p2,
11fdf7f2 172 state<Geometry>& st) const
b32b8144 173 {
b32b8144
FG
174 if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
175 {
b32b8144
FG
176 typedef geometry::formula::area_formulas
177 <
11fdf7f2
TL
178 typename result_type<Geometry>::type,
179 SeriesOrder, ExpandEpsN
b32b8144
FG
180 > area_formulas;
181
182 typename area_formulas::return_type_ellipsoidal result =
183 area_formulas::template ellipsoidal<FormulaPolicy::template inverse>
184 (p1, p2, m_spheroid_constants);
185
11fdf7f2
TL
186 st.m_excess_sum += result.spherical_term;
187 st.m_correction_sum += result.ellipsoidal_term;
b32b8144
FG
188
189 // Keep track whenever a segment crosses the prime meridian
190 if (area_formulas::crosses_prime_meridian(p1, p2))
191 {
11fdf7f2 192 st.m_crosses_prime_meridian++;
b32b8144
FG
193 }
194 }
195 }
196
11fdf7f2
TL
197 template <typename Geometry>
198 inline typename result_type<Geometry>::type
199 result(state<Geometry> const& st) const
b32b8144 200 {
11fdf7f2 201 return st.area(m_spheroid_constants);
b32b8144
FG
202 }
203
204private:
205 spheroid_constants m_spheroid_constants;
206
207};
208
209#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
210
211namespace services
212{
213
214
11fdf7f2
TL
215template <>
216struct default_strategy<geographic_tag>
b32b8144 217{
11fdf7f2 218 typedef strategy::area::geographic<> type;
b32b8144
FG
219};
220
221#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
222
223}
224
225}} // namespace strategy::area
226
227
228
229
230}} // namespace boost::geometry
231
232#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_AREA_HPP