Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
                }
            }
        }
Пример #6
0
        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);
                }
            }
        }
Пример #7
0
        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.");
            }
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        /// <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();
            }
            //}
        }
Пример #12
0
        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);
            }
        }
Пример #13
0
        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);
        }
Пример #14
0
 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)));
 }