/// <summary> /// Converts this LatLngPoint to a Universal Transverse Mercator point using the WGS-84 /// datum. The coordinate pair's units will be in meters, and should be usable to make /// distance calculations over short distances. /// </summary> /// <seealso cref="http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm"/> /// <param name="latlng">The point on Earth to convert to UTM</param> /// <returns>The UTM point</returns> public static UTMPoint ToUTM(this LatLngPoint latlng) { if (latlng is null) { throw new ArgumentNullException(nameof(latlng)); } var hemisphere = latlng.Latitude < 0 ? UTMPoint.GlobeHemisphere.Southern : UTMPoint.GlobeHemisphere.Northern; const double k0 = 0.9996; double phi = Degrees.Radians(latlng.Latitude); var sinPhi = Sin(phi); var cosPhi = Cos(phi); var sin2Phi = 2 * sinPhi * cosPhi; var cos2Phi = (2 * cosPhi * cosPhi) - 1; var sin4Phi = 2 * sin2Phi * cos2Phi; var cos4Phi = (2 * cos2Phi * cos2Phi) - 1; var sin6Phi = (sin4Phi * cos2Phi) + (cos4Phi * sin2Phi); var tanPhi = sinPhi / cosPhi; var ePhi = DatumWGS_84.e * sinPhi; var N = DatumWGS_84.equatorialRadius / Sqrt(1 - (ePhi * ePhi)); var utmz = 1 + (int)Floor((latlng.Longitude + 180) / 6.0); var zcm = 3 + (6.0 * (utmz - 1)) - 180; var A = Degrees.Radians((float)(latlng.Longitude - zcm)) * cosPhi; var M = DatumWGS_84.equatorialRadius * ( (phi * DatumWGS_84.alpha1) - (sin2Phi * DatumWGS_84.alpha2) + (sin4Phi * DatumWGS_84.alpha3) - (sin6Phi * DatumWGS_84.alpha4)); // Easting var T = tanPhi * tanPhi; var C = DatumWGS_84.e0sq * cosPhi * cosPhi; var Asqr = A * A; var Tsqr = T * T; var x0 = 1 - T + C; var x1 = 5 - (18 * T) + Tsqr + (72.0 * C) - (58 * DatumWGS_84.e0sq); var x2 = Asqr * x1 / 120.0; var x3 = (x0 / 6) + x2; var x4 = 1 + (Asqr * x3); var easting = k0 * N * A * x4; easting += DatumWGS_84.E0; // Northing var northing = k0 * (M + (N * tanPhi * (Asqr * ((1 / 2.0) + (Asqr * (((5 - T + (9 * C) + (4 * C * C)) / 24.0) + (Asqr * (61 - (58 * T) + Tsqr + (600 * C) - (330 * DatumWGS_84.e0sq)) / 720.0))))))); if (hemisphere == UTMPoint.GlobeHemisphere.Southern) { northing += DatumWGS_84.FalseNorthing; } return(new UTMPoint( (float)easting, (float)northing, latlng.Altitude, utmz, hemisphere)); }