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_GOODE_HPP
41 #define BOOST_GEOMETRY_PROJECTIONS_GOODE_HPP
42 
43 #include <boost/geometry/srs/projections/impl/base_static.hpp>
44 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
45 #include <boost/geometry/srs/projections/impl/projects.hpp>
46 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
47 #include <boost/geometry/srs/projections/proj/gn_sinu.hpp>
48 #include <boost/geometry/srs/projections/proj/moll.hpp>
49 
50 namespace boost { namespace geometry
51 {
52 
53 namespace projections
54 {
55     #ifndef DOXYGEN_NO_DETAIL
56     namespace detail { namespace goode
57     {
58 
59             static const double Y_COR = 0.05280;
60             static const double PHI_LIM = .71093078197902358062;
61 
62             // TODO: It would be possible to further decrease the size of par_goode
63             // because spherical sinu and moll has constant parameters.
64 
65             template <typename T, typename Par>
66             struct par_goode
67             {
68                 sinu_spheroid<T, Par>    sinu;
69                 moll_spheroid<T, Par>    moll;
70 
71                 // NOTE: It is ok to share parameters between projections because
72                 // the only member that is modified in the constructors of
73                 // spherical sinu and moll projections is es = 0 which is set
74                 // below in setup_goode() anyway.
75                 // Moreover in these projections parameters are not used
76                 // in fwd() nor inv().
77 
78                 template <typename Params>
par_goodeboost::geometry::projections::detail::goode::par_goode79                 par_goode(Params const& params, Par & par)
80                     : sinu(params, par)
81                     , moll(params, par)
82                 {}
83             };
84 
85             template <typename T, typename Par>
s_forward(T const & lp_lon,T const & lp_lat,T & xy_x,T & xy_y,Par const & par,par_goode<T,Par> const & proj_par)86             inline void s_forward(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y,
87                                   Par const& par, par_goode<T, Par> const& proj_par)
88             {
89                 if (fabs(lp_lat) <= PHI_LIM)
90                     proj_par.sinu.fwd(par, lp_lon, lp_lat, xy_x, xy_y);
91                 else {
92                     proj_par.moll.fwd(par, lp_lon, lp_lat, xy_x, xy_y);
93                     xy_y -= lp_lat >= 0.0 ? Y_COR : -Y_COR;
94                 }
95             }
96 
97             template <typename T, typename Par>
s_inverse(T const & xy_x,T xy_y,T & lp_lon,T & lp_lat,Par const & par,par_goode<T,Par> const & proj_par)98             inline void s_inverse(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat,
99                                   Par const& par, par_goode<T, Par> const& proj_par)
100             {
101                 if (fabs(xy_y) <= PHI_LIM)
102                     proj_par.sinu.inv(par, xy_x, xy_y, lp_lon, lp_lat);
103                 else {
104                     xy_y += xy_y >= 0.0 ? Y_COR : -Y_COR;
105                     proj_par.moll.inv(par, xy_x, xy_y, lp_lon, lp_lat);
106                 }
107             }
108 
109             // Goode Homolosine
110             template <typename Par>
setup_goode(Par & par)111             inline Par& setup_goode(Par& par)
112             {
113                 par.es = 0.;
114 
115                 // NOTE: The following explicit initialization of sinu projection
116                 // is not needed because setup_goode() is called before proj_par.sinu
117                 // is constructed and m_par of parent projection is used.
118 
119                 //proj_par.sinu.m_par.es = 0.;
120                 //detail::gn_sinu::setup_sinu(proj_par.sinu.m_par, proj_par.sinu.m_proj_parm);
121 
122                 return par;
123             }
124 
125     }} // namespace detail::goode
126     #endif // doxygen
127 
128     /*!
129         \brief Goode Homolosine projection
130         \ingroup projections
131         \tparam Geographic latlong point type
132         \tparam Cartesian xy point type
133         \tparam Parameters parameter type
134         \par Projection characteristics
135          - Pseudocylindrical
136          - Spheroid
137         \par Example
138         \image html ex_goode.gif
139     */
140     template <typename T, typename Parameters>
141     struct goode_spheroid
142     {
143         detail::goode::par_goode<T, Parameters> m_proj_parm;
144 
145         template <typename Params>
goode_spheroidboost::geometry::projections::goode_spheroid146         inline goode_spheroid(Params const& params, Parameters & par)
147             : m_proj_parm(params, detail::goode::setup_goode(par))
148         {}
149 
150         // FORWARD(s_forward)  spheroid
151         // Project coordinates from geographic (lon, lat) to cartesian (x, y)
fwdboost::geometry::projections::goode_spheroid152         inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
153         {
154             detail::goode::s_forward(lp_lon, lp_lat, xy_x, xy_y, par, this->m_proj_parm);
155         }
156 
157         // INVERSE(s_inverse)  spheroid
158         // Project coordinates from cartesian (x, y) to geographic (lon, lat)
invboost::geometry::projections::goode_spheroid159         inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
160         {
161             detail::goode::s_inverse(xy_x, xy_y, lp_lon, lp_lat, par, this->m_proj_parm);
162         }
163 
get_nameboost::geometry::projections::goode_spheroid164         static inline std::string get_name()
165         {
166             return "goode_spheroid";
167         }
168     };
169 
170     #ifndef DOXYGEN_NO_DETAIL
171     namespace detail
172     {
173 
174         // Static projection
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_goode,goode_spheroid)175         BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_goode, goode_spheroid)
176 
177         // Factory entry(s)
178         BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(goode_entry, goode_spheroid)
179 
180         BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(goode_init)
181         {
182             BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(goode, goode_entry);
183         }
184 
185     } // namespace detail
186     #endif // doxygen
187 
188 } // namespace projections
189 
190 }} // namespace boost::geometry
191 
192 #endif // BOOST_GEOMETRY_PROJECTIONS_GOODE_HPP
193 
194