static public Srtm3Cell CreateSrtm3Cell(string fileName, bool load) { Regex regex = new Regex("^(?'latSign'[N|S])(?'latitude'[0-9]{2})(?'longSign'[W|E])(?'longitude'[0-9]{3})", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); Match match = regex.Match(fileName); if (false == match.Success) { throw new ArgumentException("Invalid filename", "fileName"); } char latSign = match.Groups["latSign"].Value[0]; Int16 cellLat = Int16.Parse(match.Groups["latitude"].Value, System.Globalization.CultureInfo.InvariantCulture); char lonSign = match.Groups["longSign"].Value[0]; Int16 cellLon = Int16.Parse(match.Groups["longitude"].Value, System.Globalization.CultureInfo.InvariantCulture); if ((latSign == 'S') || (latSign == 's')) { cellLat = (Int16)(-cellLat); } if ((lonSign == 'W') || (lonSign == 'w')) { cellLon = (Int16)(-cellLon); } Srtm3Cell cell = new Srtm3Cell(cellLon, cellLat); if (load) { cell.LoadFromFile(new FileInfo(fileName)); } return(cell); }
static public int CalculateCellKey(Srtm3Cell cell) { if (cell == null) { throw new ArgumentNullException("cell"); } int key = (((int)cell.CellLon + 180) << 16) | ((int)cell.CellLat + 90); return(key); }
/// <summary> /// Generates an index file by listing all available SRTM cells on the FTP site. /// </summary> public void Generate() { activityLogger.Log(ActivityLogLevel.Verbose, "Downloading data for SRTM index generation"); for (SrtmContinentalRegion continentalRegion = (SrtmContinentalRegion)(SrtmContinentalRegion.None + 1); continentalRegion < SrtmContinentalRegion.End; continentalRegion++) { string region = continentalRegion.ToString(); string url = srtmSource + region + "/"; WebRequest request = WebRequest.Create(new System.Uri(url)); WebResponse response = request.GetResponse(); // Get the stream containing content returned by the server. Stream dataStream = response.GetResponseStream(); // Open the stream using a StreamReader for easy access. StreamReader reader = new StreamReader(dataStream); // Read the content. string responseFromServer = reader.ReadToEnd(); MatchCollection matches = Regex.Matches(responseFromServer, fileNamePattern, RegexOptions.IgnoreCase); // Process each match. foreach (Match match in matches) { GroupCollection groups = match.Groups; string filename = groups[1].Value.Trim(); if (filename.Length == 0) { continue; } Srtm3Cell srtm3Cell = Srtm3Cell.CreateSrtm3Cell(filename, false); SetValueForCell(srtm3Cell.CellLon, srtm3Cell.CellLat, (int)continentalRegion); } // Cleanup the streams and the response. reader.Close(); dataStream.Close(); response.Close(); } }
public IDictionary <int, Srtm3Cell> FetchCachedCellsList() { Dictionary <int, Srtm3Cell> cachedCells = new Dictionary <int, Srtm3Cell> (); DirectoryInfo cacheDir = new DirectoryInfo(Srtm3CachePath); FileInfo[] files = null; try { files = cacheDir.GetFiles("*.hgt"); foreach (FileInfo file in files) { Srtm3Cell cell = Srtm3Cell.CreateSrtm3Cell(file.Name, false); cachedCells.Add(Srtm3Cell.CalculateCellKey(cell), cell); } } catch (DirectoryNotFoundException) { // no cache found, skip } return(cachedCells); }
public IDigitalElevationModel LoadDemForArea(Bounds2 bounds) { // make sure the cache directory exists if (false == Directory.Exists(srtm3CachePath)) { Directory.CreateDirectory(srtm3CachePath); } // first create a list of geographicals cells which constitute the specified area IDictionary <int, Srtm3Cell> cellsToUse = new Dictionary <int, Srtm3Cell> (); for (int lat = CalculateCellDegrees(bounds.MinY); lat <= CalculateCellDegrees(bounds.MaxY); lat++) { for (int lng = CalculateCellDegrees(bounds.MinX); lng <= CalculateCellDegrees(bounds.MaxX); lng++) { Srtm3Cell cell = new Srtm3Cell((Int16)lng, (Int16)lat); cellsToUse.Add(Srtm3Cell.CalculateCellKey(cell), cell); } } // then fetch a list of already downloaded cells IDictionary <int, Srtm3Cell> cachedCells = FetchCachedCellsList(); try { foreach (Srtm3Cell cell in cellsToUse.Values) { // if it is not cached... if (false == cachedCells.ContainsKey(Srtm3Cell.CalculateCellKey(cell))) { // find the right subdirectory SrtmContinentalRegion continentalRegion = (SrtmContinentalRegion)index.GetValueForCell(cell.CellLon, cell.CellLat); if (continentalRegion == SrtmContinentalRegion.None) { // the cell does not exist in the index, it is probably an ocean cell // add an empty cell to the cache and go to the next cell cachedCells.Add(Srtm3Cell.CalculateCellKey(cell), cell); continue; } string filename = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.zip", cell.CellFileName); string url = srtmSource + continentalRegion.ToString() + "/" + filename; string localFilename = Path.Combine(srtm3CachePath, filename); this.activityLogger.Log(ActivityLogLevel.Verbose, "Downloading SRTM cell " + cell.CellFileName); WebRequest request = WebRequest.Create(new System.Uri(url)); WebResponse response = request.GetResponse(); // Get the stream containing content returned by the server. Stream dataStream = response.GetResponseStream(); FileStream fileStream = new FileStream(localFilename, FileMode.OpenOrCreate); //Download in chuncks byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = dataStream.Read(buffer, 0, buffer.Length)) > 0) { fileStream.Write(buffer, 0, bytesRead); } long receivedLength = fileStream.Length; fileStream.Close(); dataStream.Close(); response.Close(); // Check if the download is complete. if (response.ContentLength != -1 && response.ContentLength > receivedLength) { File.Delete(localFilename); throw new WebException("Download incomplete (content length mismatch).", null, WebExceptionStatus.ReceiveFailure, response); } // unzip it and delete the zip file FastZip zip = new FastZip(); zip.ExtractZip(localFilename, srtm3CachePath, null); File.Delete(localFilename); } // now load it cell.LoadFromCache(srtm3CachePath); } } finally { } // create elevation data int west, south, east, north; west = Srtm3Storage.CalculateCellPosition(bounds.MinX); south = Srtm3Storage.CalculateCellPosition(bounds.MinY); east = Srtm3Storage.CalculateCellPosition(bounds.MaxX); north = Srtm3Storage.CalculateCellPosition(bounds.MaxY); int width = east - west + 1; int height = north - south + 1; long requiredBytes = width * height * 2L; int loadCounter = 1; RasterDigitalElevationModelFactory factory = new RasterDigitalElevationModelFactory(1200, 1200, west, south, width, height); factory.ActivityLogger = activityLogger; RasterDigitalElevationModelBase dem = factory.CreateSupportedModel(); if (dem == null) { throw new PlatformNotSupportedException("No suitable location for the DEM found."); } // and fill the DEM with each cell points foreach (Srtm3Cell cell in cellsToUse.Values) { this.activityLogger.LogFormat(ActivityLogLevel.Normal, "Loading cell {0} of {1} into DEM", loadCounter++, cellsToUse.Values.Count); dem.CopyElevationPointsFrom(cell); } return(dem); }