inline void setup(Params const& params, Parameters& par, par_sconics<T>& proj_parm, proj_type type) { static const T half_pi = detail::half_pi<T>(); T del, cs; int err; proj_parm.type = type; err = phi12(params, proj_parm, &del); if(err) BOOST_THROW_EXCEPTION( projection_exception(err) ); switch (proj_parm.type) { case proj_tissot: proj_parm.n = sin(proj_parm.sig); cs = cos(del); proj_parm.rho_c = proj_parm.n / cs + cs / proj_parm.n; proj_parm.rho_0 = sqrt((proj_parm.rho_c - 2 * sin(par.phi0))/proj_parm.n); break; case proj_murd1: proj_parm.rho_c = sin(del)/(del * tan(proj_parm.sig)) + proj_parm.sig; proj_parm.rho_0 = proj_parm.rho_c - par.phi0; proj_parm.n = sin(proj_parm.sig); break; case proj_murd2: proj_parm.rho_c = (cs = sqrt(cos(del))) / tan(proj_parm.sig); proj_parm.rho_0 = proj_parm.rho_c + tan(proj_parm.sig - par.phi0); proj_parm.n = sin(proj_parm.sig) * cs; break; case proj_murd3: proj_parm.rho_c = del / (tan(proj_parm.sig) * tan(del)) + proj_parm.sig; proj_parm.rho_0 = proj_parm.rho_c - par.phi0; proj_parm.n = sin(proj_parm.sig) * sin(del) * tan(del) / (del * del); break; case proj_euler: proj_parm.n = sin(proj_parm.sig) * sin(del) / del; del *= 0.5; proj_parm.rho_c = del / (tan(del) * tan(proj_parm.sig)) + proj_parm.sig; proj_parm.rho_0 = proj_parm.rho_c - par.phi0; break; case proj_pconic: proj_parm.n = sin(proj_parm.sig); proj_parm.c2 = cos(del); proj_parm.c1 = 1./tan(proj_parm.sig); if (fabs(del = par.phi0 - proj_parm.sig) - epsilon10 >= half_pi) BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_half_pi_from_mean) ); proj_parm.rho_0 = proj_parm.c2 * (proj_parm.c1 - tan(del)); break; case proj_vitk1: proj_parm.n = (cs = tan(del)) * sin(proj_parm.sig) / del; proj_parm.rho_c = del / (cs * tan(proj_parm.sig)) + proj_parm.sig; proj_parm.rho_0 = proj_parm.rho_c - par.phi0; break; } par.es = 0; }
inline void setup_gn_sinu(Params const& params, Parameters& par, par_gn_sinu<T>& proj_parm) { if (pj_param_f<srs::spar::n>(params, "n", srs::dpar::n, proj_parm.n) && pj_param_f<srs::spar::m>(params, "m", srs::dpar::m, proj_parm.m)) { if (proj_parm.n <= 0 || proj_parm.m < 0) BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) ); } else BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) ); setup(par, proj_parm); }
inline void setup_eqc(Params const& params, Parameters& par, par_eqc<T>& proj_parm) { proj_parm.rc = cos(pj_get_param_r<T, srs::spar::lat_ts>(params, "lat_ts", srs::dpar::lat_ts)); if (proj_parm.rc <= 0.) BOOST_THROW_EXCEPTION( projection_exception(error_lat_ts_larger_than_90) ); par.es = 0.; }
// INVERSE(e_inverse) ellipsoid & spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi<T>(); T rho = 0.0; if( (rho = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.rho0 - xy_y)) != 0.0 ) { if (this->m_proj_parm.n < 0.) { rho = -rho; xy_x = -xy_x; xy_y = -xy_y; } lp_lat = rho / this->m_proj_parm.dd; if (this->m_proj_parm.ellips) { lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n; if (fabs(this->m_proj_parm.ec - fabs(lp_lat)) > tolerance7) { if ((lp_lat = phi1_(lp_lat, this->m_par.e, this->m_par.one_es)) == HUGE_VAL) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } else lp_lat = lp_lat < 0. ? -half_pi : half_pi; } else if (fabs(lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n2) <= 1.) lp_lat = asin(lp_lat); else lp_lat = lp_lat < 0. ? -half_pi : half_pi; lp_lon = atan2(xy_x, xy_y) / this->m_proj_parm.n; } else { lp_lon = 0.; lp_lat = this->m_proj_parm.n > 0. ? half_pi : - half_pi; } }
// INVERSE(s_healpix_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the HEALPix image */ if (in_image(xy_x, xy_y, 0, 0, 0) == 0) { lp_lon = HUGE_VAL; lp_lat = HUGE_VAL; BOOST_THROW_EXCEPTION( projection_exception(error_invalid_x_or_y) ); } return healpix_sphere_inverse(xy_x, xy_y, lp_lon, lp_lat); }
// FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi<T>(); static const T pi = detail::pi<T>(); T al, al2, g, g2, p2; p2 = fabs(lp_lat / half_pi); if ((p2 - tolerance) > 1.) { BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } if (p2 > 1.) p2 = 1.; if (fabs(lp_lat) <= tolerance) { xy_x = lp_lon; xy_y = 0.; } else if (fabs(lp_lon) <= tolerance || fabs(p2 - 1.) < tolerance) { xy_x = 0.; xy_y = pi * tan(.5 * asin(p2)); if (lp_lat < 0.) xy_y = -xy_y; } else { al = .5 * fabs(pi / lp_lon - lp_lon / pi); al2 = al * al; g = sqrt(1. - p2 * p2); g = g / (p2 + g - 1.); g2 = g * g; p2 = g * (2. / p2 - 1.); p2 = p2 * p2; xy_x = g - p2; g = p2 + al2; xy_x = pi * (al * xy_x + sqrt(al2 * xy_x * xy_x - g * (g2 - p2))) / g; if (lp_lon < 0.) xy_x = -xy_x; xy_y = fabs(xy_x / pi); xy_y = 1. - xy_y * (xy_y + 2. * al); if (xy_y < -tolerance) { BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } if (xy_y < 0.) xy_y = 0.; else xy_y = sqrt(xy_y) * (lp_lat < 0. ? -pi : pi); } }
inline void setup(Parameters const& par, par_aea<T>& proj_parm) { T cosphi, sinphi; int secant; if (fabs(proj_parm.phi1 + proj_parm.phi2) < epsilon10) BOOST_THROW_EXCEPTION( projection_exception(error_conic_lat_equal) ); proj_parm.n = sinphi = sin(proj_parm.phi1); cosphi = cos(proj_parm.phi1); secant = fabs(proj_parm.phi1 - proj_parm.phi2) >= epsilon10; if( (proj_parm.ellips = (par.es > 0.))) { T ml1, m1; proj_parm.en = pj_enfn<T>(par.es); m1 = pj_msfn(sinphi, cosphi, par.es); ml1 = pj_qsfn(sinphi, par.e, par.one_es); if (secant) { /* secant cone */ T ml2, m2; sinphi = sin(proj_parm.phi2); cosphi = cos(proj_parm.phi2); m2 = pj_msfn(sinphi, cosphi, par.es); ml2 = pj_qsfn(sinphi, par.e, par.one_es); if (ml2 == ml1) BOOST_THROW_EXCEPTION( projection_exception(0) ); proj_parm.n = (m1 * m1 - m2 * m2) / (ml2 - ml1); } proj_parm.ec = 1. - .5 * par.one_es * log((1. - par.e) / (1. + par.e)) / par.e; proj_parm.c = m1 * m1 + proj_parm.n * ml1; proj_parm.dd = 1. / proj_parm.n; proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n * pj_qsfn(sin(par.phi0), par.e, par.one_es)); } else { if (secant) proj_parm.n = .5 * (proj_parm.n + sin(proj_parm.phi2)); proj_parm.n2 = proj_parm.n + proj_parm.n; proj_parm.c = cosphi * cosphi + proj_parm.n2 * sinphi; proj_parm.dd = 1. / proj_parm.n; proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n2 * sin(par.phi0)); } }
// INVERSE(e_healpix_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the HEALPix image. */ if (in_image(xy_x, xy_y, 0, 0, 0) == 0) { lp_lon = HUGE_VAL; lp_lat = HUGE_VAL; BOOST_THROW_EXCEPTION( projection_exception(error_invalid_x_or_y) ); } healpix_sphere_inverse(xy_x, xy_y, lp_lon, lp_lat); lp_lat = auth_lat(this->params(), m_proj_parm, lp_lat, 1); }
// INVERSE(s_rhealpix_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the rHEALPix image. */ if (in_image(xy_x, xy_y, 1, this->m_proj_parm.north_square, this->m_proj_parm.south_square) == 0) { lp_lon = HUGE_VAL; lp_lat = HUGE_VAL; BOOST_THROW_EXCEPTION( projection_exception(error_invalid_x_or_y) ); } combine_caps(xy_x, xy_y, this->m_proj_parm.north_square, this->m_proj_parm.south_square, 1); return healpix_sphere_inverse(xy_x, xy_y, lp_lon, lp_lat); }
// FORWARD(e_forward) ellipsoid & spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T rho = this->m_proj_parm.c - (this->m_proj_parm.ellips ? this->m_proj_parm.n * pj_qsfn(sin(lp_lat), this->m_par.e, this->m_par.one_es) : this->m_proj_parm.n2 * sin(lp_lat)); if (rho < 0.) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); rho = this->m_proj_parm.dd * sqrt(rho); xy_x = rho * sin( lp_lon *= this->m_proj_parm.n ); xy_y = this->m_proj_parm.rho0 - rho * cos(lp_lon); }
inline void s_forward(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& /*par*/, ProjParm const& proj_parm) { static const T half_pi = detail::half_pi<T>(); T coslam, cosphi, sinphi; sinphi = sin(lp_lat); cosphi = cos(lp_lat); coslam = cos(lp_lon); switch (proj_parm.mode) { case equit: xy_y = cosphi * coslam; goto oblcon; case obliq: xy_y = proj_parm.sinph0 * sinphi + proj_parm.cosph0 * cosphi * coslam; oblcon: if (fabs(fabs(xy_y) - 1.) < tolerance) if (xy_y < 0.) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); else xy_x = xy_y = 0.; else { xy_y = acos(xy_y); xy_y /= sin(xy_y); xy_x = xy_y * cosphi * sin(lp_lon); xy_y *= (proj_parm.mode == equit) ? sinphi : proj_parm.cosph0 * sinphi - proj_parm.sinph0 * cosphi * coslam; } break; case n_pole: lp_lat = -lp_lat; coslam = -coslam; BOOST_FALLTHROUGH; case s_pole: if (fabs(lp_lat - half_pi) < epsilon10) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); xy_x = (xy_y = (half_pi + lp_lat)) * sin(lp_lon); xy_y *= coslam; break; } }
inline void setup_rhealpix(Params const& params, Parameters& par, par_healpix<T>& proj_parm) { proj_parm.north_square = pj_get_param_i<srs::spar::north_square>(params, "north_square", srs::dpar::north_square); proj_parm.south_square = pj_get_param_i<srs::spar::south_square>(params, "south_square", srs::dpar::south_square); /* Check for valid north_square and south_square inputs. */ if ((proj_parm.north_square < 0) || (proj_parm.north_square > 3)) { BOOST_THROW_EXCEPTION( projection_exception(error_axis) ); } if ((proj_parm.south_square < 0) || (proj_parm.south_square > 3)) { BOOST_THROW_EXCEPTION( projection_exception(error_axis) ); } if (par.es != 0.0) { proj_parm.apa = pj_authset<T>(par.es); /* For auth_lat(). */ proj_parm.qp = pj_qsfn(1.0, par.e, par.one_es); /* For auth_lat(). */ par.a = par.a*sqrt(0.5*proj_parm.qp); /* Set par.a to authalic radius. */ // TODO: why not the same as in healpix? //pj_calc_ellipsoid_params(par, par.a, par.es); par.ra = 1.0/par.a; } else { } }
inline void setup_lcca(Parameters& par, par_lcca<T>& proj_parm) { T s2p0, N0, R0, tan0, tan20; if (!pj_enfn(par.es, proj_parm.en)) BOOST_THROW_EXCEPTION( projection_exception(0) ); if (!pj_param(par.params, "tlat_0").i) BOOST_THROW_EXCEPTION( projection_exception(50) ); if (par.phi0 == 0.) BOOST_THROW_EXCEPTION( projection_exception(51) ); proj_parm.l = sin(par.phi0); proj_parm.M0 = pj_mlfn(par.phi0, proj_parm.l, cos(par.phi0), proj_parm.en); s2p0 = proj_parm.l * proj_parm.l; R0 = 1. / (1. - par.es * s2p0); N0 = sqrt(R0); R0 *= par.one_es * N0; tan0 = tan(par.phi0); tan20 = tan0 * tan0; proj_parm.r0 = N0 / tan0; proj_parm.C = 1. / (6. * R0 * N0); boost::ignore_unused(tan20); }
inline void setup_wintri(Params& params, Parameters& par, par_aitoff<T>& proj_parm) { static const T two_div_pi = detail::two_div_pi<T>(); T phi1; proj_parm.mode = mode_winkel_tripel; if (pj_param_r<srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1, phi1)) { if ((proj_parm.cosphi1 = cos(phi1)) == 0.) BOOST_THROW_EXCEPTION( projection_exception(error_lat_larger_than_90) ); } else /* 50d28' or phi1=acos(2/pi) */ proj_parm.cosphi1 = two_div_pi; setup(par); }
inline T aacos(T const& v) { T av = 0; if ((av = geometry::math::abs(v)) >= 1.0) { if (av > aasincos::ONE_TOL<T>()) { BOOST_THROW_EXCEPTION( projection_exception(error_acos_asin_arg_too_large) ); } return (v < 0.0 ? geometry::math::pi<T>() : 0.0); } return acos(v); }
inline void setup_oea(Params const& params, Parameters& par, par_oea<T>& proj_parm) { if (((proj_parm.n = pj_get_param_f<T, srs::spar::n>(params, "n", srs::dpar::n)) <= 0.) || ((proj_parm.m = pj_get_param_f<T, srs::spar::m>(params, "m", srs::dpar::m)) <= 0.)) { BOOST_THROW_EXCEPTION( projection_exception(error_invalid_m_or_n) ); } else { proj_parm.theta = pj_get_param_r<T, srs::spar::theta>(params, "theta", srs::dpar::theta); proj_parm.sp0 = sin(par.phi0); proj_parm.cp0 = cos(par.phi0); proj_parm.rn = 1./ proj_parm.n; proj_parm.rm = 1./ proj_parm.m; proj_parm.two_r_n = 2. * proj_parm.rn; proj_parm.two_r_m = 2. * proj_parm.rm; proj_parm.hm = 0.5 * proj_parm.m; proj_parm.hn = 0.5 * proj_parm.n; par.es = 0.; } }
// INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi<T>(); static const T pi = detail::pi<T>(); static const T pi_sqr = detail::pi_sqr<T>(); static const T third = detail::third<T>(); static const T two_pi = detail::two_pi<T>(); static const T C2_27 = vandg::C2_27<T>(); static const T PI4_3 = vandg::PI4_3<T>(); static const T TPISQ = vandg::TPISQ<T>(); static const T HPISQ = vandg::HPISQ<T>(); T t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2; x2 = xy_x * xy_x; if ((ay = fabs(xy_y)) < tolerance) { lp_lat = 0.; t = x2 * x2 + TPISQ * (x2 + HPISQ); lp_lon = fabs(xy_x) <= tolerance ? 0. : .5 * (x2 - pi_sqr + sqrt(t)) / xy_x; return; } y2 = xy_y * xy_y; r = x2 + y2; r2 = r * r; c1 = - pi * ay * (r + pi_sqr); c3 = r2 + two_pi * (ay * r + pi * (y2 + pi * (ay + half_pi))); c2 = c1 + pi_sqr * (r - 3. * y2); c0 = pi * ay; c2 /= c3; al = c1 / c3 - third * c2 * c2; m = 2. * sqrt(-third * al); d = C2_27 * c2 * c2 * c2 + (c0 * c0 - third * c2 * c1) / c3; if (((t = fabs(d = 3. * d / (al * m))) - tolerance) <= 1.) { d = t > 1. ? (d > 0. ? 0. : pi) : acos(d); lp_lat = pi * (m * cos(d * third + PI4_3) - third * c2); if (xy_y < 0.) lp_lat = -lp_lat; t = r2 + TPISQ * (x2 - y2 + HPISQ); lp_lon = fabs(xy_x) <= tolerance ? 0. : .5 * (r - pi_sqr + (t <= 0. ? 0. : sqrt(t))) / xy_x; } else { BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } }
inline T pj_inv_mlfn(T const& arg, T const& es, detail::en<T> const& en) { static const T EPS = 1e-11; static const int MAX_ITER = 10; T s, t, phi, k = 1./(1.-es); int i; phi = arg; for (i = MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */ s = sin(phi); t = 1. - es * s * s; phi -= t = (pj_mlfn(phi, s, cos(phi), en) - arg) * (t * sqrt(t)) * k; if (geometry::math::abs(t) < EPS) return phi; } BOOST_THROW_EXCEPTION( projection_exception(error_non_conv_inv_meri_dist) ); return phi; }
// INVERSE(e_inverse) ellipsoid & spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const { CalculationType theta, dr, S, dif; int i; xy_x /= this->m_par.k0; xy_y /= this->m_par.k0; theta = atan2(xy_x , this->m_proj_parm.r0 - xy_y); dr = xy_y - xy_x * tan(0.5 * theta); lp_lon = theta / this->m_proj_parm.l; S = dr; for (i = MAX_ITER; i ; --i) { S -= (dif = (fS(S, this->m_proj_parm.C) - dr) / fSp(S, this->m_proj_parm.C)); if (fabs(dif) < DEL_TOL) break; } if (!i) BOOST_THROW_EXCEPTION( projection_exception(-20) ); lp_lat = pj_inv_mlfn(S + this->m_proj_parm.M0, this->m_par.es, this->m_proj_parm.en); }
inline void setup(Parameters& par, par_nsper<T>& proj_parm) { if ((proj_parm.height = pj_param(par.params, "dh").f) <= 0.) BOOST_THROW_EXCEPTION( projection_exception(-30) ); if (fabs(fabs(par.phi0) - geometry::math::half_pi<T>()) < EPS10) proj_parm.mode = par.phi0 < 0. ? S_POLE : N_POLE; else if (fabs(par.phi0) < EPS10) proj_parm.mode = EQUIT; else { proj_parm.mode = OBLIQ; proj_parm.sinph0 = sin(par.phi0); proj_parm.cosph0 = cos(par.phi0); } proj_parm.pn1 = proj_parm.height / par.a; /* normalize by radius */ proj_parm.p = 1. + proj_parm.pn1; proj_parm.rp = 1. / proj_parm.p; proj_parm.h = 1. / proj_parm.pn1; proj_parm.pfact = (proj_parm.p + 1.) * proj_parm.h; par.es = 0.; }
inline void setup(Params const& params, Parameters& par, par_nsper<T>& proj_parm) { proj_parm.height = pj_get_param_f<T, srs::spar::h>(params, "h", srs::dpar::h); if (proj_parm.height <= 0.) BOOST_THROW_EXCEPTION( projection_exception(error_h_less_than_zero) ); if (fabs(fabs(par.phi0) - geometry::math::half_pi<T>()) < epsilon10) proj_parm.mode = par.phi0 < 0. ? s_pole : n_pole; else if (fabs(par.phi0) < epsilon10) proj_parm.mode = equit; else { proj_parm.mode = obliq; proj_parm.sinph0 = sin(par.phi0); proj_parm.cosph0 = cos(par.phi0); } proj_parm.pn1 = proj_parm.height / par.a; /* normalize by radius */ proj_parm.p = 1. + proj_parm.pn1; proj_parm.rp = 1. / proj_parm.p; proj_parm.h = 1. / proj_parm.pn1; proj_parm.pfact = (proj_parm.p + 1.) * proj_parm.h; par.es = 0.; }
inline void setup_tpeqd(Params const& params, Parameters& par, par_tpeqd<T>& proj_parm) { T lam_1, lam_2, phi_1, phi_2, A12, pp; /* get control point locations */ phi_1 = pj_get_param_r<T, srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1); lam_1 = pj_get_param_r<T, srs::spar::lon_1>(params, "lon_1", srs::dpar::lon_1); phi_2 = pj_get_param_r<T, srs::spar::lat_2>(params, "lat_2", srs::dpar::lat_2); lam_2 = pj_get_param_r<T, srs::spar::lon_2>(params, "lon_2", srs::dpar::lon_2); if (phi_1 == phi_2 && lam_1 == lam_2) BOOST_THROW_EXCEPTION( projection_exception(error_control_point_no_dist) ); par.lam0 = adjlon(0.5 * (lam_1 + lam_2)); proj_parm.dlam2 = adjlon(lam_2 - lam_1); proj_parm.cp1 = cos(phi_1); proj_parm.cp2 = cos(phi_2); proj_parm.sp1 = sin(phi_1); proj_parm.sp2 = sin(phi_2); proj_parm.cs = proj_parm.cp1 * proj_parm.sp2; proj_parm.sc = proj_parm.sp1 * proj_parm.cp2; proj_parm.ccs = proj_parm.cp1 * proj_parm.cp2 * sin(proj_parm.dlam2); proj_parm.z02 = aacos(proj_parm.sp1 * proj_parm.sp2 + proj_parm.cp1 * proj_parm.cp2 * cos(proj_parm.dlam2)); proj_parm.hz0 = .5 * proj_parm.z02; A12 = atan2(proj_parm.cp2 * sin(proj_parm.dlam2), proj_parm.cp1 * proj_parm.sp2 - proj_parm.sp1 * proj_parm.cp2 * cos(proj_parm.dlam2)); proj_parm.ca = cos(pp = aasin(proj_parm.cp1 * sin(A12))); proj_parm.sa = sin(pp); proj_parm.lp = adjlon(atan2(proj_parm.cp1 * cos(A12), proj_parm.sp1) - proj_parm.hz0); proj_parm.dlam2 *= .5; proj_parm.lamc = geometry::math::half_pi<T>() - atan2(sin(A12) * proj_parm.sp1, cos(A12)) - proj_parm.dlam2; proj_parm.thz0 = tan(proj_parm.hz0); proj_parm.rhshz0 = .5 / sin(proj_parm.hz0); proj_parm.r2z0 = 0.5 / proj_parm.z02; proj_parm.z02 *= proj_parm.z02; par.es = 0.; }
// FORWARD(s_forward) sphere // Project coordinates from geographic (lon, lat) to cartesian (x, y) inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { if (this->m_proj_parm.m == 0.0) lp_lat = this->m_proj_parm.n != 1. ? aasin(this->m_proj_parm.n * sin(lp_lat)): lp_lat; else { T k, V; int i; k = this->m_proj_parm.n * sin(lp_lat); for (i = max_iter; i ; --i) { lp_lat -= V = (this->m_proj_parm.m * lp_lat + sin(lp_lat) - k) / (this->m_proj_parm.m + cos(lp_lat)); if (fabs(V) < loop_tol) break; } if (!i) { BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } } xy_x = this->m_proj_parm.C_x * lp_lon * (this->m_proj_parm.m + cos(lp_lat)); xy_y = this->m_proj_parm.C_y * lp_lat; }
inline void s_inverse(T xy_x, T xy_y, T& lp_lon, T& lp_lat, Par const& par, ProjParm const& proj_parm) { static const T pi = detail::pi<T>(); static const T half_pi = detail::half_pi<T>(); T cosc, c_rh, sinc; if ((c_rh = boost::math::hypot(xy_x, xy_y)) > pi) { if (c_rh - epsilon10 > pi) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); c_rh = pi; } else if (c_rh < epsilon10) { lp_lat = par.phi0; lp_lon = 0.; return; } if (proj_parm.mode == obliq || proj_parm.mode == equit) { sinc = sin(c_rh); cosc = cos(c_rh); if (proj_parm.mode == equit) { lp_lat = aasin(xy_y * sinc / c_rh); xy_x *= sinc; xy_y = cosc * c_rh; } else { lp_lat = aasin(cosc * proj_parm.sinph0 + xy_y * sinc * proj_parm.cosph0 / c_rh); xy_y = (cosc - proj_parm.sinph0 * sin(lp_lat)) * c_rh; xy_x *= sinc * proj_parm.cosph0; } lp_lon = xy_y == 0. ? 0. : atan2(xy_x, xy_y); } else if (proj_parm.mode == n_pole) { lp_lat = half_pi - c_rh; lp_lon = atan2(xy_x, -xy_y); } else { lp_lat = c_rh - half_pi; lp_lon = atan2(xy_x, xy_y); } }