/// <summary> /// Used to convert latlon from degrees to radians /// </summary> /// <param name="latLon">Latitude and Longidute object in degrees</param> /// <returns>Latitude and Longidute object in radians</returns> private LatLon ToRadians(LatLon latLon) { return new LatLon { Latitude = latLon.Latitude * Math.PI / 180, Longitude = latLon.Longitude * Math.PI / 180, }; }
/// <summary> /// Used to convert latlon from radians to degrees /// <param name="latLon">Latitude and Longidute object in radians</param> /// <returns>Latitude and Longidute object in degrees</returns> /// </summary> private LatLon ToDegrees(LatLon latLon) { return new LatLon { Latitude = latLon.Latitude * 180 / Math.PI, Longitude = latLon.Longitude * 180 / Math.PI, }; }
/// <summary> /// Abridged Molodensky transformation between 2 datums /// </summary> /// <param name="input"></param> /// <param name="from"></param> /// <param name="to"></param> /// <returns></returns> private LatLon Molodensky(LatLon input, string from, string to) { // from->WGS84 - to->WGS84 = from->WGS84 + WGS84->to = from->to double dX = Datums[from].DeltaX - Datums[to].DeltaX; double dY = Datums[from].DeltaY - Datums[to].DeltaY; double dZ = Datums[from].DeltaZ - Datums[to].DeltaZ; double slat = Math.Sin(input.Latitude); double clat = Math.Cos(input.Latitude); double slon = Math.Sin(input.Longitude); double clon = Math.Cos(input.Longitude); double ssqlat = slat * slat; //dlat = ((-dx * slat * clon - dy * slat * slon + dz * clat) // + (da * rn * from_esq * slat * clat / from_a) // + (df * (rm * adb + rn / adb )* slat * clat)) // / (rm + from.h); double from_f = Datums[from].Flatenning; double df = Datums[to].Flatenning - from_f; double from_a = Datums[from].EquatorialEarthRadius; double da = Datums[to].EquatorialEarthRadius - from_a; double from_esq = Datums[from].EccentricitySquared; double adb = 1.0 / (1.0 - from_f); double rn = from_a / Math.Sqrt(1 - from_esq * ssqlat); double rm = from_a * (1 - from_esq) / Math.Pow((1 - from_esq * ssqlat), 1.5); double from_h = 0.0; // we're flat! double dlat = (-dX * slat * clon - dY * slat * slon + dZ * clat + da * rn * from_esq * slat * clat / from_a + +df * (rm * adb + rn / adb) * slat * clat) / (rm + from_h); // dlon = (-dx * slon + dy * clon) / ((rn + from.h) * clat); double dlon = (-dX * slon + dY * clon) / ((rn + from_h) * clat); // result lat (radians) return new LatLon { Latitude = input.Latitude + dlat, Longitude = input.Longitude + dlon }; }
/// <summary> /// Lat/Lon to Local Grid conversion /// </summary> /// <param name="latLon"></param> /// <param name="from"></param> /// <param name="to"></param> /// <returns></returns> private NorthEast LatLon2Grid(LatLon latLon, string from, string to) { // Datum data for Lat/Lon to TM conversion double a = Datums[from].EquatorialEarthRadius; double e = Datums[from].Eccentricity; // sqrt(esq); double b = Datums[from].PolarEarthRadius; double lat = latLon.Latitude; double lon = latLon.Longitude; double slat1 = Math.Sin(lat); double clat1 = Math.Cos(lat); double clat1sq = clat1 * clat1; double tanlat1sq = slat1 * slat1 / clat1sq; double e2 = e * e; double e4 = e2 * e2; double e6 = e4 * e2; double eg = (e * a / b); double eg2 = eg * eg; double l1 = 1 - e2 / 4 - 3 * e4 / 64 - 5 * e6 / 256; double l2 = 3 * e2 / 8 + 3 * e4 / 32 + 45 * e6 / 1024; double l3 = 15 * e4 / 256 + 45 * e6 / 1024; double l4 = 35 * e6 / 3072; double M = a * (l1 * lat - l2 * Math.Sin(2 * lat) + l3 * Math.Sin(4 * lat) - l4 * Math.Sin(6 * lat)); //double rho = a*(1-e2) / pow((1-(e*slat1)*(e*slat1)),1.5); double nu = a / Math.Sqrt(1 - (e * slat1) * (e * slat1)); double p = lon - Grids[to].CentralLongitude; double k0 = Grids[to].ScaleFactor; // y = northing = K1 + K2p2 + K3p4, where double K1 = M * k0; double K2 = k0 * nu * slat1 * clat1 / 2; double K3 = (k0 * nu * slat1 * clat1 * clat1sq / 24) * (5 - tanlat1sq + 9 * eg2 * clat1sq + 4 * eg2 * eg2 * clat1sq * clat1sq); // ING north double Y = K1 + K2 * p * p + K3 * p * p * p * p - Grids[to].FalseNorthing; // x = easting = K4p + K5p3, where double K4 = k0 * nu * clat1; double K5 = (k0 * nu * clat1 * clat1sq / 6) * (1 - tanlat1sq + eg2 * clat1 * clat1); // ING east double X = K4 * p + K5 * p * p * p + Grids[to].FalseEasting; // final rounded results return new NorthEast { North = (int)(Y + 0.5), East = (int)(X + 0.5), }; }
/// <summary> /// WGS84 to Israel New Grid (ITM) conversion /// </summary> /// <param name="latLon">Latitide and Longitude in WGS84</param> /// <returns>North East Coordinates in ITM grid</returns> public NorthEast Wgs84ToItm(LatLon latLon) { // 1. Molodensky WGS84 -> GRS80 var latLon80 = Molodensky(ToRadians(latLon), WGS84, GRS80); // 2. Lat/Lon (GRS80) -> Local Grid (ITM) return LatLon2Grid(latLon80, GRS80, ITM); }
/// <summary> /// WGS84 to Israel Old Grid (ICS) conversion /// </summary> /// <param name="latLon">Latitide and Longitude in WGS84</param> /// <returns>North East Coordinates in ICS grid</returns> public NorthEast Wgs84ToIcs(LatLon latLon) { // 1. Molodensky WGS84 -> Clark_1880_modified var latLon80 = Molodensky(ToRadians(latLon), WGS84, CLARK80M); // 2. Lat/Lon (Clark_1880_modified) -> Local Grid (ICS) return LatLon2Grid(latLon80, CLARK80M, ICS); }