PJ *PROJECTION(laea) { double t; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; P->destructor = destructor; t = fabs(P->phi0); if (fabs(t - M_HALFPI) < EPS10) Q->mode = P->phi0 < 0. ? S_POLE : N_POLE; else if (fabs(t) < EPS10) Q->mode = EQUIT; else Q->mode = OBLIQ; if (P->es != 0.0) { double sinphi; P->e = sqrt(P->es); Q->qp = pj_qsfn(1., P->e, P->one_es); Q->mmf = .5 / (1. - P->es); Q->apa = pj_authset(P->es); if (0==Q->apa) return destructor(P, ENOMEM); switch (Q->mode) { case N_POLE: case S_POLE: Q->dd = 1.; break; case EQUIT: Q->dd = 1. / (Q->rq = sqrt(.5 * Q->qp)); Q->xmf = 1.; Q->ymf = .5 * Q->qp; break; case OBLIQ: Q->rq = sqrt(.5 * Q->qp); sinphi = sin(P->phi0); Q->sinb1 = pj_qsfn(sinphi, P->e, P->one_es) / Q->qp; Q->cosb1 = sqrt(1. - Q->sinb1 * Q->sinb1); Q->dd = cos(P->phi0) / (sqrt(1. - P->es * sinphi * sinphi) * Q->rq * Q->cosb1); Q->ymf = (Q->xmf = Q->rq) / Q->dd; Q->xmf *= Q->dd; break; } P->inv = e_inverse; P->fwd = e_forward; } else { if (Q->mode == OBLIQ) { Q->sinb1 = sin(P->phi0); Q->cosb1 = cos(P->phi0); } P->inv = s_inverse; P->fwd = s_forward; } return P; }
static PJ_XY e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal/spheroidal, forward */ PJ_XY xy = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double sbeta; double psi, psi2, psi6; /* Spheroidal case, using sine latitude */ sbeta = sin(lp.phi); /* In the ellipsoidal case, we convert sbeta to sine of authalic latitude */ if (P->es != 0.0) { sbeta = pj_qsfn(sbeta, P->e, 1.0 - P->es) / Q->qp; /* Rounding error. */ if (fabs(sbeta) > 1) sbeta = sbeta > 0 ? 1 : -1; } /* Equal Earth projection */ psi = asin(M * sbeta); psi2 = psi * psi; psi6 = psi2 * psi2 * psi2; xy.x = lp.lam * cos(psi) / (M * (A1 + 3 * A2 * psi2 + psi6 * (7 * A3 + 9 * A4 * psi2))); xy.y = psi * (A1 + A2 * psi2 + psi6 * (A3 + A4 * psi2)); /* Adjusting x and y for authalic radius */ xy.x *= Q->rqda; xy.y *= Q->rqda; return xy; }
PJ *PROJECTION(rhealpix) { struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; Q->north_square = pj_param(P->ctx, P->params,"inorth_square").i; Q->south_square = pj_param(P->ctx, P->params,"isouth_square").i; /* Check for valid north_square and south_square inputs. */ if (Q->north_square < 0 || Q->north_square > 3) { E_ERROR(-47); } if (Q->south_square < 0 || Q->south_square > 3) { E_ERROR(-47); } if (P->es) { Q->apa = pj_authset(P->es); /* For auth_lat(). */ Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; P->fwd = e_rhealpix_forward; P->inv = e_rhealpix_inverse; } else { P->fwd = s_rhealpix_forward; P->inv = s_rhealpix_inverse; } return P; }
static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; coslam = cos(lp.lam); sinlam = sin(lp.lam); sinphi = sin(lp.phi); q = pj_qsfn(sinphi, P->e, P->one_es); if (Q->mode == OBLIQ || Q->mode == EQUIT) { sinb = q / Q->qp; cosb = sqrt(1. - sinb * sinb); } switch (Q->mode) { case OBLIQ: b = 1. + Q->sinb1 * sinb + Q->cosb1 * cosb * coslam; break; case EQUIT: b = 1. + cosb * coslam; break; case N_POLE: b = M_HALFPI + lp.phi; q = Q->qp - q; break; case S_POLE: b = lp.phi - M_HALFPI; q = Q->qp + q; break; } if (fabs(b) < EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } switch (Q->mode) { case OBLIQ: b = sqrt(2. / b); xy.y = Q->ymf * b * (Q->cosb1 * sinb - Q->sinb1 * cosb * coslam); goto eqcon; break; case EQUIT: b = sqrt(2. / (1. + cosb * coslam)); xy.y = b * sinb * Q->ymf; eqcon: xy.x = Q->xmf * b * cosb * sinlam; break; case N_POLE: case S_POLE: if (q >= 0.) { b = sqrt(q); xy.x = b * sinlam; xy.y = coslam * (Q->mode == S_POLE ? b : -b); } else xy.x = xy.y = 0.; break; } return xy; }
void setup_laea(Parameters& par, par_laea& proj_parm) { double t; if (fabs((t = fabs(par.phi0)) - HALFPI) < EPS10) proj_parm.mode = par.phi0 < 0. ? S_POLE : N_POLE; else if (fabs(t) < EPS10) proj_parm.mode = EQUIT; else proj_parm.mode = OBLIQ; if (par.es) { double sinphi; par.e = sqrt(par.es); proj_parm.qp = pj_qsfn(1., par.e, par.one_es); proj_parm.mmf = .5 / (1. - par.es); pj_authset(par.es, proj_parm.apa); switch (proj_parm.mode) { case N_POLE: case S_POLE: proj_parm.dd = 1.; break; case EQUIT: proj_parm.dd = 1. / (proj_parm.rq = sqrt(.5 * proj_parm.qp)); proj_parm.xmf = 1.; proj_parm.ymf = .5 * proj_parm.qp; break; case OBLIQ: proj_parm.rq = sqrt(.5 * proj_parm.qp); sinphi = sin(par.phi0); proj_parm.sinb1 = pj_qsfn(sinphi, par.e, par.one_es) / proj_parm.qp; proj_parm.cosb1 = sqrt(1. - proj_parm.sinb1 * proj_parm.sinb1); proj_parm.dd = cos(par.phi0) / (sqrt(1. - par.es * sinphi * sinphi) * proj_parm.rq * proj_parm.cosb1); proj_parm.ymf = (proj_parm.xmf = proj_parm.rq) / proj_parm.dd; proj_parm.xmf *= proj_parm.dd; break; } // par.inv = e_inverse; // par.fwd = e_forward; } else { if (proj_parm.mode == OBLIQ) { proj_parm.sinb1 = sin(par.phi0); proj_parm.cosb1 = cos(par.phi0); } // par.inv = s_inverse; // par.fwd = s_forward; } }
inline void setup_healpix(Parameters& par, par_healpix<T>& proj_parm) { 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. */ pj_calc_ellipsoid_params(par, par.a, par.es); /* Ensure we have a consistent parameter set */ } else { } }
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)); } }
inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const { double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; coslam = cos(lp_lon); sinlam = sin(lp_lon); sinphi = sin(lp_lat); q = pj_qsfn(sinphi, this->m_par.e, this->m_par.one_es); if (this->m_proj_parm.mode == OBLIQ || this->m_proj_parm.mode == EQUIT) { sinb = q / this->m_proj_parm.qp; cosb = sqrt(1. - sinb * sinb); } switch (this->m_proj_parm.mode) { case OBLIQ: b = 1. + this->m_proj_parm.sinb1 * sinb + this->m_proj_parm.cosb1 * cosb * coslam; break; case EQUIT: b = 1. + cosb * coslam; break; case N_POLE: b = HALFPI + lp_lat; q = this->m_proj_parm.qp - q; break; case S_POLE: b = lp_lat - HALFPI; q = this->m_proj_parm.qp + q; break; } if (fabs(b) < EPS10) throw proj_exception();; switch (this->m_proj_parm.mode) { case OBLIQ: xy_y = this->m_proj_parm.ymf * ( b = sqrt(2. / b) ) * (this->m_proj_parm.cosb1 * sinb - this->m_proj_parm.sinb1 * cosb * coslam); goto eqcon; break; case EQUIT: xy_y = (b = sqrt(2. / (1. + cosb * coslam))) * sinb * this->m_proj_parm.ymf; eqcon: xy_x = this->m_proj_parm.xmf * b * cosb * sinlam; break; case N_POLE: case S_POLE: if (q >= 0.) { xy_x = (b = sqrt(q)) * sinlam; xy_y = coslam * (this->m_proj_parm.mode == S_POLE ? b : -b); } else xy_x = xy_y = 0.; break; } }
/** * Return the authalic latitude of latitude alpha (if inverse=0) or * return the approximate latitude of authalic latitude alpha (if inverse=1). * P contains the relavent ellipsoid parameters. **/ double auth_lat(PJ *P, double alpha, int inverse) { if (inverse == 0) { /* Authalic latitude. */ double q = pj_qsfn(sin(alpha), P->e, 1.0 - P->es); double qp = P->qp; double ratio = q/qp; if (fabsl(ratio) > 1) { /* Rounding error. */ ratio = pj_sign(ratio); } return asin(ratio); } else { /* Approximation to inverse authalic latitude. */ return pj_authlat(alpha, P->apa); } }
void setup_cea(Parameters& par, par_cea& proj_parm) { double t = 0; if (pj_param(par.params, "tlat_ts").i && (par.k0 = cos(t = pj_param(par.params, "rlat_ts").f)) < 0.) throw proj_exception(-24); if (par.es) { t = sin(t); par.k0 /= sqrt(1. - par.es * t * t); par.e = sqrt(par.es); if (!pj_authset(par.es, proj_parm.apa)) throw proj_exception(0); proj_parm.qp = pj_qsfn(1., par.e, par.one_es); } else { } }
void setup_cea(Parameters& par, par_cea& proj_parm) { double t = 0; if (pj_param(par.params, "tlat_ts").i && (par.k0 = cos(t = pj_param(par.params, "rlat_ts").f)) < 0.) throw proj_exception(-24); if (par.es) { t = sin(t); par.k0 /= sqrt(1. - par.es * t * t); par.e = sqrt(par.es); pj_authset(par.es, proj_parm.apa); proj_parm.qp = pj_qsfn(1., par.e, par.one_es); // par.inv = e_inverse; // par.fwd = e_forward; } else { // par.inv = s_inverse; // par.fwd = s_forward; } }
inline T auth_lat(const Parameters& par, const par_healpix<T>& proj_parm, T const& alpha, int inverse) { if (inverse == 0) { /* Authalic latitude. */ T q = pj_qsfn(sin(alpha), par.e, 1.0 - par.es); T qp = proj_parm.qp; T ratio = q/qp; if (math::abs(ratio) > 1) { /* Rounding error. */ ratio = pj_sign(ratio); } return asin(ratio); } else { /* Approximation to inverse authalic latitude. */ return pj_authlat(alpha, proj_parm.apa); } }
PJ *PROJECTION(healpix) { struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) return freeup_new (P); P->opaque = Q; if (P->es) { Q->apa = pj_authset(P->es); /* For auth_lat(). */ Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; P->fwd = e_healpix_forward; P->inv = e_healpix_inverse; } else { P->fwd = s_healpix_forward; P->inv = s_healpix_inverse; } return P; }
PJ *PROJECTION(eqearth) { struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque))); if (nullptr==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; P->destructor = destructor; P->fwd = e_forward; P->inv = e_inverse; Q->rqda = 1.0; /* Ellipsoidal case */ if (P->es != 0.0) { Q->apa = pj_authset(P->es); /* For auth_lat(). */ if (nullptr == Q->apa) return destructor(P, ENOMEM); Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ Q->rqda = sqrt(0.5*Q->qp); /* Authalic radius divided by major axis */ } return P; }
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 { } }
#define sinph0 P->sinb1 #define cosph0 P->cosb1 #define EPS10 1.e-10 #define NITER 20 #define CONV 1.e-10 #define N_POLE 0 #define S_POLE 1 #define EQUIT 2 #define OBLIQ 3 FORWARD(e_forward); /* ellipsoid */ double coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0; coslam = cos(lp.lam); sinlam = sin(lp.lam); sinphi = sin(lp.phi); q = pj_qsfn(sinphi, P->e, P->one_es); if (P->mode == OBLIQ || P->mode == EQUIT) { sinb = q / P->qp; cosb = sqrt(1. - sinb * sinb); } switch (P->mode) { case OBLIQ: b = 1. + P->sinb1 * sinb + P->cosb1 * cosb * coslam; break; case EQUIT: b = 1. + cosb * coslam; break; case N_POLE: b = HALFPI + lp.phi; q = P->qp - q; break;
// 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 fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const { xy_x = this->m_par.k0 * lp_lon; xy_y = .5 * pj_qsfn(sin(lp_lat), this->m_par.e, this->m_par.one_es) / this->m_par.k0; }