1 #ifndef BOOST_GEOMETRY_PROJECTIONS_IGH_HPP
2 #define BOOST_GEOMETRY_PROJECTIONS_IGH_HPP
4 // Boost.Geometry - extensions-gis-projections (based on PROJ4)
5 // This file is automatically generated. DO NOT EDIT.
7 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
9 // This file was modified by Oracle on 2017.
10 // Modifications copyright (c) 2017, Oracle and/or its affiliates.
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
13 // Use, modification and distribution is subject to the Boost Software License,
14 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
17 // This file is converted from PROJ4, http://trac.osgeo.org/proj
18 // PROJ4 is originally written by Gerald Evenden (then of the USGS)
19 // PROJ4 is maintained by Frank Warmerdam
20 // PROJ4 is converted to Boost.Geometry by Barend Gehrels
22 // Last updated version of proj: 4.9.1
24 // Original copyright notice:
26 // Permission is hereby granted, free of charge, to any person obtaining a
27 // copy of this software and associated documentation files (the "Software"),
28 // to deal in the Software without restriction, including without limitation
29 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
30 // and/or sell copies of the Software, and to permit persons to whom the
31 // Software is furnished to do so, subject to the following conditions:
33 // The above copyright notice and this permission notice shall be included
34 // in all copies or substantial portions of the Software.
36 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
37 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
41 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
42 // DEALINGS IN THE SOFTWARE.
44 #include <boost/geometry/util/math.hpp>
45 #include <boost/shared_ptr.hpp>
47 #include <boost/geometry/srs/projections/impl/base_static.hpp>
48 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
49 #include <boost/geometry/srs/projections/impl/projects.hpp>
50 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
51 #include <boost/geometry/srs/projections/proj/gn_sinu.hpp>
52 #include <boost/geometry/srs/projections/proj/moll.hpp>
54 namespace boost { namespace geometry
57 namespace srs { namespace par4
61 }} //namespace srs::par4
65 #ifndef DOXYGEN_NO_DETAIL
66 namespace detail { namespace igh
69 template <typename CalculationType, typename Parameters>
72 boost::shared_ptr<base_v<CalculationType, Parameters> > pj[12];
77 inline T d4044118() { return (T(40) + T(44)/T(60.) + T(11.8)/T(3600.)) * geometry::math::d2r<T>(); } // 40d 44' 11.8" [degrees]
80 inline T d10() { return T(10) * geometry::math::d2r<T>(); }
82 inline T d20() { return T(20) * geometry::math::d2r<T>(); }
84 inline T d30() { return T(30) * geometry::math::d2r<T>(); }
86 inline T d40() { return T(40) * geometry::math::d2r<T>(); }
88 inline T d50() { return T(50) * geometry::math::d2r<T>(); }
90 inline T d60() { return T(60) * geometry::math::d2r<T>(); }
92 inline T d80() { return T(80) * geometry::math::d2r<T>(); }
94 inline T d90() { return T(90) * geometry::math::d2r<T>(); }
96 inline T d100() { return T(100) * geometry::math::d2r<T>(); }
98 inline T d140() { return T(140) * geometry::math::d2r<T>(); }
100 inline T d160() { return T(160) * geometry::math::d2r<T>(); }
101 template <typename T>
102 inline T d180() { return T(180) * geometry::math::d2r<T>(); }
104 static const double EPSLN = 1.e-10; // allow a little 'slack' on zone edge positions
106 // Converted from #define SETUP(n, proj, x_0, y_0, lon_0)
107 template <template <typename, typename> class Entry, typename Parameters, typename CalculationType>
108 inline void do_setup(int n, Parameters const& par, par_igh<CalculationType, Parameters>& proj_parm,
109 CalculationType const& x_0, CalculationType const& y_0,
110 CalculationType const& lon_0)
112 Entry<CalculationType, Parameters> entry;
113 proj_parm.pj[n-1].reset(entry.create_new(par));
114 proj_parm.pj[n-1]->mutable_params().x0 = x_0;
115 proj_parm.pj[n-1]->mutable_params().y0 = y_0;
116 proj_parm.pj[n-1]->mutable_params().lam0 = lon_0;
119 // template class, using CRTP to implement forward/inverse
120 template <typename CalculationType, typename Parameters>
121 struct base_igh_spheroid : public base_t_fi<base_igh_spheroid<CalculationType, Parameters>,
122 CalculationType, Parameters>
125 typedef CalculationType geographic_type;
126 typedef CalculationType cartesian_type;
128 par_igh<CalculationType, Parameters> m_proj_parm;
130 inline base_igh_spheroid(const Parameters& par)
131 : base_t_fi<base_igh_spheroid<CalculationType, Parameters>,
132 CalculationType, Parameters>(*this, par) {}
134 // FORWARD(s_forward) spheroid
135 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
136 inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
138 static const CalculationType d4044118 = igh::d4044118<CalculationType>();
139 static const CalculationType d20 = igh::d20<CalculationType>();
140 static const CalculationType d40 = igh::d40<CalculationType>();
141 static const CalculationType d80 = igh::d80<CalculationType>();
142 static const CalculationType d100 = igh::d100<CalculationType>();
145 if (lp_lat >= d4044118) { // 1|2
146 z = (lp_lon <= -d40 ? 1: 2);
148 else if (lp_lat >= 0) { // 3|4
149 z = (lp_lon <= -d40 ? 3: 4);
151 else if (lp_lat >= -d4044118) { // 5|6|7|8
152 if (lp_lon <= -d100) z = 5; // 5
153 else if (lp_lon <= -d20) z = 6; // 6
154 else if (lp_lon <= d80) z = 7; // 7
158 if (lp_lon <= -d100) z = 9; // 9
159 else if (lp_lon <= -d20) z = 10; // 10
160 else if (lp_lon <= d80) z = 11; // 11
164 lp_lon -= this->m_proj_parm.pj[z-1]->params().lam0;
165 this->m_proj_parm.pj[z-1]->fwd(lp_lon, lp_lat, xy_x, xy_y);
166 xy_x += this->m_proj_parm.pj[z-1]->params().x0;
167 xy_y += this->m_proj_parm.pj[z-1]->params().y0;
170 // INVERSE(s_inverse) spheroid
171 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
172 inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
174 static const CalculationType d4044118 = igh::d4044118<CalculationType>();
175 static const CalculationType d10 = igh::d10<CalculationType>();
176 static const CalculationType d20 = igh::d20<CalculationType>();
177 static const CalculationType d40 = igh::d40<CalculationType>();
178 static const CalculationType d50 = igh::d50<CalculationType>();
179 static const CalculationType d60 = igh::d60<CalculationType>();
180 static const CalculationType d80 = igh::d80<CalculationType>();
181 static const CalculationType d90 = igh::d90<CalculationType>();
182 static const CalculationType d100 = igh::d100<CalculationType>();
183 static const CalculationType d160 = igh::d160<CalculationType>();
184 static const CalculationType d180 = igh::d180<CalculationType>();
186 static const CalculationType c2 = 2.0;
188 const CalculationType y90 = this->m_proj_parm.dy0 + sqrt(c2); // lt=90 corresponds to y=y0+sqrt(2.0)
191 if (xy_y > y90+EPSLN || xy_y < -y90+EPSLN) // 0
193 else if (xy_y >= d4044118) // 1|2
194 z = (xy_x <= -d40? 1: 2);
195 else if (xy_y >= 0) // 3|4
196 z = (xy_x <= -d40? 3: 4);
197 else if (xy_y >= -d4044118) { // 5|6|7|8
198 if (xy_x <= -d100) z = 5; // 5
199 else if (xy_x <= -d20) z = 6; // 6
200 else if (xy_x <= d80) z = 7; // 7
204 if (xy_x <= -d100) z = 9; // 9
205 else if (xy_x <= -d20) z = 10; // 10
206 else if (xy_x <= d80) z = 11; // 11
214 xy_x -= this->m_proj_parm.pj[z-1]->params().x0;
215 xy_y -= this->m_proj_parm.pj[z-1]->params().y0;
216 this->m_proj_parm.pj[z-1]->inv(xy_x, xy_y, lp_lon, lp_lat);
217 lp_lon += this->m_proj_parm.pj[z-1]->params().lam0;
220 case 1: ok = (lp_lon >= -d180-EPSLN && lp_lon <= -d40+EPSLN) ||
221 ((lp_lon >= -d40-EPSLN && lp_lon <= -d10+EPSLN) &&
222 (lp_lat >= d60-EPSLN && lp_lat <= d90+EPSLN)); break;
223 case 2: ok = (lp_lon >= -d40-EPSLN && lp_lon <= d180+EPSLN) ||
224 ((lp_lon >= -d180-EPSLN && lp_lon <= -d160+EPSLN) &&
225 (lp_lat >= d50-EPSLN && lp_lat <= d90+EPSLN)) ||
226 ((lp_lon >= -d50-EPSLN && lp_lon <= -d40+EPSLN) &&
227 (lp_lat >= d60-EPSLN && lp_lat <= d90+EPSLN)); break;
228 case 3: ok = (lp_lon >= -d180-EPSLN && lp_lon <= -d40+EPSLN); break;
229 case 4: ok = (lp_lon >= -d40-EPSLN && lp_lon <= d180+EPSLN); break;
230 case 5: ok = (lp_lon >= -d180-EPSLN && lp_lon <= -d100+EPSLN); break;
231 case 6: ok = (lp_lon >= -d100-EPSLN && lp_lon <= -d20+EPSLN); break;
232 case 7: ok = (lp_lon >= -d20-EPSLN && lp_lon <= d80+EPSLN); break;
233 case 8: ok = (lp_lon >= d80-EPSLN && lp_lon <= d180+EPSLN); break;
234 case 9: ok = (lp_lon >= -d180-EPSLN && lp_lon <= -d100+EPSLN); break;
235 case 10: ok = (lp_lon >= -d100-EPSLN && lp_lon <= -d20+EPSLN); break;
236 case 11: ok = (lp_lon >= -d20-EPSLN && lp_lon <= d80+EPSLN); break;
237 case 12: ok = (lp_lon >= d80-EPSLN && lp_lon <= d180+EPSLN); break;
240 z = (!ok? 0: z); // projectable?
242 // if (!z) pj_errno = -15; // invalid x or y
243 if (!z) lp_lon = HUGE_VAL;
244 if (!z) lp_lat = HUGE_VAL;
247 static inline std::string get_name()
249 return "igh_spheroid";
254 // Interrupted Goode Homolosine
255 template <typename CalculationType, typename Parameters>
256 inline void setup_igh(Parameters& par, par_igh<CalculationType, Parameters>& proj_parm)
258 static const CalculationType d0 = 0;
259 static const CalculationType d4044118 = igh::d4044118<CalculationType>();
260 static const CalculationType d20 = igh::d20<CalculationType>();
261 static const CalculationType d30 = igh::d30<CalculationType>();
262 static const CalculationType d60 = igh::d60<CalculationType>();
263 static const CalculationType d100 = igh::d100<CalculationType>();
264 static const CalculationType d140 = igh::d140<CalculationType>();
265 static const CalculationType d160 = igh::d160<CalculationType>();
271 +--------------+-------------------------+ Zones 1,2,9,10,11 & 12:
272 |1 |2 | Mollweide projection
274 +--------------+-------------------------+ Zones 3,4,5,6,7 & 8:
275 |3 |4 | Sinusoidal projection
277 0 +-------+------+-+-----------+-----------+
280 +-------+--------+-----------+-----------+
283 +-------+--------+-----------+-----------+
288 CalculationType lp_lam = 0, lp_phi = d4044118;
289 CalculationType xy1_x, xy1_y;
290 CalculationType xy3_x, xy3_y;
293 do_setup<sinu_entry>(3, par, proj_parm, -d100, d0, -d100);
294 do_setup<sinu_entry>(4, par, proj_parm, d30, d0, d30);
295 do_setup<sinu_entry>(5, par, proj_parm, -d160, d0, -d160);
296 do_setup<sinu_entry>(6, par, proj_parm, -d60, d0, -d60);
297 do_setup<sinu_entry>(7, par, proj_parm, d20, d0, d20);
298 do_setup<sinu_entry>(8, par, proj_parm, d140, d0, d140);
301 do_setup<moll_entry>(1, par, proj_parm, -d100, d0, -d100);
304 proj_parm.pj[0]->fwd(lp_lam, lp_phi, xy1_x, xy1_y); // zone 1
305 proj_parm.pj[2]->fwd(lp_lam, lp_phi, xy3_x, xy3_y); // zone 3
306 // y0 + xy1_y = xy3_y for lt = 40d44'11.8"
307 proj_parm.dy0 = xy3_y - xy1_y;
309 proj_parm.pj[0]->mutable_params().y0 = proj_parm.dy0;
311 // mollweide zones (cont'd)
312 do_setup<moll_entry>( 2, par, proj_parm, d30, proj_parm.dy0, d30);
313 do_setup<moll_entry>( 9, par, proj_parm, -d160, -proj_parm.dy0, -d160);
314 do_setup<moll_entry>(10, par, proj_parm, -d60, -proj_parm.dy0, -d60);
315 do_setup<moll_entry>(11, par, proj_parm, d20, -proj_parm.dy0, d20);
316 do_setup<moll_entry>(12, par, proj_parm, d140, -proj_parm.dy0, d140);
321 }} // namespace detail::igh
325 \brief Interrupted Goode Homolosine projection
327 \tparam Geographic latlong point type
328 \tparam Cartesian xy point type
329 \tparam Parameters parameter type
330 \par Projection characteristics
334 \image html ex_igh.gif
336 template <typename CalculationType, typename Parameters>
337 struct igh_spheroid : public detail::igh::base_igh_spheroid<CalculationType, Parameters>
339 inline igh_spheroid(const Parameters& par) : detail::igh::base_igh_spheroid<CalculationType, Parameters>(par)
341 detail::igh::setup_igh(this->m_par, this->m_proj_parm);
345 #ifndef DOXYGEN_NO_DETAIL
350 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::par4::igh, igh_spheroid, igh_spheroid)
353 template <typename CalculationType, typename Parameters>
354 class igh_entry : public detail::factory_entry<CalculationType, Parameters>
357 virtual base_v<CalculationType, Parameters>* create_new(const Parameters& par) const
359 return new base_v_fi<igh_spheroid<CalculationType, Parameters>, CalculationType, Parameters>(par);
363 template <typename CalculationType, typename Parameters>
364 inline void igh_init(detail::base_factory<CalculationType, Parameters>& factory)
366 factory.add_to_factory("igh", new igh_entry<CalculationType, Parameters>);
369 } // namespace detail
372 } // namespace projections
374 }} // namespace boost::geometry
376 #endif // BOOST_GEOMETRY_PROJECTIONS_IGH_HPP