Exemple #1
0
        /// <summary>
        /// Generate an excel output of all nodes with
        /// - their computed coordinates relative to entry
        /// - their distance from entry
        /// - their distance from the ground surface above them
        /// </summary>
        /// <param name="visualTopoFile"></param>
        /// <param name="dataSet"></param>
        private void Run_ExcelExport(string visualTopoFile, DEMDataSet dataSet)
        {
            try
            {
                StopwatchLog timeLog = StopwatchLog.StartNew(_logger);

                //=======================
                // Generation params
                //
                string outputDir = Directory.GetCurrentDirectory();

                VisualTopoModel model = _visualTopoService.LoadFile(visualTopoFile, Encoding.GetEncoding("ISO-8859-1")
                                                                    , decimalDegrees: true
                                                                    , ignoreRadialBeams: true);

                // for debug,
                //var b = GetBranches(model); // graph list of all nodes
                //var lowestPoint = model.Sets.Min(s => s.Data.Min(d => d.GlobalGeoPoint?.Elevation ?? 0));

                BoundingBox bbox = model.BoundingBox                                                                                  // relative coords
                                   .Translate(model.EntryPoint.Longitude, model.EntryPoint.Latitude, model.EntryPoint.Elevation ?? 0) // absolute coords
                                   .Pad(50)                                                                                           // margin around model
                                   .ReprojectTo(model.SRID, dataSet.SRID);
                _elevationService.DownloadMissingFiles(dataSet, bbox);

                timeLog.LogTime("Terrain height map");

                //=======================
                // Get entry elevation (need to reproject to DEM coordinate system first)
                // and sections entry elevations
                //
                _visualTopoService.ComputeFullCavityElevations(model, dataSet); // will add TerrainElevationAbove and entry elevations


                // CSV
                string csvFileName = Path.GetFileName(Path.ChangeExtension(visualTopoFile, ".csv"));
                File.WriteAllBytes(csvFileName, _visualTopoService.ExportToCsv(model, "\t").ToArray());

                // Excel
                string xlsFileName = Path.GetFileName(Path.ChangeExtension(visualTopoFile, ".xlsx"));

                using (MemoryStream ms = _visualTopoService.ExportToExcel(model, autoFitColumns: false))
                {
                    File.WriteAllBytes(xlsFileName, ms.ToArray());
                }

                timeLog.LogTime("Cavity points elevation");


                timeLog.LogTime("3D model");
            }
            catch (Exception ex)
            {
                _logger.LogError("Error :" + ex.Message);
            }
        }
Exemple #2
0
        /// <summary>
        /// Generates a VisualTopo file 3D model
        /// </summary>
        /// <remarks>LT* (Lambert Carto) projections are not supported and could produce imprecise results (shifted by +10meters)</remarks>
        /// <param name="vtopoFile">VisualTopo .TRO file</param>
        /// <param name="imageryProvider">Imagery provider for terrain texture. Set to null for untextured model</param>
        /// <param name="bboxMarginMeters">Terrain margin (meters) around VisualTopo model</param>
        public void Run_3DModelGeneration(string vtopoFile, ImageryProvider imageryProvider, float bboxMarginMeters = 1000, bool generateTopoOnlyModel = false, float zFactor = 1f)
        {
            try
            {
                //=======================
                // Generation params
                //
                int    outputSRID      = 3857;                         // Output SRID
                float  lineWidth       = 1.0F;                         // Topo lines width (meters)
                var    dataset         = DEMDataSet.AW3D30;            // DEM dataset for terrain and elevation
                int    TEXTURE_TILES   = 8;                            // Texture quality (number of tiles for bigger side) 4: med, 8: high, 12: ultra
                string outputDir       = Directory.GetCurrentDirectory();
                bool   GENERATE_LINE3D = false;

                //=======================
                // Open and parse file
                //
                // model will have available properties
                // => Graph (nodes/arcs)
                // => BoundingBox
                // => Topology3D -> list of point-to-point lines
                // => SRID of model file
                StopwatchLog    timeLog = StopwatchLog.StartNew(_logger);
                VisualTopoModel model   = _visualTopoService.LoadFile(vtopoFile, Encoding.GetEncoding("ISO-8859-1")
                                                                      , decimalDegrees: true
                                                                      , ignoreRadialBeams: true
                                                                      , zFactor);
                timeLog.LogTime($"Loading {vtopoFile} model file");

                // for debug,
                //var b = GetBranches(model); // graph list of all nodes
                //var lowestPoint = model.Sets.Min(s => s.Data.Min(d => d.GlobalGeoPoint?.Elevation ?? 0));

                BoundingBox bbox = model.BoundingBox                                                                                  // relative coords
                                   .Translate(model.EntryPoint.Longitude, model.EntryPoint.Latitude, model.EntryPoint.Elevation ?? 0) // absolute coords
                                   .Pad(bboxMarginMeters)                                                                             // margin around model
                                   .ReprojectTo(model.SRID, dataset.SRID);                                                            // DEM coords
                                                                                                                                      // Get height map
                                                                                                                                      // Note that ref Bbox means that the bbox will be adjusted to match DEM data
                var heightMap        = _elevationService.GetHeightMap(ref bbox, dataset, downloadMissingFiles: true);
                var bboxTerrainSpace = bbox.ReprojectTo(dataset.SRID, outputSRID);                                                    // terrain coords
                timeLog.LogTime("Terrain height map");

                //=======================
                // Get entry elevation (need to reproject to DEM coordinate system first)
                // and sections entry elevations
                //
                _visualTopoService.ComputeFullCavityElevations(model, dataset, zFactor); // will add TerrainElevationAbove and entry elevations
                _visualTopoService.Create3DTriangulation(model);
                timeLog.LogTime("Cavity points elevation");

                // Model origin
                GeoPoint axisOriginWorldSpace = model.EntryPoint.ReprojectTo(model.SRID, outputSRID)
                                                .CenterOnOrigin(bboxTerrainSpace);
                Vector3 axisOriginModelSpace = model.EntryPoint.AsVector3();

                //=======================
                // Local transform function from model coordinates (relative to entry, in meters)
                // and global coordinates absolute in final 3D model space
                //
                IEnumerable <GeoPoint> TransformLine(IEnumerable <GeoPoint> line)
                {
                    var newLine = line.Translate(model.EntryPoint)             // Translate to entry (=> global topo coord space)
                                  .ReprojectTo(model.SRID, outputSRID)         // Reproject to terrain coord space
                                  .CenterOnOrigin(bboxTerrainSpace)            // Center on terrain space origin
                                  .CenterOnOrigin(axisOriginWorldSpace);

                    return(newLine);
                };


                //=======================
                // 3D model
                //
                var gltfModel = _gltfService.CreateNewModel();

                // Add X/Y/Z axis on entry point
                var axis = _meshService.CreateAxis();
                _gltfService.AddMesh(gltfModel, "Axis", axis, doubleSided: false);

                int i = 0;

                var triangulation = model.TriangulationFull3D.Clone()
                                    .Translate(axisOriginModelSpace)             // already zScaled if zFactor > 1
                                    .ReprojectTo(model.SRID, outputSRID)
                                    .CenterOnOrigin(bboxTerrainSpace)
                                    .CenterOnOrigin(axisOriginWorldSpace.AsVector3());
                gltfModel = _gltfService.AddMesh(gltfModel, "Cavite3D", model.TriangulationFull3D, VectorsExtensions.CreateColor(0, 255, 0), doubleSided: false);

                if (GENERATE_LINE3D)
                {
                    foreach (var line in model.Topology3D) // model.Topology3D is the graph of topo paths
                    {
                        // Add line to model
                        gltfModel = _gltfService.AddLine(gltfModel
                                                         , string.Concat("GPX", i++)    // name of 3D node
                                                         , TransformLine(line)          // call transform function
                                                         , color: VectorsExtensions.CreateColor(255, 0, 0, 128)
                                                         , lineWidth);
                    }
                }
                timeLog.LogTime("Topo 3D model");


                //axis = _meshService.CreateAxis(10,100);
                //_gltfService.AddMesh(gltfModel, "Axis", axis, doubleSided: false);

                if (generateTopoOnlyModel)
                {
                    // Uncomment this to save 3D model for topo only (without terrain)
                    gltfModel.SaveGLB(string.Concat(Path.GetFileNameWithoutExtension(vtopoFile) + $"Z{zFactor}_TopoOnly.glb"));
                }

                // Reproject and center height map coordinates
                heightMap = heightMap.ReprojectTo(dataset.SRID, outputSRID)
                            .CenterOnOrigin(bboxTerrainSpace)
                            .ZScale(zFactor)
                            .CenterOnOrigin(axisOriginWorldSpace);
                //.BakeCoordinates();
                timeLog.LogTime("Height map transform");

                //=======================
                // Textures
                //
                PBRTexture pbrTexture = null;
                if (imageryProvider != null)
                {
                    TileRange tiles    = _imageryService.DownloadTiles(bbox, imageryProvider, TEXTURE_TILES);
                    string    fileName = Path.Combine(outputDir, "Texture.jpg");
                    timeLog.LogTime("Imagery download");

                    Console.WriteLine("Construct texture...");
                    //TextureInfo texInfo = _imageryService.ConstructTexture(tiles, bbox, fileName, TextureImageFormat.image_jpeg);
                    var         topoTexture = model.Topology3D.SelectMany(l => l).Translate(model.EntryPoint).ReprojectTo(model.SRID, 4326);
                    TextureInfo texInfo     = _imageryService.ConstructTextureWithGpxTrack(tiles, bbox, fileName, TextureImageFormat.image_jpeg
                                                                                           , topoTexture, false);

                    pbrTexture = PBRTexture.Create(texInfo, null);
                    timeLog.LogTime("Texture creation");
                }
                //
                //=======================

                // Triangulate height map
                _logger.LogInformation($"Triangulating height map and generating 3D mesh...");

                gltfModel = _gltfService.AddTerrainMesh(gltfModel, heightMap, pbrTexture);
                gltfModel.SaveGLB(string.Concat(Path.GetFileNameWithoutExtension(vtopoFile) + $"Z{zFactor}.glb"));
                timeLog.LogTime("3D model");
            }
            catch (Exception ex)
            {
                _logger.LogError("Error :" + ex.Message);
            }
        }
        /// <summary>
        /// Compiles the given <paramref name="buddyText"/> into a TDIL file as string.
        /// </summary>
        /// <param name="buddyText">Buddy language text to compile</param>
        /// <returns>Compiled buddy text</returns>
        /// <exception cref="ArgumentNullException">If the given <paramref name="buddyText"/> is NULL or empty</exception>
        /// <exception cref="BuddyCompilerException">If something went wrong during the compilation process</exception>
        public virtual string Compile(string buddyText)
        {
            if (string.IsNullOrEmpty(buddyText))
            {
                throw new ArgumentNullException(nameof(buddyText));
            }

            StopwatchLog   compilerStopwatch = StopwatchLog.StartNew(LogCompilerPerformance);
            TdilFileWriter tdilFileWriter    = new TdilFileWriter("0.1.2");

            try {
                // TODO Remove workaround add 'Vorbedingung'
                if (!buddyText.Contains("Vorbedingung: -") && buddyText.Contains("Anwendung: "))
                {
                    int insertPoint = buddyText.IndexOf("Schritte:");
                    buddyText = buddyText.Insert(insertPoint, "Vorbedingung: -\r\n\r\n");
                }

                // TODO Remove workaround add final linefeeds
                if (!buddyText.EndsWith("\r\n"))
                {
                    buddyText += "\r\n";
                }

                // Process text
                StopwatchLog  textProcessorStopwatch = StopwatchLog.StartNew(LogBuddyTextProcessorPerformance);
                BuddyTextInfo buddyTextInfo          = _buddyTextProcessor.ProcessText(buddyText);
                textProcessorStopwatch.Dispose(buddyTextInfo);

                // In the case of an short form, create standard names
                if (buddyTextInfo.IsShortForm)
                {
                    buddyTextInfo.ApplicationText = "untitled";
                    buddyTextInfo.UseCaseText     = "untitled";
                    buddyTextInfo.ScenarioText    = "untitled";
                }

                // TODO Check if this is a workaround and remove it
                if (string.IsNullOrEmpty(buddyTextInfo.VersionText))
                {
                    buddyTextInfo.VersionText = "*";
                }

                // Little verification
                ushort expectedNoOfSteps = CalculateNoOfSteps(buddyText);
                if (expectedNoOfSteps != buddyTextInfo.Steps.Length)
                {
                    ThrowUncompilableDirectiveException(buddyText, expectedNoOfSteps, buddyTextInfo.Steps.Length);
                }

                string[] buddyTextSteps = buddyTextInfo.Steps;

                // Normalize directives
                string[] normalizedBuddyTextSteps;
                using (StopwatchLog.StartNew(LogNormalizingPerformance)) {
                    normalizedBuddyTextSteps = NormalizeSteps(buddyTextSteps, buddyTextInfo.Parameters);
                }

                // Create unit name
                UnitName unitName          = new UnitName(buddyTextInfo.ApplicationText, buddyTextInfo.VersionText, buddyTextInfo.UseCaseText, buddyTextInfo.ScenarioText);
                string   qualifiedUnitName = unitName.ToQualifiedString();

                using (CompilingContext compilingContext = new CompilingContext()) {
                    // Compile directives
                    string[] directiveSet = new string[1000];
                    int      pr           = 0;
                    using (StopwatchLog.StartNew(LogInstructionTranslationPerformance)) {
                        for (int i = -1; ++i != normalizedBuddyTextSteps.Length;)
                        {
                            string actionLine = normalizedBuddyTextSteps[i];
                            string directive  = _instructionTranslator.ToDirective(actionLine);
                            directiveSet[pr++] = directive;
                        }
                        Array.Resize(ref directiveSet, pr);
                    }

                    // Add alias references
                    string[] aliasReferenceSet = compilingContext.AliasReferenceSet;
                    tdilFileWriter.AddAlias(aliasReferenceSet);

                    // Add unit references
                    string[] unitReferenceSet   = compilingContext.UnitReferenceSet;
                    string[] qualifiedUnitNames = ToQualifiedUnitNames(unitReferenceSet);
                    tdilFileWriter.AddImport(qualifiedUnitNames);

                    // Write unit
                    using (StopwatchLog.StartNew(LogTdilUnitWritingPerformance)) {
                        using (TdilUnitWriter tdilUnitWriter = tdilFileWriter.CreateUnit(qualifiedUnitName)) {
                            string executeSectionName           = unitName.GetEncodedScenarioName();
                            BuddyTextParameter[] unitParameters = buddyTextInfo.Parameters;
                            string[]             parameterNames = new string[unitParameters.Length];
                            for (int l = -1; ++l != parameterNames.Length;)
                            {
                                parameterNames[l] = unitParameters[l].Name;
                            }

                            // Write main section
                            using (TdilSectionWriter tdilSectionWriter = tdilUnitWriter.CreateSection("Main")) {
                                // Declare parameters
                                for (int i = -1; ++i != unitParameters.Length;)
                                {
                                    BuddyTextParameter unitParameter = unitParameters[i];
                                    tdilSectionWriter.AppendLine("{0} = {1}", unitParameter.Name, unitParameter.DefaultValue);
                                }

                                // Add start statement
                                tdilSectionWriter.AppendLine("start(,, \"{{{0}}}\")", buddyTextInfo.ApplicationText);

                                // Add argument invocation line if there are some
                                string argInvLine = null;
                                if (parameterNames.Length != 0)
                                {
                                    string argSetLine = string.Join(", ", parameterNames);
                                    argInvLine = $"({argSetLine})";
                                }

                                tdilSectionWriter.AppendLine("gosub {0}:{1}", executeSectionName, argInvLine);

                                // Add close statement
                                tdilSectionWriter.AppendLine("close(_Application,, Default)");
                                tdilSectionWriter.AppendLine("kill(_Application,, 3000)");

                                tdilSectionWriter.AppendLine("close(\"AcroRd32\",, Default)");
                                tdilSectionWriter.AppendLine("kill(\"AcroRd32\",, 3000)");
                            }

                            // Write execute section
                            using (TdilSectionWriter tdilSectionWriter = tdilUnitWriter.CreateSection(executeSectionName, parameterNames)) {
                                for (int l = -1; ++l != directiveSet.Length;)
                                {
                                    tdilSectionWriter.AppendLine(directiveSet[l]);
                                }
                            }
                        }
                    }
                }
            } catch (BuddyCompilerException) {
                throw;
            } catch (Exception ex) {
                throw new BuddyCompilerException("Error on compiling buddy language unit.", ex);
            }

            string tdilFileContent = tdilFileWriter.WriteToString();

            compilerStopwatch.Dispose();

            return(tdilFileContent);
        }