예제 #1
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);
        }
예제 #2
0
        public List <GeoPoint> GetLineGeometryElevation(IEnumerable <GeoPoint> lineGeoPoints, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear)
        {
            if (lineGeoPoints == null)
            {
                throw new ArgumentNullException(nameof(lineGeoPoints), "Point list is null");
            }

            IGeometry geometry = GeometryService.ParseGeoPointAsGeometryLine(lineGeoPoints);

            return(GetLineGeometryElevation(geometry, dataSet, interpolationMode));
        }
예제 #3
0
        public IntervisibilityReport GetIntervisibilityReport(GeoPoint source, GeoPoint target, DEMDataSet dataSet
                                                              , bool downloadMissingFiles           = true
                                                              , double sourceVerticalOffset         = 0d
                                                              , InterpolationMode interpolationMode = InterpolationMode.Bilinear)
        {
            try
            {
                var elevationLine = GeometryService.ParseGeoPointAsGeometryLine(source, target);

                if (downloadMissingFiles)
                {
                    this.DownloadMissingFiles(dataSet, elevationLine.GetBoundingBox());
                }

                var geoPoints = this.GetLineGeometryElevation(elevationLine, dataSet);

                var metrics = geoPoints.ComputeVisibilityMetrics(sourceVerticalOffset, dataSet.NoDataValue);

                return(new IntervisibilityReport(geoPoints, metrics, originVerticalOffset: sourceVerticalOffset));
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(GetIntervisibilityReport)} error: {ex.Message}");
                throw;
            }
        }
예제 #4
0
 public void DownloadRasterFile(DemFileReport report, DEMDataSet dataset)
 {
     throw new NotImplementedException();
 }
예제 #5
0
        public HeightMap GetHeightMap(ref BoundingBox bbox, DEMDataSet dataSet)
        {
            DownloadMissingFiles(dataSet, bbox);

            // Locate which files are needed
            // Find files matching coords
            List <FileMetadata> bboxMetadata = GetCoveringFiles(bbox, dataSet);

            if (bboxMetadata.Count == 0)
            {
                string errorMessage = $"Dataset {dataSet.Name} has no coverage for provided bounding box.";
                this._logger.LogWarning(errorMessage);
                throw new Exception(errorMessage);
            }
            else
            {
                // Check if bounding box is fully covered (will result in invalid models without any error being thrown)
                bool covered = this.IsBoundingBoxCovered(bbox, bboxMetadata.Select(m => m.BoundingBox));
                if (!covered)
                {
                    const string errorMessage = "Bounding box is partially covered by DEM dataset. Heightmap in its current state supports only full data tiles.";
                    this._logger.LogWarning(errorMessage);
                    throw new Exception(errorMessage);
                }
                else
                {
                    // get height map for each file at bbox
                    List <HeightMap> tilesHeightMap = new List <HeightMap>(bboxMetadata.Count);
                    foreach (FileMetadata metadata in bboxMetadata)
                    {
                        using (IRasterFile raster = _IRasterService.OpenFile(metadata.Filename, dataSet.FileFormat.Type))
                        {
                            tilesHeightMap.Add(raster.GetHeightMapInBBox(bbox, metadata, NO_DATA_OUT));
                        }
                    }

                    HeightMap heightMap;
                    if (tilesHeightMap.Count == 1)
                    {
                        heightMap = tilesHeightMap.First();
                        bbox      = heightMap.BoundingBox;
                    }
                    else
                    {
                        // Merge height maps
                        int totalHeight = tilesHeightMap.GroupBy(h => h.BoundingBox.xMin).Select(g => g.Sum(v => v.Height)).First();
                        int totalWidth  = tilesHeightMap.GroupBy(h => h.BoundingBox.yMin).Select(g => g.Sum(v => v.Width)).First();

                        heightMap             = new HeightMap(totalWidth, totalHeight);
                        heightMap.BoundingBox = new BoundingBox(xmin: tilesHeightMap.Min(h => h.BoundingBox.xMin)
                                                                , xmax: tilesHeightMap.Max(h => h.BoundingBox.xMax)
                                                                , ymin: tilesHeightMap.Min(h => h.BoundingBox.yMin)
                                                                , ymax: tilesHeightMap.Max(h => h.BoundingBox.yMax));
                        bbox = heightMap.BoundingBox;
                        heightMap.Coordinates = tilesHeightMap.SelectMany(hmap => hmap.Coordinates).Sort();
                        heightMap.Count       = totalWidth * totalHeight;
                        heightMap.Minimum     = tilesHeightMap.Min(hmap => hmap.Minimum);
                        heightMap.Maximum     = tilesHeightMap.Max(hmap => hmap.Maximum);
                    }
                    System.Diagnostics.Debug.Assert(heightMap.Count == tilesHeightMap.Sum(h => h.Count));


                    return(heightMap);
                }
            }
        }
예제 #6
0
        private void DownloadMissingFiles_FromReport(IEnumerable <DemFileReport> report, DEMDataSet dataSet)
        {
            // Generate metadata files if missing
            foreach (var file in report.Where(r => r.IsMetadataGenerated == false && r.IsExistingLocally == true))
            {
                _IRasterService.GenerateFileMetadata(file.LocalName, dataSet.FileFormat, false);
            }
            List <DemFileReport> filesToDownload = new List <DemFileReport>(report.Where(kvp => kvp.IsExistingLocally == false));

            if (filesToDownload.Count == 0)
            {
                _logger?.LogTrace("No missing file(s).");
            }
            else
            {
                _logger?.LogInformation($"Downloading {filesToDownload.Count} missing file(s).");

                try
                {
                    Parallel.ForEach(filesToDownload, file =>
                    {
                        _IRasterService.DownloadRasterFile(file, dataSet);
                    }
                                     );

                    _IRasterService.GenerateDirectoryMetadata(dataSet, false, false);
                    _IRasterService.LoadManifestMetadata(dataSet, true);
                }
                catch (AggregateException ex)
                {
                    _logger?.LogError(ex, $"Error downloading missing files. Check internet connection or retry later. {ex.GetInnerMostException().Message}");
                    throw;
                }
            }
        }
예제 #7
0
 public string GetLocalDEMFilePath(DEMDataSet dataset, string fileTitle)
 {
     return(Path.Combine(GetLocalDEMPath(dataset), fileTitle));
 }
예제 #8
0
        private IEnumerable <DEMFileSource> GetSources(DEMDataSet dataSet, string vrtFileName)
        {
            Uri localVrtUri  = new Uri(Path.GetFullPath(vrtFileName), UriKind.Absolute);
            Uri remoteVrtUri = new Uri(dataSet.DataSource.IndexFilePath, UriKind.Absolute);

            double[] geoTransform;
            var      registration = dataSet.FileFormat.Registration;
            Dictionary <string, string> properties;

            // Create an XmlReader
            using (FileStream fileStream = new FileStream(vrtFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                using (XmlReader reader = XmlReader.Create(fileStream))
                {
                    if (reader.ReadToFollowing("GeoTransform"))
                    {
                        geoTransform = ParseGeoTransform(reader.ReadElementContentAsString());
                    }
                    else
                    {
                        throw new Exception("GeoTransform element not found!");
                    }

                    string sourceName = "";
                    if (reader.ReadToFollowing("VRTRasterBand"))
                    {
                        properties = new Dictionary <string, string>();
                        while (reader.Read())
                        {
                            if (reader.NodeType == XmlNodeType.Element)
                            {
                                if (reader.Name == "ComplexSource" || reader.Name == "SimpleSource")
                                {
                                    sourceName = reader.Name;
                                    break;
                                }
                                properties[reader.Name] = reader.ReadElementContentAsString();
                            }
                        }


                        bool isOnFirstSource = true;
                        while (isOnFirstSource || reader.ReadToFollowing(sourceName))
                        {
                            DEMFileSource source = ParseGDALSource(reader);

                            // SetLocalFileName
                            source.SourceFileNameAbsolute = new Uri(remoteVrtUri, source.SourceFileName).ToString();
                            source.LocalFileName          = new Uri(localVrtUri, source.SourceFileName).LocalPath;

                            // Transform origin
                            // Xp = padfTransform[0] + P * padfTransform[1] + L * padfTransform[2];
                            // Yp = padfTransform[3] + P * padfTransform[4] + L * padfTransform[5];
                            source.OriginLon = geoTransform[0] + source.DstxOff * geoTransform[1] + source.DstyOff * geoTransform[2];
                            source.OriginLat = geoTransform[3] + source.DstxOff * geoTransform[4] + source.DstyOff * geoTransform[5];
                            source.DestLon   = geoTransform[0] + (source.DstxOff + source.DstxSize) * geoTransform[1] + (source.DstyOff + source.DstySize) * geoTransform[2];
                            source.DestLat   = geoTransform[3] + (source.DstxOff + source.DstxSize) * geoTransform[4] + (source.DstyOff + source.DstySize) * geoTransform[5];

                            if (registration == DEMFileRegistrationMode.Grid)
                            {
                                source.BBox = new BoundingBox(Math.Round(source.OriginLon + geoTransform[1] / 2, 10),
                                                              Math.Round(source.DestLon - +geoTransform[1] / 2, 10),
                                                              Math.Round(source.DestLat - geoTransform[5] / 2, 10),
                                                              Math.Round(source.OriginLat + geoTransform[5] / 2, 10));
                            }
                            else
                            {
                                source.OriginLon = Math.Round(source.OriginLon, 10);
                                source.OriginLat = Math.Round(source.OriginLat, 10);
                                source.DestLon   = Math.Round(source.DestLon, 10);
                                source.DestLat   = Math.Round(source.DestLat, 10);
                                source.BBox      = new BoundingBox(source.OriginLon, source.DestLon, source.DestLat, source.OriginLat);
                            }


                            isOnFirstSource = false;

                            yield return(source);
                        }
                    }
                }
        }
예제 #9
0
 public void Setup(DEMDataSet dataset, string dataSetLocalDir)
 {
     this.dataset  = dataset;
     this.localDir = dataSetLocalDir;
 }
예제 #10
0
 public string GetLocalDEMPath(DEMDataSet dataset)
 {
     return(dataset.DataSource.IsGlobalFile ?
            Path.GetDirectoryName(dataset.DataSource.IndexFilePath)
                 : Path.Combine(_localDirectory, dataset.Name));
 }
예제 #11
0
 public IEnumerable <DEMFileSource> GetCoveredFileSources(DEMDataSet dataset, BoundingBox bbox)
 {
     throw new NotImplementedException(nameof(NasaGranuleFileService));
 }
예제 #12
0
        public static FileMetadata Migrate(IRasterService rasterService, ILogger logger, FileMetadata oldMetadata, string dataRootDirectory, DEMDataSet dataSet)
        {
            if (oldMetadata != null)
            {
                logger.LogInformation($"Migration metadata file {oldMetadata.Filename} from {oldMetadata.Version} to {FileMetadata.FILEMETADATA_VERSION}");

                // 2.2 version requires regeneration
                oldMetadata = rasterService.ParseMetadata(Path.Combine(rasterService.LocalDirectory, oldMetadata.Filename), dataSet.FileFormat);

                //switch (oldMetadata.Version)
                //{
                //    case "2.0":

                //        // 2.1 : relative path
                //        // Find dataset root within path
                //        DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(oldMetadata.Filename));
                //        while (dir.Name != dataSet.Name)
                //        {
                //            dir = dir.Parent;
                //        }
                //        dir = dir.Parent;
                //        // replace directory
                //        oldMetadata.Filename = oldMetadata.Filename.Replace(dir.FullName, dataRootDirectory);
                //        Uri fullPath = new Uri(oldMetadata.Filename, UriKind.Absolute);
                //        if (!(dataRootDirectory.Last() == Path.DirectorySeparatorChar))
                //            dataRootDirectory += Path.DirectorySeparatorChar;
                //        Uri relRoot = new Uri(dataRootDirectory, UriKind.Absolute);

                //        oldMetadata.Filename = Uri.UnescapeDataString(relRoot.MakeRelativeUri(fullPath).ToString());
                //        oldMetadata.FileFormat = dataSet.FileFormat;

                //        break;

                //    case "2.1":

                //        // 2.2 : [Metadata regneration required] file format is now mapped to DEMFileDefinition, lat/lon bounds names changed for clarity, file format changed from DEMFileFormat (name + file extenstion)
                //        //
                //        // to DEMFileDefinition
                //        oldMetadata.FileFormat = dataSet.FileFormat;

                //        break;

                //    default:

                //        // DEMFileFormat
                //        oldMetadata.FileFormat = dataSet.FileFormat;
                //        break;
                //}

                // set version and fileFormat
                oldMetadata.Version = FileMetadata.FILEMETADATA_VERSION;
            }
            return(oldMetadata);
        }
예제 #13
0
        /// <summary>
        /// Ensures local directories are created and download VRT file if needed
        /// </summary>
        void IDEMDataSetIndex.Setup(DEMDataSet dataSet, string dataSetLocalDir)
        {
            try
            {
                if (dataSet == null)
                {
                    throw new ArgumentNullException(nameof(dataSet), "Dataset is null.");
                }

                if (_cacheByDemName.ContainsKey(dataSet.Name))
                {
                    return;
                }

                _logger?.LogInformation($"Setup for {dataSet.Name} dataset.");

                if (!Directory.Exists(dataSetLocalDir))
                {
                    Directory.CreateDirectory(dataSetLocalDir);
                }

                string vrtFileName = Path.Combine(dataSetLocalDir, UrlHelper.GetFileNameFromUrl(dataSet.DataSource.IndexFilePath));


                bool download = true;
                if (File.Exists(vrtFileName))
                {
                    // Download if too old file
                    if ((DateTime.Now - File.GetLastWriteTime(vrtFileName)).TotalDays > MAX_AGE_DAYS)
                    {
                        _logger?.LogInformation("VRT file is too old.");
                    }
                    else if (IsCorrupted(dataSet, vrtFileName))
                    {
                        _logger?.LogInformation("VRT file is corrupted.");
                    }
                    else
                    {
                        download = false;
                    }
                }

                if (download)
                {
                    lock (DOWNLOAD_LOCKER)
                    {
                        if (download)
                        {
                            _logger?.LogInformation($"Downloading index file from {dataSet.DataSource.IndexFilePath}... This file will be downloaded once and stored locally.");

                            HttpClient client = _httpClientFactory.CreateClient();

                            using (HttpResponseMessage response = client.GetAsync(dataSet.DataSource.IndexFilePath).Result)
                                using (FileStream fs = new FileStream(vrtFileName, FileMode.Create, FileAccess.Write))
                                {
                                    var contentbytes = client.GetByteArrayAsync(dataSet.DataSource.IndexFilePath).Result;
                                    fs.Write(contentbytes, 0, contentbytes.Length);
                                }
                            download = false;
                        }
                    }
                }

                // Cache

                if (_cacheByDemName == null)
                {
                    _cacheByDemName = new ConcurrentDictionary <string, List <DEMFileSource> >();
                }
                if (_cacheByDemName.ContainsKey(vrtFileName) == false)
                {
                    _cacheByDemName[dataSet.Name] = this.GetSources(dataSet, vrtFileName).ToList();
                }
            }
            catch (Exception ex)
            {
                _logger?.LogError("Unhandled exception: " + ex.Message);
                _logger?.LogInformation(ex.ToString());
                throw;
            }
        }
예제 #14
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);
        }
예제 #15
0
 public GeoPoint GetPointElevation(GeoPoint location, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear)
 {
     return(GetPointElevation(location.Latitude, location.Longitude, dataSet, interpolationMode));
 }
예제 #16
0
 public string GetDEMLocalPath(DEMDataSet dataSet)
 {
     return(_IRasterService.GetLocalDEMPath(dataSet));
 }
예제 #17
0
 public string GetLocalDEMPath(DEMDataSet dataset)
 {
     return(dataset.DataSource.DataSourceType == Datasets.DEMDataSourceType.LocalFileSystem ?
            Path.GetFullPath(dataset.DataSource.IndexFilePath)
                 : Path.Combine(_localDirectory, dataset.Name));
 }