public static GeoCoordinate GetEndPoint(GeoCoordinate start, double azimuth, double distance) { double b = distance / OrthographicProjection.EarthRadiusKm; double sLat = ToRadians(90 - start.Latitude); double radAz = ToRadians(azimuth); double a = Math.Acos(Math.Cos(b) * Math.Cos(sLat) + Math.Sin(sLat) * Math.Sin(b) * Math.Cos(radAz)); double B = Math.Asin(Math.Sin(b) * Math.Sin(radAz) / Math.Sin(a)); double lat2 = ToDegrees(a); lat2 = 90 - lat2; double lon2 = ToDegrees(B) + start.Longitude; lon2 = OrthographicProjection.SanitizeLongitude(lon2); return(new GeoCoordinate(lat2, lon2)); }
public static void LLtoUTM(int referenceEllipsoid, double lat, double Long, out double utmNorthing, out double utmEasting, out string utmZone) { //converts lat/long to UTM coords. Equations from USGS Bulletin 1532 //East Longitudes are positive, West longitudes are negative. //North latitudes are positive, South latitudes are negative //Lat and Long are in decimal degrees //Written by Chuck Gantz- [email protected] double a = ellipsoid[referenceEllipsoid].EquatorialRadius; double eccSquared = ellipsoid[referenceEllipsoid].eccentricitySquared; double k0 = 0.9996; double LongOrigin; double eccPrimeSquared; double N, T, C, A, M; //Make sure the longitude is between -180.00 .. 179.9 double LongTemp = OrthographicProjection.SanitizeLongitude(Long); double LatRad = OrthographicProjection.ToRadians(lat); double LongRad = OrthographicProjection.ToRadians(LongTemp); double LongOriginRad; int ZoneNumber; ZoneNumber = (int)((LongTemp + 180) / 6) + 1; if (lat >= 56.0 && lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0) { ZoneNumber = 32; } // Special zones for Svalbard if (lat >= 72.0 && lat < 84.0) { if (LongTemp >= 0.0 && LongTemp < 9.0) { ZoneNumber = 31; } else if (LongTemp >= 9.0 && LongTemp < 21.0) { ZoneNumber = 33; } else if (LongTemp >= 21.0 && LongTemp < 33.0) { ZoneNumber = 35; } else if (LongTemp >= 33.0 && LongTemp < 42.0) { ZoneNumber = 37; } } LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin in middle of zone LongOriginRad = OrthographicProjection.ToRadians(LongOrigin); //compute the UTM Zone from the latitude and longitude utmZone = String.Format("{0}{1}", ZoneNumber, UTMLetterDesignator(lat)); eccPrimeSquared = (eccSquared) / (1 - eccSquared); N = a / Math.Sqrt(1 - eccSquared * Math.Sin(LatRad) * Math.Sin(LatRad)); T = Math.Tan(LatRad) * Math.Tan(LatRad); C = eccPrimeSquared * Math.Cos(LatRad) * Math.Cos(LatRad); A = Math.Cos(LatRad) * (LongRad - LongOriginRad); M = a * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.Sin(2 * LatRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.Sin(4 * LatRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Math.Sin(6 * LatRad)); utmEasting = k0 * N * (A + (1 - T + C) * A * A * A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120) + 500000.0; utmNorthing = k0 * (M + N * Math.Tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 + (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720)); if (lat < 0) { utmNorthing += 10000000.0; //10000000 meter offset for southern hemisphere } }
static public void UTMtoLL(int referenceEllipsoid, double utmNorthing, double utmEasting, string utmZone, out double lat, out double Long) { //converts UTM coords to lat/long. Equations from USGS Bulletin 1532 //East Longitudes are positive, West longitudes are negative. //North latitudes are positive, South latitudes are negative //Lat and Long are in decimal degrees. //Written by Chuck Gantz- [email protected] double k0 = 0.9996; double a = ellipsoid[referenceEllipsoid].EquatorialRadius; double eccSquared = ellipsoid[referenceEllipsoid].eccentricitySquared; double eccPrimeSquared; double e1 = (1 - Math.Sqrt(1 - eccSquared)) / (1 + Math.Sqrt(1 - eccSquared)); double N1, T1, C1, R1, D, M; double LongOrigin; double mu, phi1, phi1Rad; double x, y; int ZoneNumber; string ZoneLetter; int NorthernHemisphere; //1 for northern hemispher, 0 for southern x = utmEasting - 500000.0; //remove 500,000 meter offset for longitude y = utmNorthing; // UTM zone is number and letter utmZone = utmZone.Trim(); int idx = utmZone.Length - 1; ZoneLetter = utmZone.Substring(idx); // last character ZoneNumber = int.Parse(utmZone.Substring(0, idx)); if (String.Compare(ZoneLetter, "N") >= 0) // if((* ZoneLetter - 'N') >= 0) { NorthernHemisphere = 1; //point is in northern hemisphere } else { NorthernHemisphere = 0; //point is in southern hemisphere y -= 10000000.0; //remove 10,000,000 meter offset used for southern hemisphere } LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin in middle of zone eccPrimeSquared = (eccSquared) / (1 - eccSquared); M = y / k0; mu = M / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256)); phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.Sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.Sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.Sin(6 * mu); phi1 = OrthographicProjection.ToDegrees(phi1Rad); N1 = a / Math.Sqrt(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad)); T1 = Math.Tan(phi1Rad) * Math.Tan(phi1Rad); C1 = eccPrimeSquared * Math.Cos(phi1Rad) * Math.Cos(phi1Rad); R1 = a * (1 - eccSquared) / Math.Pow(1 - eccSquared * Math.Sin(phi1Rad) * Math.Sin(phi1Rad), 1.5); D = x / (N1 * k0); lat = phi1Rad - (N1 * Math.Tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720); lat = OrthographicProjection.ToDegrees(lat); Long = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) * D * D * D * D * D / 120) / Math.Cos(phi1Rad); Long = LongOrigin + OrthographicProjection.ToDegrees(Long); }