#define PROJ_PARMS__ \ double height; \ double sinph0; \ double cosph0; \ double p; \ double rp; \ double pn1; \ double pfact; \ double h; \ double cg; \ double sg; \ double sw; \ double cw; \ int mode; \ int tilt; #define PJ_LIB__ #include PROJ_HEAD(nsper, "Near-sided perspective") "\n\tAzi, Sph\n\th="; PROJ_HEAD(tpers, "Tilted perspective") "\n\tAzi, Sph\n\ttilt= azi= h="; # define EPS10 1.e-10 # define N_POLE 0 # define S_POLE 1 # define EQUIT 2 # define OBLIQ 3 FORWARD(s_forward); /* spheroid */ double coslam, cosphi, sinphi; sinphi = sin(lp.phi); cosphi = cos(lp.phi); coslam = cos(lp.lam); switch (P->mode) { case OBLIQ: xy.y = P->sinph0 * sinphi + P->cosph0 * cosphi * coslam; break; case EQUIT: xy.y = cosphi * coslam; break; case S_POLE: xy.y = - sinphi; break; case N_POLE: xy.y = sinphi; break; } if (xy.y < P->rp) F_ERROR; xy.y = P->pn1 / (P->p - xy.y); xy.x = xy.y * cosphi * sin(lp.lam); switch (P->mode) { case OBLIQ: xy.y *= (P->cosph0 * sinphi - P->sinph0 * cosphi * coslam); break; case EQUIT: xy.y *= sinphi; break; case N_POLE: coslam = - coslam; case S_POLE: xy.y *= cosphi * coslam; break; } if (P->tilt) { double yt, ba; yt = xy.y * P->cg + xy.x * P->sg; ba = 1. / (yt * P->sw * P->h + P->cw); xy.x = (xy.x * P->cg - xy.y * P->sg) * P->cw * ba; xy.y = yt * ba; } return (xy); } INVERSE(s_inverse); /* spheroid */ double rh, cosz, sinz; if (P->tilt) { double bm, bq, yt; yt = 1./(P->pn1 - xy.y * P->sw); bm = P->pn1 * xy.x * yt; bq = P->pn1 * xy.y * P->cw * yt; xy.x = bm * P->cg + bq * P->sg; xy.y = bq * P->cg - bm * P->sg; } rh = hypot(xy.x, xy.y); if ((sinz = 1. - rh * rh * P->pfact) < 0.) I_ERROR; sinz = (P->p - sqrt(sinz)) / (P->pn1 / rh + rh / P->pn1); cosz = sqrt(1. - sinz * sinz); if (fabs(rh) <= EPS10) { lp.lam = 0.; lp.phi = P->phi0; } else { switch (P->mode) { case OBLIQ: lp.phi = asin(cosz * P->sinph0 + xy.y * sinz * P->cosph0 / rh); xy.y = (cosz - P->sinph0 * sin(lp.phi)) * rh; xy.x *= sinz * P->cosph0; break; case EQUIT: lp.phi = asin(xy.y * sinz / rh); xy.y = cosz * rh; xy.x *= sinz; break; case N_POLE: lp.phi = asin(cosz); xy.y = -xy.y; break; case S_POLE: lp.phi = - asin(cosz); break; } lp.lam = atan2(xy.x, xy.y); } return (lp); } FREEUP; if (P) pj_dalloc(P); } static PJ * setup(PJ *P) { if ((P->height = pj_param(P->ctx, P->params, "dh").f) <= 0.) E_ERROR(-30); if (fabs(fabs(P->phi0) - HALFPI) < EPS10) P->mode = P->phi0 < 0. ? S_POLE : N_POLE; else if (fabs(P->phi0) < EPS10) P->mode = EQUIT; else { P->mode = OBLIQ; P->sinph0 = sin(P->phi0); P->cosph0 = cos(P->phi0); } P->pn1 = P->height / P->a; /* normalize by radius */ P->p = 1. + P->pn1; P->rp = 1. / P->p; P->h = 1. / P->pn1; P->pfact = (P->p + 1.) * P->h; P->inv = s_inverse; P->fwd = s_forward; P->es = 0.; return P; } ENTRY0(nsper) P->tilt = 0; ENDENTRY(setup(P)) ENTRY0(tpers) double omega, gamma; omega = pj_param(P->ctx, P->params, "dtilt").f * DEG_TO_RAD; gamma = pj_param(P->ctx, P->params, "dazi").f * DEG_TO_RAD; P->tilt = 1; P->cg = cos(gamma); P->sg = sin(gamma); P->cw = cos(omega); P->sw = sin(omega); ENDENTRY(setup(P))