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); } } } }
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"); }
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); }
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); }
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()}"); } }
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; } }
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; } }
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)); }
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); } } } }
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); }
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); }
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; } }