1 // Boost.Geometry - gis-projections (based on PROJ4)
3 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
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.
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)
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
18 // Last updated version of proj: 5.0.0
20 // Original copyright notice:
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:
29 // The above copyright notice and this permission notice shall be included
30 // in all copies or substantial portions of the Software.
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.
40 #ifndef BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP
41 #define BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP
43 #include <boost/geometry/srs/projections/impl/aasincos.hpp>
44 #include <boost/geometry/srs/projections/impl/base_static.hpp>
45 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
46 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
47 #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
48 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
49 #include <boost/geometry/srs/projections/impl/projects.hpp>
51 #include <boost/geometry/util/math.hpp>
53 namespace boost { namespace geometry
58 #ifndef DOXYGEN_NO_DETAIL
59 namespace detail { namespace gn_sinu
62 static const double epsilon10 = 1e-10;
63 static const int max_iter = 8;
64 static const double loop_tol = 1e-7;
78 /* Ellipsoidal Sinusoidal only */
80 template <typename T, typename Parameters>
81 struct base_gn_sinu_ellipsoid
83 par_gn_sinu_e<T> m_proj_parm;
85 // FORWARD(e_forward) ellipsoid
86 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
87 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
91 xy_y = pj_mlfn(lp_lat, s = sin(lp_lat), c = cos(lp_lat), this->m_proj_parm.en);
92 xy_x = lp_lon * c / sqrt(1. - par.es * s * s);
95 // INVERSE(e_inverse) ellipsoid
96 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
97 inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
99 static const T half_pi = detail::half_pi<T>();
103 if ((s = fabs(lp_lat = pj_inv_mlfn(xy_y, par.es, this->m_proj_parm.en))) < half_pi) {
105 lp_lon = xy_x * sqrt(1. - par.es * s * s) / cos(lp_lat);
106 } else if ((s - epsilon10) < half_pi)
109 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
111 /* General spherical sinusoidals */
113 static inline std::string get_name()
115 return "gn_sinu_ellipsoid";
120 template <typename T, typename Parameters>
121 struct base_gn_sinu_spheroid
123 par_gn_sinu_s<T> m_proj_parm;
125 // FORWARD(s_forward) sphere
126 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
127 inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const
129 if (this->m_proj_parm.m == 0.0)
130 lp_lat = this->m_proj_parm.n != 1. ? aasin(this->m_proj_parm.n * sin(lp_lat)): lp_lat;
135 k = this->m_proj_parm.n * sin(lp_lat);
136 for (i = max_iter; i ; --i) {
137 lp_lat -= V = (this->m_proj_parm.m * lp_lat + sin(lp_lat) - k) /
138 (this->m_proj_parm.m + cos(lp_lat));
139 if (fabs(V) < loop_tol)
143 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
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;
150 // INVERSE(s_inverse) sphere
151 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
152 inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const
154 xy_y /= this->m_proj_parm.C_y;
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) :
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)));
160 static inline std::string get_name()
162 return "gn_sinu_spheroid";
167 template <typename Parameters, typename T>
168 inline void setup(Parameters& par, par_gn_sinu_s<T>& proj_parm)
172 proj_parm.C_x = (proj_parm.C_y = sqrt((proj_parm.m + 1.) / proj_parm.n))/(proj_parm.m + 1.);
176 // General Sinusoidal Series
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)
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) );
185 BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) );
187 setup(par, proj_parm);
190 // Sinusoidal (Sanson-Flamsteed)
191 template <typename Parameters, typename T>
192 inline void setup_sinu(Parameters const& par, par_gn_sinu_e<T>& proj_parm)
194 proj_parm.en = pj_enfn<T>(par.es);
197 // Sinusoidal (Sanson-Flamsteed)
198 template <typename Parameters, typename T>
199 inline void setup_sinu(Parameters& par, par_gn_sinu_s<T>& proj_parm)
203 setup(par, proj_parm);
207 template <typename Parameters, typename T>
208 inline void setup_eck6(Parameters& par, par_gn_sinu_s<T>& proj_parm)
211 proj_parm.n = 2.570796326794896619231321691;
212 setup(par, proj_parm);
215 // McBryde-Thomas Flat-Polar Sinusoidal
216 template <typename Parameters, typename T>
217 inline void setup_mbtfps(Parameters& par, par_gn_sinu_s<T>& proj_parm)
220 proj_parm.n = 1.785398163397448309615660845;
221 setup(par, proj_parm);
224 }} // namespace detail::gn_sinu
228 \brief General Sinusoidal Series projection
230 \tparam Geographic latlong point type
231 \tparam Cartesian xy point type
232 \tparam Parameters parameter type
233 \par Projection characteristics
236 \par Projection parameters
240 \image html ex_gn_sinu.gif
242 template <typename T, typename Parameters>
243 struct gn_sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters>
245 template <typename Params>
246 inline gn_sinu_spheroid(Params const& params, Parameters & par)
248 detail::gn_sinu::setup_gn_sinu(params, par, this->m_proj_parm);
253 \brief Sinusoidal (Sanson-Flamsteed) projection
255 \tparam Geographic latlong point type
256 \tparam Cartesian xy point type
257 \tparam Parameters parameter type
258 \par Projection characteristics
263 \image html ex_sinu.gif
265 template <typename T, typename Parameters>
266 struct sinu_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid<T, Parameters>
268 template <typename Params>
269 inline sinu_ellipsoid(Params const& , Parameters & par)
271 detail::gn_sinu::setup_sinu(par, this->m_proj_parm);
276 \brief Sinusoidal (Sanson-Flamsteed) projection
278 \tparam Geographic latlong point type
279 \tparam Cartesian xy point type
280 \tparam Parameters parameter type
281 \par Projection characteristics
286 \image html ex_sinu.gif
288 template <typename T, typename Parameters>
289 struct sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters>
291 template <typename Params>
292 inline sinu_spheroid(Params const& , Parameters & par)
294 detail::gn_sinu::setup_sinu(par, this->m_proj_parm);
299 \brief Eckert VI projection
301 \tparam Geographic latlong point type
302 \tparam Cartesian xy point type
303 \tparam Parameters parameter type
304 \par Projection characteristics
308 \image html ex_eck6.gif
310 template <typename T, typename Parameters>
311 struct eck6_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters>
313 template <typename Params>
314 inline eck6_spheroid(Params const& , Parameters & par)
316 detail::gn_sinu::setup_eck6(par, this->m_proj_parm);
321 \brief McBryde-Thomas Flat-Polar Sinusoidal projection
323 \tparam Geographic latlong point type
324 \tparam Cartesian xy point type
325 \tparam Parameters parameter type
326 \par Projection characteristics
330 \image html ex_mbtfps.gif
332 template <typename T, typename Parameters>
333 struct mbtfps_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid<T, Parameters>
335 template <typename Params>
336 inline mbtfps_spheroid(Params const& , Parameters & par)
338 detail::gn_sinu::setup_mbtfps(par, this->m_proj_parm);
342 #ifndef DOXYGEN_NO_DETAIL
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)
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)
358 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gn_sinu_init)
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);
366 } // namespace detail
369 } // namespace projections
371 }} // namespace boost::geometry
373 #endif // BOOST_GEOMETRY_PROJECTIONS_GN_SINU_HPP