Beispiel #1
0
        /// <summary>
        /// Creates a demo tile. Useful for development
        /// </summary>
        /// <returns></returns>
        private bool BuildDemoTile()
        {
            _log.LogDebug($"#Tile.({TileX},{TileY}) Returning demo tile. (X:{TileX}, Y:{TileX},{TileY}, Z:{TileZ}), GridSize{QMConstants.DemoResolutionGridSize}");
            // Even empty tiles must have header info correctly calculated
            if (ElevData.GridSize == QMConstants.NoGridSize)
            {
                ElevData = new ElevationData(LowestElevation, QMConstants.DemoResolutionGridSize); // elevation grid
            }
            ElevData.MakeDemoTile(TileBoundaryLL);

            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = ElevData,
                GridSize = ElevData.GridSize
            };

            if (!tileBuilder.BuildQuantizedMeshTile())
            {
                _log.LogError($"Tile.({TileX},{TileY}) failed to build demo tile. Error code: {tileBuilder.BuildTileFaultCode}");
                return(false);
            }

            QMTileResponse.ResultStatus = RequestErrorStatus.OK;
            QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // return QM tile in response
            ResultStatus = RequestErrorStatus.OK;
            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// No data so return an empty tile
        /// </summary>
        /// <returns></returns>
        private bool BuildEmptyTile()
        {
            _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning empty tile. Zoom:{TileZ}, GridSize{QMConstants.FlatResolutionGridSize}");
            // Even empty tiles must have header info correctly calculated
            if (ElevData.GridSize == QMConstants.NoGridSize)
            {
                ElevData = new ElevationData(LowestElevation, QMConstants.FlatResolutionGridSize); // elevation grid
            }
            ElevData.MakeEmptyTile(TileBoundaryLL, HasLighting);
            if (ElevData.HasLighting)
            {
                ComputeNormalMap();
            }

            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = ElevData,
                GridSize = ElevData.GridSize
            };

            if (!tileBuilder.BuildQuantizedMeshTile())
            {
                _log.LogError($"Tile.({TileX},{TileY}) failed to build empty tile. Error code: {tileBuilder.BuildTileFaultCode}");
                return(false);
            }

            QMTileResponse.ResultStatus = RequestErrorStatus.OK;
            QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // return QM tile in response
            ResultStatus = RequestErrorStatus.OK;
            return(true);
        }
Beispiel #3
0
        public void TileBuilder_BuildTile()
        {
            LLBoundingBox TileBoundaryLL = MapGeo.TileXYZToRectLL(0, 0, 20, out var yFlip);
            ElevationData elevData       = new ElevationData(0, 5);

            elevData.MakeEmptyTile(TileBoundaryLL, false);
            QMTileBuilder tileBuilder = new QMTileBuilder()
            {
                TileData = elevData,
                GridSize = elevData.GridSize
            };

            var res = tileBuilder.BuildQuantizedMeshTile();

            res.Should().Be(true);
            tileBuilder.QuantizedMeshTile.Should().HaveCountGreaterOrEqualTo(162);
            tileBuilder.QuantizedMeshTile.Should().HaveCountLessOrEqualTo(164);
        }
Beispiel #4
0
        /// <summary>
        /// Executor that implements requesting and rendering grid information to create the grid rows
        /// </summary>
        /// <returns></returns>
        public async Task <bool> ExecuteAsync()
        {
            // Get the lat lon boundary from xyz tile request
            TileBoundaryLL = MapGeo.TileXYZToRectLL(TileX, TileY, TileZ, out var yFlip);
            _log.LogInformation($"#Tile#.({TileX},{TileY}) Execute Start.  DMode:{DisplayMode}, HasLighting:{HasLighting}, Zoom:{TileZ} FlipY:{yFlip}. TileBoundary:{TileBoundaryLL.ToDisplay()}, DataModel:{DataModelUid}");

            if (TileZ == 0) // Send back default root tile
            {
                MakeRootTile();
                return(true);
            }

            SiteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(DataModelUid);
            if (SiteModel == null)
            {
                ResultStatus = RequestErrorStatus.NoSuchDataModel;
                _log.LogError($"Tile.({TileX},{TileY}) Failed to obtain site model for {DataModelUid}");
                return(false);
            }

            var siteModelExtentWithSurveyedSurfaces = SiteModel.GetAdjustedDataModelSpatialExtents(null);

            _log.LogDebug($"Tile.({TileX},{TileY}) Site model extents are {siteModelExtentWithSurveyedSurfaces}. TileBoundary:{TileBoundaryLL.ToDisplay()}");
            if (!siteModelExtentWithSurveyedSurfaces.IsValidPlanExtent) // No data return empty tile
            {
                return(BuildEmptyTile());
            }

            // We will draw all missing data just below lowest elevation for site
            LowestElevation = (float)siteModelExtentWithSurveyedSurfaces.MinZ - 1F;

            Initialise();                                           // setup tile requirements

            if (TileGridSize == QMConstants.FlatResolutionGridSize) // Too far out to see detail so return empty tile
            {
                return(BuildEmptyTile());
            }

            if (DisplayMode == QMConstants.DisplayModeDemo) // development use only
            {
                return(BuildDemoTile());
            }

            try
            {
                var setupResult = await SetupPipelineTask(siteModelExtentWithSurveyedSurfaces, SiteModel.CellSize);

                if (!setupResult)
                {
                    if (ResultStatus != RequestErrorStatus.InvalidCoordinateRange)
                    {
                        _log.LogError($"Tile.({TileX},{TileY}) Unable to setup pipelinetask.");
                    }
                    return(BuildEmptyTile());
                }

                processor.Process();

                if (GriddedElevationsResponse.ResultStatus != RequestErrorStatus.OK)
                {
                    _log.LogError($"Tile.({TileX},{TileY}) Unable to obtain data for gridded data. GriddedElevationRequestResponse: {GriddedElevationsResponse.ResultStatus.ToString()}");
                    return(BuildEmptyTile());
                }

                ElevData.HasData = !float.IsPositiveInfinity(task.MinElevation); // check for data

                // Developer Debugging Only
                if (ElevData.HasData)
                {
                    OutputDebugTile("Raw");
                }

                if (!ElevData.HasData)
                {
                    return(BuildEmptyTile());
                }

                _log.LogInformation($"#Tile#.({TileX},{TileY}) Data successfully sampled. GridSize:{TileGridSize} Min:{task.MinElevation}, Max:{task.MaxElevation} FirstElev:{GriddedElevDataArray[0, 0].Elevation}, LastElev:{GriddedElevDataArray[TileGridSize - 1, TileGridSize - 1].Elevation}");

                ElevData.HasLighting = HasLighting;
                // Transform gridded data into a format the mesh builder can use
                ConvertGridToDEM(task.MinElevation, task.MaxElevation);

                // Build a quantized mesh from sampled elevations
                QMTileBuilder tileBuilder = new QMTileBuilder()
                {
                    TileData = ElevData, GridSize = TileGridSize
                };
                _log.LogInformation($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile. GridSize:{TileGridSize} Min:{ElevData.MinimumHeight}, Max:{ElevData.MaximumHeight}");
                if (!tileBuilder.BuildQuantizedMeshTile())
                {
                    _log.LogError($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile returned false with error code: {tileBuilder.BuildTileFaultCode}");
                    return(false);
                }

                QMTileResponse.data         = tileBuilder.QuantizedMeshTile; // Make tile from mesh
                ResultStatus                = RequestErrorStatus.OK;
                QMTileResponse.ResultStatus = ResultStatus;
                _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning production tile. CesiumY:{yFlip}, Zoom:{TileZ}, GridSize:{TileGridSize}");

                return(true);
            }
            catch (Exception ex)
            {
                _log.LogError(ex, $"#Tile#.({TileX},{TileY}). Exception building QuantizedMesh tile: ");
                return(false);
            }
        }