public GeoPoint GetPointElevation(double lat, double lon, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear) { GeoPoint geoPoint = new GeoPoint(lat, lon); List <FileMetadata> tiles = this.GetCoveringFiles(lat, lon, dataSet); if (tiles.Count == 0) { _logger?.LogWarning($"No coverage found matching provided point {geoPoint} for dataset {dataSet.Name}"); return(null); } else { // Init interpolator IInterpolator interpolator = GetInterpolator(interpolationMode); using (RasterFileDictionary adjacentRasters = new RasterFileDictionary()) { PopulateRasterFileDictionary(adjacentRasters, tiles.First(), _IRasterService, tiles); geoPoint.Elevation = GetElevationAtPoint(adjacentRasters, tiles.First(), lat, lon, 0, interpolator); //Debug.WriteLine(adjacentRasters.Count); } // Ensures all geotifs are properly closed } return(geoPoint); }
public IEnumerable <GeoPoint> GetPointsElevation(IEnumerable <GeoPoint> points, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear) { if (points == null) { return(null); } IEnumerable <GeoPoint> pointsWithElevation; BoundingBox bbox = points.GetBoundingBox(); DownloadMissingFiles(dataSet, bbox); List <FileMetadata> tiles = this.GetCoveringFiles(bbox, dataSet); if (tiles.Count == 0) { return(null); } else { // Init interpolator IInterpolator interpolator = GetInterpolator(interpolationMode); using (RasterFileDictionary adjacentRasters = new RasterFileDictionary()) { // Get elevation for each point pointsWithElevation = this.GetElevationData(points, adjacentRasters, tiles, interpolator); //Debug.WriteLine(adjacentRasters.Count); } // Ensures all rasters are properly closed } return(pointsWithElevation); }
public List <GeoPoint> GetLineGeometryElevation(IGeometry lineStringGeometry, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear) { if (lineStringGeometry == null || lineStringGeometry.IsEmpty) { return(null); } if (lineStringGeometry.OgcGeometryType != OgcGeometryType.LineString) { throw new Exception("Geometry must be a linestring"); } if (lineStringGeometry.SRID != 4326) { throw new Exception("Geometry SRID must be set to 4326 (WGS 84)"); } BoundingBox bbox = lineStringGeometry.GetBoundingBox(); List <FileMetadata> tiles = this.GetCoveringFiles(bbox, dataSet); // Init interpolator IInterpolator interpolator = GetInterpolator(interpolationMode); var ptStart = lineStringGeometry.Coordinates[0]; var ptEnd = lineStringGeometry.Coordinates.Last(); GeoPoint start = new GeoPoint(ptStart.Y, ptStart.X); GeoPoint end = new GeoPoint(ptEnd.Y, ptEnd.X); double lengthMeters = start.DistanceTo(end); int demResolution = dataSet.ResolutionMeters; int totalCapacity = 2 * (int)(lengthMeters / demResolution); List <GeoPoint> geoPoints = new List <GeoPoint>(totalCapacity); using (RasterFileDictionary adjacentRasters = new RasterFileDictionary()) { bool isFirstSegment = true; // used to return first point only for first segments, for all other segments last point will be returned foreach (GeoSegment segment in lineStringGeometry.Segments()) { List <FileMetadata> segTiles = this.GetCoveringFiles(segment.GetBoundingBox(), dataSet, tiles); // Find all intersection with segment and DEM grid IEnumerable <GeoPoint> intersections = this.FindSegmentIntersections(segment.Start.Longitude , segment.Start.Latitude , segment.End.Longitude , segment.End.Latitude , segTiles , isFirstSegment , true); // Get elevation for each point intersections = this.GetElevationData(intersections, adjacentRasters, segTiles, interpolator); // Add to output list geoPoints.AddRange(intersections); isFirstSegment = false; } //Debug.WriteLine(adjacentRasters.Count); } // Ensures all rasters are properly closed return(geoPoints); }
public float GetPointElevation(IRasterFile raster, FileMetadata metadata, double lat, double lon, IInterpolator interpolator = null) { // Do not dispose Dictionary, as IRasterFile disposal is the caller's responsability RasterFileDictionary rasters = new RasterFileDictionary(); rasters.Add(metadata, raster); return(GetElevationAtPoint(raster, rasters, metadata, lat, lon, 0, interpolator)); }
private FileMetadata FindTile(FileMetadata mainTile, RasterFileDictionary tiles, int x, int y, out int newX, out int newY) { int xTileOffset = x < 0 ? -1 : x >= mainTile.Width ? 1 : 0; int yTileOffset = y < 0 ? -1 : y >= mainTile.Height ? 1 : 0; if (xTileOffset == 0 && yTileOffset == 0) { newX = x; newY = y; return(mainTile); } else { int yScale = Math.Sign(mainTile.pixelSizeY); FileMetadata tile = null; foreach (var t in tiles.Keys) { var xOffset = Math.Abs(t.DataStartLon - mainTile.DataStartLon - xTileOffset); var yOffset = Math.Abs(t.DataStartLat - mainTile.DataStartLat - yScale * yTileOffset); if (xOffset < float.Epsilon && yOffset < float.Epsilon) { tile = t; break; } } //FileMetadata tile = tiles.Keys.FirstOrDefault( // t => Math.Abs(t.DataStartLat - mainTile.DataStartLat + yScale * yTileOffset) < float.Epsilon // && < float.Epsilon); if (tile == null) { // No adjacent tile found (adjacent tiles may not have been set) if (x == mainTile.Width || y == mainTile.Height) { _logger.LogWarning($"No adjacent tile found (adjacent tiles may not have been set). Returning main tile. (x,y, tile) = ({x},{y},{mainTile})"); newX = x == mainTile.Width ? mainTile.Width - 1 : x; newY = y == mainTile.Height ? mainTile.Height - 1 : y; return(mainTile); } else { throw new Exception($"No adjacent tile found (adjacent tiles may not have been set). (x,y, tile) = ({x},{y},{mainTile})"); } } else { newX = xTileOffset > 0 ? x % mainTile.Width : (mainTile.Width + x) % mainTile.Width; newY = yTileOffset < 0 ? (mainTile.Height + y) % mainTile.Height : y % mainTile.Height; return(tile); } } }
private void PopulateRasterFileDictionary(RasterFileDictionary dictionary, FileMetadata mainTile, IRasterService rasterService, IEnumerable <FileMetadata> fileMetadataList) { // Add main tile if (!dictionary.ContainsKey(mainTile)) { dictionary[mainTile] = rasterService.OpenFile(mainTile.Filename, mainTile.fileFormat); } foreach (var fileMetadata in fileMetadataList) { if (!dictionary.ContainsKey(fileMetadata)) { dictionary[fileMetadata] = rasterService.OpenFile(fileMetadata.Filename, fileMetadata.fileFormat); } } }
private float GetElevationAtPoint(FileMetadata mainTile, RasterFileDictionary tiles, int x, int y, float nullValue) { FileMetadata goodTile = FindTile(mainTile, tiles, x, y, out int xRemap, out int yRemap); if (goodTile == null) { return(nullValue); } if (tiles.ContainsKey(goodTile)) { return(tiles[goodTile].GetElevationAtPoint(goodTile, xRemap, yRemap)); } else { throw new Exception("Tile not found. Should not happen."); } }
private FileMetadata FindTile(FileMetadata mainTile, RasterFileDictionary tiles, int x, int y, out int newX, out int newY) { int xTileOffset = x < 0 ? -1 : x >= mainTile.Width ? 1 : 0; int yTileOffset = y < 0 ? -1 : y >= mainTile.Height ? 1 : 0; if (xTileOffset == 0 && yTileOffset == 0) { newX = x; newY = y; return(mainTile); } else { int yScale = Math.Sign(mainTile.pixelSizeY); FileMetadata tile = tiles.Keys.FirstOrDefault( t => Math.Abs(t.OriginLatitude - mainTile.OriginLatitude + yScale * yTileOffset) < float.Epsilon && Math.Abs(t.OriginLongitude - mainTile.OriginLongitude + xTileOffset) < float.Epsilon); newX = xTileOffset > 0 ? x % mainTile.Width : (mainTile.Width + x) % mainTile.Width; newY = yTileOffset < 0 ? (mainTile.Height + y) % mainTile.Height : y % mainTile.Height; return(tile); } }
public GeoPoint GetPointElevation(double lat, double lon, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear) { GeoPoint geoPoint = new GeoPoint(lat, lon); FileMetadata tile = this.GetCoveringFile(lat, lon, dataSet); if (tile == null) { _logger?.LogWarning($"No coverage found matching provided point {geoPoint} for dataset {dataSet.Name}"); return(null); } else { IEnumerable <FileMetadata> adjacentRasters = null; // for cell registered rasters, we need adjacent tiles for edge locations if (dataSet.FileFormat.Registration == DEMFileRegistrationMode.Cell) { // construct a bbox around the location adjacentRasters = this.GetCoveringFiles(BoundingBox.AroundPoint(lat, lon, Math.Abs(tile.PixelScaleX)), dataSet); } // Init interpolator IInterpolator interpolator = GetInterpolator(interpolationMode); // TODO : grab adjacent tiles for cell registrered datasets to allow correct interpolation when close to edges using (RasterFileDictionary tileCache = new RasterFileDictionary()) { PopulateRasterFileDictionary(tileCache, tile, _IRasterService, adjacentRasters); geoPoint.Elevation = GetElevationAtPoint(tileCache, tile, lat, lon, 0, interpolator); //Debug.WriteLine(adjacentRasters.Count); } // Ensures all geotifs are properly closed } return(geoPoint); }
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); }
/// <summary> /// Fill altitudes for each GeoPoint provided, opening as few rasters as possible /// </summary> /// <param name="intersections"></param> /// <param name="adjacentRasters"></param> /// <param name="segTiles"></param> /// <param name="interpolator"></param> public IEnumerable <GeoPoint> GetElevationData(IEnumerable <GeoPoint> intersections, RasterFileDictionary adjacentRasters, List <FileMetadata> segTiles, IInterpolator interpolator) { // Group by raster file for sequential and faster access var pointsByTileQuery = from point in intersections let pointTile = new { Point = point, Tile = segTiles.FirstOrDefault(t => this.IsPointInTile(t, point)), AdjacentTiles = segTiles.Where(t => this.IsPointInAdjacentTile(t, point)).ToList() } group pointTile by pointTile.Tile into pointsByTile where pointsByTile.Key != null select pointsByTile; float lastElevation = 0; // To interpolate well points close to tile edges, we need all adjacent tiles //using (RasterFileDictionary adjacentRasters = new RasterFileDictionary()) //{ // For each group (key = tile, values = points within this tile) // TIP: test use of Parallel (warning : a lot of files may be opened at the same time) foreach (var tilePoints in pointsByTileQuery) { // Get the tile FileMetadata mainTile = tilePoints.Key; // We open rasters first, then we iterate PopulateRasterFileDictionary(adjacentRasters, mainTile, _IRasterService, tilePoints.SelectMany(tp => tp.AdjacentTiles)); foreach (var pointile in tilePoints) { GeoPoint current = pointile.Point; lastElevation = this.GetElevationAtPoint(adjacentRasters, mainTile, current.Latitude, current.Longitude, lastElevation, interpolator); current.Elevation = lastElevation; yield return(current); } //adjacentRasters.Clear(); } //} }
public void GenerateModel(string bboxWkt, DEMDataSet litto3DDataset, ImageryProvider imageryProvider, float zFactor = 3f, bool withTexture = true, bool withboat = true, bool withWaterSurface = true, DEMDataSet fallbackDataset = null) { try { bool centerOnOrigin = true; int TEXTURE_TILES = 20; string outputDir = Directory.GetCurrentDirectory(); string modelName = $"{litto3DDataset.ResolutionMeters}m_z{zFactor}_{imageryProvider.Name}-{DateTime.Now:yyyyMMdd-hhmmss}"; _logger.LogInformation($"Getting height map data..."); var bbox = GeometryService.GetBoundingBox(bboxWkt).ReprojectTo(4326, litto3DDataset.SRID); var heightMap = _elevationService.GetHeightMap(ref bbox, litto3DDataset); heightMap = heightMap.BakeCoordinates(); var nullCoordsEnumerator = heightMap.Coordinates.Where(c => (c.Elevation ?? litto3DDataset.NoDataValue) == litto3DDataset.NoDataValue); var interpolator = _elevationService.GetInterpolator(InterpolationMode.Bilinear); using (IRasterFile raster = _rasterService.OpenFile(@"D:\Data\ELEVATION_DO_NOT_DELETE\GEBCO2020\cote azur\gebco_2020_subset.tif", DEMFileType.GEOTIFF)) using (RasterFileDictionary dic = new RasterFileDictionary()) { var metadata = raster.ParseMetaData(fallbackDataset.FileFormat); dic.Add(metadata, raster); foreach (var pt in nullCoordsEnumerator) { var proj = pt.ReprojectTo(litto3DDataset.SRID, fallbackDataset.SRID); pt.Elevation = _elevationService.GetElevationAtPoint(raster, dic, metadata, proj.Latitude, proj.Longitude, 0, interpolator, NoDataBehavior.UseNoDataDefinedInDem); } } var nullCoords = heightMap.Coordinates.Where(c => (c.Elevation ?? litto3DDataset.NoDataValue) == litto3DDataset.NoDataValue).ToList(); var nullCoordsFallbackProj = nullCoords.ReprojectTo(litto3DDataset.SRID, fallbackDataset.SRID, nullCoords.Count); var nullCoordsFallbackProj2 = _elevationService.GetPointsElevation(nullCoordsFallbackProj, fallbackDataset, InterpolationMode.Bilinear, NoDataBehavior.UseNoDataDefinedInDem); ModelGenerationTransform transform = new ModelGenerationTransform(bbox, 3857, centerOnOrigin: centerOnOrigin, zFactor, centerOnZOrigin: false); ModelGenerationTransform transformFrom4326 = new ModelGenerationTransform(bbox.ReprojectTo(2154, 4326), 3857, centerOnOrigin: centerOnOrigin, zFactor, centerOnZOrigin: false); _logger.LogInformation($"Processing height map data ({heightMap.Count} coordinates)..."); heightMap = transform.TransformHeightMap(heightMap); var min = heightMap.Coordinates.Where(g => (g.Elevation ?? 0d) > litto3DDataset.NoDataValue).Min(g => g.Elevation ?? 0d); heightMap.Coordinates = heightMap.Coordinates.Select(p => { if (p.Elevation.GetValueOrDefault(0) <= litto3DDataset.NoDataValue) { p.Elevation = min; } return(p); }); //======================= // Textures // PBRTexture pbrTexture = null; if (withTexture) { var bbox4326 = bbox.ReprojectTo(2154, 4326); Console.WriteLine("Download image tiles..."); TileRange tiles = _imageryService.DownloadTiles(bbox4326, imageryProvider, TEXTURE_TILES); string fileName = Path.Combine(outputDir, "Texture.jpg"); Console.WriteLine("Construct texture..."); //TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox4326, fileName, TextureImageFormat.image_jpeg); TextureInfo texInfo; if (withboat) { var trackPoints = GetGeoPointFromGeoJson(BoatCourseGeoJson); texInfo = _imageryService.ConstructTextureWithGpxTrack(tiles, bbox4326, fileName, TextureImageFormat.image_jpeg, trackPoints, drawGpxVertices: true, color: SixLabors.ImageSharp.PixelFormats.Rgba32.Green, 30); } else { texInfo = _imageryService.ConstructTexture(tiles, bbox4326, fileName, TextureImageFormat.image_jpeg); } // //======================= //======================= // Normal map Console.WriteLine("Height map..."); //float Z_FACTOR = 0.00002f; //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); //var normalMap = _imageryService.GenerateNormalMap(heightMap, outputDir); pbrTexture = PBRTexture.Create(texInfo, null);// normalMap); //hMap = hMap.CenterOnOrigin(Z_FACTOR); // //======================= } // Triangulate height map // and add base and sides _logger.LogInformation($"Triangulating height map and generating 3D mesh..."); heightMap = heightMap.BakeCoordinates(); var coords = heightMap.Coordinates.ToList(); var model = _sharpGltfService.CreateTerrainMesh(heightMap, pbrTexture); if (withWaterSurface) { var bottomLeft = coords[heightMap.Width * (heightMap.Height - 1)].AsVector3(); bottomLeft.Z = 0; var topRight = coords[heightMap.Width - 1].AsVector3(); topRight.Z = 0; var topLeft = coords[0].AsVector3(); topLeft.Z = 0; var bottomRight = coords.Last().AsVector3(); bottomRight.Z = 0; var waterSurface = _meshService.CreateWaterSurface(bottomLeft, topRight, topLeft, bottomRight, minZ: (float)min, color: VectorsExtensions.CreateColor(0, 150, 255, 64)); model = _sharpGltfService.AddMesh(model, "Water", waterSurface, doubleSided: true); } if (withboat) { var boatInitPos = centerOnOrigin ? new GeoPoint(0, 0).AsVector3() : new GeoPoint(43.010625204304304, 6.3711613671060086).ReprojectTo(4326, 3857).AsVector3(); var axis = _meshService.CreateAxis(2, 10, 3, 3).Translate(boatInitPos); model = _sharpGltfService.AddMesh(model, "Boat", axis, doubleSided: false); var boatCourse = transformFrom4326.TransformPoints(GetGeoPointFromGeoJson(BoatCourseGeoJson)).ToList(); //ReprojectGeodeticToCartesian().CenterOnOrigin().ToList(); model = _sharpGltfService.AddLine(model, "BoatCourse", boatCourse, VectorsExtensions.CreateColor(255, 0, 0, 128), 4); } model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + ".glb")); _logger.LogInformation($"Model exported as {Path.Combine(Directory.GetCurrentDirectory(), modelName + ".gltf")} and .glb"); //var point = new GeoPoint(43.01142119356318, 6.385200681010872).ReprojectTo(4326, 2154); //point = _elevationService.GetPointElevation(point, litto3DDataset); } catch (Exception e) { _logger.LogError(e, e.Message); } }
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); }
private float GetElevationAtPoint(RasterFileDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator) { return(GetElevationAtPoint(adjacentTiles[metadata], adjacentTiles, metadata, lat, lon, lastElevation, interpolator ?? GetInterpolator(InterpolationMode.Bilinear))); }