public void Test_FileFormat_HGT() { string fileName = "N43E005.hgt"; string sourceFile = Path.Combine("TestData", fileName + ".zip"); bool fileOk = File.Exists(sourceFile); Assert.True(fileOk, "TestData is missing"); if (!File.Exists(fileName)) { ZipFile.ExtractToDirectory(sourceFile, "."); } Assert.True(File.Exists(fileName), "Unzip failed."); // Pass the full file name fileName = Path.GetFullPath(fileName); using (IRasterFile raster = _rasterService.OpenFile(fileName, DEMFileType.SRTM_HGT)) { FileMetadata metaData = raster.ParseMetaData(new DEMFileDefinition(DEMFileType.SRTM_HGT, DEMFileRegistrationMode.Grid)); Assert.NotNull(metaData); float elevation = raster.GetElevationAtPoint(metaData, 300, 10); Assert.Equal(751f, elevation); elevation = raster.GetElevationAtPoint(metaData, 10, 300); Assert.Equal(297f, elevation); } }
public void Test_FileFormat_GeoTIFF() { string fileName = "N043E005_AVE_DSM.tif"; string sourceFile = Path.Combine("TestData", fileName + ".zip"); bool fileOk = File.Exists(sourceFile); Assert.True(fileOk, "TestData is missing"); if (!File.Exists(fileName)) { ZipFile.ExtractToDirectory(sourceFile, "."); } Assert.True(File.Exists(fileName), "Unzip failed."); // Pass the full file name fileName = Path.GetFullPath(fileName); using (IRasterFile raster = _rasterService.OpenFile(fileName, DEMFileType.GEOTIFF)) { FileMetadata metaData = raster.ParseMetaData(new DEMFileDefinition(DEMFileType.GEOTIFF, DEMFileRegistrationMode.Cell)); Assert.NotNull(metaData); float elevation = raster.GetElevationAtPoint(metaData, 1000, 200); Assert.Equal(304f, elevation); elevation = raster.GetElevationAtPoint(metaData, 200, 1000); Assert.Equal(95f, elevation); } }
public void Test_FileFormat_HGT_OutOfRange() { string fileName = "N43E005.hgt"; string sourceFile = Path.Combine("TestData", fileName + ".zip"); bool fileOk = File.Exists(sourceFile); Assert.True(fileOk, "TestData is missing"); if (!File.Exists(fileName)) { ZipFile.ExtractToDirectory(sourceFile, ".", true); } Assert.True(File.Exists(fileName), "Unzip failed."); // Pass the full file name fileName = Path.GetFullPath(fileName); using (IRasterFile raster = _rasterService.OpenFile(fileName, DEMFileFormat.SRTM_HGT)) { FileMetadata metaData = raster.ParseMetaData(); Assert.NotNull(metaData); Assert.Throws <IndexOutOfRangeException>(() => { float elevation = raster.GetElevationAtPoint(metaData, 10000, 10000); }); // Expect exception } }
private float GetElevationAtPoint(RasterFileDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator) { float heightValue = 0; try { IRasterFile mainRaster = adjacentTiles[metadata]; //const double epsilon = (Double.Epsilon * 100); float noData = metadata.NoDataValueFloat; // precise position on the grid (with commas) double ypos = (lat - metadata.StartLat) / metadata.pixelSizeY; double xpos = (lon - metadata.StartLon) / metadata.pixelSizeX; // If pure integers, then it's on the grid float xInterpolationAmount = (float)xpos % 1; float yInterpolationAmount = (float)ypos % 1; bool xOnGrid = Math.Abs(xInterpolationAmount) < float.Epsilon; bool yOnGrid = Math.Abs(yInterpolationAmount) < float.Epsilon; // If xOnGrid and yOnGrid, we are on a grid intersection, and that's all if (xOnGrid && yOnGrid) { int x = (int)Math.Round(xpos, 0); int y = (int)Math.Round(ypos, 0); var tile = FindTile(metadata, adjacentTiles, x, y, out x, out y); heightValue = mainRaster.GetElevationAtPoint(tile, x, y); } else { int xCeiling = (int)Math.Ceiling(xpos); int xFloor = (int)Math.Floor(xpos); int yCeiling = (int)Math.Ceiling(ypos); int yFloor = (int)Math.Floor(ypos); // Get 4 grid nearest points (DEM grid corners) // If not yOnGrid and not xOnGrid we are on grid horizontal line // We need elevations for top, bottom, left and right grid points (along x axis and y axis) float northWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yFloor, NO_DATA_OUT); float northEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yFloor, NO_DATA_OUT); float southWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yCeiling, NO_DATA_OUT); float southEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yCeiling, NO_DATA_OUT); float avgHeight = GetAverageExceptForNoDataValue(noData, NO_DATA_OUT, southWest, southEast, northWest, northEast); if (northWest == noData) { northWest = avgHeight; } if (northEast == noData) { northEast = avgHeight; } if (southWest == noData) { southWest = avgHeight; } if (southEast == noData) { southEast = avgHeight; } heightValue = interpolator.Interpolate(southWest, southEast, northWest, northEast, xInterpolationAmount, yInterpolationAmount); } if (heightValue == NO_DATA_OUT) { heightValue = lastElevation; } } catch (Exception e) { _logger?.LogError(e, $"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}"); } return(heightValue); }
public float GetPointsElevation(IRasterFile raster, FileMetadata metadata, IEnumerable <GeoPoint> points, IInterpolator interpolator = null) { float heightValue = 0; try { if (interpolator == null) { interpolator = GetInterpolator(InterpolationMode.Bilinear); } float noData = metadata.NoDataValueFloat; foreach (var pointsByLat in points.GroupBy(p => p.Latitude)) { double lat = pointsByLat.Key; double ypos = (lat - metadata.StartLat) / metadata.pixelSizeY; foreach (GeoPoint point in pointsByLat) { // precise position on the grid (with commas) double lon = point.Longitude; double xpos = (lon - metadata.StartLon) / metadata.pixelSizeX; // If pure integers, then it's on the grid float xInterpolationAmount = (float)xpos % 1; float yInterpolationAmount = (float)ypos % 1; bool xOnGrid = Math.Abs(xInterpolationAmount) < float.Epsilon; bool yOnGrid = Math.Abs(yInterpolationAmount) < float.Epsilon; // If xOnGrid and yOnGrid, we are on a grid intersection, and that's all if (xOnGrid && yOnGrid) { int x = (int)Math.Round(xpos, 0); int y = (int)Math.Round(ypos, 0); heightValue = raster.GetElevationAtPoint(metadata, x, y); } else { int xCeiling = (int)Math.Ceiling(xpos); int xFloor = (int)Math.Floor(xpos); int yCeiling = (int)Math.Ceiling(ypos); int yFloor = (int)Math.Floor(ypos); // Get 4 grid nearest points (DEM grid corners) // If not yOnGrid and not xOnGrid we are on grid horizontal line // We need elevations for top, bottom, left and right grid points (along x axis and y axis) float northWest = raster.GetElevationAtPoint(metadata, xFloor, yFloor); float northEast = raster.GetElevationAtPoint(metadata, xCeiling, yFloor); float southWest = raster.GetElevationAtPoint(metadata, xFloor, yCeiling); float southEast = raster.GetElevationAtPoint(metadata, xCeiling, yCeiling); float avgHeight = GetAverageExceptForNoDataValue(noData, NO_DATA_OUT, southWest, southEast, northWest, northEast); if (Math.Abs(northWest - noData) < float.Epsilon) { northWest = avgHeight; } if (Math.Abs(northEast - noData) < float.Epsilon) { northEast = avgHeight; } if (Math.Abs(southWest - noData) < float.Epsilon) { southWest = avgHeight; } if (Math.Abs(southEast - noData) < float.Epsilon) { southEast = avgHeight; } heightValue = interpolator.Interpolate(southWest, southEast, northWest, northEast, xInterpolationAmount, yInterpolationAmount); } point.Elevation = heightValue; } } } catch (Exception e) { _logger?.LogError(e, $"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}"); } return(heightValue); }
private float GetElevationAtPoint(IRasterFile mainRaster, RasterFileDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator) { float heightValue = 0; try { //const double epsilon = (Double.Epsilon * 100); float noData = metadata.NoDataValueFloat; double yPixel, xPixel, xInterpolationAmount, yInterpolationAmount; // pixel coordinates interpolated if (metadata.FileFormat.Registration == DEMFileRegistrationMode.Grid) { yPixel = Math.Sign(metadata.pixelSizeY) == 1 ? (metadata.DataEndLat - lat) / metadata.pixelSizeY : (lat - metadata.DataEndLat) / metadata.pixelSizeY; xPixel = (lon - metadata.DataStartLon) / metadata.pixelSizeX; // If at pixel center (ending by .5, .5), we are on the data point, so no need for adjacent raster checks xInterpolationAmount = (double)(xPixel) % 1d; yInterpolationAmount = (double)(yPixel) % 1d; } else { // In cell registration mode, the actual data point is at pixel center // If at pixel center (ending by .5, .5), we are on the data point, so no need for adjacent raster checks yPixel = Math.Sign(metadata.pixelSizeY) == 1 ? ((metadata.PhysicalEndLat + metadata.pixelSizeY / 2) - lat) / metadata.pixelSizeY : (lat - (metadata.PhysicalEndLat + metadata.pixelSizeY / 2)) / metadata.pixelSizeY; xPixel = (lon - (metadata.PhysicalStartLon + metadata.pixelSizeX / 2)) / metadata.pixelSizeX; xInterpolationAmount = Math.Abs((double)(xPixel) % 1d); yInterpolationAmount = Math.Abs((double)(yPixel) % 1d); } bool xOnDataPoint = Math.Abs(xInterpolationAmount) < EPSILON; bool yOnDataPoint = Math.Abs(yInterpolationAmount) < EPSILON; // If xOnGrid and yOnGrid, we are on a grid intersection, and that's all // TODO fix that // When cell registered, this true when interpolation is 0.5 / 0.5 // When grid registered, this is true if (xOnDataPoint && yOnDataPoint) { int x = (int)Math.Round(xPixel, 0); int y = (int)Math.Round(yPixel, 0); var tile = FindTile(metadata, adjacentTiles, x, y, out x, out y); heightValue = mainRaster.GetElevationAtPoint(tile, x, y); } else { int xCeiling = (int)Math.Ceiling(xPixel); int xFloor = (int)Math.Floor(xPixel); int yCeiling = (int)Math.Ceiling(yPixel); int yFloor = (int)Math.Floor(yPixel); // Get 4 grid nearest points (DEM grid corners) // If not yOnGrid and not xOnGrid we are on grid horizontal line // We need elevations for top, bottom, left and right grid points (along x axis and y axis) float northWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yFloor, noData); float northEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yFloor, noData); float southWest = GetElevationAtPoint(metadata, adjacentTiles, xFloor, yCeiling, noData); float southEast = GetElevationAtPoint(metadata, adjacentTiles, xCeiling, yCeiling, noData); float avgHeight = GetAverageExceptForNoDataValue(noData, NO_DATA_OUT, southWest, southEast, northWest, northEast); if (northWest == noData) { northWest = avgHeight; } if (northEast == noData) { northEast = avgHeight; } if (southWest == noData) { southWest = avgHeight; } if (southEast == noData) { southEast = avgHeight; } heightValue = (float)interpolator.Interpolate(southWest, southEast, northWest, northEast, xInterpolationAmount, yInterpolationAmount); } if (heightValue == NO_DATA_OUT) { heightValue = lastElevation; } } catch (Exception e) { _logger?.LogError(e, $"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}"); throw; } return(heightValue); }