Ejemplo n.º 1
0
        public void GenerateModel(string bboxWkt, DEMDataSet litto3DDataset, ImageryProvider imageryProvider, float zFactor = 3f, bool withTexture = true, bool withboat = true, bool withWaterSurface = true, DEMDataSet fallbackDataset = null)
        {
            try
            {
                bool   centerOnOrigin = true;
                int    TEXTURE_TILES  = 20;
                string outputDir      = Directory.GetCurrentDirectory();

                string modelName = $"{litto3DDataset.ResolutionMeters}m_z{zFactor}_{imageryProvider.Name}-{DateTime.Now:yyyyMMdd-hhmmss}";

                _logger.LogInformation($"Getting height map data...");


                var bbox      = GeometryService.GetBoundingBox(bboxWkt).ReprojectTo(4326, litto3DDataset.SRID);
                var heightMap = _elevationService.GetHeightMap(ref bbox, litto3DDataset);

                heightMap = heightMap.BakeCoordinates();
                var nullCoordsEnumerator = heightMap.Coordinates.Where(c => (c.Elevation ?? litto3DDataset.NoDataValue) == litto3DDataset.NoDataValue);

                var interpolator = _elevationService.GetInterpolator(InterpolationMode.Bilinear);
                using (IRasterFile raster = _rasterService.OpenFile(@"D:\Data\ELEVATION_DO_NOT_DELETE\GEBCO2020\cote azur\gebco_2020_subset.tif", DEMFileType.GEOTIFF))
                    using (RasterFileDictionary dic = new RasterFileDictionary())
                    {
                        var metadata = raster.ParseMetaData(fallbackDataset.FileFormat);
                        dic.Add(metadata, raster);
                        foreach (var pt in nullCoordsEnumerator)
                        {
                            var proj = pt.ReprojectTo(litto3DDataset.SRID, fallbackDataset.SRID);
                            pt.Elevation = _elevationService.GetElevationAtPoint(raster, dic, metadata, proj.Latitude, proj.Longitude, 0, interpolator, NoDataBehavior.UseNoDataDefinedInDem);
                        }
                    }

                var nullCoords              = heightMap.Coordinates.Where(c => (c.Elevation ?? litto3DDataset.NoDataValue) == litto3DDataset.NoDataValue).ToList();
                var nullCoordsFallbackProj  = nullCoords.ReprojectTo(litto3DDataset.SRID, fallbackDataset.SRID, nullCoords.Count);
                var nullCoordsFallbackProj2 = _elevationService.GetPointsElevation(nullCoordsFallbackProj, fallbackDataset, InterpolationMode.Bilinear, NoDataBehavior.UseNoDataDefinedInDem);

                ModelGenerationTransform transform         = new ModelGenerationTransform(bbox, 3857, centerOnOrigin: centerOnOrigin, zFactor, centerOnZOrigin: false);
                ModelGenerationTransform transformFrom4326 = new ModelGenerationTransform(bbox.ReprojectTo(2154, 4326), 3857, centerOnOrigin: centerOnOrigin, zFactor, centerOnZOrigin: false);

                _logger.LogInformation($"Processing height map data ({heightMap.Count} coordinates)...");
                heightMap = transform.TransformHeightMap(heightMap);

                var min = heightMap.Coordinates.Where(g => (g.Elevation ?? 0d) > litto3DDataset.NoDataValue).Min(g => g.Elevation ?? 0d);
                heightMap.Coordinates = heightMap.Coordinates.Select(p =>
                {
                    if (p.Elevation.GetValueOrDefault(0) <= litto3DDataset.NoDataValue)
                    {
                        p.Elevation = min;
                    }
                    return(p);
                });

                //=======================
                // Textures
                //
                PBRTexture pbrTexture = null;
                if (withTexture)
                {
                    var bbox4326 = bbox.ReprojectTo(2154, 4326);
                    Console.WriteLine("Download image tiles...");
                    TileRange tiles    = _imageryService.DownloadTiles(bbox4326, imageryProvider, TEXTURE_TILES);
                    string    fileName = Path.Combine(outputDir, "Texture.jpg");

                    Console.WriteLine("Construct texture...");
                    //TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox4326, fileName, TextureImageFormat.image_jpeg);

                    TextureInfo texInfo;
                    if (withboat)
                    {
                        var trackPoints = GetGeoPointFromGeoJson(BoatCourseGeoJson);
                        texInfo = _imageryService.ConstructTextureWithGpxTrack(tiles, bbox4326, fileName, TextureImageFormat.image_jpeg, trackPoints, drawGpxVertices: true, color: SixLabors.ImageSharp.PixelFormats.Rgba32.Green, 30);
                    }
                    else
                    {
                        texInfo = _imageryService.ConstructTexture(tiles, bbox4326, 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);// normalMap);

                    //hMap = hMap.CenterOnOrigin(Z_FACTOR);
                    //
                    //=======================
                }
                // Triangulate height map
                // and add base and sides
                _logger.LogInformation($"Triangulating height map and generating 3D mesh...");

                heightMap = heightMap.BakeCoordinates();
                var coords = heightMap.Coordinates.ToList();

                var model = _sharpGltfService.CreateTerrainMesh(heightMap, pbrTexture);



                if (withWaterSurface)
                {
                    var bottomLeft  = coords[heightMap.Width * (heightMap.Height - 1)].AsVector3(); bottomLeft.Z = 0;
                    var topRight    = coords[heightMap.Width - 1].AsVector3(); topRight.Z = 0;
                    var topLeft     = coords[0].AsVector3(); topLeft.Z = 0;
                    var bottomRight = coords.Last().AsVector3(); bottomRight.Z = 0;

                    var waterSurface = _meshService.CreateWaterSurface(bottomLeft, topRight, topLeft, bottomRight,
                                                                       minZ: (float)min,
                                                                       color: VectorsExtensions.CreateColor(0, 150, 255, 64));
                    model = _sharpGltfService.AddMesh(model, "Water", waterSurface, doubleSided: true);
                }

                if (withboat)
                {
                    var boatInitPos = centerOnOrigin ? new GeoPoint(0, 0).AsVector3() : new GeoPoint(43.010625204304304, 6.3711613671060086).ReprojectTo(4326, 3857).AsVector3();
                    var axis        = _meshService.CreateAxis(2, 10, 3, 3).Translate(boatInitPos);
                    model = _sharpGltfService.AddMesh(model, "Boat", axis, doubleSided: false);
                    var boatCourse = transformFrom4326.TransformPoints(GetGeoPointFromGeoJson(BoatCourseGeoJson)).ToList(); //ReprojectGeodeticToCartesian().CenterOnOrigin().ToList();
                    model = _sharpGltfService.AddLine(model, "BoatCourse", boatCourse, VectorsExtensions.CreateColor(255, 0, 0, 128), 4);
                }



                model.SaveGLB(Path.Combine(Directory.GetCurrentDirectory(), modelName + ".glb"));



                _logger.LogInformation($"Model exported as {Path.Combine(Directory.GetCurrentDirectory(), modelName + ".gltf")} and .glb");

                //var point = new GeoPoint(43.01142119356318, 6.385200681010872).ReprojectTo(4326, 2154);
                //point = _elevationService.GetPointElevation(point, litto3DDataset);
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
            }
        }