Example #1
0
        public List <GeoPoint> GetLineGeometryElevation(SqlGeometry lineStringGeometry, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear)
        {
            if (lineStringGeometry == null || lineStringGeometry.IsNull)
            {
                return(null);
            }
            if (lineStringGeometry.STGeometryType().Value != "LineString")
            {
                throw new Exception("Geometry must be a linestring");
            }
            if (lineStringGeometry.STSrid.Value != 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);

            double lengthMeters  = lineStringGeometry.STLength().Value;
            int    demResolution = dataSet.ResolutionMeters;
            int    totalCapacity = 2 * (int)(lengthMeters / demResolution);

            List <GeoPoint> geoPoints = new List <GeoPoint>(totalCapacity);

            using (GeoTiffDictionary adjacentGeoTiffs = new GeoTiffDictionary())
            {
                bool isFirstSegment = true;                 // used to return first point only for first segments, for all other segments last point will be returned
                foreach (SqlGeometry segment in lineStringGeometry.Segments())
                {
                    List <FileMetadata> segTiles = this.GetCoveringFiles(segment.GetBoundingBox(), dataSet, tiles);

                    // Find all intersection with segment and DEM grid
                    List <GeoPoint> intersections = this.FindSegmentIntersections(segment.STStartPoint().STX.Value
                                                                                  , segment.STStartPoint().STY.Value
                                                                                  , segment.STEndPoint().STX.Value
                                                                                  , segment.STEndPoint().STY.Value
                                                                                  , segTiles
                                                                                  , isFirstSegment
                                                                                  , true);

                    // Get elevation for each point
                    this.GetElevationData(ref intersections, adjacentGeoTiffs, segTiles, interpolator);

                    // Add to output list
                    geoPoints.AddRange(intersections);

                    isFirstSegment = false;
                }
                //Debug.WriteLine(adjacentGeoTiffs.Count);
            }              // Ensures all geotifs are properly closed

            return(geoPoints);
        }
Example #2
0
        /// <summary>
        /// Fill altitudes for each GeoPoint provided, opening as few GeoTiffs as possible
        /// </summary>
        /// <param name="intersections"></param>
        /// <param name="segTiles"></param>
        public void GetElevationData(ref List <GeoPoint> intersections, GeoTiffDictionary adjacentGeoTiffs, List <FileMetadata> segTiles, IInterpolator interpolator)
        {
            // Group by tiff 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;


            try
            {
                float lastElevation = 0;

                // To interpolate well points close to tile edges, we need all adjacent tiles
                //using (GeoTiffDictionary adjacentGeoTiffs = new GeoTiffDictionary())
                //{
                // 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 geotiffs first, then we iterate
                    PopulateGeoTiffDictionary(adjacentGeoTiffs, mainTile, _IGeoTiffService, tilePoints.SelectMany(tp => tp.AdjacentTiles));


                    foreach (var pointile in tilePoints)
                    {
                        GeoPoint current = pointile.Point;
                        lastElevation     = this.ParseGeoDataAtPoint(adjacentGeoTiffs, mainTile, current.Latitude, current.Longitude, lastElevation, interpolator);
                        current.Elevation = lastElevation;
                    }

                    //adjacentGeoTiffs.Clear();
                }
            }
            //}

            catch (Exception e)
            {
                Trace.TraceError($"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}");
            }
        }
Example #3
0
        private void PopulateGeoTiffDictionary(GeoTiffDictionary dictionary, FileMetadata mainTile, IGeoTiffService geoTiffService, IEnumerable <FileMetadata> fileMetadataList)
        {
            // Add main tile
            if (!dictionary.ContainsKey(mainTile))
            {
                dictionary[mainTile] = geoTiffService.OpenFile(mainTile.Filename);
            }

            foreach (var fileMetadata in fileMetadataList)
            {
                if (!dictionary.ContainsKey(fileMetadata))
                {
                    dictionary[fileMetadata] = geoTiffService.OpenFile(fileMetadata.Filename);
                }
            }
        }
Example #4
0
        private float GetElevationAtPoint(FileMetadata mainTile, GeoTiffDictionary tiles, int x, int y, float nullValue)
        {
            int          xRemap, yRemap;
            FileMetadata goodTile = FindTile(mainTile, tiles, x, y, out xRemap, out yRemap);

            if (goodTile == null)
            {
                return(nullValue);
            }

            if (tiles.ContainsKey(goodTile))
            {
                return(tiles[goodTile].ParseGeoDataAtPoint(goodTile, xRemap, yRemap));
            }
            else
            {
                throw new Exception("Tile not found. Should not happen.");
            }
        }
Example #5
0
        private FileMetadata FindTile(FileMetadata mainTile, GeoTiffDictionary 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 => t.OriginLatitude == mainTile.OriginLatitude + yScale * yTileOffset &&
                    t.OriginLongitude == mainTile.OriginLongitude + xTileOffset);
                newX = xTileOffset > 0 ? x % mainTile.Width : (mainTile.Width + x) % mainTile.Width;
                newY = yTileOffset < 0 ? (mainTile.Height + y) % mainTile.Height : y % mainTile.Height;
                return(tile);
            }
        }
Example #6
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);

            // Init interpolator
            IInterpolator interpolator = GetInterpolator(interpolationMode);

            List <GeoPoint> geoPoints = new List <GeoPoint>();

            using (GeoTiffDictionary adjacentGeoTiffs = new GeoTiffDictionary())
            {
                PopulateGeoTiffDictionary(adjacentGeoTiffs, tiles.First(), _IGeoTiffService, tiles);

                geoPoint.Elevation = ParseGeoDataAtPoint(adjacentGeoTiffs, tiles.First(), lat, lon, 0, interpolator);


                //Debug.WriteLine(adjacentGeoTiffs.Count);
            }              // Ensures all geotifs are properly closed

            return(geoPoint);
        }
Example #7
0
        public float ParseGeoDataAtPoint(GeoTiffDictionary adjacentTiles, FileMetadata metadata, double lat, double lon, float lastElevation, IInterpolator interpolator)
        {
            float heightValue = 0;

            try
            {
                IGeoTiff mainTiff = 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 = xInterpolationAmount == 0;
                bool yOnGrid = yInterpolationAmount == 0;

                // 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 = mainTiff.ParseGeoDataAtPoint(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)
            {
                Trace.TraceError($"Error while getting elevation data : {e.Message}{Environment.NewLine}{e.ToString()}");
            }
            return(heightValue);
        }