static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; lp.phi = xy.y / FYC; if (fabs(lp.phi) >= 1.) { if (fabs(lp.phi) > ONEEPS) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else { lp.phi = (lp.phi < 0.) ? -M_HALFPI : M_HALFPI; } } else lp.phi = asin(lp.phi); lp.lam = xy.x / ( FXC * (2. * cos(C23 * (lp.phi *= 3.)) - 1.) ); if (fabs(lp.phi = sin(lp.phi) / CS) >= 1.) { if (fabs(lp.phi) > ONEEPS) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else { lp.phi = (lp.phi < 0.) ? -M_HALFPI : M_HALFPI; } } else lp.phi = asin(lp.phi); return lp; }
static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */ PJ_LP lp = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); PJ_XY t; double yc = 0.0; int i = 0; const int N_MAX_ITER = 1000; /* Arbitrarily chosen number... */ lp.phi = Q->phi_2; lp.lam = xy.x / cos(lp.phi); do { t = loc_for(lp, P, &yc); const double denom = t.y - yc; if( denom != 0 || fabs(t.y - xy.y) > TOL ) { if( denom == 0 ) { proj_errno_set(P, PJD_ERR_NON_CONVERGENT); return proj_coord_error().lp; } lp.phi = ((lp.phi - Q->phi_1) * (xy.y - yc) / denom) + Q->phi_1; } if( t.x != 0 || fabs(t.x - xy.x) > TOL ) lp.lam = lp.lam * xy.x / t.x; i ++; } while (i < N_MAX_ITER && (fabs(t.x - xy.x) > TOL || fabs(t.y - xy.y) > TOL)); if( i == N_MAX_ITER ) { proj_errno_set(P, PJD_ERR_NON_CONVERGENT); return proj_coord_error().lp; } return lp; }
static PJ_LP mbtfpq_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; double t; lp.phi = RYC * xy.y; if (fabs(lp.phi) > 1.) { if (fabs(lp.phi) > ONETOL) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else if (lp.phi < 0.) { t = -1.; lp.phi = -M_PI; } else { t = 1.; lp.phi = M_PI; } } else lp.phi = 2. * asin(t = lp.phi); lp.lam = RXC * xy.x / (1. + 2. * cos(lp.phi)/cos(0.5 * lp.phi)); lp.phi = RC * (t + sin(lp.phi)); if (fabs(lp.phi) > 1.) if (fabs(lp.phi) > ONETOL) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else lp.phi = lp.phi < 0. ? -M_HALFPI : M_HALFPI; else lp.phi = asin(lp.phi); return lp; }
static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; long i; double t, t1; struct COEFS T; int iters; lp.lam = xy.x / FXC; lp.phi = fabs(xy.y / FYC); if (lp.phi >= 1.) { /* simple pathologic cases */ if (lp.phi > ONEEPS) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else { lp.phi = xy.y < 0. ? -M_HALFPI : M_HALFPI; lp.lam /= X[NODES].c0; } } else { /* general problem */ /* in Y space, reduce to table interval */ i = isnan(lp.phi) ? -1 : lround(floor(lp.phi * NODES)); if( i < 0 || i >= NODES ) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } for (;;) { if (Y[i].c0 > lp.phi) --i; else if (Y[i+1].c0 <= lp.phi) ++i; else break; } T = Y[i]; /* first guess, linear interp */ t = 5. * (lp.phi - T.c0)/(Y[i+1].c0 - T.c0); /* make into root */ T.c0 = (float)(T.c0 - lp.phi); for (iters = MAX_ITER; iters ; --iters) { /* Newton-Raphson */ t -= t1 = V(T,t) / DV(T,t); if (fabs(t1) < EPS) break; } if( iters == 0 ) pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT ); lp.phi = (5 * i + t) * DEG_TO_RAD; if (xy.y < 0.) lp.phi = -lp.phi; lp.lam /= V(X[i], t); } return lp; }
static PJ_XY calcofi_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ PJ_XY xy = {0.0,0.0}; double oy; /* pt O y value in Mercator */ double l1; /* l1 and l2 are distances calculated using trig that sum to the east/west distance between point O and point xy */ double l2; double ry; /* r is the point on the same station as o (60) and the same line as xy xy, r, o form a right triangle */ if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } xy.x = lp.lam; xy.y = -log(pj_tsfn(lp.phi, sin(lp.phi), P->e)); /* Mercator transform xy*/ oy = -log(pj_tsfn(PT_O_PHI, sin(PT_O_PHI), P->e)); l1 = (xy.y - oy) * tan(ROTATION_ANGLE); l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; ry = pj_phi2(P->ctx, exp(-ry), P->e); /*inverse Mercator*/ xy.x = PT_O_LINE - RAD_TO_DEG * (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); /* set a = 1, x0 = 0, and y0 = 0 so that no further unit adjustments are done */ return xy; }
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; }
static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double rho; xy.x /= P->k0; xy.y /= P->k0; xy.y = Q->rho0 - xy.y; rho = hypot(xy.x, xy.y); if (rho != 0.0) { if (Q->n < 0.) { rho = -rho; xy.x = -xy.x; xy.y = -xy.y; } if (Q->ellips) { lp.phi = pj_phi2(P->ctx, pow(rho / Q->c, 1./Q->n), P->e); if (lp.phi == HUGE_VAL) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } } else lp.phi = 2. * atan(pow(Q->c / rho, 1./Q->n)) - M_HALFPI; lp.lam = atan2(xy.x, xy.y) / Q->n; } else { lp.lam = 0.; lp.phi = Q->n > 0. ? M_HALFPI : -M_HALFPI; } return lp; }
static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; double B, dphi, tp; int i; if (fabs(xy.y = P->phi0 + xy.y) <= TOL) { lp.lam = xy.x; lp.phi = 0.; } else { lp.phi = xy.y; B = xy.x * xy.x + xy.y * xy.y; i = N_ITER; do { tp = tan(lp.phi); lp.phi -= (dphi = (xy.y * (lp.phi * tp + 1.) - lp.phi - .5 * ( lp.phi * lp.phi + B) * tp) / ((lp.phi - xy.y) / tp - 1.)); } while (fabs(dphi) > CONV && --i); if (! i) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } lp.lam = asin(xy.x * tan(lp.phi)) / sin(lp.phi); } return lp; }
PJ_COORD pj_fwd4d (PJ_COORD coo, PJ *P) { int last_errno = proj_errno_reset(P); if (!P->skip_fwd_prepare) coo = fwd_prepare (P, coo); if (HUGE_VAL==coo.v[0]) return proj_coord_error (); /* Call the highest dimensional converter available */ if (P->fwd4d) coo = P->fwd4d (coo, P); else if (P->fwd3d) coo.xyz = P->fwd3d (coo.lpz, P); else if (P->fwd) coo.xy = P->fwd (coo.lp, P); else { proj_errno_set (P, EINVAL); return proj_coord_error (); } if (HUGE_VAL==coo.v[0]) return proj_coord_error (); if (!P->skip_fwd_finalize) coo = fwd_finalize (P, coo); return error_or_coord(P, coo, last_errno); }
PJ_XYZ pj_fwd3d(PJ_LPZ lpz, PJ *P) { int last_errno; PJ_COORD coo = {{0,0,0,0}}; coo.lpz = lpz; last_errno = proj_errno_reset(P); if (!P->skip_fwd_prepare) coo = fwd_prepare (P, coo); if (HUGE_VAL==coo.v[0]) return proj_coord_error ().xyz; /* Do the transformation, using the lowest dimensional transformer feasible */ if (P->fwd3d) coo.xyz = P->fwd3d(coo.lpz, P); else if (P->fwd4d) coo = P->fwd4d (coo, P); else if (P->fwd) coo.xy = P->fwd (coo.lp, P); else { proj_errno_set (P, EINVAL); return proj_coord_error ().xyz; } if (HUGE_VAL==coo.v[0]) return proj_coord_error ().xyz; if (!P->skip_fwd_finalize) coo = fwd_finalize (P, coo); return error_or_coord(P, coo, last_errno).xyz; }
static PJ_XY geos_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ PJ_XY xy = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double r, Vx, Vy, Vz, tmp; /* Calculation of geocentric latitude. */ lp.phi = atan (Q->radius_p2 * tan (lp.phi)); /* Calculation of the three components of the vector from satellite to ** position on earth surface (lon,lat).*/ r = (Q->radius_p) / hypot(Q->radius_p * cos (lp.phi), sin (lp.phi)); Vx = r * cos (lp.lam) * cos (lp.phi); Vy = r * sin (lp.lam) * cos (lp.phi); Vz = r * sin (lp.phi); /* Check visibility. */ if (((Q->radius_g - Vx) * Vx - Vy * Vy - Vz * Vz * Q->radius_p_inv2) < 0.) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } /* Calculation based on view angles from satellite. */ tmp = Q->radius_g - Vx; if(Q->flip_axis) { xy.x = Q->radius_g_1 * atan (Vy / hypot (Vz, tmp)); xy.y = Q->radius_g_1 * atan (Vz / tmp); } else { xy.x = Q->radius_g_1 * atan (Vy / tmp); xy.y = Q->radius_g_1 * atan (Vz / hypot (Vy, tmp)); } return xy; }
static PJ_LP geos_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double Vx, Vy, Vz, a, b, det, k; /* Setting three components of vector from satellite to position.*/ Vx = -1.0; if(Q->flip_axis) { Vz = tan (xy.y / (Q->radius_g - 1.0)); Vy = tan (xy.x / (Q->radius_g - 1.0)) * sqrt (1.0 + Vz * Vz); } else { Vy = tan (xy.x / (Q->radius_g - 1.0)); Vz = tan (xy.y / (Q->radius_g - 1.0)) * sqrt (1.0 + Vy * Vy); } /* Calculation of terms in cubic equation and determinant.*/ a = Vy * Vy + Vz * Vz + Vx * Vx; b = 2 * Q->radius_g * Vx; if ((det = (b * b) - 4 * a * Q->C) < 0.) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } /* Calculation of three components of vector from satellite to position.*/ k = (-b - sqrt(det)) / (2 * a); Vx = Q->radius_g + k * Vx; Vy *= k; Vz *= k; /* Calculation of longitude and latitude.*/ lp.lam = atan2 (Vy, Vx); lp.phi = atan (Vz * cos (lp.lam) / Vx); return lp; }
/* Measure numerical deviation after n roundtrips fwd-inv (or inv-fwd) */ double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coord) { int i; PJ_COORD t, org; if (0==P) return HUGE_VAL; if (n < 1) { proj_errno_set (P, EINVAL); return HUGE_VAL; } /* in the first half-step, we generate the output value */ org = *coord; *coord = proj_trans (P, direction, org); t = *coord; /* now we take n-1 full steps in inverse direction: We are */ /* out of phase due to the half step already taken */ for (i = 0; i < n - 1; i++) t = proj_trans (P, direction, proj_trans (P, -direction, t) ); /* finally, we take the last half-step */ t = proj_trans (P, -direction, t); /* checking for angular *input* since we do a roundtrip, and end where we begin */ if (proj_angular_input (P, direction)) return proj_lpz_dist (P, org, t); return proj_xyz_dist (org, t); }
PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coord) { /*************************************************************************************** Apply the transformation P to the coordinate coord, preferring the 4D interfaces if available. See also pj_approx_2D_trans and pj_approx_3D_trans in pj_internal.c, which work similarly, but prefers the 2D resp. 3D interfaces if available. ***************************************************************************************/ if (0==P) return coord; if (P->inverted) direction = -direction; switch (direction) { case PJ_FWD: return pj_fwd4d (coord, P); case PJ_INV: return pj_inv4d (coord, P); case PJ_IDENT: return coord; default: break; } proj_errno_set (P, EINVAL); return proj_coord_error (); }
static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double phip, lamp, phipp, lampp, cp, esp, con, delp; int i; phipp = 2. * (atan (exp (xy.y / Q->kR)) - M_FORTPI); lampp = xy.x / Q->kR; cp = cos (phipp); phip = aasin (P->ctx, Q->cosp0 * sin (phipp) + Q->sinp0 * cp * cos (lampp)); lamp = aasin (P->ctx, cp * sin (lampp) / cos (phip)); con = (Q->K - log (tan (M_FORTPI + 0.5 * phip)))/Q->c; for (i = NITER; i ; --i) { esp = P->e * sin(phip); delp = (con + log(tan(M_FORTPI + 0.5 * phip)) - Q->hlf_e * log((1. + esp)/(1. - esp)) ) * (1. - esp * esp) * cos(phip) * P->rone_es; phip -= delp; if (fabs(delp) < EPS) break; } if (i) { lp.phi = phip; lp.lam = lamp / Q->c; } else { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } return (lp); }
static PJ_LP vandg_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; double t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2; x2 = xy.x * xy.x; if ((ay = fabs(xy.y)) < TOL) { lp.phi = 0.; t = x2 * x2 + TPISQ * (x2 + HPISQ); lp.lam = fabs(xy.x) <= TOL ? 0. : .5 * (x2 - PISQ + sqrt(t)) / xy.x; return (lp); } y2 = xy.y * xy.y; r = x2 + y2; r2 = r * r; c1 = - M_PI * ay * (r + PISQ); c3 = r2 + M_TWOPI * (ay * r + M_PI * (y2 + M_PI * (ay + M_HALFPI))); c2 = c1 + PISQ * (r - 3. * y2); c0 = M_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; const double al_mul_m = al * m; if( al_mul_m == 0 ) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return proj_coord_error().lp; } d = 3. * d /al_mul_m; t = fabs(d); if ((t - TOL) <= 1.) { d = t > 1. ? (d > 0. ? 0. : M_PI) : acos(d); lp.phi = M_PI * (m * cos(d * THIRD + PI4_3) - THIRD * c2); if (xy.y < 0.) lp.phi = -lp.phi; t = r2 + TPISQ * (x2 - y2 + HPISQ); lp.lam = fabs(xy.x) <= TOL ? 0. : .5 * (r - PISQ + (t <= 0. ? 0. : sqrt(t))) / xy.x; } else { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } return lp; }
static PJ_XY vandg_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */ PJ_XY xy = {0.0,0.0}; double al, al2, g, g2, p2; p2 = fabs(lp.phi / M_HALFPI); if ((p2 - TOL) > 1.) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } if (p2 > 1.) p2 = 1.; if (fabs(lp.phi) <= TOL) { xy.x = lp.lam; xy.y = 0.; } else if (fabs(lp.lam) <= TOL || fabs(p2 - 1.) < TOL) { xy.x = 0.; xy.y = M_PI * tan(.5 * asin(p2)); if (lp.phi < 0.) xy.y = -xy.y; } else { al = .5 * fabs(M_PI / lp.lam - lp.lam / M_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 = M_PI * (al * xy.x + sqrt(al2 * xy.x * xy.x - g * (g2 - p2))) / g; if (lp.lam < 0.) xy.x = -xy.x; xy.y = fabs(xy.x / M_PI); xy.y = 1. - xy.y * (xy.y + 2. * al); if (xy.y < -TOL) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } if (xy.y < 0.) xy.y = 0.; else xy.y = sqrt(xy.y) * (lp.phi < 0. ? -M_PI : M_PI); } return xy; }
static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ LP lp = {0.0,0.0}; struct pj_opaque *Q = P->opaque; xy.y += Q->ml0; if (fabs(xy.y) <= TOL) { lp.lam = xy.x; lp.phi = 0.; } else { double r, c, sp, cp, s2ph, ml, mlb, mlp, dPhi; int i; r = xy.y * xy.y + xy.x * xy.x; for (lp.phi = xy.y, i = I_ITER; i ; --i) { sp = sin(lp.phi); s2ph = sp * ( cp = cos(lp.phi)); if (fabs(cp) < ITOL) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } c = sp * (mlp = sqrt(1. - P->es * sp * sp)) / cp; ml = pj_mlfn(lp.phi, sp, cp, Q->en); mlb = ml * ml + r; mlp = P->one_es / (mlp * mlp * mlp); lp.phi += ( dPhi = ( ml + ml + c * mlb - 2. * xy.y * (c * ml + 1.) ) / ( P->es * s2ph * (mlb - 2. * xy.y * ml) / c + 2.* (xy.y - ml) * (c * mlp - 1. / s2ph) - mlp - mlp )); if (fabs(dPhi) <= ITOL) break; } if (!i) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } c = sin(lp.phi); lp.lam = asin(xy.x * tan(lp.phi) * sqrt(1. - P->es * c * c)) / sin(lp.phi); } return lp; }
static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ XY xy = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double coslam, cosphi, sinphi; sinphi = sin(lp.phi); cosphi = cos(lp.phi); coslam = cos(lp.lam); switch (Q->mode) { case EQUIT: xy.y = 1. + cosphi * coslam; goto oblcon; case OBLIQ: xy.y = 1. + Q->sinb1 * sinphi + Q->cosb1 * cosphi * coslam; oblcon: if (xy.y <= EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } xy.y = sqrt(2. / xy.y); xy.x = xy.y * cosphi * sin(lp.lam); xy.y *= Q->mode == EQUIT ? sinphi : Q->cosb1 * sinphi - Q->sinb1 * cosphi * coslam; break; case N_POLE: coslam = -coslam; /*-fallthrough*/ case S_POLE: if (fabs(lp.phi + P->phi0) < EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } xy.y = M_FORTPI - lp.phi * .5; xy.y = 2. * (Q->mode == S_POLE ? cos(xy.y) : sin(xy.y)); xy.x = xy.y * sin(lp.lam); xy.y *= coslam; break; } return xy; }
int proj_errno_restore (const PJ *P, int err) { /****************************************************************************** Use proj_errno_restore when the current function succeeds, but the error flag was set on entry, and stored/reset using proj_errno_reset in order to monitor for new errors. See usage example under proj_errno_reset () ******************************************************************************/ if (0==err) return 0; proj_errno_set (P, err); return 0; }
static PJ_LP s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double rh; rh = hypot(xy.x, xy.y = Q->cphi1 - xy.y); lp.phi = Q->cphi1 + Q->phi1 - rh; if (fabs(lp.phi) > M_HALFPI) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) lp.lam = 0.; else lp.lam = rh * atan2(xy.x, xy.y) / cos(lp.phi); return lp; }
static PJ_LP collg_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse */ PJ_LP lp = {0.0,0.0}; lp.phi = xy.y / FYC - 1.; if (fabs(lp.phi = 1. - lp.phi * lp.phi) < 1.) lp.phi = asin(lp.phi); else if (fabs(lp.phi) > ONEEPS) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } else { lp.phi = lp.phi < 0. ? -M_HALFPI : M_HALFPI; } if ((lp.lam = 1. - sin(lp.phi)) <= 0.) lp.lam = 0.; else lp.lam = xy.x / (FXC * sqrt(lp.lam)); return (lp); }
static PJ_XY sterea_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */ PJ_XY xy = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double cosc, sinc, cosl, k; lp = pj_gauss(P->ctx, lp, Q->en); sinc = sin(lp.phi); cosc = cos(lp.phi); cosl = cos(lp.lam); const double denom = 1. + Q->sinc0 * sinc + Q->cosc0 * cosc * cosl; if( denom == 0.0 ) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return proj_coord_error().xy; } k = P->k0 * Q->R2 / denom; xy.x = k * cosc * sin(lp.lam); xy.y = k * (Q->cosc0 * sinc - Q->sinc0 * cosc * cosl); return xy; }
static PJ_LP e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */ PJ_LP lp = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double s, rh; rh = hypot(xy.x, xy.y = Q->am1 - xy.y); lp.phi = pj_inv_mlfn(P->ctx, Q->am1 + Q->m1 - rh, P->es, Q->en); if ((s = fabs(lp.phi)) < M_HALFPI) { s = sin(lp.phi); lp.lam = rh * atan2(xy.x, xy.y) * sqrt(1. - P->es * s * s) / cos(lp.phi); } else if (fabs(s - M_HALFPI) <= EPS10) lp.lam = 0.; else { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } return lp; }
static PJ_XY s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */ PJ_XY xy = {0.0,0.0}; long i; double dphi; (void) P; dphi = fabs(lp.phi); i = isnan(lp.phi) ? -1 : lround(floor(dphi * C1)); if( i < 0 ){ proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } if (i >= NODES) i = NODES - 1; dphi = RAD_TO_DEG * (dphi - RC1 * i); xy.x = V(X[i], dphi) * FXC * lp.lam; xy.y = V(Y[i], dphi) * FYC; if (lp.phi < 0.) xy.y = -xy.y; return xy; }
static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double rho; if (fabs(fabs(lp.phi) - M_HALFPI) < EPS10) { if ((lp.phi * Q->n) <= 0.) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } rho = 0.; } else { rho = Q->c * (Q->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), P->e), Q->n) : pow(tan(M_FORTPI + .5 * lp.phi), -Q->n)); } lp.lam *= Q->n; xy.x = P->k0 * (rho * sin( lp.lam) ); xy.y = P->k0 * (Q->rho0 - rho * cos(lp.lam) ); return xy; }
static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ LP lp = {0.0,0.0}; struct pj_opaque *Q = P->opaque; double cosz=0.0, rh, sinz=0.0; rh = hypot(xy.x, xy.y); if ((lp.phi = rh * .5 ) > 1.) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } lp.phi = 2. * asin(lp.phi); if (Q->mode == OBLIQ || Q->mode == EQUIT) { sinz = sin(lp.phi); cosz = cos(lp.phi); } switch (Q->mode) { case EQUIT: lp.phi = fabs(rh) <= EPS10 ? 0. : asin(xy.y * sinz / rh); xy.x *= sinz; xy.y = cosz * rh; break; case OBLIQ: lp.phi = fabs(rh) <= EPS10 ? P->phi0 : asin(cosz * Q->sinb1 + xy.y * sinz * Q->cosb1 / rh); xy.x *= sinz * Q->cosb1; xy.y = (cosz - sin(lp.phi) * Q->sinb1) * rh; break; case N_POLE: xy.y = -xy.y; lp.phi = M_HALFPI - lp.phi; break; case S_POLE: lp.phi -= M_HALFPI; break; } lp.lam = (xy.y == 0. && (Q->mode == EQUIT || Q->mode == OBLIQ)) ? 0. : atan2(xy.x, xy.y); return (lp); }
int proj_vgrid_init(PJ* P, const char *grids) { /********************************************** Initizalize and populate gridlist. Takes a PJ-object and the plus-parameter name that is used in the proj-string to specify the grids to load, e.g. "+grids". The + should be left out here. Returns the number of loaded grids. ***********************************************/ /* prepend "s" to the "grids" string to allow usage with pj_param */ char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) ); sprintf(sgrids, "%s%s", "s", grids); if (P->vgridlist_geoid == NULL) { P->vgridlist_geoid = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, sgrids).s, &(P->vgridlist_geoid_count) ); if( P->vgridlist_geoid == NULL || P->vgridlist_geoid_count == 0 ) { pj_dealloc(sgrids); return 0; } } if (P->vgridlist_geoid_count == 0) { proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID); } pj_dealloc(sgrids); return P->vgridlist_geoid_count; }
static PJ_XY calcofi_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */ PJ_XY xy = {0.0,0.0}; double oy; double l1; double l2; double ry; if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return xy; } xy.x = lp.lam; xy.y = log(tan(M_FORTPI + .5 * lp.phi)); oy = log(tan(M_FORTPI + .5 * PT_O_PHI)); l1 = (xy.y - oy) * tan(ROTATION_ANGLE); l2 = -xy.x - l1 + PT_O_LAMBDA; ry = l2 * cos(ROTATION_ANGLE) * sin(ROTATION_ANGLE) + xy.y; ry = M_HALFPI - 2. * atan(exp(-ry)); xy.x = PT_O_LINE - RAD_TO_DEG * (ry - PT_O_PHI) * DEG_TO_LINE / cos(ROTATION_ANGLE); xy.y = PT_O_STATION + RAD_TO_DEG * (ry - lp.phi) * DEG_TO_STATION / sin(ROTATION_ANGLE); return xy; }
static PJ_LP lcca_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */ PJ_LP lp = {0.0,0.0}; struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque); double theta, dr, S, dif; int i; xy.x /= P->k0; xy.y /= P->k0; theta = atan2(xy.x , Q->r0 - xy.y); dr = xy.y - xy.x * tan(0.5 * theta); lp.lam = theta / Q->l; S = dr; for (i = MAX_ITER; i ; --i) { S -= (dif = (fS(S, Q->C) - dr) / fSp(S, Q->C)); if (fabs(dif) < DEL_TOL) break; } if (!i) { proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION); return lp; } lp.phi = pj_inv_mlfn(P->ctx, S + Q->M0, P->es, Q->en); return lp; }