public ModelRoot Run(ModelRoot gltfModel, BoundingBox bbox, bool computeElevations, DEMDataSet dataSet, bool downloadMissingFiles) { #if TOLIST try { // Download buildings and convert them to GeoJson var features = _osmDataService.GetOsmDataAsGeoJson(bbox, DataSettings).ToList(); // Create internal building model var parsed = this.CreateModelsFromGeoJson <T>(features, ModelFactory).ToList(); //_logger.LogInformation($"Computing elevations ({parsed.Models.Count} lines, {parsed.TotalPoints} total points)..."); // Compute elevations (faster elevation when point count is known in advance) // Download elevation data if missing if (computeElevations && downloadMissingFiles) { _elevationService.DownloadMissingFiles(dataSet, bbox); } parsed = this.ComputeModelElevationsAndTransform(parsed, computeElevations, dataSet, downloadMissingFiles).ToList(); gltfModel = this.AddToModel(gltfModel, glTFNodeName, parsed); return(gltfModel); } catch (Exception ex) { _logger.LogError($"{typeof(T).Name} generator error: {ex.Message}"); throw; } #else try { // Download buildings and convert them to GeoJson IEnumerable <IFeature> features = _osmDataService.GetOsmDataAsGeoJson(bbox, DataSettings); // Create internal building model IEnumerable <T> parsed = this.CreateModelsFromGeoJson <T>(features, ModelFactory); //_logger.LogInformation($"Computing elevations ({parsed.Models.Count} lines, {parsed.TotalPoints} total points)..."); // Compute elevations (faster elevation when point count is known in advance) // Download elevation data if missing if (computeElevations && downloadMissingFiles) { _elevationService.DownloadMissingFiles(dataSet, bbox); } parsed = this.ComputeModelElevationsAndTransform(parsed, computeElevations, dataSet, downloadMissingFiles); gltfModel = this.AddToModel(gltfModel, glTFNodeName, parsed); return(gltfModel); } catch (Exception ex) { _logger.LogError($"{typeof(T).Name} generator error: {ex.Message}"); throw; } #endif }
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); }
private (ModelRoot Model, double widthMeters, double heightMeters, double averageElevation, BoundingBox projectedBbox) GenerateSampleModel(BoundingBox bbox, DEMDataSet dataset, bool withTexture = true) { try { int TEXTURE_TILES = 8; // 4: med, 8: high string outputDir = Directory.GetCurrentDirectory(); //_rasterService.GenerateDirectoryMetadata(dataset, false); ImageryProvider provider = ImageryProvider.MapBoxSatellite;// new TileDebugProvider(new GeoPoint(43.5,5.5)); _logger.LogInformation($"Getting height map data..."); var heightMap = _elevationService.GetHeightMap(ref bbox, dataset); var wgs84bbox = bbox; ModelGenerationTransform transform = new ModelGenerationTransform(bbox, 3857, true, 1.5f, true); _logger.LogInformation($"Processing height map data ({heightMap.Count} coordinates)..."); heightMap = transform.TransformHeightMap(heightMap); //======================= // Textures // PBRTexture pbrTexture = null; if (withTexture) { Console.WriteLine("Download image tiles..."); TileRange tiles = _imageryService.DownloadTiles(bbox, provider, TEXTURE_TILES); string fileName = Path.Combine(outputDir, "Texture.jpg"); Console.WriteLine("Construct texture..."); TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); // //======================= //======================= // Normal map Console.WriteLine("Height map..."); //float Z_FACTOR = 0.00002f; //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); //var normalMap = _imageryService.GenerateNormalMap(heightMap, outputDir); pbrTexture = PBRTexture.Create(texInfo, null); //hMap = hMap.CenterOnOrigin(Z_FACTOR); // //======================= } // Triangulate height map // and add base and sides _logger.LogInformation($"Triangulating height map and generating 3D mesh..."); var model = _sharpGltfService.CreateTerrainMesh(heightMap, pbrTexture); var width = new GeoPoint(wgs84bbox.Center[1], bbox.Center[0] - bbox.Width / 2f).DistanceTo(new GeoPoint(wgs84bbox.Center[1], bbox.Center[0] + bbox.Width / 2f)); var height = new GeoPoint(bbox.Center[1] - bbox.Height / 2f, wgs84bbox.Center[0]).DistanceTo(new GeoPoint(bbox.Center[1] + bbox.Height, wgs84bbox.Center[0])); return(model, width, height, wgs84bbox.Center[2], heightMap.BoundingBox); } catch (Exception ex) { _logger.LogError(ex, ex.Message); return(null, 0, 0, 0, null); } }
protected abstract IEnumerable <T> ComputeModelElevationsAndTransform(IEnumerable <T> models, bool computeElevations, DEMDataSet dataSet, bool downloadMissingFiles);
public GDALVRTFileService(string localDirectory, DEMDataSet dataSet) { this.localDirectory = localDirectory; this.dataSet = dataSet; }
private static void Test_GetMetadataFromVRT(ElevationService elevationService, DEMDataSet dataSet) { GDALVRTFileService gdalService = new GDALVRTFileService(elevationService.GetDEMLocalPath(dataSet), dataSet); gdalService.Setup(false); GDALSource source = gdalService.Sources().FirstOrDefault(s => s.SourceFileName.EndsWith("N043E006_AVE_DSM.tif")); }
internal void RunSensorLog(DEMDataSet largeDataSet, DEMDataSet localDataset) { //// sensor log needs data filtering //// => some coordinates are null (not in the json data) //// => most accurate is RelativeElevation //// => this is height above initial point, need to sum with start elevation //try //{ // string outputDir = Path.GetFullPath("."); // //string _gpxFile = Path.Combine("SampleData", "20191022-Puch-Pöllau.gpx"); // string sensorLogFile = Path.Combine("SampleData", "20191023-Puch-Pöllau-sensorlog.json"); // var sensorLog = SensorLog.FromJson(sensorLogFile); // //sensorLog.Plot("sensorLog.png"); // string balloonModel = Path.Combine("SampleData", "OE-SOE.glb"); // float Z_FACTOR = 2f; // float trailWidthMeters = 5f; // ModelRoot balloon = ModelRoot.Load(balloonModel); // //======================= // /// Line strip from SensorLog // /// // var pointsGpx = sensorLog.ToGPX().ToList(); // var geoPoints = sensorLog.ToGeoPoints().ToList(); // var firstElevation = _elevationService.GetPointElevation(geoPoints.First(), localDataset); // foreach (var p in pointsGpx) p.Elevation += firstElevation.Elevation.Value; // foreach (var p in geoPoints) p.Elevation += firstElevation.Elevation.Value; // var model = _sharpGltfService.CreateNewModel(); // //var largeMesh = GetMeshFromGpxTrack(outputDir, largeDataSet, geoPoints // // , bboxScale: 5 // // , zFactor: Z_FACTOR // // , generateTIN: false // // , tinPrecision: 500d // // , drawGpxOnTexture: false // // , ImageryProvider.OpenTopoMap); // //meshes.Add(largeMesh); // model = GetMeshFromGpxTrack(model, outputDir, localDataset, geoPoints // , bboxScale: (1.05, 1.05) // , zFactor: Z_FACTOR // , generateTIN: false // , tinPrecision: 50d // , drawGpxOnTexture: true // , ImageryProvider.EsriWorldImagery); // var gpxPoints = geoPoints.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); // model = _sharpGltfService.AddLine(model, gpxPoints, new Vector4(0, 1, 0, 0.5f), trailWidthMeters); // // model export // Console.WriteLine("GenerateModel..."); // var node = model.LogicalNodes.First(); // pointsGpx = pointsGpx.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); // // animations // node = CreateAnimationFromGpx("GPX", node, pointsGpx, 1f); // node = CreateAnimationFromGpx("GPX x500", node, pointsGpx, 500f); // //var sceneBuilderBalloon = balloon.DefaultScene.ToSceneBuilder(); // //var sceneBuilderTerrain = model.DefaultScene.ToSceneBuilder(); // //sceneBuilderBalloon. // model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), $"{GetType().Name}.glb")); //} //catch (Exception ex) //{ // _logger.LogError(ex, ex.Message); //} }
void TestEdges(DEMDataSet dataSet, double lat, double lon , string rasterSouthWestName, string rasterSouthEastName , string rasterNorthWestName, string rasterNorthEastName) { DEMFileType fileType = dataSet.FileFormat.Type; int rasterSize = dataSet.PointsPerDegree; double amountx = (1d / rasterSize) / 4d; double amounty = (1d / rasterSize) / 4d; // Regenerates all metadata //_rasterService.GenerateDirectoryMetadata(dataSet // , force: true // , deleteOnError: false // , maxDegreeOfParallelism: 1); _elevationService.DownloadMissingFiles(dataSet, lat, lon); var tiles = _rasterService.GenerateReportForLocation(dataSet, lat, lon); Debug.Assert(tiles.Count == 4); Debug.Assert(tiles.Any(t => string.Equals(Path.GetFileName(t.LocalName), rasterSouthWestName, StringComparison.OrdinalIgnoreCase))); Debug.Assert(tiles.Any(t => string.Equals(Path.GetFileName(t.LocalName), rasterSouthEastName, StringComparison.OrdinalIgnoreCase))); Debug.Assert(tiles.Any(t => string.Equals(Path.GetFileName(t.LocalName), rasterNorthWestName, StringComparison.OrdinalIgnoreCase))); Debug.Assert(tiles.Any(t => string.Equals(Path.GetFileName(t.LocalName), rasterNorthEastName, StringComparison.OrdinalIgnoreCase))); if (dataSet.FileFormat.Registration == DEMFileRegistrationMode.Cell) { using (var rasterNW = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterNorthWestName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterNE = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterNorthEastName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterSW = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterSouthWestName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterSE = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterSouthEastName, Path.GetFileName(t.LocalName))).LocalName, fileType)) { var elevNW = rasterNW.GetElevationAtPoint(rasterNW.ParseMetaData(dataSet.FileFormat), rasterSize - 1, rasterSize - 1); var elevNE = rasterNE.GetElevationAtPoint(rasterNE.ParseMetaData(dataSet.FileFormat), 0, rasterSize - 1); var elevSW = rasterSW.GetElevationAtPoint(rasterSW.ParseMetaData(dataSet.FileFormat), rasterSize - 1, 0); var elevSE = rasterSE.GetElevationAtPoint(rasterSE.ParseMetaData(dataSet.FileFormat), 0, 0); BilinearInterpolator interpolator = new BilinearInterpolator(); var elev0 = interpolator.Interpolate(elevSW, elevSE, elevNW, elevNE, 0.25, 0.25); var apiElev0 = _elevationService.GetPointElevation(lat + amounty, lon - amountx, dataSet); Debug.Assert((elev0 - apiElev0.Elevation.Value) < double.Epsilon); var elev1 = interpolator.Interpolate(elevSW, elevSE, elevNW, elevNE, 0.75, 0.25); var apiElev1 = _elevationService.GetPointElevation(lat + amounty, lon + amountx, dataSet); Debug.Assert((elev1 - apiElev1.Elevation.Value) < double.Epsilon); var elev2 = interpolator.Interpolate(elevSW, elevSE, elevNW, elevNE, 0.25, 0.75); var apiElev2 = _elevationService.GetPointElevation(lat - amounty, lon - amountx, dataSet); Debug.Assert((elev2 - apiElev2.Elevation.Value) < double.Epsilon); var elev3 = interpolator.Interpolate(elevSW, elevSE, elevNW, elevNE, 0.75, 0.75); var apiElev3 = _elevationService.GetPointElevation(lat - amounty, lon + amountx, dataSet); Debug.Assert((elev3 - apiElev3.Elevation.Value) < double.Epsilon); } } else { using (var rasterNW = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterNorthWestName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterNE = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterNorthEastName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterSW = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterSouthWestName, Path.GetFileName(t.LocalName))).LocalName, fileType)) using (var rasterSE = _rasterService.OpenFile(tiles.First(t => string.Equals(rasterSouthEastName, Path.GetFileName(t.LocalName))).LocalName, fileType)) { // Northen row, west to east var elevN0 = rasterNW.GetElevationAtPoint(rasterNW.ParseMetaData(dataSet.FileFormat), rasterSize - 1, rasterSize - 1); var elevN1 = rasterNW.GetElevationAtPoint(rasterNW.ParseMetaData(dataSet.FileFormat), rasterSize, rasterSize - 1); var elevN2 = rasterNE.GetElevationAtPoint(rasterNE.ParseMetaData(dataSet.FileFormat), 1, rasterSize - 1); // middle row, west to east var elevM0 = rasterNW.GetElevationAtPoint(rasterNW.ParseMetaData(dataSet.FileFormat), rasterSize - 1, rasterSize); var elevM1 = rasterNW.GetElevationAtPoint(rasterNW.ParseMetaData(dataSet.FileFormat), rasterSize, rasterSize); var elevM2 = rasterNE.GetElevationAtPoint(rasterNE.ParseMetaData(dataSet.FileFormat), 1, rasterSize); // Sourthen row, west to east var elevS0 = rasterSW.GetElevationAtPoint(rasterSW.ParseMetaData(dataSet.FileFormat), rasterSize - 1, 1); var elevS1 = rasterSW.GetElevationAtPoint(rasterSW.ParseMetaData(dataSet.FileFormat), rasterSize, 1); var elevS2 = rasterSE.GetElevationAtPoint(rasterSE.ParseMetaData(dataSet.FileFormat), 1, 1); BilinearInterpolator interpolator = new BilinearInterpolator(); var elev0 = interpolator.Interpolate(elevM0, elevM1, elevN0, elevN1, 0.75, 0.75); var apiElev0 = _elevationService.GetPointElevation(lat + amounty, lon - amountx, dataSet); Debug.Assert((elev0 - apiElev0.Elevation.Value) < double.Epsilon); var elev1 = interpolator.Interpolate(elevM1, elevM2, elevN1, elevN2, 0.25, 0.75); var apiElev1 = _elevationService.GetPointElevation(lat + amounty, lon + amountx, dataSet); Debug.Assert((elev1 - apiElev1.Elevation.Value) < double.Epsilon); var elev2 = interpolator.Interpolate(elevS0, elevS1, elevM0, elevM1, 0.75, 0.25); var apiElev2 = _elevationService.GetPointElevation(lat - amounty, lon - amountx, dataSet); Debug.Assert((elev2 - apiElev2.Elevation.Value) < double.Epsilon); var elev3 = interpolator.Interpolate(elevS1, elevS2, elevM1, elevM2, 0.25, 0.25); var apiElev3 = _elevationService.GetPointElevation(lat - amounty, lon + amountx, dataSet); Debug.Assert((elev3 - apiElev3.Elevation.Value) < double.Epsilon); } } }
private string FileNameFromGranuleId(string granuleId, DEMDataSet dataSet) { var fileName = string.Concat(Path.GetFileNameWithoutExtension(granuleId), dataSet.FileFormat.FileExtension); return(fileName); }
public void Setup(DEMDataSet dataSet, string dataSetLocalDir) { try { if (dataSet == null) { throw new ArgumentNullException(nameof(dataSet), "Dataset is null."); } NasaGranuleDataSource dataSource = dataSet.DataSource as NasaGranuleDataSource; if (dataSource is null) { throw new ArgumentException(nameof(dataSet), $"Dataset source is {dataSet.DataSource.DataSourceType}, only {nameof(DEMDataSourceType.NasaEarthData)} sources are supported by {nameof(NasaGranuleFileService)} null."); } if (!Directory.Exists(dataSetLocalDir)) { Directory.CreateDirectory(dataSetLocalDir); } string indexFileName = Path.Combine(dataSetLocalDir, UrlHelper.GetFileNameFromUrl(dataSource.IndexFilePath)); bool download = !File.Exists(indexFileName); List <NasaDemFile> links = null; if (download) { // Fetch Earth data collection page by page until we have no result left // this.logger.LogInformation($"Fetching granules from collection {dataSource.CollectionId} to disk... This will be done once."); bool hasData = true; int pageIndex = 0; int PAGE_SIZE = 2000; links = new List <NasaDemFile>(30000); var httpClient = httpClientFactory.CreateClient(); do { pageIndex++; logger.LogInformation($"Getting entries on page {pageIndex} with page size of {PAGE_SIZE} ({(pageIndex - 1) * PAGE_SIZE} entries so far)..."); var url = dataSource.GetUrl(PAGE_SIZE, pageIndex); var json = httpClient.GetStringAsync(url).GetAwaiter().GetResult(); hasData = !string.IsNullOrWhiteSpace(json); if (hasData) { var result = NasaCmrGranuleResult.FromJson(json); hasData = result.Feed.Entry.Any(); if (hasData) { // Only retrieve bbox and dem file link (zip file) links.AddRange(result.Feed.Entry.Select(GetNasaDemFile).Where(file => file != null)); } } }while (hasData); var jsonResult = JsonConvert.SerializeObject(links); File.WriteAllText(indexFileName, JsonConvert.SerializeObject(links)); logger.LogInformation($"{links.Count} entries written to index file {indexFileName}"); } // Cache if (_cacheByDemName == null) { _cacheByDemName = new ConcurrentDictionary <string, List <DEMFileSource> >(); } if (_cacheByDemName.ContainsKey(dataSet.Name) == false) { _cacheByDemName[dataSet.Name] = this.GetSources(dataSet, indexFileName); } } catch (Exception ex) { this.logger?.LogError("Unhandled exception: " + ex.Message); this.logger?.LogInformation(ex.ToString()); throw; } }
public ModelRoot Run(ModelRoot model, OsmLayer layers, BoundingBox bbox, GeoTransformPipeline transform, bool computeElevations, DEMDataSet dataSet = null, bool downloadMissingFiles = true, bool withBuildingsColors = false, string defaultBuildingsColor = null) { model = model ?? _gltfService.CreateNewModel(); if (layers == OsmLayer.None) { return(model); } IOsmDataService osmDataService = _dataServiceFactory.Create(Settings.DataServiceType); List <IOsmProcessor> processors = Build(layers, computeElevations, transform, withBuildingsColors, defaultBuildingsColor); foreach (var p in processors) { p.DataSettings.FlatGeobufTilesDirectory = Settings.FlatGeobufTilesDirectory; p.Init(_elevationService, _gltfService, _meshService, osmDataService, _logger); model = p.Run(model, bbox, computeElevations, dataSet, downloadMissingFiles); } return(model); }
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; } }
public void Run() { try { // SF GeoPoint location4326 = new GeoPoint(37.766974, -122.431062); //GeoPoint location4326 = new GeoPoint( 43.542544, 5.445379); DEMDataSet dataset = DEMDataSet.NASADEM; double radius = 5000; GeoPoint location3857 = location4326.ReprojectTo(4326, 3857); BoundingBox bbox3857 = BoundingBox.AroundPoint(location3857, radius); // 5km around point bbox3857.SRID = 3857; BoundingBox bbox4326 = bbox3857.ReprojectTo(Reprojection.SRID_PROJECTED_MERCATOR, Reprojection.SRID_GEODETIC); HeightMap heightMap = _elevationService.GetHeightMap(ref bbox4326, dataset); // Highest point var highest = heightMap.Coordinates.First(pt => pt.Elevation.Value == heightMap.Maximum); _logger.LogInformation($"Highest point: {highest} at {highest.DistanceTo(location4326)} meters"); OsmHighwayProcessor roadsProcessor = new OsmHighwayProcessor(GeoTransformPipeline.Default); // Download buildings and convert them to GeoJson IEnumerable <IFeature> features = _osmService.GetOsmDataAsGeoJson(bbox4326, BasicOsmDataFilter.Create(new string[] { "highway" })); // Create internal building model IEnumerable <HighwayModel> parsed = roadsProcessor.CreateModelsFromGeoJson <HighwayModel>(features, roadsProcessor.ModelFactory); int parallelCount = -1; Parallel.ForEach(parsed, new ParallelOptions { MaxDegreeOfParallelism = parallelCount }, model => //foreach(var model in parsed.Models) { model.LineString = _elevationService.GetLineGeometryElevation(model.LineString, dataset); } ); var osmRoads = parsed.ToDictionary(p => p.Id, p => p); var osmRoadLines = parsed.ToDictionary(p => p.Id, p => p.LineString); (Slope Slope, HighwayModel Road)maxSlope = (Slope.Zero, null); (Slope Slope, HighwayModel Road)maxAvgSlope = (Slope.Zero, null); foreach (var model in osmRoadLines) { var metrics = model.Value.ComputeMetrics(); var slope = GetMaxSlope(model.Value); if (slope > maxSlope.Slope) { maxSlope.Slope = slope; maxSlope.Road = osmRoads[model.Key]; } var slopeAvg = ComputeSlope(model.Value.First(), model.Value.Last()); if (slopeAvg > maxAvgSlope.Slope) { maxAvgSlope.Slope = slopeAvg; maxSlope.Road = osmRoads[model.Key]; } } //int parallelCount = -1; //Parallel.ForEach(parsed.Models, new ParallelOptions { MaxDegreeOfParallelism = parallelCount }, model => ////foreach (var model in parsed.Models) //{ // model.LineString =_elevationService.GetLineGeometryElevation(model.LineString, dataset); //} //); //osmRoadLines = parsed.Models.ToDictionary(p => p.Id, p => p.LineString); //maxSlope = (Slope.Zero, null); //maxAvgSlope = (Slope.Zero, null); //foreach (var model in osmRoadLines) //{ // var metrics = model.Value.ComputeMetrics(); // var slope = GetMaxSlope(model.Value); // if (slope > maxSlope.Slope) // { // maxSlope.Slope = slope; // maxSlope.Road = osmRoads[model.Key]; // } // var slopeAvg = ComputeSlope(model.Value.First(), model.Value.Last()); // if (slopeAvg > maxAvgSlope.Slope) // { // maxAvgSlope.Slope = slopeAvg; // maxSlope.Road = osmRoads[model.Key]; // } //} } catch (Exception ex) { _logger.LogError(ex, $"Error in {nameof(HighestPointFinder)}"); } }
public string GetDEMLocalPath(DEMDataSet dataSet) { return(_IGeoTiffService.GetLocalDEMPath(dataSet)); }
internal void RunGPX(DEMDataSet largeDataSet, DEMDataSet localDataset) { try { string outputDir = Path.GetFullPath("."); string _gpxFile = Path.Combine("SampleData", "20191022-Puch-Pöllau.gpx"); string sensorLogFile = Path.Combine("SampleData", "20191023-Puch-Pöllau-sensorlog.json"); var sensorLog = SensorLog.FromJson(sensorLogFile); //sensorLog.Plot("sensorLog.png"); string balloonModel = Path.Combine("SampleData", "OE-SOE.glb"); float Z_FACTOR = 2f; float trailWidthMeters = 5f; ModelRoot balloon = ModelRoot.Load(balloonModel); //======================= /// Line strip from GPX /// // Get GPX points var segments = GpxImport.ReadGPX_Segments <GpxTrackPoint>(_gpxFile, p => p); var pointsGpx = segments.SelectMany(seg => seg); var geoPoints = pointsGpx.ToGeoPoints(); var model = _sharpGltfService.CreateNewModel(); //var largeMesh = GetMeshFromGpxTrack(outputDir, largeDataSet, geoPoints // , bboxScale: 5 // , zFactor: Z_FACTOR // , generateTIN: false // , tinPrecision: 500d // , drawGpxOnTexture: false // , ImageryProvider.OpenTopoMap); //meshes.Add(largeMesh); model = GetMeshFromGpxTrack(model, outputDir, localDataset, geoPoints , bboxScale: (1.3, 1.5) , zFactor: Z_FACTOR , generateTIN: false , tinPrecision: 50d , drawGpxOnTexture: true , ImageryProvider.EsriWorldImagery); var gpxPoints = geoPoints.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); model = _sharpGltfService.AddLine(model, gpxPoints, new Vector4(0, 1, 0, 0.5f), trailWidthMeters); // model export Console.WriteLine("GenerateModel..."); var node = model.LogicalNodes.First(); pointsGpx = pointsGpx.ReprojectGeodeticToCartesian().ZScale(Z_FACTOR); // animations node = CreateAnimationFromGpx("GPX", node, pointsGpx, 1f); node = CreateAnimationFromGpx("GPX x500", node, pointsGpx, 500f); var sceneBuilderBalloon = balloon.DefaultScene.ToSceneBuilder(); var sceneBuilderTerrain = model.DefaultScene.ToSceneBuilder(); //sceneBuilderBalloon. model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), $"{GetType().Name}.glb")); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
internal void Run(DEMDataSet dataSet, bool trackIn3D = true, bool generateTIN = false, int outputSrid = Reprojection.SRID_PROJECTED_LAMBERT_93) { try { string _gpxFile = Path.Combine("SampleData", "BikeRide.gpx"); bool withTexture = true; float Z_FACTOR = 4f; float Z_TRANSLATE_GPX_TRACK_METERS = 5; float trailWidthMeters = 5f; int skipGpxPointsEvery = 1; ImageryProvider provider = ImageryProvider.MapBoxSatellite; // new TileDebugProvider(null, maxDegreeOfParallelism: 1);// ImageryProvider.MapBoxSatellite; string outputDir = Path.GetFullPath("."); //======================= /// Line strip from GPX /// // Get GPX points var segments = GpxImport.ReadGPX_Segments(_gpxFile); var points = segments.SelectMany(seg => seg); var bbox = points.GetBoundingBox().Scale(1.3, 1.3); // DEBUG // Test case : ASTER GDEMv3 : 5.5 43.5 Z=315 // 303 307 308 // 309 *315* 317 // 314 321 324 //points = GenerateDebugTrailPointsGenerateDebugTrailPoints(5.003, 5.006, 43.995, 43.997, 0.0001, 0.001); //points = GenerateDebugTrailPointsGenerateDebugTrailPoints(5.4990, 5.501, 43.4990, 43.501, 0.0001, 0.001); //points = GenerateDebugTrailPointsGenerateDebugTrailPoints(5.49, 5.51, 43.49, 43.51, 0.0005, 0.001); //bbox = points.GetBoundingBox().Scale(1.3,1.3); IEnumerable <GeoPoint> gpxPointsElevated = _elevationService.GetPointsElevation(points, dataSet); // //======================= //======================= /// Height map (get dem elevation for bbox) /// HeightMap hMap = _elevationService.GetHeightMap(ref bbox, dataSet); // var refPoint = new GeoPoint(43.5, 5.5); // hMap = hMap.BakeCoordinates(); // var hMapRefPoint = hMap.Coordinates.OrderBy(c => c.DistanceSquaredTo(refPoint)).First(); // var gpxRefPoint = gpxPointsElevated.OrderBy(c => c.DistanceSquaredTo(refPoint)).First(); // hMapRefPoint.Elevation += 60; // gpxRefPoint.Elevation += 60; hMap = hMap.ReprojectTo(4326, outputSrid) //.CenterOnOrigin() .ZScale(Z_FACTOR) .BakeCoordinates(); // //======================= //======================= // Textures // PBRTexture pbrTexture = null; if (withTexture) { Console.WriteLine("Download image tiles..."); TileRange tiles = _imageryService.DownloadTiles(bbox, provider, 8); string fileName = Path.Combine(outputDir, "Texture.jpg"); Console.WriteLine("Construct texture..."); TextureInfo texInfo = _imageryService.ConstructTextureWithGpxTrack(tiles, bbox, fileName, TextureImageFormat.image_jpeg, gpxPointsElevated, false); // //======================= //======================= // Normal map Console.WriteLine("Height map..."); //float Z_FACTOR = 0.00002f; //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); var normalMap = _imageryService.GenerateNormalMap(hMap, outputDir); pbrTexture = PBRTexture.Create(texInfo, normalMap); //hMap = hMap.CenterOnOrigin(Z_FACTOR); // //======================= } //======================= // MESH 3D terrain Console.WriteLine("Height map..."); Console.WriteLine("GenerateTriangleMesh..."); //hMap = _elevationService.GetHeightMap(bbox, _dataSet); ModelRoot model = null; if (generateTIN) { model = TINGeneration.GenerateTIN(hMap, 10d, _sharpGltfService, pbrTexture, outputSrid); } else { //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); // generate mesh with texture model = _sharpGltfService.CreateTerrainMesh(hMap, pbrTexture); } if (trackIn3D) { // take 1 point evert nth gpxPointsElevated = gpxPointsElevated.Where((x, i) => (i + 1) % skipGpxPointsEvery == 0); gpxPointsElevated = gpxPointsElevated.ZTranslate(Z_TRANSLATE_GPX_TRACK_METERS) .ReprojectTo(4326, outputSrid) //.CenterOnOrigin() //.CenterOnOrigin(hMap.BoundingBox) .ZScale(Z_FACTOR); model = _sharpGltfService.AddLine(model, gpxPointsElevated, new Vector4(0, 1, 0, 0.5f), trailWidthMeters); } // model export Console.WriteLine("GenerateModel..."); model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), $"{GetType().Name} dst{dataSet.Name} TIN{generateTIN} Srid{outputSrid}.glb")); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
internal ModelRoot GetMeshFromGpxTrack(ModelRoot model, string outputDir, DEMDataSet dataSet, IEnumerable <GeoPoint> gpxPoints4326, (double x, double y) bboxScale, float zFactor, bool generateTIN,
public void Run(DEMDataSet dataset, bool withTexture = true) { try { int TEXTURE_TILES = 4; // 4: med, 8: high //_rasterService.GenerateDirectoryMetadata(dataset, false); Stopwatch sw = Stopwatch.StartNew(); string modelName = $"MontBlanc_{dataset.Name}"; string outputDir = Directory.GetCurrentDirectory(); ImageryProvider provider = ImageryProvider.EsriWorldImagery;// new TileDebugProvider(new GeoPoint(43.5,5.5)); //// You can get your boox from https://geojson.net/ (save as WKT) //string bboxWKT = "POLYGON((5.54888 43.519525, 5.61209 43.519525, 5.61209 43.565225, 5.54888 43.565225, 5.54888 43.519525))"; //// string bboxWKT = //// "POLYGON((5.594457381483949 43.545276557046044,5.652135604140199 43.545276557046044,5.652135604140199 43.52038635099936,5.594457381483949 43.52038635099936,5.594457381483949 43.545276557046044))"; //// _logger.LogInformation($"Processing model {modelName}..."); //// //// //// _logger.LogInformation($"Getting bounding box geometry..."); //var bbox = GeometryService.GetBoundingBox(bboxWKT); // DjebelMarra var bbox = new BoundingBox(24.098067346557492, 24.42468219234563, 12.7769822830208, 13.087504129660111); // MontBlanc //var bbox = GeometryService.GetBoundingBox("POLYGON((6.618804355541963 45.9658287141746,7.052764316479463 45.9658287141746,7.052764316479463 45.72379929776474,6.618804355541963 45.72379929776474,6.618804355541963 45.9658287141746))"); //var bbox = new BoundingBox(5.5613898348431485,5.597185285307553,43.49372969433046,43.50939068558466); _logger.LogInformation($"Getting height map data..."); var heightMap = _elevationService.GetHeightMap(ref bbox, dataset); ModelGenerationTransform transform = new ModelGenerationTransform(bbox, 3857, true, 1.5f, true); _logger.LogInformation($"Processing height map data ({heightMap.Count} coordinates)..."); heightMap = transform.TransformHeightMap(heightMap); //======================= // Textures // PBRTexture pbrTexture = null; if (withTexture) { Console.WriteLine("Download image tiles..."); TileRange tiles = _imageryService.DownloadTiles(bbox, provider, TEXTURE_TILES); string fileName = Path.Combine(outputDir, "Texture.jpg"); Console.WriteLine("Construct texture..."); TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); // //======================= //======================= // Normal map Console.WriteLine("Height map..."); //float Z_FACTOR = 0.00002f; //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); var normalMap = _imageryService.GenerateNormalMap(heightMap, outputDir); pbrTexture = PBRTexture.Create(texInfo, normalMap); //hMap = hMap.CenterOnOrigin(Z_FACTOR); // //======================= } // Triangulate height map // and add base and sides _logger.LogInformation($"Triangulating height map and generating 3D mesh..."); var model = _sharpGltfService.CreateTerrainMesh(heightMap, pbrTexture); model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + ".glb")); model.SaveAsWavefront(Path.Combine(Directory.GetCurrentDirectory(), modelName + ".obj")); model = _sharpGltfService.CreateTerrainMesh(heightMap, GenOptions.Normals | GenOptions.BoxedBaseElevationMin); model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + "_normalsBox.glb")); model.SaveAsWavefront(Path.Combine(Directory.GetCurrentDirectory(), modelName + "_normalsBox.obj")); _logger.LogInformation($"Model exported as {Path.Combine(Directory.GetCurrentDirectory(), modelName + ".gltf")} and .glb"); _logger.LogInformation($"Done in {sw.Elapsed:g}"); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
public void Run() { try { // ventoux //double lat1 = 44.17346; //double lon1 = 5.27829; // ste victoire //double lat1 = 43.532456; //double lon1 = 5.612444; // bottom ste victoire (fuveau) //double lat1 = 43.49029208393125; //double lon1 = 5.587234497070313; //double lat2 = 43.53013134607789; //double lon2 = 5.581398010253906; // geneva //double lat1 = 46.08129825372404; //double lon1 = 3.382026672363281; // mont blanc //double lat2 = 45.833; //double lon2 = 6.864; // bob //double lat1 = 37.212627; //double lon1 = 22.321612; //double lat2 = 37.208179; //double lon2 = 22.324373; double lat2 = 44.116655590545705; double lat1 = 44.19524951146881; double lon2 = 5.802505910396577; double lon1 = 5.806566774845124; Stopwatch sw = new Stopwatch(); _logger.LogInformation("Line elevation"); sw.Restart(); // Line starting at mont ventoux peak to Mont Blanc DEMDataSet dataSet = DEMDataSet.ASTER_GDEMV3; // High level way var metrics = _elevationService.GetIntervisibilityReport(new GeoPoint(lat1, lon1), new GeoPoint(lat2, lon2), dataSet , downloadMissingFiles: true, sourceVerticalOffset: 0); PlotVisibilityReport(metrics, 2048, 600, "VisReport.png"); // Low level (tests from 0 to 2000 m) var elevationLine = GeometryService.ParseGeoPointAsGeometryLine(new GeoPoint(lat1, lon1), new GeoPoint(lat2, lon2)); var geoPoints = _elevationService.GetLineGeometryElevation(elevationLine, dataSet); for (int i = 300; i < 10000; i += 500) { var report = _elevationService.GetIntervisibilityReport(geoPoints, i); PlotVisibilityReport(report, 2048, 600, $"VisReport_{i}.png"); } _logger.LogInformation($"{dataSet.Name} metrics: {metrics.ToString()}"); //var geoJson = ConvertLineElevationResultToGeoJson(simplified); _logger.LogInformation($"Done in {sw.Elapsed.TotalMilliseconds:N1}ms"); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
public void Run(DEMDataSet dataset, bool withTexture = true) { try { //_rasterService.GenerateDirectoryMetadata(dataset, false); Stopwatch sw = Stopwatch.StartNew(); string modelName = $"Montagne Sainte Victoire {dataset.Name}"; string outputDir = Directory.GetCurrentDirectory(); ImageryProvider provider = ImageryProvider.MapBoxSatelliteStreet;// new TileDebugProvider(new GeoPoint(43.5,5.5)); // You can get your boox from https://geojson.net/ (save as WKT) string bboxWKT = "POLYGON((5.54888 43.519525, 5.61209 43.519525, 5.61209 43.565225, 5.54888 43.565225, 5.54888 43.519525))"; // string bboxWKT = // "POLYGON((5.594457381483949 43.545276557046044,5.652135604140199 43.545276557046044,5.652135604140199 43.52038635099936,5.594457381483949 43.52038635099936,5.594457381483949 43.545276557046044))"; // _logger.LogInformation($"Processing model {modelName}..."); // // // _logger.LogInformation($"Getting bounding box geometry..."); var bbox = GeometryService.GetBoundingBox(bboxWKT); //var bbox = new BoundingBox(5.5613898348431485,5.597185285307553,43.49372969433046,43.50939068558466); _logger.LogInformation($"Getting height map data..."); var heightMap = _elevationService.GetHeightMap(ref bbox, dataset); _logger.LogInformation($"Processing height map data ({heightMap.Count} coordinates)..."); heightMap = heightMap .ReprojectGeodeticToCartesian() // Reproject to 3857 (useful to get coordinates in meters) .ZScale(2f); // Elevation exageration //======================= // Textures // PBRTexture pbrTexture = null; if (withTexture) { Console.WriteLine("Download image tiles..."); TileRange tiles = _imageryService.DownloadTiles(bbox, provider, TEXTURE_TILES); string fileName = Path.Combine(outputDir, "Texture.jpg"); Console.WriteLine("Construct texture..."); TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg); // //======================= //======================= // Normal map Console.WriteLine("Height map..."); //float Z_FACTOR = 0.00002f; //hMap = hMap.CenterOnOrigin().ZScale(Z_FACTOR); var normalMap = _imageryService.GenerateNormalMap(heightMap, outputDir); pbrTexture = PBRTexture.Create(texInfo, normalMap); //hMap = hMap.CenterOnOrigin(Z_FACTOR); // //======================= } // Triangulate height map // and add base and sides _logger.LogInformation($"Triangulating height map and generating 3D mesh..."); var model = _sharpGltfService.CreateTerrainMesh(heightMap, pbrTexture); model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + ".glb")); model = _sharpGltfService.CreateTerrainMesh(heightMap, GenOptions.Normals | GenOptions.BoxedBaseElevationMin); model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + "_normalsBox.glb")); _logger.LogInformation($"Model exported as {Path.Combine(Directory.GetCurrentDirectory(), modelName + ".gltf")} and .glb"); _logger.LogInformation($"Done in {sw.Elapsed:g}"); } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
static void SpatialTrace_GeometryWithDEMGrid(ElevationService elevationService, IGeoTiffService geoTiffService, string wktBbox, DEMDataSet dataSet) { SpatialTrace.Enable(); DEM.Net.Lib.BoundingBox bbox = null; if (wktBbox != null) { SqlGeometry geom = GeometryService.ParseWKTAsGeometry(wktBbox); SpatialTrace.TraceGeometry(geom, "Bbox"); bbox = geom.ToGeography().STBuffer(60).GetBoundingBox(); //SpatialTrace.Indent("Line Segments"); //int i = 0; //foreach (var seg in geom.Segments()) //{ // i++; // Color color = (i % 2 == 0) ? Colors.Blue : Colors.Red; // SpatialTrace.SetLineColor(color); // SpatialTrace.TraceGeometry(seg, "Seg" + i, "Seg" + i); //} SpatialTrace.Unindent(); } Dictionary <string, DemFileReport> tiles = geoTiffService.GenerateReport(dataSet, bbox); SpatialTrace.Indent("DEM tiles"); SpatialTrace.SetLineColor(Colors.Black); foreach (var tile in tiles) { SpatialTrace.SetFillColor(tile.Value.IsExistingLocally ? Color.FromArgb(128, 0, 255, 0) : Color.FromArgb(128, 255, 0, 0)); SqlGeometry tileBbox = tile.Value.Source.BBox.AsGeomety(); SpatialTrace.TraceGeometry(tileBbox, $"{tile.ToString()}"); } SpatialTrace.Unindent(); // View spatial trace in bin\debug with spatial trace viewer SpatialTrace.ShowDialog(); SpatialTrace.Disable(); }