#define PROJ_PARMS__ \ double phits; \ double sinX1; \ double cosX1; \ double akm1; \ int mode; #define PJ_LIB__ #include PROJ_HEAD(stere, "Stereographic") "\n\tAzi, Sph&Ell\n\tlat_ts="; PROJ_HEAD(ups, "Universal Polar Stereographic") "\n\tAzi, Sph&Ell\n\tsouth"; #define sinph0 P->sinX1 #define cosph0 P->cosX1 #define EPS10 1.e-10 #define TOL 1.e-8 #define NITER 8 #define CONV 1.e-10 #define S_POLE 0 #define N_POLE 1 #define OBLIQ 2 #define EQUIT 3 static double ssfn_(double phit, double sinphi, double eccen) { sinphi *= eccen; return (tan (.5 * (HALFPI + phit)) * pow((1. - sinphi) / (1. + sinphi), .5 * eccen)); } FORWARD(e_forward); /* ellipsoid */ double coslam, sinlam, sinX=0.0, cosX=0.0, X, A, sinphi; coslam = cos(lp.lam); sinlam = sin(lp.lam); sinphi = sin(lp.phi); if (P->mode == OBLIQ || P->mode == EQUIT) { sinX = sin(X = 2. * atan(ssfn_(lp.phi, sinphi, P->e)) - HALFPI); cosX = cos(X); } switch (P->mode) { case OBLIQ: A = P->akm1 / (P->cosX1 * (1. + P->sinX1 * sinX + P->cosX1 * cosX * coslam)); xy.y = A * (P->cosX1 * sinX - P->sinX1 * cosX * coslam); goto xmul; case EQUIT: A = 2. * P->akm1 / (1. + cosX * coslam); xy.y = A * sinX; xmul: xy.x = A * cosX; break; case S_POLE: lp.phi = -lp.phi; coslam = - coslam; sinphi = -sinphi; case N_POLE: xy.x = P->akm1 * pj_tsfn(lp.phi, sinphi, P->e); xy.y = - xy.x * coslam; break; } xy.x = xy.x * sinlam; return (xy); } FORWARD(s_forward); /* spheroid */ double sinphi, cosphi, coslam, sinlam; sinphi = sin(lp.phi); cosphi = cos(lp.phi); coslam = cos(lp.lam); sinlam = sin(lp.lam); switch (P->mode) { case EQUIT: xy.y = 1. + cosphi * coslam; goto oblcon; case OBLIQ: xy.y = 1. + sinph0 * sinphi + cosph0 * cosphi * coslam; oblcon: if (xy.y <= EPS10) F_ERROR; xy.x = (xy.y = P->akm1 / xy.y) * cosphi * sinlam; xy.y *= (P->mode == EQUIT) ? sinphi : cosph0 * sinphi - sinph0 * cosphi * coslam; break; case N_POLE: coslam = - coslam; lp.phi = - lp.phi; case S_POLE: if (fabs(lp.phi - HALFPI) < TOL) F_ERROR; xy.x = sinlam * ( xy.y = P->akm1 * tan(FORTPI + .5 * lp.phi) ); xy.y *= coslam; break; } return (xy); } INVERSE(e_inverse); /* ellipsoid */ double cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, halfpi=0.0; int i; rho = hypot(xy.x, xy.y); switch (P->mode) { case OBLIQ: case EQUIT: cosphi = cos( tp = 2. * atan2(rho * P->cosX1 , P->akm1) ); sinphi = sin(tp); if( rho == 0.0 ) phi_l = asin(cosphi * P->sinX1); else phi_l = asin(cosphi * P->sinX1 + (xy.y * sinphi * P->cosX1 / rho)); tp = tan(.5 * (HALFPI + phi_l)); xy.x *= sinphi; xy.y = rho * P->cosX1 * cosphi - xy.y * P->sinX1* sinphi; halfpi = HALFPI; halfe = .5 * P->e; break; case N_POLE: xy.y = -xy.y; case S_POLE: phi_l = HALFPI - 2. * atan(tp = - rho / P->akm1); halfpi = -HALFPI; halfe = -.5 * P->e; break; } for (i = NITER; i--; phi_l = lp.phi) { sinphi = P->e * sin(phi_l); lp.phi = 2. * atan(tp * pow((1.+sinphi)/(1.-sinphi), halfe)) - halfpi; if (fabs(phi_l - lp.phi) < CONV) { if (P->mode == S_POLE) lp.phi = -lp.phi; lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2(xy.x, xy.y); return (lp); } } I_ERROR; } INVERSE(s_inverse); /* spheroid */ double c, rh, sinc, cosc; sinc = sin(c = 2. * atan((rh = hypot(xy.x, xy.y)) / P->akm1)); cosc = cos(c); lp.lam = 0.; switch (P->mode) { case EQUIT: if (fabs(rh) <= EPS10) lp.phi = 0.; else lp.phi = asin(xy.y * sinc / rh); if (cosc != 0. || xy.x != 0.) lp.lam = atan2(xy.x * sinc, cosc * rh); break; case OBLIQ: if (fabs(rh) <= EPS10) lp.phi = P->phi0; else lp.phi = asin(cosc * sinph0 + xy.y * sinc * cosph0 / rh); if ((c = cosc - sinph0 * sin(lp.phi)) != 0. || xy.x != 0.) lp.lam = atan2(xy.x * sinc * cosph0, c * rh); break; case N_POLE: xy.y = -xy.y; case S_POLE: if (fabs(rh) <= EPS10) lp.phi = P->phi0; else lp.phi = asin(P->mode == S_POLE ? - cosc : cosc); lp.lam = (xy.x == 0. && xy.y == 0.) ? 0. : atan2(xy.x, xy.y); break; } return (lp); } FREEUP; if (P) pj_dalloc(P); } static PJ * setup(PJ *P) { /* general initialization */ double t; if (fabs((t = fabs(P->phi0)) - HALFPI) < EPS10) P->mode = P->phi0 < 0. ? S_POLE : N_POLE; else P->mode = t > EPS10 ? OBLIQ : EQUIT; P->phits = fabs(P->phits); if (P->es) { double X; switch (P->mode) { case N_POLE: case S_POLE: if (fabs(P->phits - HALFPI) < EPS10) P->akm1 = 2. * P->k0 / sqrt(pow(1+P->e,1+P->e)*pow(1-P->e,1-P->e)); else { P->akm1 = cos(P->phits) / pj_tsfn(P->phits, t = sin(P->phits), P->e); t *= P->e; P->akm1 /= sqrt(1. - t * t); } break; case EQUIT: case OBLIQ: t = sin(P->phi0); X = 2. * atan(ssfn_(P->phi0, t, P->e)) - HALFPI; t *= P->e; P->akm1 = 2. * P->k0 * cos(P->phi0) / sqrt(1. - t * t); P->sinX1 = sin(X); P->cosX1 = cos(X); break; } P->inv = e_inverse; P->fwd = e_forward; } else { switch (P->mode) { case OBLIQ: sinph0 = sin(P->phi0); cosph0 = cos(P->phi0); case EQUIT: P->akm1 = 2. * P->k0; break; case S_POLE: case N_POLE: P->akm1 = fabs(P->phits - HALFPI) >= EPS10 ? cos(P->phits) / tan(FORTPI - .5 * P->phits) : 2. * P->k0 ; break; } P->inv = s_inverse; P->fwd = s_forward; } return P; } ENTRY0(stere) P->phits = pj_param(P->ctx, P->params, "tlat_ts").i ? pj_param(P->ctx, P->params, "rlat_ts").f : HALFPI; ENDENTRY(setup(P)) ENTRY0(ups) /* International Ellipsoid */ P->phi0 = pj_param(P->ctx, P->params, "bsouth").i ? - HALFPI: HALFPI; if (!P->es) E_ERROR(-34); P->k0 = .994; P->x0 = 2000000.; P->y0 = 2000000.; P->phits = HALFPI; P->lam0 = 0.; ENDENTRY(setup(P))