File indexing completed on 2025-01-18 09:35:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 #ifndef BOOST_GEOMETRY_PROJECTIONS_ETMERC_HPP
0055 #define BOOST_GEOMETRY_PROJECTIONS_ETMERC_HPP
0056
0057 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0058 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0059 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0060 #include <boost/geometry/srs/projections/impl/function_overloads.hpp>
0061 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0062 #include <boost/geometry/srs/projections/impl/projects.hpp>
0063
0064 #include <boost/math/special_functions/hypot.hpp>
0065
0066 namespace boost { namespace geometry
0067 {
0068
0069 namespace projections
0070 {
0071 #ifndef DOXYGEN_NO_DETAIL
0072 namespace detail { namespace etmerc
0073 {
0074
0075 static const int PROJ_ETMERC_ORDER = 6;
0076
0077 template <typename T>
0078 struct par_etmerc
0079 {
0080 T Qn;
0081 T Zb;
0082 T cgb[6];
0083 T cbg[6];
0084 T utg[6];
0085 T gtu[6];
0086 };
0087
0088 template <typename T>
0089 inline T log1py(T const& x) {
0090 volatile T
0091 y = 1 + x,
0092 z = y - 1;
0093
0094
0095
0096
0097 return z == 0 ? x : x * log(y) / z;
0098 }
0099
0100 template <typename T>
0101 inline T asinhy(T const& x) {
0102 T y = fabs(x);
0103 y = log1py(y * (1 + y/(boost::math::hypot(1.0, y) + 1)));
0104 return x < 0 ? -y : y;
0105 }
0106
0107 template <typename T>
0108 inline T gatg(const T *p1, int len_p1, T const& B) {
0109 const T *p;
0110 T h = 0, h1, h2 = 0, cos_2B;
0111
0112 cos_2B = 2*cos(2*B);
0113 for (p = p1 + len_p1, h1 = *--p; p - p1; h2 = h1, h1 = h)
0114 h = -h2 + cos_2B*h1 + *--p;
0115 return (B + h*sin(2*B));
0116 }
0117
0118
0119 template <typename T>
0120 inline T clenS(const T *a, int size, T const& arg_r, T const& arg_i, T *R, T *I) {
0121 T r, i, hr, hr1, hr2, hi, hi1, hi2;
0122 T sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i;
0123
0124
0125 const T* p = a + size;
0126 sin_arg_r = sin(arg_r);
0127 cos_arg_r = cos(arg_r);
0128 sinh_arg_i = sinh(arg_i);
0129 cosh_arg_i = cosh(arg_i);
0130 r = 2*cos_arg_r*cosh_arg_i;
0131 i = -2*sin_arg_r*sinh_arg_i;
0132
0133 for (hi1 = hr1 = hi = 0, hr = *--p; a - p;) {
0134 hr2 = hr1;
0135 hi2 = hi1;
0136 hr1 = hr;
0137 hi1 = hi;
0138 hr = -hr2 + r*hr1 - i*hi1 + *--p;
0139 hi = -hi2 + i*hr1 + r*hi1;
0140 }
0141 r = sin_arg_r*cosh_arg_i;
0142 i = cos_arg_r*sinh_arg_i;
0143 *R = r*hr - i*hi;
0144 *I = r*hi + i*hr;
0145 return(*R);
0146 }
0147
0148
0149 template <typename T>
0150 inline T clens(const T *a, int size, T const& arg_r) {
0151 T r, hr, hr1, hr2, cos_arg_r;
0152
0153 const T* p = a + size;
0154 cos_arg_r = cos(arg_r);
0155 r = 2*cos_arg_r;
0156
0157
0158 for (hr1 = 0, hr = *--p; a - p;) {
0159 hr2 = hr1;
0160 hr1 = hr;
0161 hr = -hr2 + r*hr1 + *--p;
0162 }
0163 return(sin(arg_r)*hr);
0164 }
0165
0166 template <typename T, typename Parameters>
0167 struct base_etmerc_ellipsoid
0168 {
0169 par_etmerc<T> m_proj_parm;
0170
0171
0172
0173 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0174 {
0175 T sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe;
0176 T Cn = lp_lat, Ce = lp_lon;
0177
0178
0179 Cn = gatg(this->m_proj_parm.cbg, PROJ_ETMERC_ORDER, Cn);
0180
0181 sin_Cn = sin(Cn);
0182 cos_Cn = cos(Cn);
0183 sin_Ce = sin(Ce);
0184 cos_Ce = cos(Ce);
0185
0186 Cn = atan2(sin_Cn, cos_Ce*cos_Cn);
0187 Ce = atan2(sin_Ce*cos_Cn, boost::math::hypot(sin_Cn, cos_Cn*cos_Ce));
0188
0189
0190 Ce = asinhy(tan(Ce));
0191 Cn += clenS(this->m_proj_parm.gtu, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe);
0192 Ce += dCe;
0193 if (fabs(Ce) <= 2.623395162778) {
0194 xy_y = this->m_proj_parm.Qn * Cn + this->m_proj_parm.Zb;
0195 xy_x = this->m_proj_parm.Qn * Ce;
0196 } else
0197 xy_x = xy_y = HUGE_VAL;
0198 }
0199
0200
0201
0202 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0203 {
0204 T sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe;
0205 T Cn = xy_y, Ce = xy_x;
0206
0207
0208 Cn = (Cn - this->m_proj_parm.Zb)/this->m_proj_parm.Qn;
0209 Ce = Ce/this->m_proj_parm.Qn;
0210
0211 if (fabs(Ce) <= 2.623395162778) {
0212
0213 Cn += clenS(this->m_proj_parm.utg, PROJ_ETMERC_ORDER, 2*Cn, 2*Ce, &dCn, &dCe);
0214 Ce += dCe;
0215 Ce = atan(sinh(Ce));
0216
0217 sin_Cn = sin(Cn);
0218 cos_Cn = cos(Cn);
0219 sin_Ce = sin(Ce);
0220 cos_Ce = cos(Ce);
0221 Ce = atan2(sin_Ce, cos_Ce*cos_Cn);
0222 Cn = atan2(sin_Cn*cos_Ce, boost::math::hypot(sin_Ce, cos_Ce*cos_Cn));
0223
0224 lp_lat = gatg(this->m_proj_parm.cgb, PROJ_ETMERC_ORDER, Cn);
0225 lp_lon = Ce;
0226 }
0227 else
0228 lp_lat = lp_lon = HUGE_VAL;
0229 }
0230
0231 static inline std::string get_name()
0232 {
0233 return "etmerc_ellipsoid";
0234 }
0235
0236 };
0237
0238 template <typename Parameters, typename T>
0239 inline void setup(Parameters& par, par_etmerc<T>& proj_parm)
0240 {
0241 T f, n, np, Z;
0242
0243 if (par.es <= 0) {
0244 BOOST_THROW_EXCEPTION( projection_exception(error_ellipsoid_use_required) );
0245 }
0246
0247 f = par.es / (1 + sqrt(1 - par.es));
0248
0249
0250 np = n = f/(2 - f);
0251
0252
0253
0254
0255
0256
0257 proj_parm.cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 +
0258 n*(-2854/675.0 ))))));
0259 proj_parm.cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 +
0260 n*( 4642/4725.0))))));
0261 np *= n;
0262 proj_parm.cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 +
0263 n*( 2323/945.0)))));
0264 proj_parm.cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 +
0265 n*(-1522/945.0)))));
0266 np *= n;
0267
0268 proj_parm.cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 +
0269 n*( 73814/2835.0))));
0270 proj_parm.cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 +
0271 n*(-12686/2835.0))));
0272 np *= n;
0273
0274 proj_parm.cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0)));
0275 proj_parm.cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0)));
0276 np *= n;
0277 proj_parm.cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 ));
0278 proj_parm.cbg[4] = np*(-734/315.0 + n*( 109598/31185.0));
0279 np *= n;
0280 proj_parm.cgb[5] = np*(601676/22275.0 );
0281 proj_parm.cbg[5] = np*(444337/155925.0);
0282
0283
0284
0285 np = n*n;
0286
0287 proj_parm.Qn = par.k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0)));
0288
0289
0290
0291 proj_parm.utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 +
0292 n*( 81/512.0 + n*(-96199/604800.0))))));
0293 proj_parm.gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 +
0294 n*(-127/288.0 + n*( 7891/37800.0 ))))));
0295 proj_parm.utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 +
0296 n*( 1118711/3870720.0)))));
0297 proj_parm.gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 +
0298 n*(-1983433/1935360.0)))));
0299 np *= n;
0300 proj_parm.utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 +
0301 n*( -5569/90720.0 ))));
0302 proj_parm.gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 +
0303 n*(167603/181440.0))));
0304 np *= n;
0305 proj_parm.utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0)));
0306 proj_parm.gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0)));
0307 np *= n;
0308 proj_parm.utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0));
0309 proj_parm.gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0));
0310 np *= n;
0311 proj_parm.utg[5] = np*(-20648693/638668800.0);
0312 proj_parm.gtu[5] = np*(212378941/319334400.0);
0313
0314
0315 Z = gatg(proj_parm.cbg, PROJ_ETMERC_ORDER, par.phi0);
0316
0317
0318
0319 proj_parm.Zb = - proj_parm.Qn*(Z + clens(proj_parm.gtu, PROJ_ETMERC_ORDER, 2*Z));
0320 }
0321
0322
0323 template <typename Parameters, typename T>
0324 inline void setup_etmerc(Parameters& par, par_etmerc<T>& proj_parm)
0325 {
0326 setup(par, proj_parm);
0327 }
0328
0329
0330 template <typename Params, typename Parameters, typename T>
0331 inline void setup_utm(Params const& params, Parameters& par, par_etmerc<T>& proj_parm)
0332 {
0333 static const T pi = detail::pi<T>();
0334
0335 int zone;
0336
0337 if (par.es == 0.0) {
0338 BOOST_THROW_EXCEPTION( projection_exception(error_ellipsoid_use_required) );
0339 }
0340
0341 par.y0 = pj_get_param_b<srs::spar::south>(params, "south", srs::dpar::south) ? 10000000. : 0.;
0342 par.x0 = 500000.;
0343 if (pj_param_i<srs::spar::zone>(params, "zone", srs::dpar::zone, zone))
0344 {
0345 if (zone > 0 && zone <= 60)
0346 --zone;
0347 else {
0348 BOOST_THROW_EXCEPTION( projection_exception(error_invalid_utm_zone) );
0349 }
0350 }
0351 else
0352 {
0353 zone = int_floor((adjlon(par.lam0) + pi) * 30. / pi);
0354 if (zone < 0)
0355 zone = 0;
0356 else if (zone >= 60)
0357 zone = 59;
0358 }
0359 par.lam0 = (zone + .5) * pi / 30. - pi;
0360 par.k0 = 0.9996;
0361 par.phi0 = 0.;
0362
0363 setup(par, proj_parm);
0364 }
0365
0366 }}
0367 #endif
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 template <typename T, typename Parameters>
0385 struct etmerc_ellipsoid : public detail::etmerc::base_etmerc_ellipsoid<T, Parameters>
0386 {
0387 template <typename Params>
0388 inline etmerc_ellipsoid(Params const& , Parameters & par)
0389 {
0390 detail::etmerc::setup_etmerc(par, this->m_proj_parm);
0391 }
0392 };
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409 template <typename T, typename Parameters>
0410 struct utm_ellipsoid : public detail::etmerc::base_etmerc_ellipsoid<T, Parameters>
0411 {
0412 template <typename Params>
0413 inline utm_ellipsoid(Params const& params, Parameters & par)
0414 {
0415 detail::etmerc::setup_utm(params, par, this->m_proj_parm);
0416 }
0417 };
0418
0419 #ifndef DOXYGEN_NO_DETAIL
0420 namespace detail
0421 {
0422
0423
0424 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_etmerc, etmerc_ellipsoid)
0425 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_utm, utm_ellipsoid)
0426
0427
0428 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(etmerc_entry, etmerc_ellipsoid)
0429 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(utm_entry, utm_ellipsoid)
0430
0431 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(etmerc_init)
0432 {
0433 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(etmerc, etmerc_entry);
0434 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(utm, utm_entry);
0435 }
0436
0437 }
0438 #endif
0439
0440 }
0441
0442 }}
0443
0444 #endif
0445