]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/srs/projections/proj/aea.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / srs / projections / proj / aea.hpp
CommitLineData
92f5a8d4 1// Boost.Geometry - gis-projections (based on PROJ4)
11fdf7f2
TL
2
3// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
4
92f5a8d4
TL
5// This file was modified by Oracle on 2017, 2018, 2019.
6// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
11fdf7f2
TL
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// This file is converted from PROJ4, http://trac.osgeo.org/proj
14// PROJ4 is originally written by Gerald Evenden (then of the USGS)
15// PROJ4 is maintained by Frank Warmerdam
16// PROJ4 is converted to Boost.Geometry by Barend Gehrels
17
92f5a8d4
TL
18 // Author: Gerald Evenden (1995)
19 // Thomas Knudsen (2016) - revise/add regression tests
20
21// Last updated version of proj: 5.0.0
11fdf7f2
TL
22
23// Original copyright notice:
24
25// Purpose: Implementation of the aea (Albers Equal Area) projection.
26// Author: Gerald Evenden
27// Copyright (c) 1995, Gerald Evenden
28
29// Permission is hereby granted, free of charge, to any person obtaining a
30// copy of this software and associated documentation files (the "Software"),
31// to deal in the Software without restriction, including without limitation
32// the rights to use, copy, modify, merge, publish, distribute, sublicense,
33// and/or sell copies of the Software, and to permit persons to whom the
34// Software is furnished to do so, subject to the following conditions:
35
36// The above copyright notice and this permission notice shall be included
37// in all copies or substantial portions of the Software.
38
39// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
40// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45// DEALINGS IN THE SOFTWARE.
46
92f5a8d4
TL
47#ifndef BOOST_GEOMETRY_PROJECTIONS_AEA_HPP
48#define BOOST_GEOMETRY_PROJECTIONS_AEA_HPP
49
11fdf7f2
TL
50#include <boost/core/ignore_unused.hpp>
51#include <boost/geometry/util/math.hpp>
52#include <boost/math/special_functions/hypot.hpp>
53
54#include <boost/geometry/srs/projections/impl/base_static.hpp>
55#include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
56#include <boost/geometry/srs/projections/impl/projects.hpp>
57#include <boost/geometry/srs/projections/impl/factory_entry.hpp>
58#include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
59#include <boost/geometry/srs/projections/impl/pj_msfn.hpp>
92f5a8d4 60#include <boost/geometry/srs/projections/impl/pj_param.hpp>
11fdf7f2
TL
61#include <boost/geometry/srs/projections/impl/pj_qsfn.hpp>
62
63
64namespace boost { namespace geometry
65{
66
11fdf7f2
TL
67namespace projections
68{
69 #ifndef DOXYGEN_NO_DETAIL
70 namespace detail { namespace aea
71 {
72
92f5a8d4
TL
73 static const double epsilon10 = 1.e-10;
74 static const double tolerance7 = 1.e-7;
75 static const double epsilon = 1.0e-7;
76 static const double tolerance = 1.0e-10;
77 static const int n_iter = 15;
11fdf7f2
TL
78
79 template <typename T>
80 struct par_aea
81 {
82 T ec;
83 T n;
84 T c;
85 T dd;
86 T n2;
87 T rho0;
88 T phi1;
89 T phi2;
92f5a8d4
TL
90 detail::en<T> en;
91 bool ellips;
11fdf7f2
TL
92 };
93
94 /* determine latitude angle phi-1 */
95 template <typename T>
96 inline T phi1_(T const& qs, T const& Te, T const& Tone_es)
97 {
98 int i;
99 T Phi, sinpi, cospi, con, com, dphi;
100
101 Phi = asin (.5 * qs);
92f5a8d4 102 if (Te < epsilon)
11fdf7f2 103 return( Phi );
92f5a8d4 104 i = n_iter;
11fdf7f2
TL
105 do {
106 sinpi = sin (Phi);
107 cospi = cos (Phi);
108 con = Te * sinpi;
109 com = 1. - con * con;
110 dphi = .5 * com * com / cospi * (qs / Tone_es -
111 sinpi / com + .5 / Te * log ((1. - con) /
112 (1. + con)));
113 Phi += dphi;
92f5a8d4 114 } while (fabs(dphi) > tolerance && --i);
11fdf7f2
TL
115 return( i ? Phi : HUGE_VAL );
116 }
117
92f5a8d4
TL
118 template <typename T, typename Parameters>
119 struct base_aea_ellipsoid
11fdf7f2 120 {
92f5a8d4 121 par_aea<T> m_proj_parm;
11fdf7f2
TL
122
123 // FORWARD(e_forward) ellipsoid & spheroid
124 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
92f5a8d4 125 inline void fwd(Parameters const& par, T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
11fdf7f2 126 {
92f5a8d4
TL
127 T rho = this->m_proj_parm.c - (this->m_proj_parm.ellips
128 ? this->m_proj_parm.n * pj_qsfn(sin(lp_lat), par.e, par.one_es)
129 : this->m_proj_parm.n2 * sin(lp_lat));
130 if (rho < 0.)
131 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
11fdf7f2
TL
132 rho = this->m_proj_parm.dd * sqrt(rho);
133 xy_x = rho * sin( lp_lon *= this->m_proj_parm.n );
134 xy_y = this->m_proj_parm.rho0 - rho * cos(lp_lon);
135 }
136
137 // INVERSE(e_inverse) ellipsoid & spheroid
138 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
92f5a8d4 139 inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const
11fdf7f2 140 {
92f5a8d4 141 static const T half_pi = detail::half_pi<T>();
11fdf7f2 142
92f5a8d4 143 T rho = 0.0;
11fdf7f2
TL
144 if( (rho = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.rho0 - xy_y)) != 0.0 ) {
145 if (this->m_proj_parm.n < 0.) {
146 rho = -rho;
147 xy_x = -xy_x;
148 xy_y = -xy_y;
149 }
150 lp_lat = rho / this->m_proj_parm.dd;
151 if (this->m_proj_parm.ellips) {
152 lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n;
92f5a8d4
TL
153 if (fabs(this->m_proj_parm.ec - fabs(lp_lat)) > tolerance7) {
154 if ((lp_lat = phi1_(lp_lat, par.e, par.one_es)) == HUGE_VAL)
155 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
11fdf7f2 156 } else
92f5a8d4 157 lp_lat = lp_lat < 0. ? -half_pi : half_pi;
11fdf7f2
TL
158 } else if (fabs(lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n2) <= 1.)
159 lp_lat = asin(lp_lat);
160 else
92f5a8d4 161 lp_lat = lp_lat < 0. ? -half_pi : half_pi;
11fdf7f2
TL
162 lp_lon = atan2(xy_x, xy_y) / this->m_proj_parm.n;
163 } else {
164 lp_lon = 0.;
92f5a8d4 165 lp_lat = this->m_proj_parm.n > 0. ? half_pi : - half_pi;
11fdf7f2
TL
166 }
167 }
168
169 static inline std::string get_name()
170 {
171 return "aea_ellipsoid";
172 }
173
174 };
175
176 template <typename Parameters, typename T>
92f5a8d4 177 inline void setup(Parameters const& par, par_aea<T>& proj_parm)
11fdf7f2
TL
178 {
179 T cosphi, sinphi;
180 int secant;
181
92f5a8d4
TL
182 if (fabs(proj_parm.phi1 + proj_parm.phi2) < epsilon10)
183 BOOST_THROW_EXCEPTION( projection_exception(error_conic_lat_equal) );
11fdf7f2
TL
184 proj_parm.n = sinphi = sin(proj_parm.phi1);
185 cosphi = cos(proj_parm.phi1);
92f5a8d4 186 secant = fabs(proj_parm.phi1 - proj_parm.phi2) >= epsilon10;
11fdf7f2
TL
187 if( (proj_parm.ellips = (par.es > 0.))) {
188 T ml1, m1;
189
92f5a8d4 190 proj_parm.en = pj_enfn<T>(par.es);
11fdf7f2
TL
191 m1 = pj_msfn(sinphi, cosphi, par.es);
192 ml1 = pj_qsfn(sinphi, par.e, par.one_es);
193 if (secant) { /* secant cone */
194 T ml2, m2;
195
196 sinphi = sin(proj_parm.phi2);
197 cosphi = cos(proj_parm.phi2);
198 m2 = pj_msfn(sinphi, cosphi, par.es);
199 ml2 = pj_qsfn(sinphi, par.e, par.one_es);
92f5a8d4
TL
200 if (ml2 == ml1)
201 BOOST_THROW_EXCEPTION( projection_exception(0) );
202
11fdf7f2
TL
203 proj_parm.n = (m1 * m1 - m2 * m2) / (ml2 - ml1);
204 }
205 proj_parm.ec = 1. - .5 * par.one_es * log((1. - par.e) /
206 (1. + par.e)) / par.e;
207 proj_parm.c = m1 * m1 + proj_parm.n * ml1;
208 proj_parm.dd = 1. / proj_parm.n;
209 proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n * pj_qsfn(sin(par.phi0),
210 par.e, par.one_es));
211 } else {
212 if (secant) proj_parm.n = .5 * (proj_parm.n + sin(proj_parm.phi2));
213 proj_parm.n2 = proj_parm.n + proj_parm.n;
214 proj_parm.c = cosphi * cosphi + proj_parm.n2 * sinphi;
215 proj_parm.dd = 1. / proj_parm.n;
216 proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n2 * sin(par.phi0));
217 }
218 }
219
220
221 // Albers Equal Area
92f5a8d4
TL
222 template <typename Params, typename Parameters, typename T>
223 inline void setup_aea(Params const& params, Parameters const& par, par_aea<T>& proj_parm)
11fdf7f2 224 {
92f5a8d4
TL
225 proj_parm.phi1 = 0.0;
226 proj_parm.phi2 = 0.0;
227 bool is_phi1_set = pj_param_r<srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1, proj_parm.phi1);
228 bool is_phi2_set = pj_param_r<srs::spar::lat_2>(params, "lat_2", srs::dpar::lat_2, proj_parm.phi2);
229
230 // Boost.Geometry specific, set default parameters manually
231 if (! is_phi1_set || ! is_phi2_set) {
232 bool const use_defaults = ! pj_get_param_b<srs::spar::no_defs>(params, "no_defs", srs::dpar::no_defs);
233 if (use_defaults) {
234 if (!is_phi1_set)
235 proj_parm.phi1 = 29.5;
236 if (!is_phi2_set)
237 proj_parm.phi2 = 45.5;
238 }
239 }
240
11fdf7f2
TL
241 setup(par, proj_parm);
242 }
243
244 // Lambert Equal Area Conic
92f5a8d4
TL
245 template <typename Params, typename Parameters, typename T>
246 inline void setup_leac(Params const& params, Parameters const& par, par_aea<T>& proj_parm)
11fdf7f2 247 {
92f5a8d4 248 static const T half_pi = detail::half_pi<T>();
11fdf7f2 249
92f5a8d4
TL
250 proj_parm.phi2 = pj_get_param_r<T, srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1);
251 proj_parm.phi1 = pj_get_param_b<srs::spar::south>(params, "south", srs::dpar::south) ? -half_pi : half_pi;
11fdf7f2
TL
252 setup(par, proj_parm);
253 }
254
255 }} // namespace detail::aea
256 #endif // doxygen
257
258 /*!
259 \brief Albers Equal Area projection
260 \ingroup projections
261 \tparam Geographic latlong point type
262 \tparam Cartesian xy point type
263 \tparam Parameters parameter type
264 \par Projection characteristics
265 - Conic
266 - Spheroid
267 - Ellipsoid
268 \par Projection parameters
269 - lat_1: Latitude of first standard parallel (degrees)
270 - lat_2: Latitude of second standard parallel (degrees)
271 \par Example
272 \image html ex_aea.gif
273 */
92f5a8d4
TL
274 template <typename T, typename Parameters>
275 struct aea_ellipsoid : public detail::aea::base_aea_ellipsoid<T, Parameters>
11fdf7f2 276 {
92f5a8d4
TL
277 template <typename Params>
278 inline aea_ellipsoid(Params const& params, Parameters const& par)
11fdf7f2 279 {
92f5a8d4 280 detail::aea::setup_aea(params, par, this->m_proj_parm);
11fdf7f2
TL
281 }
282 };
283
284 /*!
285 \brief Lambert Equal Area Conic projection
286 \ingroup projections
287 \tparam Geographic latlong point type
288 \tparam Cartesian xy point type
289 \tparam Parameters parameter type
290 \par Projection characteristics
291 - Conic
292 - Spheroid
293 - Ellipsoid
294 \par Projection parameters
295 - lat_1: Latitude of first standard parallel (degrees)
296 - south: Denotes southern hemisphere UTM zone (boolean)
297 \par Example
298 \image html ex_leac.gif
299 */
92f5a8d4
TL
300 template <typename T, typename Parameters>
301 struct leac_ellipsoid : public detail::aea::base_aea_ellipsoid<T, Parameters>
11fdf7f2 302 {
92f5a8d4
TL
303 template <typename Params>
304 inline leac_ellipsoid(Params const& params, Parameters const& par)
11fdf7f2 305 {
92f5a8d4 306 detail::aea::setup_leac(params, par, this->m_proj_parm);
11fdf7f2
TL
307 }
308 };
309
310 #ifndef DOXYGEN_NO_DETAIL
311 namespace detail
312 {
313
314 // Static projection
92f5a8d4
TL
315 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_aea, aea_ellipsoid)
316 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_leac, leac_ellipsoid)
11fdf7f2
TL
317
318 // Factory entry(s)
92f5a8d4
TL
319 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(aea_entry, aea_ellipsoid)
320 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(leac_entry, leac_ellipsoid)
11fdf7f2 321
92f5a8d4 322 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(aea_init)
11fdf7f2 323 {
92f5a8d4
TL
324 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(aea, aea_entry)
325 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(leac, leac_entry)
11fdf7f2
TL
326 }
327
328 } // namespace detail
329 #endif // doxygen
330
331} // namespace projections
332
333}} // namespace boost::geometry
334
335#endif // BOOST_GEOMETRY_PROJECTIONS_AEA_HPP
336