Beispiel #1
0
        public void Execute_DualSurveyedSurfaces_DifferingInTime(SurveyedSurfacePatchType patchType, GridDataType expectedGridType)
        {
            AddApplicationGridRouting();

            var asAtDate  = DateTime.UtcNow;
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();

            // Construct a surveyed surface from the design
            DITAGFileAndSubGridRequestsWithIgniteFixture.ConstructSingleFlatTriangleSurveyedSurfaceAboutOrigin(ref siteModel, 1.0f, asAtDate);
            DITAGFileAndSubGridRequestsWithIgniteFixture.ConstructSingleFlatTriangleSurveyedSurfaceAboutOrigin(ref siteModel, 1.0f, asAtDate.AddMinutes(1));

            var filteredSurveyedSurfaces = new TRex.SurveyedSurfaces.SurveyedSurfaces();

            siteModel.SurveyedSurfaces.FilterSurveyedSurfaceDetails(false, Consts.MIN_DATETIME_AS_UTC, Consts.MIN_DATETIME_AS_UTC,
                                                                    false, filteredSurveyedSurfaces, new Guid[0]);

            var req    = new SurfaceElevationPatchRequestViaLocalCompute();
            var result = req.Execute(new SurfaceElevationPatchArgument(siteModel.ID, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                                                                       siteModel.CellSize, patchType, SubGridTreeBitmapSubGridBits.FullMask, filteredSurveyedSurfaces));

            ValidateSurveyedSurfaceSuGridResult(siteModel, expectedGridType, patchType, result);

            if (expectedGridType == GridDataType.HeightAndTime)
            {
                // Check the times on the result cells are correct
                result.ForEach((x, y) =>
                {
                    if (((ClientHeightAndTimeLeafSubGrid)result).Cells[x, y] != Consts.NullHeight)
                    {
                        ((ClientHeightAndTimeLeafSubGrid)result).Times[x, y].Should().Be
                            (patchType == SurveyedSurfacePatchType.EarliestSingleElevation ? asAtDate.Ticks : asAtDate.AddMinutes(1).Ticks);
                    }
                });
            }
        }
Beispiel #2
0
        public void Execute_FailWithNonExistentDesignReference(SurveyedSurfacePatchType patchType)
        {
            AddApplicationGridRouting();

            var asAtDate  = DateTime.UtcNow;
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();

            // Construct a surveyed surface from the design
            DITAGFileAndSubGridRequestsWithIgniteFixture.ConstructSingleFlatTriangleSurveyedSurfaceAboutOrigin(ref siteModel, 1.0f, asAtDate);

            // Delete the second surveyed surface TTM file from both it's original location and the project temporary folder
            string fileToDelete = siteModel.SurveyedSurfaces[0].DesignDescriptor.FullPath;

            File.Exists(fileToDelete).Should().BeTrue();
            File.Delete(fileToDelete);
            File.Exists(fileToDelete).Should().BeFalse();

            fileToDelete = Path.Combine(FilePathHelper.GetTempFolderForProject(siteModel.ID), siteModel.SurveyedSurfaces[0].DesignDescriptor.FileName);
            File.Exists(fileToDelete).Should().BeTrue();
            File.Delete(fileToDelete);
            File.Exists(fileToDelete).Should().BeFalse();

            var req    = new SurfaceElevationPatchRequestViaLocalCompute();
            var result = req.Execute(new SurfaceElevationPatchArgument(siteModel.ID, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                                                                       siteModel.CellSize, patchType, SubGridTreeBitmapSubGridBits.FullMask, siteModel.SurveyedSurfaces));

            result.Should().BeNull();
        }
Beispiel #3
0
        public void Execute_SingleSurveyedSurface_WithSpatialCaching(SurveyedSurfacePatchType patchType, GridDataType expectedGridType)
        {
            AddApplicationGridRouting();

            var asAtDate  = DateTime.UtcNow;
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();

            // Construct a surveyed surface from the design
            DITAGFileAndSubGridRequestsWithIgniteFixture.ConstructSingleFlatTriangleSurveyedSurfaceAboutOrigin(ref siteModel, 1.0f, asAtDate);

            var cache   = new TRexSpatialMemoryCache(100, 10000, 0.5);
            var context = cache.LocateOrCreateContext(siteModel.ID, expectedGridType, $"Execute_SingleSurveyedSurface_WithSpatialCaching-{patchType}", TimeSpan.FromHours(1));
            var req     = new SurfaceElevationPatchRequestViaLocalCompute(cache, context);

            // Make one call which will populate the cache
            var result = req.Execute(new SurfaceElevationPatchArgument(siteModel.ID, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                                                                       siteModel.CellSize, patchType, SubGridTreeBitmapSubGridBits.FullMask, siteModel.SurveyedSurfaces));

            ValidateSurveyedSurfaceSuGridResult(siteModel, expectedGridType, patchType, result);

            // Make a second call which will utilise the value in the cache
            var result2 = req.Execute(new SurfaceElevationPatchArgument(siteModel.ID, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                                                                        siteModel.CellSize, patchType, SubGridTreeBitmapSubGridBits.FullMask, siteModel.SurveyedSurfaces));

            ValidateSurveyedSurfaceSuGridResult(siteModel, expectedGridType, patchType, result2);

            result.Should().BeEquivalentTo(result2);
        }
Beispiel #4
0
        public async Task Execute_SingleSurveyedSurfaceAsync(SurveyedSurfacePatchType patchType, GridDataType expectedGridType)
        {
            AddApplicationGridRouting();

            var asAtDate  = DateTime.UtcNow;
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();

            // Construct a surveyed surface from the design
            DITAGFileAndSubGridRequestsWithIgniteFixture.ConstructSingleFlatTriangleSurveyedSurfaceAboutOrigin(ref siteModel, 1.0f, asAtDate);

            var req    = new SurfaceElevationPatchRequestViaLocalCompute();
            var result = await req.ExecuteAsync(new SurfaceElevationPatchArgument(siteModel.ID, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                                                                                  siteModel.CellSize, patchType, SubGridTreeBitmapSubGridBits.FullMask, siteModel.SurveyedSurfaces));

            ValidateSurveyedSurfaceSuGridResult(siteModel, expectedGridType, patchType, result);
        }
Beispiel #5
0
        /// <summary>
        /// Constructor taking the full state of the surface patch computation operation
        /// </summary>
        public SurfaceElevationPatchArgument(Guid siteModelID,
                                             int oTGCellBottomLeftX,
                                             int oTGCellBottomLeftY,
                                             double cellSize,
                                             SurveyedSurfacePatchType surveyedSurfacePatchType,
                                             SubGridTreeBitmapSubGridBits processingMap,
                                             ISurveyedSurfaces includedSurveyedSurfaces)
        {
            SiteModelID              = siteModelID;
            OTGCellBottomLeftX       = oTGCellBottomLeftX;
            OTGCellBottomLeftY       = oTGCellBottomLeftY;
            CellSize                 = cellSize;
            SurveyedSurfacePatchType = surveyedSurfacePatchType;
            ProcessingMap            = processingMap == null ? new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled) : new SubGridTreeBitmapSubGridBits(processingMap);

            // Prepare the list of surveyed surfaces for use by all invocations using this argument
            includedSurveyedSurfaces?.SortChronologically(surveyedSurfacePatchType == SurveyedSurfacePatchType.LatestSingleElevation);
            IncludedSurveyedSurfaces = includedSurveyedSurfaces?.Select(x => x.ID).ToArray() ?? new Guid[0];
        }
Beispiel #6
0
        private void ValidateSurveyedSurfaceSuGridResult(ISiteModel siteModel, GridDataType expectedGridType,
                                                         SurveyedSurfacePatchType patchType, IClientLeafSubGrid result)
        {
            result.Should().NotBeNull();
            result.CellSize.Should().Be(siteModel.CellSize);
            result.IndexOriginOffset.Should().Be(SubGridTreeConsts.DefaultIndexOriginOffset);
            result.Level.Should().Be(SubGridTreeConsts.SubGridTreeLevels);
            result.WorldExtents().Should().BeEquivalentTo(new BoundingWorldExtent3D(0, 0, SubGridTreeConsts.SubGridTreeDimension * siteModel.CellSize, SubGridTreeConsts.SubGridTreeDimension * siteModel.CellSize));

            result.GridDataType.Should().Be(expectedGridType);
            if (patchType == SurveyedSurfacePatchType.EarliestSingleElevation || patchType == SurveyedSurfacePatchType.LatestSingleElevation)
            {
                result.Should().BeOfType <ClientHeightAndTimeLeafSubGrid>();
            }
            else
            {
                result.Should().BeOfType <ClientCompositeHeightsLeafSubgrid>();
            }

            result.CountNonNullCells().Should().Be(903);
        }
Beispiel #7
0
        /// <summary>
        /// Performs the donkey work of the elevation patch calculation
        /// </summary>
        public IClientLeafSubGrid Execute(ISiteModel siteModel, int otgCellBottomLeftX, int otgCellBottomLeftY, double cellSize, SurveyedSurfacePatchType patchType,
                                          Guid[] includedSurveyedSurfaces, IDesignFiles designs, ISurveyedSurfaces surveyedSurfaces, SubGridTreeBitmapSubGridBits processingMap)
        {
            var calcResult = DesignProfilerRequestResult.UnknownError;

            try
            {
                if (!Enum.IsDefined(typeof(SurveyedSurfacePatchType), patchType))
                {
                    _log.LogError($"Unknown SurveyedSurfacePatchType: {patchType}, returning null");
                    return(null);
                }

                if (includedSurveyedSurfaces == null)
                {
                    _log.LogError("Included surveyed surfaces list is null, returning null");
                    return(null);
                }

                if (processingMap == null)
                {
                    _log.LogError("Supplied processing map is null, returning null");
                    return(null);
                }

                var patch = _clientLeafSubGridFactory.GetSubGridEx(
                    patchType == SurveyedSurfacePatchType.CompositeElevations ? GridDataType.CompositeHeights : GridDataType.HeightAndTime,
                    cellSize, SubGridTreeConsts.SubGridTreeLevels,
                    otgCellBottomLeftX, otgCellBottomLeftY);

                // Assign
                var patchSingle = patchType != SurveyedSurfacePatchType.CompositeElevations
          ? patch as ClientHeightAndTimeLeafSubGrid
          : null;

                var patchComposite = patchType == SurveyedSurfacePatchType.CompositeElevations
          ? patch as ClientCompositeHeightsLeafSubgrid
          : null;

                patch.CalculateWorldOrigin(out var originX, out var originY);

                var halfCellSize            = cellSize / 2;
                var originXPlusHalfCellSize = originX + halfCellSize;
                var originYPlusHalfCellSize = originY + halfCellSize;

                // Work down through the list of surfaces in the time ordering provided by the caller
                foreach (var surveyedSurfaceUid in includedSurveyedSurfaces)
                {
                    if (processingMap.IsEmpty())
                    {
                        break;
                    }

                    var thisSurveyedSurface = surveyedSurfaces.Locate(surveyedSurfaceUid);
                    if (thisSurveyedSurface == null)
                    {
                        _log.LogError($"Surveyed surface {surveyedSurfaceUid} not found in site model, returning null");
                        calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                        return(null);
                    }

                    // Lock & load the design
                    var design = designs.Lock(thisSurveyedSurface.DesignDescriptor.DesignID, siteModel, cellSize, out _);

                    if (design == null)
                    {
                        _log.LogError($"Failed to lock design file {thisSurveyedSurface.DesignDescriptor} in {nameof(CalculateSurfaceElevationPatch)}");
                        calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                        return(null);
                    }

                    try
                    {
                        if (!design.HasElevationDataForSubGridPatch(
                                otgCellBottomLeftX >> SubGridTreeConsts.SubGridIndexBitsPerLevel,
                                otgCellBottomLeftY >> SubGridTreeConsts.SubGridIndexBitsPerLevel))
                        {
                            continue;
                        }

                        var asAtDate = thisSurveyedSurface.AsAtDate.Ticks;
                        var hint     = -1;

                        // Walk across the sub grid checking for a design elevation for each appropriate cell
                        // based on the processing bit mask passed in
                        processingMap.ForEachSetBit((x, y) =>
                        {
                            // If we can interpolate a height for the requested cell, then update the cell height
                            // and decrement the bit count so that we know when we've handled all the requested cells

                            if (design.InterpolateHeight(ref hint,
                                                         originXPlusHalfCellSize + cellSize * x, originYPlusHalfCellSize + cellSize * y,
                                                         0, out var z))
                            {
                                // Check for composite elevation processing
                                if (patchType == SurveyedSurfacePatchType.CompositeElevations)
                                {
                                    // Set the first elevation if not already set
                                    if (patchComposite.Cells[x, y].FirstHeightTime == 0)
                                    {
                                        patchComposite.Cells[x, y].FirstHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].FirstHeight     = (float)z;
                                    }

                                    // Always set the latest elevation (surfaces ordered by increasing date)
                                    patchComposite.Cells[x, y].LastHeightTime = asAtDate;
                                    patchComposite.Cells[x, y].LastHeight     = (float)z;

                                    // Update the lowest height
                                    if (patchComposite.Cells[x, y].LowestHeightTime == 0 ||
                                        patchComposite.Cells[x, y].LowestHeight > z)
                                    {
                                        patchComposite.Cells[x, y].LowestHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].LowestHeight     = (float)z;
                                    }

                                    // Update the highest height
                                    if (patchComposite.Cells[x, y].HighestHeightTime == 0 ||
                                        patchComposite.Cells[x, y].HighestHeight > z)
                                    {
                                        patchComposite.Cells[x, y].HighestHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].HighestHeight     = (float)z;
                                    }
                                }
                                else // earliest/latest singular value processing
                                {
                                    patchSingle.Times[x, y] = asAtDate;
                                    patchSingle.Cells[x, y] = (float)z;
                                }
                            }

                            // Only clear the processing bit if earliest or latest information is wanted from the surveyed surfaces
                            if (patchType != SurveyedSurfacePatchType.CompositeElevations)
                            {
                                processingMap.ClearBit(x, y);
                            }

                            return(true);
                        });
                    }
                    finally
                    {
                        designs.UnLock(thisSurveyedSurface.DesignDescriptor.DesignID, design);
                    }
                }

                calcResult = DesignProfilerRequestResult.OK;

                return(patch);
            }
            catch (Exception e)
            {
                _log.LogError(e, $"Exception occurred calculating surveyed surface patch, calcResult = {calcResult}");
                return(null);
            }
        }
Beispiel #8
0
        public IClientLeafSubGrid ExtractFromCachedItem(IClientLeafSubGrid cachedItem, SubGridTreeBitmapSubGridBits map, SurveyedSurfacePatchType patchType)
        {
            var resultItem = _clientLeafSubGridFactory.GetSubGridEx
                                 (patchType == SurveyedSurfacePatchType.CompositeElevations ? GridDataType.CompositeHeights : GridDataType.HeightAndTime,
                                 cachedItem.CellSize, cachedItem.Level, cachedItem.OriginX, cachedItem.OriginY);

            resultItem.AssignFromCachedPreProcessedClientSubGrid(cachedItem, map);

            return(resultItem);
        }
Beispiel #9
0
        /// <summary>
        /// Constructor that accepts the common parameters around a set of sub grids the requester will be asked to process
        /// and initializes the requester state ready to start processing individual sub grid requests.
        /// </summary>
        public void Initialize(ISubGridsRequestArgument subGridsRequestArgument,
                               ISiteModel siteModel,
                               GridDataType gridDataType,
                               IStorageProxy storageProxy,
                               ICombinedFilter filter,
                               bool hasOverrideSpatialCellRestriction,
                               BoundingIntegerExtent2D overrideSpatialCellRestriction,
                               int maxNumberOfPassesToReturn,
                               AreaControlSet areaControlSet,
                               IFilteredValuePopulationControl populationControl,
                               ISubGridTreeBitMask pdExistenceMap,
                               ITRexSpatialMemoryCache subGridCache,
                               ITRexSpatialMemoryCacheContext[] subGridCacheContexts,
                               ISurveyedSurfaces filteredSurveyedSurfaces,
                               ISurfaceElevationPatchRequest surfaceElevationPatchRequest,
                               IOverrideParameters overrides,
                               ILiftParameters liftParams)
        {
            _siteModel    = siteModel;
            _gridDataType = gridDataType;
            _filter       = filter;

            _hasOverrideSpatialCellRestriction = hasOverrideSpatialCellRestriction;
            _overrideSpatialCellRestriction    = overrideSpatialCellRestriction;

            _retriever = DIContext.Obtain <ISubGridRetrieverFactory>().Instance(subGridsRequestArgument,
                                                                                siteModel,
                                                                                gridDataType,
                                                                                storageProxy,
                                                                                filter,
                                                                                _filterAnnex,
                                                                                hasOverrideSpatialCellRestriction,
                                                                                overrideSpatialCellRestriction,
                                                                                maxNumberOfPassesToReturn,
                                                                                areaControlSet,
                                                                                populationControl,
                                                                                pdExistenceMap,
                                                                                subGridCacheContexts,
                                                                                overrides,
                                                                                liftParams);

            _returnEarliestFilteredCellPass = _filter.AttributeFilter.ReturnEarliestFilteredCellPass;
            _processingMap = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            _surfaceElevationPatchRequest = surfaceElevationPatchRequest;

            _subGridCache         = subGridCache;
            _subGridCacheContexts = subGridCacheContexts;

            _surveyedSurfacePatchType = _filter.AttributeFilter.ReturnEarliestFilteredCellPass ? SurveyedSurfacePatchType.EarliestSingleElevation : SurveyedSurfacePatchType.LatestSingleElevation;

            _filteredSurveyedSurfaces = filteredSurveyedSurfaces;
            _filteredSurveyedSurfaces?.SortChronologically(_surveyedSurfacePatchType == SurveyedSurfacePatchType.LatestSingleElevation);
            _filteredSurveyedSurfacesAsGuidArray = _filteredSurveyedSurfaces?.Select(x => x.ID).ToArray() ?? new Guid[0];

            var elevRangeDesignFilter = _filter.AttributeFilter.ElevationRangeDesign;

            if (elevRangeDesignFilter.DesignID != Guid.Empty)
            {
                var design = _siteModel.Designs.Locate(elevRangeDesignFilter.DesignID);
                if (design == null)
                {
                    _log.LogError($"ElevationRangeDesign {elevRangeDesignFilter.DesignID} is unknown in project {siteModel.ID}");
                }
                else
                {
                    _elevationRangeDesign = new DesignWrapper(elevRangeDesignFilter, design);
                }
            }

            if (_filter.SpatialFilter.IsDesignMask)
            {
                _surfaceDesignMaskDesign = _siteModel.Designs.Locate(_filter.SpatialFilter.SurfaceDesignMaskDesignUid);
            }

            _filter.AttributeFilter.SiteModel = _siteModel;
        }