コード例 #1
0
        protected override IEnumerable <PisteModel> ComputeModelElevationsAndTransform(IEnumerable <PisteModel> models, bool computeElevations, DEMDataSet dataSet, bool downloadMissingFiles)
        {
            using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock("Elevations+Reprojection", _logger, LogLevel.Debug))
            {
                if (computeElevations)
                {
                    foreach (var model in models)
                    {
                        model.LineString = Transform.TransformPoints(_elevationService.GetLineGeometryElevation(model.LineString, dataSet))
                                           .ToList();

                        yield return(model);
                    }
                    //Parallel.ForEach(models, model =>
                    //{
                    //    model.LineString = Transform.TransformPoints(_elevationService.GetLineGeometryElevation(model.LineString, dataSet))
                    //                         .ToList();
                    //});
                }
                else
                {
                    foreach (var model in models)
                    {
                        model.LineString = new List <GeoPoint>(Transform.TransformPoints(model.LineString));
                        yield return(model);
                    }
                }
            }
        }
コード例 #2
0
        public IEnumerable <T> CreateModelsFromGeoJson <T>(IEnumerable <IFeature> features, OsmModelFactory <T> validator) where T : CommonModel
        {
            int numValid   = 0;
            int numInvalid = 0;

            using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock(nameof(CreateModelsFromGeoJson), _logger, LogLevel.Debug))
            {
                foreach (var feature in features)
                {
                    validator.RegisterTags(feature as Feature);
                    foreach (T model in validator.CreateModel(feature as Feature))
                    {
                        if (model == null)
                        {
                            numInvalid++;
                            _logger.LogWarning($"{nameof(CreateModelsFromGeoJson)}: {feature.Attributes["osmid"]}, type {feature.Geometry.OgcGeometryType} not supported.");
                        }
                        else if (validator.ParseTags(model)) // Model not processed further if tag parsing fails
                        {
                            numValid++;
                            yield return(model);
                        }
                    }
                }
            }

            _logger.LogInformation($"{nameof(CreateModelsFromGeoJson)} done for {validator._totalPoints} points. {numValid:N0} valid models, {numInvalid:N0} invalid");
        }
コード例 #3
0
ファイル: ImageryService.cs プロジェクト: falconlulu/DEM.Net
        public TileRange DownloadTiles(TileRange tiles, ImageryProvider provider)
        {
            if (provider is ITileGenerator generator)
            {
                // download tiles
                using (TimeSpanBlock timer = new TimeSpanBlock("Tile generation", _logger))
                {
                    // Max download threads defined in provider
                    var parallelOptions = new ParallelOptions()
                    {
                        MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                    };
                    var range = tiles.EnumerateRange().ToList();
                    _logger?.LogInformation($"Generating {range.Count} tiles with {provider.Name} generator...");
                    Parallel.ForEach(range, parallelOptions, tileInfo =>
                    {
                        var contentbytes = generator.GenerateTile(tileInfo.X, tileInfo.Y, tileInfo.Zoom);
                        tiles.Add(new MapTile(contentbytes, provider.TileSize, null, tileInfo));
                    }
                                     );
                }
            }
            else
            {
                // download tiles
                Stopwatch swDownload = Stopwatch.StartNew();
                _logger?.LogTrace("Starting images download");


                // Max download threads defined in provider
                var parallelOptions = new ParallelOptions()
                {
                    MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                };
                var range = tiles.EnumerateRange().ToList();
                _logger?.LogInformation($"Downloading {range.Count} tiles...");
                Parallel.ForEach(range, parallelOptions, tileInfo =>
                {
                    Uri tileUri      = BuildUri(provider, tileInfo.X, tileInfo.Y, tileInfo.Zoom);
                    var contentBytes = cache.GetOrCreate(tileUri, entry =>
                    {
                        entry.SetSlidingExpiration(TimeSpan.FromMinutes(options.ImageryCacheExpirationMinutes));

                        return(_httpClient.GetByteArrayAsync(tileUri).Result);
                    });
                    //var contentBytes = _httpClient.GetByteArrayAsync(tileUri).Result;
                    tiles.Add(new MapTile(contentBytes, provider.TileSize, tileUri, tileInfo));
                }
                                 );

                swDownload.Stop();
                _logger?.LogInformation($"DownloadImages done in : {swDownload.Elapsed:g}");
            }


            return(tiles);
        }
コード例 #4
0
        public TileRange DownloadTiles(TileRange tiles, ImageryProvider provider)
        {
            if (provider is ITileGenerator generator)
            {
                // download tiles
                using (TimeSpanBlock timer = new TimeSpanBlock("Tile generation", _logger))
                {
                    // Max download threads defined in provider
                    var parallelOptions = new ParallelOptions()
                    {
                        MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                    };
                    var range = tiles.TilesInfo.ToList();
                    _logger?.LogInformation($"Generating {range.Count} tiles with {provider.Name} generator...");
                    Parallel.ForEach(range, parallelOptions, tile =>
                    {
                        var contentbytes = generator.GenerateTile(tile.X, tile.Y, tile.Zoom);
                        tiles.Add(new MapTile(contentbytes, provider.TileSize, null, tile));
                    }
                                     );
                }
            }
            else
            {
                // download tiles
                Stopwatch swDownload = Stopwatch.StartNew();
                _logger?.LogTrace("Starting images download");


                // Max download threads defined in provider
                var parallelOptions = new ParallelOptions()
                {
                    MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                };
                var range = tiles.TilesInfo.ToList();
                _logger?.LogInformation($"Downloading {range.Count} tiles...");
                Parallel.ForEach(range, parallelOptions, tile =>
                {
                    Uri tileUri = BuildUri(provider, tile.X, tile.Y, tile.Zoom);

                    var contentBytes = cache.GetTile(tileUri, provider, tile);

                    tiles.Add(new MapTile(contentBytes, provider.TileSize, tileUri, tile));
                }
                                 );

                swDownload.Stop();
                _logger?.LogInformation($"DownloadImages done in : {swDownload.Elapsed:g}");
            }


            return(tiles);
        }
コード例 #5
0
        public void Run()
        {
            _logger.LogInformation("OnStarted has been called.");

            try
            {
                //using (TimeSpanBlock timer = new TimeSpanBlock(nameof(OsmExtensionSample), _logger))
                //{
                //    services.GetService<OsmExtensionSample>().Run();
                //}
                using (TimeSpanBlock timer = new TimeSpanBlock(nameof(VisualTopoSample), _logger))
                {
                    services.GetService <VisualTopoSample>().Run();
                }
                //using (TimeSpanBlock timer = new TimeSpanBlock(nameof(HighestPointFinder), _logger))
                //{
                //    services.GetService<HighestPointFinder>().Run();
                //}


                //using (TimeSpanBlock timer = new TimeSpanBlock(nameof(HelladicSample), _logger))
                //{
                //    services.GetService<HelladicSample>().Run();
                //}

                Debugger.Break();

                //using (TimeSpanBlock timer = new TimeSpanBlock(nameof(SketchfabSample), _logger))
                //{
                //    services.GetService<SketchfabSample>().Run();
                //}

                //Debugger.Break();



                //using (TimeSpanBlock timer = new TimeSpanBlock(nameof(OsmExtensionSample), _logger))
                //{
                //    services.GetService<OsmExtensionSample>().Run();
                //    if (cancellationToken.IsCancellationRequested) return Task.FromCanceled(cancellationToken);
                //}
            }
            catch (Exception ex)
            {
                _logger.LogError($"Error: {ex.ToString()}");
            }
        }
コード例 #6
0
        public int GetOsmDataCount(BoundingBox bbox, IOsmDataSettings filter)
        {
            try
            {
                using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock("GetOsmDataAsGeoJson", _logger, LogLevel.Debug))
                {
                    OverpassQuery query = new OverpassQuery(bbox, _logger);
                    if (filter != null)
                    {
                        if (filter.WaysFilter != null)
                        {
                            foreach (var tagFilter in filter.WaysFilter)
                            {
                                query.WithWays(tagFilter);
                            }
                        }
                        if (filter.RelationsFilter != null)
                        {
                            foreach (var tagFilter in filter.RelationsFilter)
                            {
                                query.WithRelations(tagFilter);
                            }
                        }
                        if (filter.NodesFilter != null)
                        {
                            foreach (var tagFilter in filter.NodesFilter)
                            {
                                query.WithNodes(tagFilter);
                            }
                        }
                    }

                    var task = query.AsCount()
                               .RunQueryAsync()
                               .ToCountAsync();

                    OverpassCountResult count = task.GetAwaiter().GetResult();

                    return(count.Tags.Nodes * 2);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(GetOsmDataAsGeoJson)} error: {ex.Message}");
                throw;
            }
        }
コード例 #7
0
        public IEnumerable <IFeature> GetOsmDataAsGeoJson(BoundingBox bbox, IOsmDataSettings filter)
        {
            try
            {
                using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock(nameof(GetOsmDataAsGeoJson), _logger, LogLevel.Debug))
                {
                    OverpassQuery query = new OverpassQuery(bbox, _logger);
                    if (filter != null)
                    {
                        if (filter.WaysFilter != null)
                        {
                            foreach (var tagFilter in filter.WaysFilter)
                            {
                                query.WithWays(tagFilter);
                            }
                        }
                        if (filter.RelationsFilter != null)
                        {
                            foreach (var tagFilter in filter.RelationsFilter)
                            {
                                query.WithRelations(tagFilter);
                            }
                        }
                        if (filter.NodesFilter != null)
                        {
                            foreach (var tagFilter in filter.NodesFilter)
                            {
                                query.WithNodes(tagFilter);
                            }
                        }
                    }

                    var task = query.ToGeoJSONAsync();

                    FeatureCollection ways = task.GetAwaiter().GetResult();

                    _logger.LogInformation($"{ways?.Count} features downloaded");

                    return(ways);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"{nameof(GetOsmDataAsGeoJson)} error: {ex.Message}");
                throw;
            }
        }
コード例 #8
0
        public TriangulationNormals Triangulate(IEnumerable <BuildingModel> buildingModels)
        {
            List <Vector3> positions = new List <Vector3>();
            List <Vector4> colors    = new List <Vector4>();
            List <int>     indices   = new List <int>();
            List <Vector3> normals   = new List <Vector3>();

            using (TimeSpanBlock timer = new TimeSpanBlock(nameof(Triangulate), _logger, LogLevel.Information))
            {
                // Get highest base point
                // Retrieve building size
                int numWithHeight = 0;
                int numWithColor  = 0;
                int numTotal      = 0;

                foreach (var building in buildingModels)
                {
                    numTotal++;
                    numWithHeight += building.HasHeightInformation ? 1 : 0;
                    numWithColor  += (building.Color.HasValue || building.RoofColor.HasValue) ? 1 : 0;

                    var triangulation = this.Triangulate(building);

                    var positionsVec3   = triangulation.Positions.ToVector3GlTFSpace().ToList();
                    var buildingNormals = _meshService.ComputeMeshNormals(positionsVec3, triangulation.Indices);

                    int initialPositionsCount = positions.Count;

                    positions.AddRange(positionsVec3);
                    indices.AddRange(triangulation.Indices.Select(i => i + initialPositionsCount).ToList());
                    colors.AddRange(triangulation.Colors);
                    normals.AddRange(buildingNormals);
                }

                _logger.LogInformation($"Building heights: {numWithHeight:N0}/{numTotal:N0} ({numWithHeight / (float)numTotal:P}) with height information.");
                _logger.LogInformation($"Building colors: {numWithColor:N0}/{numTotal:N0} ({numWithColor / (float)numTotal:P}) with color information.");
            }


            return(new TriangulationNormals(positions, indices, normals, colors));
        }
コード例 #9
0
        protected override IEnumerable <HighwayModel> ComputeModelElevationsAndTransform(IEnumerable <HighwayModel> models, bool computeElevations, DEMDataSet dataSet, bool downloadMissingFiles)
        {
            using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock("Elevations+Reprojection", _logger, LogLevel.Debug))
            {
                if (computeElevations)
                {
                    foreach (var model in models)
                    {
                        IEnumerable <GeoPoint> lineString = model.LineString;
                        if (dataSet.SRID != 4326)
                        {
                            lineString = lineString.ReprojectTo(4326, dataSet.SRID);
                        }

                        model.LineString = Transform.TransformPoints(_elevationService.GetLineGeometryElevation(lineString, dataSet))
                                           .ToList();

                        yield return(model);
                    }
                    //int parallelCount = -1;
                    //Parallel.ForEach(models, new ParallelOptions { MaxDegreeOfParallelism = parallelCount }, model =>
                    //   {

                    //       model.LineString = Transform.TransformPoints(_elevationService.GetLineGeometryElevation(model.LineString, dataSet))
                    //                            .ToList();

                    //       yield return model;
                    //   }
                    //);
                }
                else
                {
                    foreach (var model in models)
                    {
                        model.LineString = new List <GeoPoint>(Transform.TransformPoints(model.LineString));
                        yield return(model);
                    }
                }
            }
        }
コード例 #10
0
        public TileRange DownloadTiles(TileRange tiles, ImageryProvider provider)
        {
            Stopwatch sw         = Stopwatch.StartNew();
            int       intervalMs = 1000;

            if (provider is ITileGenerator generator)
            {
                // download tiles
                using (TimeSpanBlock timer = new TimeSpanBlock("Tile generation", _logger))
                {
                    // Max download threads defined in provider
                    var parallelOptions = new ParallelOptions()
                    {
                        MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                    };
                    var range = tiles.TilesInfo.ToList();
                    _logger?.LogInformation($"Generating {range.Count} tiles with {provider.Name} generator...");
                    Parallel.ForEach(range, parallelOptions, tile =>
                    {
                        var contentbytes = generator.GenerateTile(tile.X, tile.Y, tile.Zoom);
                        tiles.Add(new MapTile(contentbytes, provider.TileSize, null, tile));
                    }
                                     );
                }
            }
            else
            {
                // download tiles
                Stopwatch swDownload = Stopwatch.StartNew();
                _logger?.LogTrace("Starting images download");


                // Max download threads defined in provider
                var parallelOptions = new ParallelOptions()
                {
                    MaxDegreeOfParallelism = provider.MaxDegreeOfParallelism
                };
                var range = tiles.TilesInfo.ToList();
                int numTilesDownloaded = 0;
                _logger?.LogInformation($"Downloading {range.Count} tiles...");
                try
                {
                    Parallel.ForEach(range, parallelOptions, (tile, state) =>
                    {
                        Uri tileUri = BuildUri(provider, tile.X, tile.Y, tile.Zoom);

                        var contentBytes = cache.GetTile(tileUri, provider, tile);

                        tiles.Add(new MapTile(contentBytes, provider.TileSize, tileUri, tile));

                        Interlocked.Increment(ref numTilesDownloaded);

                        if (sw.ElapsedMilliseconds > intervalMs)
                        {
                            _logger.LogInformation($"{numTilesDownloaded:N0}/{range.Count:N0} tiles downloaded...");
                            sw.Restart();
                        }
                    }
                                     );
                }
                catch (AggregateException ex)
                {
                    throw ex.GetInnerMostException();
                }
                catch (Exception)
                {
                    throw;
                }


                swDownload.Stop();
                _logger?.LogInformation($"DownloadImages done in : {swDownload.Elapsed:g}");
            }


            return(tiles);
        }
コード例 #11
0
        private Location3DModelResponse Generate3DLocationModel(Location3DModelRequest request, Location3DModelSettings settings)
        {
            Location3DModelResponse response = new Location3DModelResponse();

            try
            {
                bool imageryFailed = false;
                using (TimeSpanBlock timer = new TimeSpanBlock($"3D model {request.Id}", _logger))
                {
                    BoundingBox bbox = GetBoundingBoxAroundLocation(request.Latitude, request.Longitude, settings.SideSizeKm);

                    HeightMap hMap      = _elevationService.GetHeightMap(ref bbox, settings.Dataset);
                    var       transform = new ModelGenerationTransform(bbox, Reprojection.SRID_PROJECTED_MERCATOR, centerOnOrigin: true, settings.ZScale, centerOnZOrigin: true);

                    response.Attributions.AddRange(settings.Attributions);   // will be added to the model
                    response.Attributions.Add(settings.Dataset.Attribution); // will be added to the model


                    PBRTexture pbrTexture = null;
                    if (settings.ImageryProvider != null)
                    {
                        response.Attributions.Add(settings.ImageryProvider.Attribution); // will be added to the model

                        // Imagery
                        TileRange tiles = _imageryService.ComputeBoundingBoxTileRange(bbox, settings.ImageryProvider, settings.MinTilesPerImage);
                        Debug.Assert(tiles.Count < 400);

                        tiles = _imageryService.DownloadTiles(tiles, settings.ImageryProvider);

                        string      fileName = Path.Combine(settings.OutputDirectory, $"{request.Id}_Texture.jpg");
                        TextureInfo texInfo  = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg);

                        transform.BoundingBox = bbox;
                        hMap = transform.TransformHeightMap(hMap);


                        //var normalMap = _imageryService.GenerateNormalMap(hMap, settings.OutputDirectory, $"{request.Id}_normalmap.png");
                        pbrTexture = PBRTexture.Create(texInfo);
                    }

                    // Center on origin
                    //hMap = hMap.CenterOnOrigin(out Matrix4x4 transform).BakeCoordinates();
                    //response.Origin = new GeoPoint(request.Latitude, request.Longitude).ReprojectTo(Reprojection.SRID_GEODETIC, Reprojection.SRID_PROJECTED_MERCATOR);

                    ModelRoot model = _gltfService.CreateNewModel();

                    //=======================
                    // Buildings
                    if (settings.OsmBuildings)
                    {
                        model = _sampleOsmProcessor.Run(model, OsmLayer.Buildings, bbox, transform, computeElevations: true, settings.Dataset, settings.DownloadMissingFiles);
                    }


                    if (settings.GenerateTIN)
                    {
                        model = AddTINMesh(model, hMap, 2d, _gltfService, pbrTexture, Reprojection.SRID_PROJECTED_MERCATOR);
                    }
                    else
                    {
                        model = _gltfService.AddTerrainMesh(model, hMap, pbrTexture);
                    }
                    model.Asset.Generator = "DEM Net Elevation API with SharpGLTF";
                    //model.TryUseExtrasAsList(true).AddRange(response.Attributions);
                    model.SaveGLB(Path.Combine(settings.OutputDirectory, string.Concat(imageryFailed ? "imageryFailed_" : "", settings.ModelFileNameGenerator(settings, request))));

                    // cleanup
                    //if (pbrTexture != null)
                    //{
                    //    if (pbrTexture.NormalTexture != null) File.Delete(pbrTexture.NormalTexture.FilePath);
                    //    File.Delete(pbrTexture.BaseColorTexture.FilePath);
                    //}

                    response.Elapsed  = timer.Elapsed;
                    response.NumTiles = pbrTexture.BaseColorTexture.TileCount;
                }
            }
            catch (Exception)
            {
                throw;
            }
            return(response);
        }
コード例 #12
0
        protected override IEnumerable <BuildingModel> ComputeModelElevationsAndTransform(IEnumerable <BuildingModel> modelsEnum, bool computeElevations, DEMDataSet dataSet, bool downloadMissingFiles)
        {
            Dictionary <int, GeoPoint> reprojectedPointsById = null;

            //// georeference
            //var bbox = new BoundingBox();
            //foreach (var p in models.Models)
            //{
            //    foreach (var pt in p.ExteriorRing)
            //        bbox.UnionWith(pt.Longitude, pt.Latitude, 0);
            //}
            //var bbox3857 = bbox.ReprojectTo(4326, 3857);

            List <BuildingModel> models = modelsEnum.ToList();

            using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock("Elevations+Reprojection", _logger, LogLevel.Debug))
            {
                // Select all points (outer ring) + (inner rings)
                // They all have an Id, so we can lookup in which building they should be mapped after
                var allBuildingPoints = models
                                        .SelectMany(b => b.Points);

                // Compute elevations if requested
                IEnumerable <GeoPoint> geoPoints = computeElevations ? _elevationService.GetPointsElevation(allBuildingPoints
                                                                                                            , dataSet
                                                                                                            , behavior: NoDataBehavior.SetToZero
                                                                                                            , downloadMissingFiles: downloadMissingFiles)
                                                                    : allBuildingPoints;

                geoPoints = Transform?.TransformPoints(geoPoints);

                reprojectedPointsById = geoPoints.ToDictionary(p => p.Id.Value, p => p);

                //.ZScale(zScale)
                //.ReprojectGeodeticToCartesian(pointCount)
                //.CenterOnOrigin(bbox3857)
            }

            using (TimeSpanBlock timeSpanBlock = new TimeSpanBlock("Remap points", _logger, LogLevel.Debug))
            {
                int checksum = 0;
                foreach (var buiding in models)
                {
                    foreach (var point in buiding.Points)
                    {
                        //if (reprojectedPointsById.TryGetValue(point.Id.Value, out var newPoint))
                        var newPoint = reprojectedPointsById[point.Id.Value];
                        {
                            point.Latitude  = newPoint.Latitude;
                            point.Longitude = newPoint.Longitude;
                            point.Elevation = newPoint.Elevation;
                            checksum++;
                        }
                    }

                    yield return(buiding);
                }
                Debug.Assert(checksum == reprojectedPointsById.Count);
                reprojectedPointsById.Clear();
                reprojectedPointsById = null;
            }
        }