]>
Commit | Line | Data |
---|---|---|
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 | 18 | // Last updated version of proj: 5.0.0 |
11fdf7f2 TL |
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 | ||
92f5a8d4 TL |
40 | #ifndef BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP |
41 | #define BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP | |
11fdf7f2 | 42 | |
92f5a8d4 | 43 | #include <boost/geometry/srs/projections/impl/aasincos.hpp> |
11fdf7f2 TL |
44 | #include <boost/geometry/srs/projections/impl/base_static.hpp> |
45 | #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> | |
11fdf7f2 | 46 | #include <boost/geometry/srs/projections/impl/factory_entry.hpp> |
11fdf7f2 | 47 | #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp> |
92f5a8d4 TL |
48 | #include <boost/geometry/srs/projections/impl/pj_param.hpp> |
49 | #include <boost/geometry/srs/projections/impl/projects.hpp> | |
11fdf7f2 | 50 | |
92f5a8d4 | 51 | #include <boost/geometry/util/math.hpp> |
11fdf7f2 | 52 | |
92f5a8d4 | 53 | namespace boost { namespace geometry |
11fdf7f2 | 54 | { |
11fdf7f2 TL |
55 | |
56 | namespace projections | |
57 | { | |
58 | #ifndef DOXYGEN_NO_DETAIL | |
59 | namespace detail { namespace gn_sinu | |
60 | { | |
61 | ||
92f5a8d4 TL |
62 | static const double epsilon10 = 1e-10; |
63 | static const int max_iter = 8; | |
64 | static const double loop_tol = 1e-7; | |
11fdf7f2 TL |
65 | |
66 | template <typename T> | |
92f5a8d4 | 67 | struct par_gn_sinu_e |
11fdf7f2 | 68 | { |
92f5a8d4 | 69 | detail::en<T> en; |
11fdf7f2 TL |
70 | }; |
71 | ||
92f5a8d4 TL |
72 | template <typename T> |
73 | struct par_gn_sinu_s | |
11fdf7f2 | 74 | { |
92f5a8d4 TL |
75 | T m, n, C_x, C_y; |
76 | }; | |
11fdf7f2 | 77 | |
92f5a8d4 | 78 | /* Ellipsoidal Sinusoidal only */ |
11fdf7f2 | 79 | |
92f5a8d4 TL |
80 | template <typename T, typename Parameters> |
81 | struct base_gn_sinu_ellipsoid | |
82 | { | |
83 | par_gn_sinu_e<T> m_proj_parm; | |
11fdf7f2 TL |
84 | |
85 | // FORWARD(e_forward) ellipsoid | |
86 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 87 | inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 88 | { |
92f5a8d4 | 89 | T s, c; |
11fdf7f2 TL |
90 | |
91 | xy_y = pj_mlfn(lp_lat, s = sin(lp_lat), c = cos(lp_lat), this->m_proj_parm.en); | |
92f5a8d4 | 92 | xy_x = lp_lon * c / sqrt(1. - par.es * s * s); |
11fdf7f2 TL |
93 | } |
94 | ||
95 | // INVERSE(e_inverse) ellipsoid | |
96 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 97 | inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 98 | { |
92f5a8d4 | 99 | static const T half_pi = detail::half_pi<T>(); |
11fdf7f2 | 100 | |
92f5a8d4 | 101 | T s; |
11fdf7f2 | 102 | |
92f5a8d4 | 103 | if ((s = fabs(lp_lat = pj_inv_mlfn(xy_y, par.es, this->m_proj_parm.en))) < half_pi) { |
11fdf7f2 | 104 | s = sin(lp_lat); |
92f5a8d4 TL |
105 | lp_lon = xy_x * sqrt(1. - par.es * s * s) / cos(lp_lat); |
106 | } else if ((s - epsilon10) < half_pi) | |
11fdf7f2 TL |
107 | lp_lon = 0.; |
108 | else | |
92f5a8d4 | 109 | BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); |
11fdf7f2 TL |
110 | } |
111 | /* General spherical sinusoidals */ | |
112 | ||
113 | static inline std::string get_name() | |
114 | { | |
115 | return "gn_sinu_ellipsoid"; | |
116 | } | |
117 | ||
118 | }; | |
119 | ||
92f5a8d4 TL |
120 | template <typename T, typename Parameters> |
121 | struct base_gn_sinu_spheroid | |
11fdf7f2 | 122 | { |
92f5a8d4 | 123 | par_gn_sinu_s<T> m_proj_parm; |
11fdf7f2 TL |
124 | |
125 | // FORWARD(s_forward) sphere | |
126 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 127 | inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 128 | { |
92f5a8d4 | 129 | if (this->m_proj_parm.m == 0.0) |
11fdf7f2 TL |
130 | lp_lat = this->m_proj_parm.n != 1. ? aasin(this->m_proj_parm.n * sin(lp_lat)): lp_lat; |
131 | else { | |
92f5a8d4 | 132 | T k, V; |
11fdf7f2 TL |
133 | int i; |
134 | ||
135 | k = this->m_proj_parm.n * sin(lp_lat); | |
92f5a8d4 | 136 | for (i = max_iter; i ; --i) { |
11fdf7f2 TL |
137 | lp_lat -= V = (this->m_proj_parm.m * lp_lat + sin(lp_lat) - k) / |
138 | (this->m_proj_parm.m + cos(lp_lat)); | |
92f5a8d4 | 139 | if (fabs(V) < loop_tol) |
11fdf7f2 TL |
140 | break; |
141 | } | |
92f5a8d4 TL |
142 | if (!i) { |
143 | BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); | |
144 | } | |
11fdf7f2 TL |
145 | } |
146 | xy_x = this->m_proj_parm.C_x * lp_lon * (this->m_proj_parm.m + cos(lp_lat)); | |
147 | xy_y = this->m_proj_parm.C_y * lp_lat; | |
148 | } | |
149 | ||
150 | // INVERSE(s_inverse) sphere | |
151 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 152 | inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 TL |
153 | { |
154 | xy_y /= this->m_proj_parm.C_y; | |
92f5a8d4 | 155 | lp_lat = (this->m_proj_parm.m != 0.0) ? aasin((this->m_proj_parm.m * xy_y + sin(xy_y)) / this->m_proj_parm.n) : |
11fdf7f2 TL |
156 | ( this->m_proj_parm.n != 1. ? aasin(sin(xy_y) / this->m_proj_parm.n) : xy_y ); |
157 | lp_lon = xy_x / (this->m_proj_parm.C_x * (this->m_proj_parm.m + cos(xy_y))); | |
158 | } | |
159 | ||
160 | static inline std::string get_name() | |
161 | { | |
162 | return "gn_sinu_spheroid"; | |
163 | } | |
164 | ||
165 | }; | |
166 | ||
167 | template <typename Parameters, typename T> | |
92f5a8d4 | 168 | inline void setup(Parameters& par, par_gn_sinu_s<T>& proj_parm) |
11fdf7f2 TL |
169 | { |
170 | par.es = 0; | |
92f5a8d4 | 171 | |
11fdf7f2 TL |
172 | proj_parm.C_x = (proj_parm.C_y = sqrt((proj_parm.m + 1.) / proj_parm.n))/(proj_parm.m + 1.); |
173 | } | |
174 | ||
175 | ||
176 | // General Sinusoidal Series | |
92f5a8d4 TL |
177 | template <typename Params, typename Parameters, typename T> |
178 | inline void setup_gn_sinu(Params const& params, Parameters& par, par_gn_sinu_s<T>& proj_parm) | |
11fdf7f2 | 179 | { |
92f5a8d4 TL |
180 | if (pj_param_f<srs::spar::n>(params, "n", srs::dpar::n, proj_parm.n) |
181 | && pj_param_f<srs::spar::m>(params, "m", srs::dpar::m, proj_parm.m)) { | |
182 | if (proj_parm.n <= 0 || proj_parm.m < 0) | |
183 | BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) ); | |
11fdf7f2 | 184 | } else |
92f5a8d4 TL |
185 | BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) ); |
186 | ||
11fdf7f2 TL |
187 | setup(par, proj_parm); |
188 | } | |
189 | ||
190 | // Sinusoidal (Sanson-Flamsteed) | |
191 | template <typename Parameters, typename T> | |
92f5a8d4 | 192 | inline void setup_sinu(Parameters const& par, par_gn_sinu_e<T>& proj_parm) |
11fdf7f2 | 193 | { |
92f5a8d4 TL |
194 | proj_parm.en = pj_enfn<T>(par.es); |
195 | } | |
196 | ||
197 | // Sinusoidal (Sanson-Flamsteed) | |
198 | template <typename Parameters, typename T> | |
199 | inline void setup_sinu(Parameters& par, par_gn_sinu_s<T>& proj_parm) | |
200 | { | |
201 | proj_parm.n = 1.; | |
202 | proj_parm.m = 0.; | |
203 | setup(par, proj_parm); | |
11fdf7f2 TL |
204 | } |
205 | ||
206 | // Eckert VI | |
207 | template <typename Parameters, typename T> | |
92f5a8d4 | 208 | inline void setup_eck6(Parameters& par, par_gn_sinu_s<T>& proj_parm) |
11fdf7f2 TL |
209 | { |
210 | proj_parm.m = 1.; | |
211 | proj_parm.n = 2.570796326794896619231321691; | |
212 | setup(par, proj_parm); | |
213 | } | |
214 | ||
215 | // McBryde-Thomas Flat-Polar Sinusoidal | |
216 | template <typename Parameters, typename T> | |
92f5a8d4 | 217 | inline void setup_mbtfps(Parameters& par, par_gn_sinu_s<T>& proj_parm) |
11fdf7f2 TL |
218 | { |
219 | proj_parm.m = 0.5; | |
220 | proj_parm.n = 1.785398163397448309615660845; | |
221 | setup(par, proj_parm); | |
222 | } | |
223 | ||
224 | }} // namespace detail::gn_sinu | |
225 | #endif // doxygen | |
226 | ||
227 | /*! | |
228 | \brief General Sinusoidal Series projection | |
229 | \ingroup projections | |
230 | \tparam Geographic latlong point type | |
231 | \tparam Cartesian xy point type | |
232 | \tparam Parameters parameter type | |
233 | \par Projection characteristics | |
234 | - Pseudocylindrical | |
235 | - Spheroid | |
236 | \par Projection parameters | |
237 | - m (real) | |
238 | - n (real) | |
239 | \par Example | |
240 | \image html ex_gn_sinu.gif | |
241 | */ | |
92f5a8d4 TL |
242 | template <typename T, typename Parameters> |
243 | struct gn_sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters> | |
11fdf7f2 | 244 | { |
92f5a8d4 TL |
245 | template <typename Params> |
246 | inline gn_sinu_spheroid(Params const& params, Parameters & par) | |
11fdf7f2 | 247 | { |
92f5a8d4 | 248 | detail::gn_sinu::setup_gn_sinu(params, par, this->m_proj_parm); |
11fdf7f2 TL |
249 | } |
250 | }; | |
251 | ||
252 | /*! | |
253 | \brief Sinusoidal (Sanson-Flamsteed) projection | |
254 | \ingroup projections | |
255 | \tparam Geographic latlong point type | |
256 | \tparam Cartesian xy point type | |
257 | \tparam Parameters parameter type | |
258 | \par Projection characteristics | |
259 | - Pseudocylindrical | |
260 | - Spheroid | |
261 | - Ellipsoid | |
262 | \par Example | |
263 | \image html ex_sinu.gif | |
264 | */ | |
92f5a8d4 TL |
265 | template <typename T, typename Parameters> |
266 | struct sinu_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid<T, Parameters> | |
11fdf7f2 | 267 | { |
92f5a8d4 TL |
268 | template <typename Params> |
269 | inline sinu_ellipsoid(Params const& , Parameters & par) | |
11fdf7f2 | 270 | { |
92f5a8d4 | 271 | detail::gn_sinu::setup_sinu(par, this->m_proj_parm); |
11fdf7f2 TL |
272 | } |
273 | }; | |
274 | ||
275 | /*! | |
276 | \brief Sinusoidal (Sanson-Flamsteed) projection | |
277 | \ingroup projections | |
278 | \tparam Geographic latlong point type | |
279 | \tparam Cartesian xy point type | |
280 | \tparam Parameters parameter type | |
281 | \par Projection characteristics | |
282 | - Pseudocylindrical | |
283 | - Spheroid | |
284 | - Ellipsoid | |
285 | \par Example | |
286 | \image html ex_sinu.gif | |
287 | */ | |
92f5a8d4 TL |
288 | template <typename T, typename Parameters> |
289 | struct sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters> | |
11fdf7f2 | 290 | { |
92f5a8d4 TL |
291 | template <typename Params> |
292 | inline sinu_spheroid(Params const& , Parameters & par) | |
11fdf7f2 | 293 | { |
92f5a8d4 | 294 | detail::gn_sinu::setup_sinu(par, this->m_proj_parm); |
11fdf7f2 TL |
295 | } |
296 | }; | |
297 | ||
298 | /*! | |
299 | \brief Eckert VI projection | |
300 | \ingroup projections | |
301 | \tparam Geographic latlong point type | |
302 | \tparam Cartesian xy point type | |
303 | \tparam Parameters parameter type | |
304 | \par Projection characteristics | |
305 | - Pseudocylindrical | |
306 | - Spheroid | |
307 | \par Example | |
308 | \image html ex_eck6.gif | |
309 | */ | |
92f5a8d4 TL |
310 | template <typename T, typename Parameters> |
311 | struct eck6_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters> | |
11fdf7f2 | 312 | { |
92f5a8d4 TL |
313 | template <typename Params> |
314 | inline eck6_spheroid(Params const& , Parameters & par) | |
11fdf7f2 | 315 | { |
92f5a8d4 | 316 | detail::gn_sinu::setup_eck6(par, this->m_proj_parm); |
11fdf7f2 TL |
317 | } |
318 | }; | |
319 | ||
320 | /*! | |
321 | \brief McBryde-Thomas Flat-Polar Sinusoidal projection | |
322 | \ingroup projections | |
323 | \tparam Geographic latlong point type | |
324 | \tparam Cartesian xy point type | |
325 | \tparam Parameters parameter type | |
326 | \par Projection characteristics | |
327 | - Pseudocylindrical | |
328 | - Spheroid | |
329 | \par Example | |
330 | \image html ex_mbtfps.gif | |
331 | */ | |
92f5a8d4 TL |
332 | template <typename T, typename Parameters> |
333 | struct mbtfps_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters> | |
11fdf7f2 | 334 | { |
92f5a8d4 TL |
335 | template <typename Params> |
336 | inline mbtfps_spheroid(Params const& , Parameters & par) | |
11fdf7f2 | 337 | { |
92f5a8d4 | 338 | detail::gn_sinu::setup_mbtfps(par, this->m_proj_parm); |
11fdf7f2 TL |
339 | } |
340 | }; | |
341 | ||
342 | #ifndef DOXYGEN_NO_DETAIL | |
343 | namespace detail | |
344 | { | |
345 | ||
346 | // Static projection | |
92f5a8d4 TL |
347 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gn_sinu, gn_sinu_spheroid) |
348 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_sinu, sinu_spheroid, sinu_ellipsoid) | |
349 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck6, eck6_spheroid) | |
350 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_mbtfps, mbtfps_spheroid) | |
11fdf7f2 TL |
351 | |
352 | // Factory entry(s) | |
92f5a8d4 TL |
353 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gn_sinu_entry, gn_sinu_spheroid) |
354 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(sinu_entry, sinu_spheroid, sinu_ellipsoid) | |
355 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck6_entry, eck6_spheroid) | |
356 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbtfps_entry, mbtfps_spheroid) | |
357 | ||
358 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gn_sinu_init) | |
11fdf7f2 | 359 | { |
92f5a8d4 TL |
360 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gn_sinu, gn_sinu_entry); |
361 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(sinu, sinu_entry); | |
362 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck6, eck6_entry); | |
363 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mbtfps, mbtfps_entry); | |
11fdf7f2 TL |
364 | } |
365 | ||
366 | } // namespace detail | |
367 | #endif // doxygen | |
368 | ||
369 | } // namespace projections | |
370 | ||
371 | }} // namespace boost::geometry | |
372 | ||
373 | #endif // BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP | |
374 |