// IGH -> MSTS Tile public static TileCoordinate ConvertToTile(IghCoordinate coordinates, out double x, out double z) { var coord = ConvertToTile(coordinates); x = coord.X; z = coord.Z; return(coord); }
// IGH -> MSTS Precise Tile public static PreciseTileCoordinate ConvertToTile(IghCoordinate coordinates) { var tileX = coordinates.Sample / 2048; var tileZ = coordinates.Line / 2048; var x = tileX - Math.Floor(tileX); var z = tileZ - Math.Floor(tileZ); Debug.Assert(z >= 0, "tileZ is off the top"); Debug.Assert(z <= 1, "tileZ is off the bottom"); Debug.Assert(x >= 0, "tileX is off the left"); Debug.Assert(x <= 1, "tileX is off the right"); return(new PreciseTileCoordinate((int)Math.Floor(tileX) - 16384, 16384 - (int)Math.Floor(tileZ) - 1, x, z)); }
// Lat/Lon -> MSTS IGH public static IghCoordinate ConvertToIgh(LatitudeLongitudeCoordinate coordinates) { // Latitude/Longitude -> Line/Sample Algorithm // Based on C code provided by the USGS, available at ftp://edcftp.cr.usgs.gov/pub/software/misc/gihll2ls.c. // By D. Steinwand, HSTX/EROS Data Center, June, 1993. Debug.Assert(coordinates.Latitude >= -90, "latitude is off the bottom"); Debug.Assert(coordinates.Latitude <= 90, "latitude is off the top"); Debug.Assert(coordinates.Longitude >= -180, "longitude is off the left"); Debug.Assert(coordinates.Longitude <= 180, "longitude is off the right"); double lat = coordinates.Latitude * Math.PI / 180; double lon = coordinates.Longitude * Math.PI / 180; int region = -1; if (lat >= IghParallel41) /* If on or above 40 44' 11.8" */ { if (lon <= -IghMeridian40) /* If to the left of -40 */ { region = 0; } else { region = 2; } } else if (lat >= 0.0) /* Between 0.0 and 40 44' 11.8" */ { if (lon <= -IghMeridian40) /* If to the left of -40 */ { region = 1; } else { region = 3; } } else if (lat >= -IghParallel41) /* Between 0.0 & -40 44' 11.8" */ { if (lon <= -IghMeridian100) /* If between -180 and -100 */ { region = 4; } else if (lon <= -IghMeridian20) /* If between -100 and -20 */ { region = 5; } else if (lon <= IghMeridian80) /* If between -20 and 80 */ { region = 8; } else /* If between 80 and 180 */ { region = 9; } } else /* Below -40 44' 11.8" */ { if (lon <= -IghMeridian100) /* If between -180 and -100 */ { region = 6; } else if (lon <= -IghMeridian20) /* If between -100 and -20 */ { region = 7; } else if (lon <= IghMeridian80) /* If between -20 and 80 */ { region = 10; } else /* If between 80 and 180 */ { region = 11; } } double y = 0; double x = 0; if ((region == 1) || (region == 3) || (region == 4) || (region == 5) || (region == 8) || (region == 9)) { var delta_lon = adjust_lon(lon - IghLongitudeCenter[region]); y = lat; x = IghLongitudeCenter[region] + delta_lon * Math.Cos(lat); } else { var delta_lon = adjust_lon(lon - IghLongitudeCenter[region]); var theta = lat; var constant = Math.PI * Math.Sin(lat); /* Iterate using the Newton-Raphson method to find theta * -----------------------------------------------------*/ for (var i = 0; ; i++) { var delta_theta = -(theta + Math.Sin(theta) - constant) / (1.0 + Math.Cos(theta)); theta += delta_theta; if (Math.Abs(delta_theta) < 0.00000000001) { break; } if (i >= 30) { //giherror("Iteration failed to converge", "Goode-forward"); return(null); } } theta /= 2.0; y = 1.4142135623731 * Math.Sin(theta) - 0.0528035274542 * Math.Sign(lat); x = IghLongitudeCenter[region] + 0.900316316158 * delta_lon * Math.Cos(theta); } Debug.Assert(y >= -Math.PI / 2, "y is off the bottom"); Debug.Assert(y <= +Math.PI / 2, "y is off the top"); Debug.Assert(x >= -Math.PI, "x is off the left"); Debug.Assert(x <= +Math.PI, "x is off the right"); var igh = new IghCoordinate(IghImageTop - y * IghRadius, x * IghRadius - IghImageLeft); Debug.Assert(igh.Line >= 0, "line is off the top"); Debug.Assert(igh.Line <= IghImageHeight, "line is off the bottom"); Debug.Assert(igh.Sample >= 0, "line is off the left"); Debug.Assert(igh.Sample <= IghImageWidth, "line is off the right"); return(igh); }
const double IghMeridian100 = 100d / 180 * Math.PI; // 100deg // IGH -> Lat/Lon public static LatitudeLongitudeCoordinate ConvertToLatLon(IghCoordinate coordinates) { // Line/Sample -> Latitude/Longitude Algorithm // Based on C code provided by the USGS, available at ftp://edcftp.cr.usgs.gov/pub/software/misc/gihll2ls.c. // By D. Steinwand, HSTX/EROS Data Center, June, 1993. Debug.Assert(coordinates.Line >= 0, "line is off the top"); Debug.Assert(coordinates.Line <= IghImageHeight, "line is off the bottom"); Debug.Assert(coordinates.Sample >= 0, "line is off the left"); Debug.Assert(coordinates.Sample <= IghImageWidth, "line is off the right"); double y = (IghImageTop - coordinates.Line) / IghRadius; double x = (IghImageLeft + coordinates.Sample) / IghRadius; Debug.Assert(y >= -Math.PI / 2, "y is off the bottom"); Debug.Assert(y <= +Math.PI / 2, "y is off the top"); Debug.Assert(x >= -Math.PI, "x is off the left"); Debug.Assert(x <= +Math.PI, "x is off the right"); int region = -1; if (y >= IghParallel41) /* If on or above 40 44' 11.8" */ { if (x <= -IghMeridian40) /* If to the left of -40 */ { region = 0; } else { region = 2; } } else if (y >= 0.0) /* Between 0.0 and 40 44' 11.8" */ { if (x <= -IghMeridian40) /* If to the left of -40 */ { region = 1; } else { region = 3; } } else if (y >= -IghParallel41) /* Between 0.0 & -40 44' 11.8" */ { if (x <= -IghMeridian100) /* If between -180 and -100 */ { region = 4; } else if (x <= -IghMeridian20) /* If between -100 and -20 */ { region = 5; } else if (x <= IghMeridian80) /* If between -20 and 80 */ { region = 8; } else /* If between 80 and 180 */ { region = 9; } } else /* Below -40 44' 11.8" */ { if (x <= -IghMeridian100) /* If between -180 and -100 */ { region = 6; } else if (x <= -IghMeridian20) /* If between -100 and -20 */ { region = 7; } else if (x <= IghMeridian80) /* If between -20 and 80 */ { region = 10; } else /* If between 80 and 180 */ { region = 11; } } x = x - IghLongitudeCenter[region]; double lat = 0; double lon = 0; if ((region == 1) || (region == 3) || (region == 4) || (region == 5) || (region == 8) || (region == 9)) { lat = y; if (Math.Abs(lat) > Math.PI / 2) { // giherror("Input data error", "Goode-inverse"); return(null); } double temp = Math.Abs(lat) - Math.PI / 2; if (Math.Abs(temp) > double.Epsilon) { temp = IghLongitudeCenter[region] + x / Math.Cos(lat); lon = adjust_lon(temp); } else { lon = IghLongitudeCenter[region]; } } else { double arg = (y + 0.0528035274542 * Math.Sign(y)) / 1.4142135623731; if (Math.Abs(arg) > 1.0) { return(null); } double theta = Math.Asin(arg); lon = IghLongitudeCenter[region] + (x / (0.900316316158 * Math.Cos(theta))); if (lon < -Math.PI) { return(null); } arg = (2.0 * theta + Math.Sin(2.0 * theta)) / Math.PI; if (Math.Abs(arg) > 1.0) { return(null); } lat = Math.Asin(arg); } /////////////////////////////////////////////////////////////////// return(new LatitudeLongitudeCoordinate(lat * 180 / Math.PI, lon * 180 / Math.PI)); }