void UtmToLatLon (double a, double f, int utmXZone, char utmYZone, double easting, double northing, double& lat, double& lon) { double recf; double b; double eSquared; double e2Squared; double tn; double ap; double bp; double cp; double dp; double ep; double nfn; double tmd; double sr; double sn; double ftphi; double s; double c; double t; double eta; double de; double dlam; double olam; recf = 1.0 / f; b = a * (recf - 1) / recf; eSquared = CalculateESquared (a, b); e2Squared = CalculateE2Squared (a, b); tn = (a - b) / (a + b); ap = a * (1.0 - tn + 5.0 * ((tn * tn) - (tn * tn * tn)) / 4.0 + 81.0 * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 64.0); bp = 3.0 * a * (tn - (tn * tn) + 7.0 * ((tn * tn * tn) - (tn * tn * tn * tn)) / 8.0 + 55.0 * (tn * tn * tn * tn * tn) / 64.0) / 2.0; cp = 15.0 * a * ((tn * tn) - (tn * tn * tn) + 3.0 * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 4.0) / 16.0; dp = 35.0 * a * ((tn * tn * tn) - (tn * tn * tn * tn) + 11.0 * (tn * tn * tn * tn * tn) / 16.0) / 48.0; ep = 315.0 * a * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 512.0; if ((utmYZone <= 'M' && utmYZone >= 'C') || (utmYZone <= 'm' && utmYZone >= 'c')) { nfn = 10000000.0; } else { nfn = 0; } LKASSERT(ok!=0); tmd = (northing - nfn) / ok; sr = sphsr (a, eSquared, 0.0); LKASSERT(sr!=0); ftphi = tmd / sr; double t10, t11, t14, t15; for (int i = 0; i < 5; i++) { t10 = sphtmd (ap, bp, cp, dp, ep, ftphi); sr = sphsr (a, eSquared, ftphi); LKASSERT(sr!=0); ftphi = ftphi + (tmd - t10) / sr; } sr = sphsr (a, eSquared, ftphi); sn = sphsn (a, eSquared, ftphi); s = sin (ftphi); c = cos (ftphi); LKASSERT(c!=0); t = s / c; eta = e2Squared * (c * c); de = easting - fe; LKASSERT(sn!=0); LKASSERT(sr!=0); t10 = t / (2.0 * sr * sn * (ok * ok)); t11 = t * (5.0 + 3.0 * (t * t) + eta - 4.0 * (eta * eta) - 9.0 * (t * t) * eta) / (24.0 * sr * (sn * sn * sn) * (ok * ok * ok * ok)); lat = ftphi - (de * de) * t10 + (de * de * de * de) * t11; t14 = 1.0 / (sn * c * ok); t15 = (1.0 + 2.0 * (t * t) + eta) / (6 * (sn * sn * sn) * c * (ok * ok * ok)); dlam = de * t14 - (de * de * de) * t15; olam = (utmXZone * 6 - 183.0) * deg2rad; lon = olam + dlam; lon *= rad2deg; lat *= rad2deg; }
void UTMCoord::utmToLatLon (double a, double f, int utmXZone, char utmYZone, double easting, double northing, double& lat, double& lon) const // Purpose: // This function converts the specified UTM coordinate to a lat/lon // coordinate. // Pre: // - utmXZone must be between 1 and 60, inclusive. // - utmYZone must be one of: CDEFGHJKLMNPQRSTUVWX // Parameters: // double a: // Ellipsoid semi-major axis, in meters. (For WGS84 datum, use 6378137.0) // double f: // Ellipsoid flattening. (For WGS84 datum, use 1 / 298.257223563) // int utmXZone: // The horizontal zone number of the UTM coordinate. // char utmYZone: // The vertical zone letter of the UTM coordinate. // double easting, double northing: // The UTM coordinate to convert. // double& lat: // Upon exit, lat contains the latitude. // double& lon: // Upon exit, lon contains the longitude. // Notes: // The code in this function is a C conversion of some of the source code // from the Mapping Datum Transformation Software (MADTRAN) program, written // in PowerBasic. To get the source code for MADTRAN, go to: // // http://164.214.2.59/publications/guides/MADTRAN/index.html // // and download MADTRAN.ZIP { double recf; double b; double eSquared; double e2Squared; double tn; double ap; double bp; double cp; double dp; double ep; double nfn; double tmd; double sr; double sn; double ftphi; double s; double c; double t; double eta; double de; double dlam; double olam; recf = 1.0 / f; b = a * (recf - 1) / recf; eSquared = calculateESquared (a, b); e2Squared = calculateE2Squared (a, b); tn = (a - b) / (a + b); ap = a * (1.0 - tn + 5.0 * ((tn * tn) - (tn * tn * tn)) / 4.0 + 81.0 * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 64.0); bp = 3.0 * a * (tn - (tn * tn) + 7.0 * ((tn * tn * tn) - (tn * tn * tn * tn)) / 8.0 + 55.0 * (tn * tn * tn * tn * tn) / 64.0) / 2.0; cp = 15.0 * a * ((tn * tn) - (tn * tn * tn) + 3.0 * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 4.0) / 16.0; dp = 35.0 * a * ((tn * tn * tn) - (tn * tn * tn * tn) + 11.0 * (tn * tn * tn * tn * tn) / 16.0) / 48.0; ep = 315.0 * a * ((tn * tn * tn * tn) - (tn * tn * tn * tn * tn)) / 512.0; if ((utmYZone <= 'M' && utmYZone >= 'C') || (utmYZone <= 'm' && utmYZone >= 'c')) { nfn = 10000000.0; } else { nfn = 0; } tmd = (northing - nfn) / ok; sr = sphsr (a, eSquared, 0.0); ftphi = tmd / sr; double t10, t11, t14, t15; for (int i = 0; i < 5; i++) { t10 = sphtmd (ap, bp, cp, dp, ep, ftphi); sr = sphsr (a, eSquared, ftphi); ftphi = ftphi + (tmd - t10) / sr; } sr = sphsr (a, eSquared, ftphi); sn = sphsn (a, eSquared, ftphi); s = sin (ftphi); c = cos (ftphi); t = s / c; eta = e2Squared * (c * c); de = easting - fe; t10 = t / (2.0 * sr * sn * (ok * ok)); t11 = t * (5.0 + 3.0 * (t * t) + eta - 4.0 * (eta * eta) - 9.0 * (t * t) * eta) / (24.0 * sr * (sn * sn * sn) * (ok * ok * ok * ok)); lat = ftphi - (de * de) * t10 + (de * de * de * de) * t11; t14 = 1.0 / (sn * c * ok); t15 = (1.0 + 2.0 * (t * t) + eta) / (6 * (sn * sn * sn) * c * (ok * ok * ok)); dlam = de * t14 - (de * de * de) * t15; olam = (utmXZone * 6 - 183.0) * DEG_TO_RAD; lon = olam + dlam; lon *= RAD_TO_DEG; lat *= RAD_TO_DEG; }