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); } }); } }
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(); }
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); }
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); }
/// <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]; }
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); }
/// <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); } }
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); }
/// <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; }