File indexing completed on 2025-01-18 09:35:44
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 #ifndef BOOST_GEOMETRY_PROJECTIONS_LSAT_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_LSAT_HPP
0042
0043 #include <boost/geometry/srs/projections/impl/aasincos.hpp>
0044 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0045 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0046 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0047 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0048 #include <boost/geometry/srs/projections/impl/projects.hpp>
0049
0050 #include <boost/geometry/util/math.hpp>
0051
0052 namespace boost { namespace geometry
0053 {
0054
0055 namespace projections
0056 {
0057 #ifndef DOXYGEN_NO_DETAIL
0058 namespace detail { namespace lsat
0059 {
0060 static const double tolerance = 1e-7;
0061
0062 template <typename T>
0063 struct par_lsat
0064 {
0065 T a2, a4, b, c1, c3;
0066 T q, t, u, w, p22, sa, ca, xj, rlm, rlm2;
0067 };
0068
0069
0070 template <typename T>
0071 inline void
0072 seraz0(T lam, T const& mult, par_lsat<T>& proj_parm)
0073 {
0074 T sdsq, h, s, fc, sd, sq, d__1 = 0;
0075
0076 lam *= geometry::math::d2r<T>();
0077 sd = sin(lam);
0078 sdsq = sd * sd;
0079 s = proj_parm.p22 * proj_parm.sa * cos(lam) * sqrt((1. + proj_parm.t * sdsq)
0080 / ((1. + proj_parm.w * sdsq) * (1. + proj_parm.q * sdsq)));
0081
0082 d__1 = 1. + proj_parm.q * sdsq;
0083 h = sqrt((1. + proj_parm.q * sdsq) / (1. + proj_parm.w * sdsq)) * ((1. + proj_parm.w * sdsq)
0084 / (d__1 * d__1) - proj_parm.p22 * proj_parm.ca);
0085
0086 sq = sqrt(proj_parm.xj * proj_parm.xj + s * s);
0087 fc = mult * (h * proj_parm.xj - s * s) / sq;
0088 proj_parm.b += fc;
0089 proj_parm.a2 += fc * cos(lam + lam);
0090 proj_parm.a4 += fc * cos(lam * 4.);
0091 fc = mult * s * (h + proj_parm.xj) / sq;
0092 proj_parm.c1 += fc * cos(lam);
0093 proj_parm.c3 += fc * cos(lam * 3.);
0094 }
0095
0096 template <typename T, typename Parameters>
0097 struct base_lsat_ellipsoid
0098 {
0099 par_lsat<T> m_proj_parm;
0100
0101
0102
0103 inline void fwd(Parameters const& par, T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const
0104 {
0105 static const T fourth_pi = detail::fourth_pi<T>();
0106 static const T half_pi = detail::half_pi<T>();
0107 static const T one_and_half_pi = detail::one_and_half_pi<T>();
0108 static const T two_and_half_pi = detail::two_and_half_pi<T>();
0109
0110 int l, nn;
0111 T lamt = 0.0, xlam, sdsq, c, d, s, lamdp = 0.0, phidp, lampp, tanph;
0112 T lamtp, cl, sd, sp, sav, tanphi;
0113
0114 if (lp_lat > half_pi)
0115 lp_lat = half_pi;
0116 else if (lp_lat < -half_pi)
0117 lp_lat = -half_pi;
0118
0119 if (lp_lat >= 0. )
0120 lampp = half_pi;
0121 else
0122 lampp = one_and_half_pi;
0123 tanphi = tan(lp_lat);
0124 for (nn = 0;;) {
0125 T fac;
0126 sav = lampp;
0127 lamtp = lp_lon + this->m_proj_parm.p22 * lampp;
0128 cl = cos(lamtp);
0129 if (fabs(cl) < tolerance)
0130 lamtp -= tolerance;
0131 if( cl < 0 )
0132 fac = lampp + sin(lampp) * half_pi;
0133 else
0134 fac = lampp - sin(lampp) * half_pi;
0135 for (l = 50; l; --l) {
0136 lamt = lp_lon + this->m_proj_parm.p22 * sav;
0137 c = cos(lamt);
0138 if (fabs(c) < tolerance)
0139 lamt -= tolerance;
0140 xlam = (par.one_es * tanphi * this->m_proj_parm.sa + sin(lamt) * this->m_proj_parm.ca) / c;
0141 lamdp = atan(xlam) + fac;
0142 if (fabs(fabs(sav) - fabs(lamdp)) < tolerance)
0143 break;
0144 sav = lamdp;
0145 }
0146 if (!l || ++nn >= 3 || (lamdp > this->m_proj_parm.rlm && lamdp < this->m_proj_parm.rlm2))
0147 break;
0148 if (lamdp <= this->m_proj_parm.rlm)
0149 lampp = two_and_half_pi;
0150 else if (lamdp >= this->m_proj_parm.rlm2)
0151 lampp = half_pi;
0152 }
0153 if (l) {
0154 sp = sin(lp_lat);
0155 phidp = aasin((par.one_es * this->m_proj_parm.ca * sp - this->m_proj_parm.sa * cos(lp_lat) *
0156 sin(lamt)) / sqrt(1. - par.es * sp * sp));
0157 tanph = log(tan(fourth_pi + .5 * phidp));
0158 sd = sin(lamdp);
0159 sdsq = sd * sd;
0160 s = this->m_proj_parm.p22 * this->m_proj_parm.sa * cos(lamdp) * sqrt((1. + this->m_proj_parm.t * sdsq)
0161 / ((1. + this->m_proj_parm.w * sdsq) * (1. + this->m_proj_parm.q * sdsq)));
0162 d = sqrt(this->m_proj_parm.xj * this->m_proj_parm.xj + s * s);
0163 xy_x = this->m_proj_parm.b * lamdp + this->m_proj_parm.a2 * sin(2. * lamdp) + this->m_proj_parm.a4 *
0164 sin(lamdp * 4.) - tanph * s / d;
0165 xy_y = this->m_proj_parm.c1 * sd + this->m_proj_parm.c3 * sin(lamdp * 3.) + tanph * this->m_proj_parm.xj / d;
0166 } else
0167 xy_x = xy_y = HUGE_VAL;
0168 }
0169
0170
0171
0172 inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0173 {
0174 static const T fourth_pi = detail::fourth_pi<T>();
0175 static const T half_pi = detail::half_pi<T>();
0176
0177 int nn;
0178 T lamt, sdsq, s, lamdp, phidp, sppsq, dd, sd, sl, fac, scl, sav, spp;
0179
0180 lamdp = xy_x / this->m_proj_parm.b;
0181 nn = 50;
0182 do {
0183 sav = lamdp;
0184 sd = sin(lamdp);
0185 sdsq = sd * sd;
0186 s = this->m_proj_parm.p22 * this->m_proj_parm.sa * cos(lamdp) * sqrt((1. + this->m_proj_parm.t * sdsq)
0187 / ((1. + this->m_proj_parm.w * sdsq) * (1. + this->m_proj_parm.q * sdsq)));
0188 lamdp = xy_x + xy_y * s / this->m_proj_parm.xj - this->m_proj_parm.a2 * sin(
0189 2. * lamdp) - this->m_proj_parm.a4 * sin(lamdp * 4.) - s / this->m_proj_parm.xj * (
0190 this->m_proj_parm.c1 * sin(lamdp) + this->m_proj_parm.c3 * sin(lamdp * 3.));
0191 lamdp /= this->m_proj_parm.b;
0192 } while (fabs(lamdp - sav) >= tolerance && --nn);
0193 sl = sin(lamdp);
0194 fac = exp(sqrt(1. + s * s / this->m_proj_parm.xj / this->m_proj_parm.xj) * (xy_y -
0195 this->m_proj_parm.c1 * sl - this->m_proj_parm.c3 * sin(lamdp * 3.)));
0196 phidp = 2. * (atan(fac) - fourth_pi);
0197 dd = sl * sl;
0198 if (fabs(cos(lamdp)) < tolerance)
0199 lamdp -= tolerance;
0200 spp = sin(phidp);
0201 sppsq = spp * spp;
0202 lamt = atan(((1. - sppsq * par.rone_es) * tan(lamdp) *
0203 this->m_proj_parm.ca - spp * this->m_proj_parm.sa * sqrt((1. + this->m_proj_parm.q * dd) * (
0204 1. - sppsq) - sppsq * this->m_proj_parm.u) / cos(lamdp)) / (1. - sppsq
0205 * (1. + this->m_proj_parm.u)));
0206 sl = lamt >= 0. ? 1. : -1.;
0207 scl = cos(lamdp) >= 0. ? 1. : -1;
0208 lamt -= half_pi * (1. - scl) * sl;
0209 lp_lon = lamt - this->m_proj_parm.p22 * lamdp;
0210 if (fabs(this->m_proj_parm.sa) < tolerance)
0211 lp_lat = aasin(spp / sqrt(par.one_es * par.one_es + par.es * sppsq));
0212 else
0213 lp_lat = atan((tan(lamdp) * cos(lamt) - this->m_proj_parm.ca * sin(lamt)) /
0214 (par.one_es * this->m_proj_parm.sa));
0215 }
0216
0217 static inline std::string get_name()
0218 {
0219 return "lsat_ellipsoid";
0220 }
0221
0222 };
0223
0224
0225 template <typename Params, typename Parameters, typename T>
0226 inline void setup_lsat(Params const& params, Parameters& par, par_lsat<T>& proj_parm)
0227 {
0228 static T const d2r = geometry::math::d2r<T>();
0229 static T const pi = detail::pi<T>();
0230 static T const two_pi = detail::two_pi<T>();
0231
0232 int land, path;
0233 T lam, alf, esc, ess;
0234
0235 land = pj_get_param_i<srs::spar::lsat>(params, "lsat", srs::dpar::lsat);
0236 if (land <= 0 || land > 5)
0237 BOOST_THROW_EXCEPTION( projection_exception(error_lsat_not_in_range) );
0238
0239 path = pj_get_param_i<srs::spar::path>(params, "path", srs::dpar::path);
0240 if (path <= 0 || path > (land <= 3 ? 251 : 233))
0241 BOOST_THROW_EXCEPTION( projection_exception(error_path_not_in_range) );
0242
0243 if (land <= 3) {
0244 par.lam0 = d2r * 128.87 - two_pi / 251. * path;
0245 proj_parm.p22 = 103.2669323;
0246 alf = d2r * 99.092;
0247 } else {
0248 par.lam0 = d2r * 129.3 - two_pi / 233. * path;
0249 proj_parm.p22 = 98.8841202;
0250 alf = d2r * 98.2;
0251 }
0252 proj_parm.p22 /= 1440.;
0253 proj_parm.sa = sin(alf);
0254 proj_parm.ca = cos(alf);
0255 if (fabs(proj_parm.ca) < 1e-9)
0256 proj_parm.ca = 1e-9;
0257 esc = par.es * proj_parm.ca * proj_parm.ca;
0258 ess = par.es * proj_parm.sa * proj_parm.sa;
0259 proj_parm.w = (1. - esc) * par.rone_es;
0260 proj_parm.w = proj_parm.w * proj_parm.w - 1.;
0261 proj_parm.q = ess * par.rone_es;
0262 proj_parm.t = ess * (2. - par.es) * par.rone_es * par.rone_es;
0263 proj_parm.u = esc * par.rone_es;
0264 proj_parm.xj = par.one_es * par.one_es * par.one_es;
0265 proj_parm.rlm = pi * (1. / 248. + .5161290322580645);
0266 proj_parm.rlm2 = proj_parm.rlm + two_pi;
0267 proj_parm.a2 = proj_parm.a4 = proj_parm.b = proj_parm.c1 = proj_parm.c3 = 0.;
0268 seraz0(0., 1., proj_parm);
0269 for (lam = 9.; lam <= 81.0001; lam += 18.)
0270 seraz0(lam, 4., proj_parm);
0271 for (lam = 18; lam <= 72.0001; lam += 18.)
0272 seraz0(lam, 2., proj_parm);
0273 seraz0(90., 1., proj_parm);
0274 proj_parm.a2 /= 30.;
0275 proj_parm.a4 /= 60.;
0276 proj_parm.b /= 30.;
0277 proj_parm.c1 /= 15.;
0278 proj_parm.c3 /= 45.;
0279 }
0280
0281 }}
0282 #endif
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 template <typename T, typename Parameters>
0301 struct lsat_ellipsoid : public detail::lsat::base_lsat_ellipsoid<T, Parameters>
0302 {
0303 template <typename Params>
0304 inline lsat_ellipsoid(Params const& params, Parameters & par)
0305 {
0306 detail::lsat::setup_lsat(params, par, this->m_proj_parm);
0307 }
0308 };
0309
0310 #ifndef DOXYGEN_NO_DETAIL
0311 namespace detail
0312 {
0313
0314
0315 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_lsat, lsat_ellipsoid)
0316
0317
0318 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(lsat_entry, lsat_ellipsoid)
0319
0320 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lsat_init)
0321 {
0322 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lsat, lsat_entry)
0323 }
0324
0325 }
0326 #endif
0327
0328 }
0329
0330 }}
0331
0332 #endif
0333