1
#ifndef GGL_PROJECTIONS_TMERC_HPP
2
#define GGL_PROJECTIONS_TMERC_HPP
4
// Generic Geometry Library - projections (based on PROJ4)
5
// This file is automatically generated. DO NOT EDIT.
7
// Copyright Barend Gehrels (1995-2009), Geodan Holding B.V. Amsterdam, the Netherlands.
8
// Copyright Bruno Lalande (2008-2009)
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 Geometry Library by Barend Gehrels (Geodan, Amsterdam)
18
// Original copyright notice:
20
// Permission is hereby granted, free of charge, to any person obtaining a
21
// copy of this software and associated documentation files (the "Software"),
22
// to deal in the Software without restriction, including without limitation
23
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
24
// and/or sell copies of the Software, and to permit persons to whom the
25
// Software is furnished to do so, subject to the following conditions:
27
// The above copyright notice and this permission notice shall be included
28
// in all copies or substantial portions of the Software.
30
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36
// DEALINGS IN THE SOFTWARE.
38
#include <boost/concept_check.hpp>
39
#include <boost/math/special_functions/hypot.hpp>
41
#include <ggl/extensions/gis/projections/impl/base_static.hpp>
42
#include <ggl/extensions/gis/projections/impl/base_dynamic.hpp>
43
#include <ggl/extensions/gis/projections/impl/projects.hpp>
44
#include <ggl/extensions/gis/projections/impl/factory_entry.hpp>
45
#include <ggl/extensions/gis/projections/impl/function_overloads.hpp>
46
#include <ggl/extensions/gis/projections/impl/pj_mlfn.hpp>
48
#include <ggl/extensions/gis/projections/epsg_traits.hpp>
50
namespace ggl { namespace projection
52
#ifndef DOXYGEN_NO_DETAIL
53
namespace detail { namespace tmerc{
54
static const double EPS10 = 1.e-10;
55
static const double FC1 = 1.;
56
static const double FC2 = .5;
57
static const double FC3 = .16666666666666666666;
58
static const double FC4 = .08333333333333333333;
59
static const double FC5 = .05;
60
static const double FC6 = .03333333333333333333;
61
static const double FC7 = .02380952380952380952;
62
static const double FC8 = .01785714285714285714;
71
// template class, using CRTP to implement forward/inverse
72
template <typename Geographic, typename Cartesian, typename Parameters>
73
struct base_tmerc_ellipsoid : public base_t_fi<base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>,
74
Geographic, Cartesian, Parameters>
77
typedef double geographic_type;
78
typedef double cartesian_type;
80
par_tmerc m_proj_parm;
82
inline base_tmerc_ellipsoid(const Parameters& par)
83
: base_t_fi<base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>,
84
Geographic, Cartesian, Parameters>(*this, par) {}
86
inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
88
double al, als, n, cosphi, sinphi, t;
91
* Fail if our longitude is more than 90 degrees from the
92
* central meridian since the results are essentially garbage.
93
* Is error -20 really an appropriate return value?
95
* http://trac.osgeo.org/proj/ticket/5
97
if( lp_lon < -HALFPI || lp_lon > HALFPI )
101
throw proj_exception( -14);
105
sinphi = sin(lp_lat); cosphi = cos(lp_lat);
106
t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
108
al = cosphi * lp_lon;
110
al /= sqrt(1. - this->m_par.es * sinphi * sinphi);
111
n = this->m_proj_parm.esp * cosphi * cosphi;
112
xy_x = this->m_par.k0 * al * (FC1 +
113
FC3 * als * (1. - t + n +
114
FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t)
115
+ FC7 * als * (61. + t * ( t * (179. - t) - 479. ) )
117
xy_y = this->m_par.k0 * (pj_mlfn(lp_lat, sinphi, cosphi, this->m_proj_parm.en) - this->m_proj_parm.ml0 +
118
sinphi * al * lp_lon * FC2 * ( 1. +
119
FC4 * als * (5. - t + n * (9. + 4. * n) +
120
FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t)
121
+ FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) )
125
inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
127
double n, con, cosphi, d, ds, sinphi, t;
129
lp_lat = pj_inv_mlfn(this->m_proj_parm.ml0 + xy_y / this->m_par.k0, this->m_par.es, this->m_proj_parm.en);
130
if (fabs(lp_lat) >= HALFPI) {
131
lp_lat = xy_y < 0. ? -HALFPI : HALFPI;
134
sinphi = sin(lp_lat);
135
cosphi = cos(lp_lat);
136
t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
137
n = this->m_proj_parm.esp * cosphi * cosphi;
138
d = xy_x * sqrt(con = 1. - this->m_par.es * sinphi * sinphi) / this->m_par.k0;
142
lp_lat -= (con * ds / (1.-this->m_par.es)) * FC2 * (1. -
143
ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) -
144
ds * FC6 * (61. + t * (90. - 252. * n +
146
- ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) )
149
ds*FC3*( 1. + 2.*t + n -
150
ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n
151
- ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) )
157
// template class, using CRTP to implement forward/inverse
158
template <typename Geographic, typename Cartesian, typename Parameters>
159
struct base_tmerc_spheroid : public base_t_fi<base_tmerc_spheroid<Geographic, Cartesian, Parameters>,
160
Geographic, Cartesian, Parameters>
163
typedef double geographic_type;
164
typedef double cartesian_type;
166
par_tmerc m_proj_parm;
168
inline base_tmerc_spheroid(const Parameters& par)
169
: base_t_fi<base_tmerc_spheroid<Geographic, Cartesian, Parameters>,
170
Geographic, Cartesian, Parameters>(*this, par) {}
172
inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
177
* Fail if our longitude is more than 90 degrees from the
178
* central meridian since the results are essentially garbage.
179
* Is error -20 really an appropriate return value?
181
* http://trac.osgeo.org/proj/ticket/5
183
if( lp_lon < -HALFPI || lp_lon > HALFPI )
187
throw proj_exception( -14);
191
b = (cosphi = cos(lp_lat)) * sin(lp_lon);
192
if (fabs(fabs(b) - 1.) <= EPS10) throw proj_exception();;
193
xy_x = this->m_proj_parm.ml0 * log((1. + b) / (1. - b));
194
if ((b = fabs( xy_y = cosphi * cos(lp_lon) / sqrt(1. - b * b) )) >= 1.) {
195
if ((b - 1.) > EPS10) throw proj_exception();
199
if (lp_lat < 0.) xy_y = -xy_y;
200
xy_y = this->m_proj_parm.esp * (xy_y - this->m_par.phi0);
203
inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
207
h = exp(xy_x / this->m_proj_parm.esp);
208
g = .5 * (h - 1. / h);
209
h = cos(this->m_par.phi0 + xy_y / this->m_proj_parm.esp);
210
lp_lat = asin(sqrt((1. - h * h) / (1. + g * g)));
211
if (xy_y < 0.) lp_lat = -lp_lat;
212
lp_lon = (g || h) ? atan2(g, h) : 0.;
216
template <typename Parameters>
217
void setup(Parameters& par, par_tmerc& proj_parm) /* general initialization */
219
boost::ignore_unused_variable_warning(par);
220
boost::ignore_unused_variable_warning(proj_parm);
222
pj_enfn(par.es, proj_parm.en);
224
proj_parm.ml0 = pj_mlfn(par.phi0, sin(par.phi0), cos(par.phi0), proj_parm.en);
225
proj_parm.esp = par.es / (1. - par.es);
226
// par.inv = e_inverse;
227
// par.fwd = e_forward;
229
proj_parm.esp = par.k0;
230
proj_parm.ml0 = .5 * proj_parm.esp;
231
// par.inv = s_inverse;
232
// par.fwd = s_forward;
237
// Transverse Mercator
238
template <typename Parameters>
239
void setup_tmerc(Parameters& par, par_tmerc& proj_parm)
241
setup(par, proj_parm);
244
// Universal Transverse Mercator (UTM)
245
template <typename Parameters>
246
void setup_utm(Parameters& par, par_tmerc& proj_parm)
249
if (!par.es) throw proj_exception(-34);
250
par.y0 = pj_param(par.params, "bsouth").i ? 10000000. : 0.;
252
if (pj_param(par.params, "tzone").i) /* zone input ? */
253
if ((zone = pj_param(par.params, "izone").i) > 0 && zone <= 60)
256
throw proj_exception(-35);
257
else /* nearest central meridian input */
258
if ((zone = int_floor((adjlon(par.lam0) + PI) * 30. / PI)) < 0)
262
par.lam0 = (zone + .5) * PI / 30. - PI;
265
setup(par, proj_parm);
268
}} // namespace detail::tmerc
272
\brief Transverse Mercator projection
274
\tparam Geographic latlong point type
275
\tparam Cartesian xy point type
276
\tparam Parameters parameter type
277
\par Projection characteristics
282
\image html ex_tmerc.gif
284
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
285
struct tmerc_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>
287
inline tmerc_ellipsoid(const Parameters& par) : detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>(par)
289
detail::tmerc::setup_tmerc(this->m_par, this->m_proj_parm);
294
\brief Universal Transverse Mercator (UTM) projection
296
\tparam Geographic latlong point type
297
\tparam Cartesian xy point type
298
\tparam Parameters parameter type
299
\par Projection characteristics
304
\image html ex_utm.gif
306
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
307
struct utm_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>
309
inline utm_ellipsoid(const Parameters& par) : detail::tmerc::base_tmerc_ellipsoid<Geographic, Cartesian, Parameters>(par)
311
detail::tmerc::setup_utm(this->m_par, this->m_proj_parm);
316
\brief Transverse Mercator projection
318
\tparam Geographic latlong point type
319
\tparam Cartesian xy point type
320
\tparam Parameters parameter type
321
\par Projection characteristics
326
\image html ex_tmerc.gif
328
template <typename Geographic, typename Cartesian, typename Parameters = parameters>
329
struct tmerc_spheroid : public detail::tmerc::base_tmerc_spheroid<Geographic, Cartesian, Parameters>
331
inline tmerc_spheroid(const Parameters& par) : detail::tmerc::base_tmerc_spheroid<Geographic, Cartesian, Parameters>(par)
333
detail::tmerc::setup_tmerc(this->m_par, this->m_proj_parm);
337
#ifndef DOXYGEN_NO_DETAIL
342
template <typename Geographic, typename Cartesian, typename Parameters>
343
class tmerc_entry : public detail::factory_entry<Geographic, Cartesian, Parameters>
346
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
349
return new base_v_fi<tmerc_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
351
return new base_v_fi<tmerc_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
355
template <typename Geographic, typename Cartesian, typename Parameters>
356
class utm_entry : public detail::factory_entry<Geographic, Cartesian, Parameters>
359
virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
361
return new base_v_fi<utm_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
365
template <typename Geographic, typename Cartesian, typename Parameters>
366
inline void tmerc_init(detail::base_factory<Geographic, Cartesian, Parameters>& factory)
368
factory.add_to_factory("tmerc", new tmerc_entry<Geographic, Cartesian, Parameters>);
369
factory.add_to_factory("utm", new utm_entry<Geographic, Cartesian, Parameters>);
372
} // namespace detail
373
// Create EPSG specializations
374
// (Proof of Concept, only for some)
376
template<typename LatLongRadian, typename Cartesian, typename Parameters>
377
struct epsg_traits<2000, LatLongRadian, Cartesian, Parameters>
379
typedef tmerc_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
380
static inline std::string par()
382
return "+proj=tmerc +lat_0=0 +lon_0=-62 +k=0.9995000000000001 +x_0=400000 +y_0=0 +ellps=clrk80 +units=m";
387
template<typename LatLongRadian, typename Cartesian, typename Parameters>
388
struct epsg_traits<2001, LatLongRadian, Cartesian, Parameters>
390
typedef tmerc_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
391
static inline std::string par()
393
return "+proj=tmerc +lat_0=0 +lon_0=-62 +k=0.9995000000000001 +x_0=400000 +y_0=0 +ellps=clrk80 +units=m";
398
template<typename LatLongRadian, typename Cartesian, typename Parameters>
399
struct epsg_traits<2002, LatLongRadian, Cartesian, Parameters>
401
typedef tmerc_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
402
static inline std::string par()
404
return "+proj=tmerc +lat_0=0 +lon_0=-62 +k=0.9995000000000001 +x_0=400000 +y_0=0 +ellps=clrk80 +towgs84=725,685,536,0,0,0,0 +units=m";
409
template<typename LatLongRadian, typename Cartesian, typename Parameters>
410
struct epsg_traits<2003, LatLongRadian, Cartesian, Parameters>
412
typedef tmerc_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
413
static inline std::string par()
415
return "+proj=tmerc +lat_0=0 +lon_0=-62 +k=0.9995000000000001 +x_0=400000 +y_0=0 +ellps=clrk80 +towgs84=72,213.7,93,0,0,0,0 +units=m";
420
template<typename LatLongRadian, typename Cartesian, typename Parameters>
421
struct epsg_traits<2039, LatLongRadian, Cartesian, Parameters>
423
typedef tmerc_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
424
static inline std::string par()
426
return "+proj=tmerc +lat_0=31.73439361111111 +lon_0=35.20451694444445 +k=1.0000067 +x_0=219529.584 +y_0=626907.39 +ellps=GRS80 +towgs84=-48,55,52,0,0,0,0 +units=m";
431
template<typename LatLongRadian, typename Cartesian, typename Parameters>
432
struct epsg_traits<29118, LatLongRadian, Cartesian, Parameters>
434
typedef utm_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
435
static inline std::string par()
437
return "+proj=utm +zone=18 +ellps=GRS67 +units=m";
442
template<typename LatLongRadian, typename Cartesian, typename Parameters>
443
struct epsg_traits<29119, LatLongRadian, Cartesian, Parameters>
445
typedef utm_ellipsoid<LatLongRadian, Cartesian, Parameters> type;
446
static inline std::string par()
448
return "+proj=utm +zone=19 +ellps=GRS67 +units=m";
455
}} // namespace ggl::projection
457
#endif // GGL_PROJECTIONS_TMERC_HPP