private UploadModelRequest GetUploadRequest(Location3DModelSettings settings, Location3DModelRequest request) { UploadModelRequest upload = new UploadModelRequest() { Description = GenerateDescription(settings, request),// "TEST",// * Generated by [DEM Net Elevation API](https://elevationapi.com)\n* Helladic test upload", FilePath = Path.Combine(settings.OutputDirectory, settings.ModelFileNameGenerator(settings, request)), IsInspectable = true, IsPrivate = false, IsPublished = true, Name = string.Concat(request.Id, " ", request.Title), Options = new ModelOptions() { Background = SkecthFabEnvironment.Tokyo_Big_Sight, Shading = ShadingType.lit }, Source = "mycenaean-atlas-project_elevationapi", TokenType = TokenType.Token }; return(upload); }
public void BatchGenerationAndUpload(string fileName, string outputDirName) { Location3DModelSettings settings = new Location3DModelSettings() { Dataset = DEMDataSet.NASADEM, ImageryProvider = ImageryProvider.ThunderForestLandscape, ZScale = 2f, SideSizeKm = 1.5f, OsmBuildings = true, DownloadMissingFiles = false, GenerateTIN = false, MaxDegreeOfParallelism = 1, OutputDirectory = Path.Combine(Directory.GetCurrentDirectory(), outputDirName) }; string currentOutFilePath = string.Concat(Path.ChangeExtension(fileName, null), $"_out.txt"); Dictionary <string, Location3DModelRequest> requests = ParseInputFile(fileName); Dictionary <string, Location3DModelResponse> responses = ParseOutputFile(currentOutFilePath); // Backup file by creating a copy var outFilePath = string.Concat(Path.ChangeExtension(fileName, null), $"_out_{DateTime.Now:ddMMyyyy-hhmmss}.txt"); bool append = responses.Count > 0; _logger.LogInformation($"Append mode: {append}"); // Restart from previous run Directory.CreateDirectory(settings.OutputDirectory); // Filter already generated files int countBefore = requests.Count; //requests = requests.Where(r => !File.Exists(Path.Combine(settings.OutputDirectory, settings.ModelFileNameGenerator(settings, r.Value)))).ToList(); if (requests.Count < countBefore) { _logger.LogInformation($"Skipping {countBefore - requests.Count} files already generated."); } // Generate and upload int sumTilesDownloaded = 0; using (StreamWriter sw = new StreamWriter(outFilePath, append: append, Encoding.UTF8)) { sw.WriteLine(string.Join("\t", "pk", "pn", "lat", "lon", "link", "tilecount_running_total", "sketchfab_status", "sketchfab_id")); foreach (var request in requests.Values) { UploadModelRequest uploadRequest; try { bool modelExists = File.Exists(Path.Combine(settings.OutputDirectory, settings.ModelFileNameGenerator(settings, request))); Location3DModelResponse response = null; if (!(modelExists && responses.TryGetValue(request.Id, out response))) // check model file exist { try { //=========================== // Generation response = Generate3DLocationModel(request, settings); sumTilesDownloaded += response.NumTiles ?? 0; response.Id = request.Id; responses[response.Id] = response; } catch (Exception ex) { _logger.LogError(ex.Message); } finally { _logger.LogInformation("Model generated. Waiting 10s..."); Thread.Sleep(10000); // wait 2 sec to dive overpassAPI some breath } } if (response != null && string.IsNullOrWhiteSpace(response.UploadedFileId)) { try { //=========================== // Upload uploadRequest = GetUploadRequest(settings, request); var sfResponse = _sketchFabApi.UploadModelAsync(uploadRequest, _sketchFabToken).GetAwaiter().GetResult(); response.UploadedFileId = sfResponse.ModelId; response.UploadStatus = sfResponse.StatusCode == HttpStatusCode.Created ? UploadStatus.OK : UploadStatus.Error; _logger.LogInformation($"Sketchfab upload ok : {response.UploadedFileId}"); } catch (Exception ex) { response.UploadStatus = UploadStatus.Error; response.UploadedFileId = null; _logger.LogError(ex.Message); } finally { _logger.LogInformation($"Waiting 10s..."); Thread.Sleep(10000); // wait 2 sec to give SkecthFab some breath } } sw.WriteLine(string.Join("\t", request.Id, request.Title, request.Latitude, request.Longitude , request.Description // link , sumTilesDownloaded // tilecount_running_total , response.UploadStatus.ToString() // sketchfab_status , response.UploadedFileId // sketchfab_id )); sw.Flush(); if (responses.Count > 0) { _logger.LogInformation($"Reponse: {responses.Last().Value.Elapsed.TotalSeconds:N3} s, Average: {responses.Average(r => r.Value.Elapsed.TotalSeconds):N3} s ({responses.Count}/{requests.Count} model(s) so far, {sumTilesDownloaded} tiles)"); } } catch (Exception ex) { _logger.LogError(ex.Message); } } } }
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); }