]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/srs/projections/proj/mod_ster.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / srs / projections / proj / mod_ster.hpp
1 // Boost.Geometry - gis-projections (based on PROJ4)
2
3 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2017, 2018, 2019.
6 // Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
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
18 // Last updated version of proj: 5.0.0
19
20 // Original copyright notice:
21
22 // Permission is hereby granted, free of charge, to any person obtaining a
23 // copy of this software and associated documentation files (the "Software"),
24 // to deal in the Software without restriction, including without limitation
25 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
26 // and/or sell copies of the Software, and to permit persons to whom the
27 // Software is furnished to do so, subject to the following conditions:
28
29 // The above copyright notice and this permission notice shall be included
30 // in all copies or substantial portions of the Software.
31
32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
33 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
35 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
37 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
38 // DEALINGS IN THE SOFTWARE.
39
40 #ifndef BOOST_GEOMETRY_PROJECTIONS_MOD_STER_HPP
41 #define BOOST_GEOMETRY_PROJECTIONS_MOD_STER_HPP
42
43 #include <boost/geometry/util/math.hpp>
44 #include <boost/math/special_functions/hypot.hpp>
45
46 #include <boost/geometry/srs/projections/impl/base_static.hpp>
47 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
48 #include <boost/geometry/srs/projections/impl/projects.hpp>
49 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
50 #include <boost/geometry/srs/projections/impl/aasincos.hpp>
51 #include <boost/geometry/srs/projections/impl/pj_zpoly1.hpp>
52
53 namespace boost { namespace geometry
54 {
55
56 namespace projections
57 {
58 #ifndef DOXYGEN_NO_DETAIL
59 namespace detail { namespace mod_ster
60 {
61
62 static const double epsilon = 1e-12;
63
64 template <typename T>
65 struct par_mod_ster
66 {
67 T cchio, schio;
68 pj_complex<T>* zcoeff;
69 int n;
70 };
71
72 /* based upon Snyder and Linck, USGS-NMD */
73
74 template <typename T, typename Parameters>
75 struct base_mod_ster_ellipsoid
76 {
77 par_mod_ster<T> m_proj_parm;
78
79 // FORWARD(e_forward) ellipsoid
80 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
81 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
82 {
83 static const T half_pi = detail::half_pi<T>();
84
85 T sinlon, coslon, esphi, chi, schi, cchi, s;
86 pj_complex<T> p;
87
88 sinlon = sin(lp_lon);
89 coslon = cos(lp_lon);
90 esphi = par.e * sin(lp_lat);
91 chi = 2. * atan(tan((half_pi + lp_lat) * .5) *
92 math::pow((T(1) - esphi) / (T(1) + esphi), par.e * T(0.5))) - half_pi;
93 schi = sin(chi);
94 cchi = cos(chi);
95 s = 2. / (1. + this->m_proj_parm.schio * schi + this->m_proj_parm.cchio * cchi * coslon);
96 p.r = s * cchi * sinlon;
97 p.i = s * (this->m_proj_parm.cchio * schi - this->m_proj_parm.schio * cchi * coslon);
98 p = pj_zpoly1(p, this->m_proj_parm.zcoeff, this->m_proj_parm.n);
99 xy_x = p.r;
100 xy_y = p.i;
101 }
102
103 // INVERSE(e_inverse) ellipsoid
104 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
105 inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
106 {
107 static const T half_pi = detail::half_pi<T>();
108
109 int nn;
110 pj_complex<T> p, fxy, fpxy, dp;
111 T den, rh = 0, z, sinz = 0, cosz = 0, chi, phi = 0, dphi, esphi;
112
113 p.r = xy_x;
114 p.i = xy_y;
115 for (nn = 20; nn ;--nn) {
116 fxy = pj_zpolyd1(p, this->m_proj_parm.zcoeff, this->m_proj_parm.n, &fpxy);
117 fxy.r -= xy_x;
118 fxy.i -= xy_y;
119 den = fpxy.r * fpxy.r + fpxy.i * fpxy.i;
120 dp.r = -(fxy.r * fpxy.r + fxy.i * fpxy.i) / den;
121 dp.i = -(fxy.i * fpxy.r - fxy.r * fpxy.i) / den;
122 p.r += dp.r;
123 p.i += dp.i;
124 if ((fabs(dp.r) + fabs(dp.i)) <= epsilon)
125 break;
126 }
127 if (nn) {
128 rh = boost::math::hypot(p.r, p.i);
129 z = 2. * atan(.5 * rh);
130 sinz = sin(z);
131 cosz = cos(z);
132 lp_lon = par.lam0;
133 if (fabs(rh) <= epsilon) {
134 /* if we end up here input coordinates were (0,0).
135 * pj_inv() adds P->lam0 to lp.lam, this way we are
136 * sure to get the correct offset */
137 lp_lon = 0.0;
138 lp_lat = par.phi0;
139 return;
140 }
141 chi = aasin(cosz * this->m_proj_parm.schio + p.i * sinz * this->m_proj_parm.cchio / rh);
142 phi = chi;
143 for (nn = 20; nn ;--nn) {
144 esphi = par.e * sin(phi);
145 dphi = 2. * atan(tan((half_pi + chi) * .5) *
146 math::pow((T(1) + esphi) / (T(1) - esphi), par.e * T(0.5))) - half_pi - phi;
147 phi += dphi;
148 if (fabs(dphi) <= epsilon)
149 break;
150 }
151 }
152 if (nn) {
153 lp_lat = phi;
154 lp_lon = atan2(p.r * sinz, rh * this->m_proj_parm.cchio * cosz - p.i *
155 this->m_proj_parm.schio * sinz);
156 } else
157 lp_lon = lp_lat = HUGE_VAL;
158 }
159
160 static inline std::string get_name()
161 {
162 return "mod_ster_ellipsoid";
163 }
164
165 };
166
167 template <typename Parameters, typename T>
168 inline void setup(Parameters& par, par_mod_ster<T>& proj_parm) /* general initialization */
169 {
170 static T const half_pi = detail::half_pi<T>();
171
172 T esphi, chio;
173
174 if (par.es != 0.0) {
175 esphi = par.e * sin(par.phi0);
176 chio = 2. * atan(tan((half_pi + par.phi0) * .5) *
177 math::pow((T(1) - esphi) / (T(1) + esphi), par.e * T(0.5))) - half_pi;
178 } else
179 chio = par.phi0;
180 proj_parm.schio = sin(chio);
181 proj_parm.cchio = cos(chio);
182 }
183
184
185 /* Miller Oblated Stereographic */
186 template <typename Parameters, typename T>
187 inline void setup_mil_os(Parameters& par, par_mod_ster<T>& proj_parm)
188 {
189 static const T d2r = geometry::math::d2r<T>();
190
191 static pj_complex<T> AB[] = {
192 {0.924500, 0.},
193 {0., 0.},
194 {0.019430, 0.}
195 };
196
197 proj_parm.n = 2;
198 par.lam0 = d2r * 20.;
199 par.phi0 = d2r * 18.;
200 proj_parm.zcoeff = AB;
201 par.es = 0.;
202
203 setup(par, proj_parm);
204 }
205
206 /* Lee Oblated Stereographic */
207 template <typename Parameters, typename T>
208 inline void setup_lee_os(Parameters& par, par_mod_ster<T>& proj_parm)
209 {
210 static const T d2r = geometry::math::d2r<T>();
211
212 static pj_complex<T> AB[] = {
213 { 0.721316, 0.},
214 { 0., 0.},
215 {-0.0088162, -0.00617325}
216 };
217
218 proj_parm.n = 2;
219 par.lam0 = d2r * -165.;
220 par.phi0 = d2r * -10.;
221 proj_parm.zcoeff = AB;
222 par.es = 0.;
223
224 setup(par, proj_parm);
225 }
226
227 // Mod. Stererographics of 48 U.S.
228 template <typename Parameters, typename T>
229 inline void setup_gs48(Parameters& par, par_mod_ster<T>& proj_parm)
230 {
231 static const T d2r = geometry::math::d2r<T>();
232
233 static pj_complex<T> AB[] = { /* 48 United States */
234 { 0.98879, 0.},
235 { 0., 0.},
236 {-0.050909, 0.},
237 { 0., 0.},
238 { 0.075528, 0.}
239 };
240
241 proj_parm.n = 4;
242 par.lam0 = d2r * -96.;
243 par.phi0 = d2r * -39.;
244 proj_parm.zcoeff = AB;
245 par.es = 0.;
246 par.a = 6370997.;
247
248 setup(par, proj_parm);
249 }
250
251 // Mod. Stererographics of Alaska
252 template <typename Parameters, typename T>
253 inline void setup_alsk(Parameters& par, par_mod_ster<T>& proj_parm)
254 {
255 static const T d2r = geometry::math::d2r<T>();
256
257 static pj_complex<T> ABe[] = { /* Alaska ellipsoid */
258 { .9945303, 0.},
259 { .0052083, -.0027404},
260 { .0072721, .0048181},
261 {-.0151089, -.1932526},
262 { .0642675, -.1381226},
263 { .3582802, -.2884586}
264 };
265
266 static pj_complex<T> ABs[] = { /* Alaska sphere */
267 { .9972523, 0.},
268 { .0052513, -.0041175},
269 { .0074606, .0048125},
270 {-.0153783, -.1968253},
271 { .0636871, -.1408027},
272 { .3660976, -.2937382}
273 };
274
275 proj_parm.n = 5;
276 par.lam0 = d2r * -152.;
277 par.phi0 = d2r * 64.;
278 if (par.es != 0.0) { /* fixed ellipsoid/sphere */
279 proj_parm.zcoeff = ABe;
280 par.a = 6378206.4;
281 par.e = sqrt(par.es = 0.00676866);
282 } else {
283 proj_parm.zcoeff = ABs;
284 par.a = 6370997.;
285 }
286
287 setup(par, proj_parm);
288 }
289
290 // Mod. Stererographics of 50 U.S.
291 template <typename Parameters, typename T>
292 inline void setup_gs50(Parameters& par, par_mod_ster<T>& proj_parm)
293 {
294 static const T d2r = geometry::math::d2r<T>();
295
296 static pj_complex<T> ABe[] = { /* GS50 ellipsoid */
297 { .9827497, 0.},
298 { .0210669, .0053804},
299 {-.1031415, -.0571664},
300 {-.0323337, -.0322847},
301 { .0502303, .1211983},
302 { .0251805, .0895678},
303 {-.0012315, -.1416121},
304 { .0072202, -.1317091},
305 {-.0194029, .0759677},
306 {-.0210072, .0834037}
307 };
308 static pj_complex<T> ABs[] = { /* GS50 sphere */
309 { .9842990, 0.},
310 { .0211642, .0037608},
311 {-.1036018, -.0575102},
312 {-.0329095, -.0320119},
313 { .0499471, .1223335},
314 { .0260460, .0899805},
315 { .0007388, -.1435792},
316 { .0075848, -.1334108},
317 {-.0216473, .0776645},
318 {-.0225161, .0853673}
319 };
320
321 proj_parm.n = 9;
322 par.lam0 = d2r * -120.;
323 par.phi0 = d2r * 45.;
324 if (par.es != 0.0) { /* fixed ellipsoid/sphere */
325 proj_parm.zcoeff = ABe;
326 par.a = 6378206.4;
327 par.e = sqrt(par.es = 0.00676866);
328 } else {
329 proj_parm.zcoeff = ABs;
330 par.a = 6370997.;
331 }
332
333 setup(par, proj_parm);
334 }
335
336 }} // namespace detail::mod_ster
337 #endif // doxygen
338
339 /*!
340 \brief Miller Oblated Stereographic projection
341 \ingroup projections
342 \tparam Geographic latlong point type
343 \tparam Cartesian xy point type
344 \tparam Parameters parameter type
345 \par Projection characteristics
346 - Azimuthal (mod)
347 \par Example
348 \image html ex_mil_os.gif
349 */
350 template <typename T, typename Parameters>
351 struct mil_os_ellipsoid : public detail::mod_ster::base_mod_ster_ellipsoid<T, Parameters>
352 {
353 template <typename Params>
354 inline mil_os_ellipsoid(Params const& , Parameters & par)
355 {
356 detail::mod_ster::setup_mil_os(par, this->m_proj_parm);
357 }
358 };
359
360 /*!
361 \brief Lee Oblated Stereographic projection
362 \ingroup projections
363 \tparam Geographic latlong point type
364 \tparam Cartesian xy point type
365 \tparam Parameters parameter type
366 \par Projection characteristics
367 - Azimuthal (mod)
368 \par Example
369 \image html ex_lee_os.gif
370 */
371 template <typename T, typename Parameters>
372 struct lee_os_ellipsoid : public detail::mod_ster::base_mod_ster_ellipsoid<T, Parameters>
373 {
374 template <typename Params>
375 inline lee_os_ellipsoid(Params const& , Parameters & par)
376 {
377 detail::mod_ster::setup_lee_os(par, this->m_proj_parm);
378 }
379 };
380
381 /*!
382 \brief Mod. Stererographics of 48 U.S. projection
383 \ingroup projections
384 \tparam Geographic latlong point type
385 \tparam Cartesian xy point type
386 \tparam Parameters parameter type
387 \par Projection characteristics
388 - Azimuthal (mod)
389 \par Example
390 \image html ex_gs48.gif
391 */
392 template <typename T, typename Parameters>
393 struct gs48_ellipsoid : public detail::mod_ster::base_mod_ster_ellipsoid<T, Parameters>
394 {
395 template <typename Params>
396 inline gs48_ellipsoid(Params const& , Parameters & par)
397 {
398 detail::mod_ster::setup_gs48(par, this->m_proj_parm);
399 }
400 };
401
402 /*!
403 \brief Mod. Stererographics of Alaska projection
404 \ingroup projections
405 \tparam Geographic latlong point type
406 \tparam Cartesian xy point type
407 \tparam Parameters parameter type
408 \par Projection characteristics
409 - Azimuthal (mod)
410 \par Example
411 \image html ex_alsk.gif
412 */
413 template <typename T, typename Parameters>
414 struct alsk_ellipsoid : public detail::mod_ster::base_mod_ster_ellipsoid<T, Parameters>
415 {
416 template <typename Params>
417 inline alsk_ellipsoid(Params const& , Parameters & par)
418 {
419 detail::mod_ster::setup_alsk(par, this->m_proj_parm);
420 }
421 };
422
423 /*!
424 \brief Mod. Stererographics of 50 U.S. projection
425 \ingroup projections
426 \tparam Geographic latlong point type
427 \tparam Cartesian xy point type
428 \tparam Parameters parameter type
429 \par Projection characteristics
430 - Azimuthal (mod)
431 \par Example
432 \image html ex_gs50.gif
433 */
434 template <typename T, typename Parameters>
435 struct gs50_ellipsoid : public detail::mod_ster::base_mod_ster_ellipsoid<T, Parameters>
436 {
437 template <typename Params>
438 inline gs50_ellipsoid(Params const& , Parameters & par)
439 {
440 detail::mod_ster::setup_gs50(par, this->m_proj_parm);
441 }
442 };
443
444 #ifndef DOXYGEN_NO_DETAIL
445 namespace detail
446 {
447
448 // Static projection
449 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_mil_os, mil_os_ellipsoid)
450 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_lee_os, lee_os_ellipsoid)
451 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gs48, gs48_ellipsoid)
452 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_alsk, alsk_ellipsoid)
453 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gs50, gs50_ellipsoid)
454
455 // Factory entry(s)
456 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mil_os_entry, mil_os_ellipsoid)
457 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(lee_os_entry, lee_os_ellipsoid)
458 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gs48_entry, gs48_ellipsoid)
459 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(alsk_entry, alsk_ellipsoid)
460 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gs50_entry, gs50_ellipsoid)
461
462 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(mod_ster_init)
463 {
464 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mil_os, mil_os_entry)
465 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lee_os, lee_os_entry)
466 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gs48, gs48_entry)
467 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(alsk, alsk_entry)
468 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gs50, gs50_entry)
469 }
470
471 } // namespace detail
472 #endif // doxygen
473
474 } // namespace projections
475
476 }} // namespace boost::geometry
477
478 #endif // BOOST_GEOMETRY_PROJECTIONS_MOD_STER_HPP
479