// Polyconic inverse equations--mapping x,y to lat/long long Projectoid::polyinv( double x, // (O) X projection coordinate double y, // (O) Y projection coordinate double *lon, // (I) Longitude double *lat) // (I) Latitude { double al; // temporary values double b; // temporary values double c; // temporary values double t; // <<<F2 OPT>>> long iflg; // error flag // Inverse equations x -= false_easting; y -= false_northing; al = ml0 + y / r_major; iflg = 0; t = x / r_major; if (fabs(al) <= .0000001) { *lon = t + lon_center; *lat = 0.0; } else { b = al * al + t * t; iflg = phi4z(es, e0, e1, e2, e3, al, b, &c, lat); if (iflg != OK) return(iflg); *lon = adjust_lon((asinz(t * c) / sin(*lat)) + lon_center); } return(OK); }
/* Van Der Grinten forward equations--mapping lat,long to x,y ---------------------------------------------------------*/ long vandgfor ( double lon, /* (I) Longitude */ double lat, /* (I) Latitude */ double *x, /* (O) X projection coordinate */ double *y /* (O) Y projection coordinate */ ) { double dlon; double theta; double al,asq; double g,gsq; double m,msq; double con; double costh,sinth; /* Forward equations -----------------*/ dlon = adjust_lon(lon - lon_center); if (fabs(lat) <= EPSLN) { *x = false_easting + R * dlon; *y = false_northing; return (GCTP_OK); } theta = asinz(2.0 * fabs(lat / PI)); if ((fabs(dlon) <= EPSLN) || (fabs(fabs(lat) - HALF_PI) <= EPSLN)) { *x = false_easting; if (lat >= 0) *y = false_northing + PI * R * tan(.5 * theta); else *y = false_northing + PI * R * -tan(.5 * theta); return(GCTP_OK); } al = .5 * fabs((PI / dlon) - (dlon / PI)); asq = al * al; gctp_sincos(theta,&sinth,&costh); g = costh / (sinth + costh - 1.0); gsq = g * g; m = g * (2.0 / sinth - 1.0); msq = m * m; con = PI * R * (al * (g - msq) + sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); if (dlon < 0) con = -con; *x = false_easting + con; con = fabs(con / (PI * R)); if (lat >= 0) *y = false_northing + PI * R * sqrt(1.0 - con * con - 2.0 * al * con); else *y = false_northing - PI * R * sqrt(1.0 - con * con - 2.0 * al * con); return(GCTP_OK); }
/* Azimuthal inverse equations--mapping x,y to lat/long ---------------------------------------------------*/ long aziminv ( double x, /* (O) X projection coordinate */ double y, /* (O) Y projection coordinate */ double *lon, /* (I) Longitude */ double *lat /* (I) Latitude */ ) { double rh; /* height above ellipsoid */ double z; /* angle */ double sinz,cosz; /* sin of z and cos of z */ double con; /* Inverse equations -----------------*/ x -= false_easting; y -= false_northing; rh = sqrt(x * x + y * y); if (rh > (2.0 * HALF_PI * r_major)) { GCTP_PRINT_ERROR("Input data error"); return(125); } z = rh / r_major; sincos(z,&sinz,&cosz); *lon = lon_center; if (fabs(rh) <= EPSLN) { *lat = lat_origin; return(OK); } *lat = asinz(cosz * sin_p12 + (y * sinz * cos_p12) / rh); con = fabs(lat_origin) - HALF_PI; if (fabs(con) <= EPSLN) { if (lat_origin >= 0.0) { *lon = adjust_lon(lon_center + atan2(x , -y)); return(OK); } else { *lon = adjust_lon(lon_center - atan2(-x , y)); return(OK); } } con = cosz - sin_p12 * sin(*lat); if ((fabs(con) < EPSLN) && (fabs(x) < EPSLN)) return(OK); *lon = adjust_lon(lon_center + atan2((x * sinz * cos_p12), (con * rh))); return(OK); }
// Wagner VII inverse equations--mapping x,y to lat,long long Projectoid::wviiinv( double x, // (I) X projection coordinate double y, // (I) Y projection coordinate double *lon, // (O) Longitude double *lat) // (O) Latitude { double t1, t2, p, c; // Inverse equations x -= false_easting; y -= false_northing; t1 = x * (1.0 / 2.66723); // <<<F2 OPT>>> t2 = y * (1.0 / 1.24104); // <<<F2 OPT>>> t1 *= t1; t2 *= t2; p = sqrt(t1 + t2); c = 2.0 * asinz(p / (2.0 * R)); *lat = asinz(y * sin(c) / (1.24104 * 0.90631 * p)); *lon = adjust_lon(lon_center + 3.0 * atan2(x * tan(c), 2.66723 * p)); return(OK); }
/* Wagner VII inverse equations--mapping x,y to lat,long -----------------------------------------------------*/ long wviiinv ( double x, /* (I) X projection coordinate */ double y, /* (I) Y projection coordinate */ double *lon, /* (O) Longitude */ double *lat /* (O) Latitude */ ) { double t1, t2, p, c; /* Inverse equations -----------------*/ x -= false_easting; y -= false_northing; t1 = x / 2.66723; t2 = y / 1.24104; t1 *= t1; t2 *= t2; p = sqrt(t1 + t2); c = 2.0 * asinz(p / (2.0 * R)); *lat = asinz(y * sin(c) / (1.24104 * 0.90631 * p)); *lon = adjust_lon(lon_center + 3.0 * atan2(x * tan(c), 2.66723 * p)); return(OK); }
/* HAMMER inverse equations--mapping x,y to lat/long ------------------------------------------------*/ int haminv( double x, /* (O) X projection coordinate */ double y, /* (O) Y projection coordinate */ double *lon, /* (I) Longitude */ double *lat) /* (I) Latitude */ { double fac; /* Inverse equations -----------------*/ x -= false_easting; y -= false_northing; fac = sqrt(4.0 * R * R - (x * x)/ 4.0 - y * y) / 2.0; *lon = adjust_lon(lon_center + 2.0 * atan2((x * fac), (2.0 * R * R - x * x/4 - y * y))); *lat = asinz(y * fac / R / R); return(OK); }
double Util::phi1z ( double eccent, /* Eccentricity angle in radians */ double qs, /* Angle in radians */ long *flag ) /* Error flag number */ { double eccnts; double dphi; double con; double com; double sinpi; double cospi; double phi; long i; phi = asinz(.5 * qs); if (eccent < EPSLN) return(phi); eccnts = eccent * eccent; for (i = 1; i <= 25; i++) { Util::gctp_sincos(phi,&sinpi,&cospi); con = eccent * sinpi; com = 1.0 - con * con; dphi = .5 * com * com / cospi * (qs / (1.0 - eccnts) - sinpi / com + .5 / eccent * log ((1.0 - con) / (1.0 + con))); phi = phi + dphi; if (fabs(dphi) <= 1e-7) return(phi); } // p_error ("Convergence error","phi1z-conv"); *flag = 001; return(ERROR); }
/* ALASKA CONFORMAL inverse equations--mapping x,y to lat/long ----------------------------------------------------------*/ long alconinv ( double x, /* (O) X projection coordinate */ double y, /* (O) Y projection coordinate */ double *lon, /* (I) Longitude */ double *lat /* (I) Latitude */ ) { double esphi; double r; double s; double br; double bi; double ai; double ar; double ci; double cr; double di; double dr; double arn = 0.0; double ain = 0.0; double crn; double cin; double fxyr; double fxyi; double fpxyr; double fpxyi; double xp,yp; double den; double dxp; double dyp; double ds; double z; double cosz; double sinz; double rh; double chi; double dphi; double phi; long j; long nn; /* Inverse equations -----------------*/ x = (x - false_easting) / r_major; y = (y - false_northing) / r_major; xp = x; yp = y; nn = 0; /* Use Knuth algorithm for summing complex terms, to convert Modified- Stereographic conformal to Oblique Stereographic coordinates. --------------------------------------------------------------------*/ do { r = xp + xp; s = xp * xp + yp * yp; ar = acoef[n]; ai = bcoef[n]; br = acoef[n -1]; bi = bcoef[n - 1]; cr = (double) (n) * ar; ci = (double) (n) * ai; dr = (double) (n -1) * br; di = (double) (n -1) * bi; for (j = 2; j <= n; j++) { arn = br + r * ar; ain = bi + r * ai; if (j < n) { br = acoef[n -j] - s * ar; bi = bcoef[n - j] - s * ai; ar = arn; ai = ain; crn = dr + r * cr; cin = di + r * ci; dr = (double) (n - j) * acoef[n -j] - s * cr; di = (double) (n - j) * bcoef[n -j] - s * ci; cr = crn; ci = cin; } } br = -s * ar; bi = -s * ai; ar = arn; ai = ain; fxyr = xp * ar - yp * ai + br - x; fxyi = yp * ar + xp * ai + bi - y; fpxyr = xp * cr - yp * ci + dr; fpxyi = yp * cr + xp * ci + ci; den = fpxyr * fpxyr + fpxyi * fpxyi; dxp = -(fxyr * fpxyr + fxyi * fpxyi) / den; dyp = -(fxyi * fpxyr - fxyr * fpxyi) / den; xp = xp + dxp; yp = yp + dyp; ds = fabs(dxp) + fabs(dyp); nn++; if (nn > 20) { p_error("Too many iterations in inverse","alcon-inv"); return(235); } } while (ds > EPSLN); /* convert Oblique Stereographic coordinates to LAT/LONG ------------------------------------------------------*/ rh = sqrt(xp * xp + yp * yp); z = 2.0 * atan(rh / 2.0); gctp_sincos(z,&sinz,&cosz); *lon = lon_center; if (fabs(rh) <= EPSLN) { *lat = lat_center; return(GCTP_OK); } chi = asinz(cosz * sin_p26 + (yp * sinz * cos_p26) / rh); nn = 0; phi = chi; do { esphi = e * sin(phi); dphi = 2.0 * atan(tan((HALF_PI + chi) / 2.0) * pow(((1.0 + esphi) / (1.0 - esphi)),(e / 2.0))) - HALF_PI - phi; phi += dphi; nn++; if (nn > 20) { p_error("Too many iterations in inverse","alcon-inv"); return(236); } } while(fabs(dphi) > EPSLN); *lat = phi; *lon = adjust_lon (lon_center + atan2((xp * sinz), (rh * cos_p26 * cosz - yp * sin_p26 * sinz))); return(GCTP_OK); }
/***************************************************************************** Name: inverse_transform Purpose: Transforms UTM/TM X,Y to lat,long Returns: GCTP_SUCCESS or GCTP_ERROR *****************************************************************************/ static int inverse_transform ( const TRANSFORMATION *trans, /* I: transformation information */ double x, /* I: X projection coordinate */ double y, /* I: Y projection coordinate */ double *lon, /* O: Longitude */ double *lat /* O: Latitude */ ) { struct tm_proj *cache_ptr = (struct tm_proj *)trans->cache; double con,phi; /* temporary angles */ double delta_phi; /* difference between longitudes */ long i; /* counter variable */ double sin_phi, cos_phi, tan_phi; /* sin cos and tangent values */ double c, cs, t, ts, n, r, d, ds; /* temporary variables */ double f, h, g, temp; /* temporary variables */ long max_iter = 6; /* maximun number of iterations */ /* Use the spherical form if possible */ if (cache_ptr->is_sphere) { f = exp(x / (cache_ptr->r_major * cache_ptr->scale_factor)); g = 0.5 * (f - 1.0/f); temp = cache_ptr->lat_origin + y /(cache_ptr->r_major * cache_ptr->scale_factor); h = cos(temp); con = sqrt((1.0 - h * h)/(1.0 + g * g)); *lat = asinz(con); if (temp < 0) *lat = -*lat; if ((g == 0) && (h == 0)) { *lon = cache_ptr->lon_center; return GCTP_SUCCESS; } else { *lon = adjust_lon(atan2(g,h) + cache_ptr->lon_center); return GCTP_SUCCESS; } } /* Inverse equations */ x = x - cache_ptr->false_easting; y = y - cache_ptr->false_northing; con = (cache_ptr->ml0 + y / cache_ptr->scale_factor) / cache_ptr->r_major; phi = con; for (i = 0; ; i++) { delta_phi = ((con + cache_ptr->e1 * sin(2.0*phi) - cache_ptr->e2 * sin(4.0*phi) + cache_ptr->e3 * sin(6.0*phi)) / cache_ptr->e0) - phi; phi += delta_phi; if (fabs(delta_phi) <= EPSLN) break; if (i >= max_iter) { GCTP_PRINT_ERROR("Latitude failed to converge in inverse " "transform"); return GCTP_ERROR; } } if (fabs(phi) < HALF_PI) { sincos(phi, &sin_phi, &cos_phi); tan_phi = tan(phi); c = cache_ptr->esp * SQUARE(cos_phi); cs = SQUARE(c); t = SQUARE(tan_phi); ts = SQUARE(t); con = 1.0 - cache_ptr->es * SQUARE(sin_phi); n = cache_ptr->r_major / sqrt(con); r = n * (1.0 - cache_ptr->es) / con; d = x / (n * cache_ptr->scale_factor); ds = SQUARE(d); *lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 * cache_ptr->esp - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c + 45.0 * ts - 252.0 * cache_ptr->esp - 3.0 * cs))); *lon = adjust_lon(cache_ptr->lon_center + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * cache_ptr->esp + 24.0 * ts))) / cos_phi)); } else { *lat = HALF_PI * gctp_get_sign(y); *lon = cache_ptr->lon_center; } return GCTP_SUCCESS; }
int inverse_albers_conic_equal_area_ellipsoid(mapx_class *current, double x, double y, double *lat, double *lon) { double phi, lam, rho, rmy, theta, q; double q_test; double cos_phi; double sin_phi; double esin_phi; double one_m_e2sin2_phi; double delta_phi; double one_m_e2; double one_over_2e; double epsilon = 1e-6; int it_max = 35; int i; x -= current->false_easting; y -= current->false_northing; rmy = current->rho0 - y; rho = sqrt( x*x + rmy*rmy ); theta = current->n >= 0 ? atan2( x, rmy) : atan2(-x, -rmy); lam = theta / current->n; q = (current->C - ( (rho*rho*current->n*current->n) / (current->Rg*current->Rg) ) ) / current->n; /*** Calculate phi using equation 3-16, Snyder 1987, p102 ***/ q_test = 1.0 - (1.0 - current->e2)/(2.0 * current->eccentricity) * log((1.0 - current->eccentricity) / (1.0 + current->eccentricity)); if (fabs(fabs(q) - fabs(q_test)) < epsilon) { phi = sign(q) * PI / 2; } else { phi = asinz(q / 2.0); one_m_e2 = 1.0 - current->e2; one_over_2e = 1.0 / (2.0 * current->eccentricity); for (i = 0; i < it_max; i++) { cos_phi = cos(phi); if (cos_phi < epsilon) { phi = sign(q) * PI / 2; break; } sin_phi = sin(phi); esin_phi = current->eccentricity * sin_phi; one_m_e2sin2_phi = 1.0 - esin_phi * esin_phi; delta_phi = one_m_e2sin2_phi * one_m_e2sin2_phi / (2.0 * cos_phi) * (q / one_m_e2 - sin_phi / one_m_e2sin2_phi + one_over_2e * log((1.0 - esin_phi) / (1.0 + esin_phi))); phi += delta_phi; if (fabs(delta_phi) < epsilon) break; } } *lat = DEGREES(phi); *lon = DEGREES(lam) + current->lon0; NORMALIZE(*lon); return 0; }
/* Initialize the General Lambert Azimuthal Equal Area projection --------------------------------------------------------------*/ int lamazforint( double r_maj, /* major axis */ double r_min, /* minor axis */ double center_long, /* (I) Center longitude */ double center_lat, /* (I) Center latitude */ double false_east, /* x offset in meters */ double false_north) /* y offset in meters */ { /* Place parameters in static storage for common use -------------------------------------------------*/ R = r_maj; if(fabs(r_min) < EPSLN ) /* sphere */ { r_major = r_maj; r_minor = r_maj; } else /* sphere or ellipsoide */ { r_major = r_maj; r_minor = r_min; } lon_center = center_long; lat_center = center_lat; false_easting = false_east; false_northing = false_north; tsincos(center_lat, &sin_lat_o, &cos_lat_o); sinphi1 = sin_lat_o; cosphi1 = cos_lat_o; es = 1.0 - SQUARE(r_minor / r_major); e = sqrt(es); if(es < 0.00001) { ind = 1; /* sphere */ qp = 2.0; q1 = 2.0; } else { ind = 0; /* ellipsoid */ qp = (1.0 - es)* (((1.0/(1.0 - es))-(1.0/(2.0*e))*log((1.0 - e)/(1.0 + e)))); if((fabs (lat_center - HALF_PI) <= EPSLN ) || (fabs (lat_center + HALF_PI) <= EPSLN )) { /* no other constants needed for LA with North and South polar Aspects lat_center = 90 or -90*/ } else { tsincos(lat_center, &sinphi1, &cosphi1); q1 = (1.0 - es) * ((sinphi1 / (1.0 - es * sinphi1 * sinphi1)) - (1.0 / (2.0 * e)) * log((1.0 - e * sinphi1)/(1.0 + e * sinphi1))); Rq = r_major * sqrt(qp/2.0); if(fabs(q1) >= fabs(qp)) { beta1 = HALF_PI * (fabs(q1/qp)/(q1/qp)); } else { beta1 = asinz(q1/qp); } tsincos(beta1, &sin_beta1, &cos_beta1); m1 = cosphi1 / sqrt(1.0 - es * sinphi1 * sinphi1); D = (r_major * m1)/ (Rq * cos_beta1); } } /* Report parameters to the user -----------------------------*/ ptitle("LAMBERT AZIMUTHAL EQUAL-AREA"); radius2(r_major, r_minor); cenlon(center_long); cenlat(center_lat); offsetp(false_easting,false_northing); return(OK); }
/* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y -----------------------------------------------------------------------*/ int lamazfor( double lon, /* (I) Longitude */ double lat, /* (I) Latitude */ double *x, /* (O) X projection coordinate */ double *y) /* (O) Y projection coordinate */ { double delta_lon; /* Delta longitude (Given longitude - center */ double sin_delta_lon; /* Sine of the delta longitude */ double cos_delta_lon; /* Cosine of the delta longitude */ double sinphi; /* Sine of the center latitude */ double cosphi; /* Cosine of the center latitude */ double sin_lat; /* Sine of the given latitude */ double cos_lat; /* Cosine of the given latitude */ double g; /* temporary varialbe */ double ksp; /* heigth above elipsiod */ char mess[60]; double qpmq, qppq, rho; double beta, sin_beta, cos_beta; double q, B; /* Forward equations -----------------*/ if( ind != 0) /* sphere */ { delta_lon = adjust_lon(lon - lon_center); tsincos(lat, &sin_lat, &cos_lat); tsincos(delta_lon, &sin_delta_lon, &cos_delta_lon); g = sin_lat_o * sin_lat + cos_lat_o * cos_lat * cos_delta_lon; if (g == -1.0) { sprintf(mess, "Point projects to a circle of radius = %lf\n", 2.0 * R); p_error(mess, "lamaz-forward"); return(113); } ksp = R * sqrt(2.0 / (1.0 + g)); *x = ksp * cos_lat * sin_delta_lon + false_easting; *y = ksp * (cos_lat_o * sin_lat - sin_lat_o * cos_lat * cos_delta_lon) + false_northing; } else /* ellipsoid */ { delta_lon = adjust_lon(lon - lon_center); tsincos(lat, &sinphi, &cosphi); q = (1.0 - es) * ((sinphi / (1.0 - es * sinphi * sinphi)) - (1.0 / (2.0 * e)) * log((1.0 - e * sinphi)/(1.0 + e * sinphi))); if (fabs(lat_center - HALF_PI) <= EPSLN) /* if Northern Polar Aspect */ { qpmq = qp - q; if (fabs(qpmq) <= EPSLN) { rho = 0.0; } else { rho = r_major * sqrt(qpmq); } *x = false_easting + rho * sin(delta_lon); *y = false_northing - rho * cos(delta_lon); } else if (fabs(lat_center + HALF_PI) <= EPSLN) /* if Southern Polar Aspect */ { qppq = qp + q; if (fabs(qppq) <= EPSLN) { rho = 0.0; } else { rho = r_major * sqrt(qppq); } *x = false_easting + rho * sin(delta_lon); *y = false_northing + rho * cos(delta_lon); } else /* with any other latitude of origin */ { beta = asinz(q/qp); tsincos(beta, &sin_beta, &cos_beta); B = Rq * sqrt((2.0/(1.0 + sin_beta1 * sin_beta + cos_beta1 * cos_beta * cos(delta_lon)))); *x = false_easting + (B*D) * (cos_beta * sin(delta_lon)); *y = false_northing + (B/D) * (cos_beta1 * sin_beta - sin_beta1 * cos_beta * cos(delta_lon)); } } return(OK); }