public void Test_SubGridTreeBitmapSubGridBitsTests_ClearBit() { // Test setting a bit on and off, at two corners to test boundary conditions SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); bits.SetBit(0, 0); Assert.NotEqual(0U, bits.Bits[0]); Assert.Equal(1, bits.CountBits()); bits.ClearBit(0, 0); Assert.Equal(0U, bits.Bits[0]); Assert.Equal(0, bits.CountBits()); bits.SetBit(31, 31); Assert.NotEqual(0U, bits.Bits[31]); Assert.Equal(1, bits.CountBits()); bits.ClearBit(31, 31); Assert.Equal(0U, bits.Bits[31]); Assert.Equal(0, bits.CountBits()); }
public void Test_SubGridTreeBitmapSubGridBitsTests_Serialisation_Arbitrary() { // Test serialisation with arbitrary bits set SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); bits.SetBit(0, 0); bits.SetBit(10, 10); bits.SetBit(20, 20); bits.SetBit(31, 31); MemoryStream ms = new MemoryStream(Consts.TREX_DEFAULT_MEMORY_STREAM_CAPACITY_ON_CREATION); BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8, true); bits.Write(bw); BinaryReader br = new BinaryReader(ms, Encoding.UTF8, true); ms.Position = 0; SubGridTreeBitmapSubGridBits bits2 = SubGridTreeBitmapSubGridBits.FullMask; bits2.Read(br); Assert.True(bits.Equals(bits2), "Bits not equal after serialisation with arbitrary mask"); Assert.Equal(4, bits.CountBits()); }
private static void PerformScan(double siteModelCellSize, FilteredValueAssignmentContext assignmentContext, SubGridTreeBitmapSubGridBits sieveBitmask, int numRowsToScan, int numColsToScan, double stepNorthX, double stepNorthY, double stepEastX, double stepEastY, double subGridMinX, double subGridMinY, double firstScanPointEast, double firstScanPointNorth) { // Skip-Iterate through the cells marking those cells that require values // calculated for them in the bitmask. Also record the actual probe locations // that determined the cells to be processed. for (var I = 0; I < numRowsToScan; I++) { var currentNorth = firstScanPointNorth + I * stepNorthY; var currentEast = firstScanPointEast + I * stepNorthX; for (var J = 0; J < numColsToScan; J++) { var eastCol = (int)Math.Floor((currentEast - subGridMinX) / siteModelCellSize); var northRow = (int)Math.Floor((currentNorth - subGridMinY) / siteModelCellSize); if (Range.InRange(eastCol, 0, SubGridTreeConsts.SubGridTreeDimensionMinus1) && Range.InRange(northRow, 0, SubGridTreeConsts.SubGridTreeDimensionMinus1)) { sieveBitmask.SetBit(eastCol, northRow); assignmentContext.ProbePositions[eastCol, northRow] .SetOffsets((float)(currentEast - subGridMinX), (float)(currentNorth - subGridMinY)); } currentEast += stepEastX; currentNorth += stepEastY; } } }
public void Test_SubGridTreeBitmapSubGridBitsTests_ForEach_Action() { // Test iteration action for empty, full and arbitrary masks SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); int sum; sum = 0; bits.ForEach((x, y) => { if (bits.BitSet(x, y)) { sum++; } }); Assert.True(sum == bits.CountBits() && sum == SubGridTreeConsts.CellsPerSubGrid, "Summation via ForEach on full mask did not give expected result"); sum = 0; bits.Clear(); bits.ForEach((x, y) => { if (bits.BitSet(x, y)) { sum++; } }); Assert.True(sum == bits.CountBits() && sum == 0, "Summation via ForEach on empty mask did not give expected result"); sum = 0; bits.SetBit(1, 1); bits.ForEach((x, y) => { if (bits.BitSet(x, y)) { sum++; } }); Assert.True(sum == bits.CountBits() && sum == 1, "Summation via ForEach on mask with single bit set at (1, 1) did not give expected result"); }
/// <summary> /// Constructs a mask using polygonal and positional spatial filtering aspects of a filter. /// </summary> private static void ConstructSubGridSpatialAndPositionalMask(SubGridCellAddress currentSubGridOrigin, InterceptList intercepts, int fromProfileCellIndex, SubGridTreeBitmapSubGridBits mask, ICellSpatialFilter cellFilter, ISubGridTree subGridTree) { var cellFilterHasSpatialOrPositionalFilters = cellFilter.HasSpatialOrPositionalFilters; var interceptsCount = intercepts.Count; mask.Clear(); for (var interceptIdx = fromProfileCellIndex; interceptIdx < interceptsCount; interceptIdx++) { // Determine the on-the-ground cell underneath the midpoint of each cell on the intercept line subGridTree.CalculateIndexOfCellContainingPosition(intercepts.Items[interceptIdx].MidPointX, intercepts.Items[interceptIdx].MidPointY, out var otgCellX, out var otgCellY); var thisSubGridOrigin = new SubGridCellAddress(otgCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, otgCellY & ~SubGridTreeConsts.SubGridLocalKeyMask); if (!currentSubGridOrigin.Equals(thisSubGridOrigin)) { break; } var cellX = otgCellX & SubGridTreeConsts.SubGridLocalKeyMask; var cellY = otgCellY & SubGridTreeConsts.SubGridLocalKeyMask; if (cellFilterHasSpatialOrPositionalFilters) { subGridTree.GetCellCenterPosition(otgCellX, otgCellY, out var cellCenterX, out var cellCenterY); if (cellFilter.IsCellInSelection(cellCenterX, cellCenterY)) { mask.SetBit(cellX, cellY); } } else { mask.SetBit(cellX, cellY); } } }
public void Test_SubGridTreeBitmapSubGridBitsTests_CountBits() { SubGridTreeBitmapSubGridBits bits = SubGridTreeBitmapSubGridBits.FullMask; Assert.Equal(bits.CountBits(), SubGridTreeConsts.CellsPerSubGrid); bits.Clear(); Assert.Equal(0, bits.CountBits()); bits.SetBit(1, 1); Assert.Equal(1, bits.CountBits()); }
private static void ConstructSubGridSpatialAndPositionalMask(ISubGridTree tree, SubGridCellAddress currentSubGridOrigin, List <T> profileCells, SubGridTreeBitmapSubGridBits mask, int fromProfileCellIndex, ICellSpatialFilter cellFilter) { mask.Clear(); // From current position to end... for (var cellIdx = fromProfileCellIndex; cellIdx < profileCells.Count; cellIdx++) { var profileCell = profileCells[cellIdx]; var thisSubGridOrigin = new SubGridCellAddress( profileCell.OTGCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, profileCell.OTGCellY & ~SubGridTreeConsts.SubGridLocalKeyMask); if (!currentSubGridOrigin.Equals(thisSubGridOrigin)) { break; } var cellX = (byte)(profileCell.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask); var cellY = (byte)(profileCell.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask); if (cellFilter.HasSpatialOrPositionalFilters) { tree.GetCellCenterPosition(profileCell.OTGCellX, profileCell.OTGCellY, out var cellCenterX, out var cellCenterY); if (cellFilter.IsCellInSelection(cellCenterX, cellCenterY)) { mask.SetBit(cellX, cellY); } } else { mask.SetBit(cellX, cellY); } } }
public void Test_SubGridTreeBitmapSubGridBitsTests_Operators_OR() { SubGridTreeBitmapSubGridBits bits1 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); SubGridTreeBitmapSubGridBits bits2 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); Assert.Equal((bits1 | bits2), bits1); bits1.ClearBit(1, 1); Assert.Equal((bits1 | bits2), bits1); bits2.SetBit(1, 1); Assert.True((bits1 | bits2).IsFull(), "ORing after clearing/setting bits did not return full mask"); }
public void Test_SubGridTreeBitmapSubGridBitsTests_Operators_XOR() { SubGridTreeBitmapSubGridBits bits1 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); SubGridTreeBitmapSubGridBits bits2 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); Assert.True((bits1 ^ bits1).IsEmpty(), "XORing bits with self did not result in empty mask"); Assert.Equal(bits1, (bits1 ^ bits2)); Assert.True((bits1 ^ bits2).IsFull(), "XORing an empty mask with a full mask did not produce a full mask"); bits2.SetBit(1, 1); Assert.True((bits1 ^ bits1).IsEmpty(), "XORing single bit with itself did not clear bit"); Assert.False((bits1 ^ bits1).BitSet(1, 1), "XORing single bit with itself did not clear bit"); }
/// <summary> /// Gets the production data values for the requested cell /// </summary> private async Task GetProductionData(ISiteModel siteModel, IDesignWrapper cutFillDesign, CellDatumResponse_ClusterCompute result, CellDatumRequestArgument_ClusterCompute arg) { var existenceMap = siteModel.ExistenceMap; var utilities = DIContext.Obtain <IRequestorUtilities>(); var requestors = utilities.ConstructRequestors(null, siteModel, arg.Overrides, arg.LiftParams, utilities.ConstructRequestorIntermediaries(siteModel, arg.Filters, true, GridDataType.CellProfile), AreaControlSet.CreateAreaControlSet(), existenceMap); // Get the sub grid relative cell location int cellX = arg.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask; int cellY = arg.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask; // Reach into the sub-grid request layer and retrieve an appropriate sub-grid var cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); cellOverrideMask.SetBit(cellX, cellY); requestors[0].CellOverrideMask = cellOverrideMask; // using the cell address get the index of cell in clientGrid var thisSubGridOrigin = new SubGridCellAddress(arg.OTGCellX, arg.OTGCellY); var requestSubGridInternalResult = requestors[0].RequestSubGridInternal(thisSubGridOrigin, true, true); if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError) { if (requestSubGridInternalResult.requestResult == ServerRequestResult.SubGridNotFound) { result.ReturnCode = CellDatumReturnCode.NoValueFound; } else { Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {requestSubGridInternalResult.requestResult}"); } return; } var cell = ((ClientCellProfileLeafSubgrid)requestSubGridInternalResult.clientGrid).Cells[cellX, cellY]; if (cell.PassCount > 0) // Cell is not in our areaControlSet... { await ExtractRequiredValue(cutFillDesign, cell, result, arg); result.TimeStampUTC = cell.LastPassTime; } }
public void Test_SubGridTreeBitmapSubGridBitsTests_ComputeCellsExtents() { // Test extents for empty, full and arbitrary masks SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); BoundingIntegerExtent2D boundsFull = bits.ComputeCellsExtents(); Assert.True(boundsFull.Equals(new BoundingIntegerExtent2D(0, 0, SubGridTreeConsts.SubGridTreeDimensionMinus1, SubGridTreeConsts.SubGridTreeDimensionMinus1)), "ComputeCellsExtents is incorrect for full grid"); bits.Clear(); BoundingIntegerExtent2D boundsClear = bits.ComputeCellsExtents(); Assert.False(boundsClear.IsValidExtent, "ComputeCellsExtents is incorrect for clear grid"); bits.SetBit(1, 1); BoundingIntegerExtent2D bounds11 = bits.ComputeCellsExtents(); Assert.True(bounds11.Equals(new BoundingIntegerExtent2D(1, 1, 1, 1)), "ComputeCellsExtents is incorrect for grid with bit set at (1, 1)"); }
public void Test_SubGridTreeBitmapSubGridBitsTests_ForEachClearBit() { // Test iteration action for empty, full and arbitrary masks SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); int sum; sum = 0; bits.ForEachClearBit((x, y) => { sum++; }); Assert.Equal(0, sum); sum = 0; bits.Clear(); bits.ForEachClearBit((x, y) => { sum++; }); Assert.Equal(sum, SubGridTreeConsts.CellsPerSubGrid); sum = 0; bits.SetBit(1, 1); bits.ForEachClearBit((x, y) => { sum++; }); Assert.Equal(sum, SubGridTreeConsts.CellsPerSubGrid - 1); }
public static void ConstructSubgridSpatialAndPositionalMask(ILeafSubGrid SubGridAsLeaf, ISiteModel SiteModel, ICombinedFilter Filter, bool AHasOverrideSpatialCellRestriction, BoundingIntegerExtent2D AOverrideSpatialCellRestriction, SubGridTreeBitmapSubGridBits PDMask, SubGridTreeBitmapSubGridBits FilterMask) { if (Filter == null || !Filter.SpatialFilter.HasSpatialOrPositionalFilters) { PDMask.Fill(); FilterMask.Fill(); return; } var originX = SubGridAsLeaf.OriginX; var originY = SubGridAsLeaf.OriginY; var cellSize = SiteModel.CellSize; // Get the world location of the origin position SiteModel.Grid.GetCellCenterPosition(originX, originY, out var OX, out var OY); var SpatialFilter = Filter.SpatialFilter; // Attempt to satisfy the calculation below on the basis of the sub grid wholly residing in the override and filter spatial restrictions if (SpatialFilter.Fence.IncludesExtent(new BoundingWorldExtent3D(OX, OY, OX + cellSize * SubGridTreeConsts.SubGridTreeDimension, OY + cellSize * SubGridTreeConsts.SubGridTreeDimension))) { // The extent of the sub grid is wholly contained in the filter, therefore there is no need to iterate though all the cells // individually... FilterMask.Fill(); // ... unless there is an override spatial cell restriction that does not enclose the extent of the sub grid if (AHasOverrideSpatialCellRestriction && !AOverrideSpatialCellRestriction.Encloses(new BoundingIntegerExtent2D((int)originX, (int)originY, (int)originX + SubGridTreeConsts.SubGridTreeDimension, (int)originY + SubGridTreeConsts.SubGridTreeDimension))) { for (byte I = 0; I < SubGridTreeConsts.SubGridTreeDimension; I++) { for (byte J = 0; J < SubGridTreeConsts.SubGridTreeDimension; J++) { if (!AOverrideSpatialCellRestriction.Includes(originX + I, originY + J)) { FilterMask.ClearBit(I, J); } } } } } else { // Perform the calculation the long hand way // ... Idea: Invert row and column order of calculation below to get and set bits based on an entire column of bits FilterMask.Clear(); // Construct the filter mask based on the spatial and location (square/circle/polygonal) filtering double CX = OX; for (byte I = 0; I < SubGridTreeConsts.SubGridTreeDimension; I++) { int OriginXPlusI = originX + I; double CY = OY; // Set to the first row in the column about to be processed for (byte J = 0; J < SubGridTreeConsts.SubGridTreeDimension; J++) { if (AHasOverrideSpatialCellRestriction && !AOverrideSpatialCellRestriction.Includes((int)OriginXPlusI, (int)(originY + J))) { // Do nothing } else { // SiteModel.Grid.GetCellCenterPosition(OriginXPlusI, originY + J, out CX, out CY); if (SpatialFilter.IsCellInSelection(CX, CY)) { FilterMask.SetBit(I, J); } } CY += cellSize; // Move to next row } CX += cellSize; // Move to next column } } }
/// <summary> /// For each point in the list, get the sub grid and extract productionData at the station/offset i.e pointOfInterest /// This could be optimized to get any poi from each sub grid before disposal /// </summary> private StationOffsetReportRequestResponse_ClusterCompute GetProductionData() { var result = new StationOffsetReportRequestResponse_ClusterCompute { ResultStatus = RequestErrorStatus.Unknown }; IDesignWrapper cutFillDesignWrapper = null; if (requestArgument.ReferenceDesign != null && requestArgument.ReferenceDesign.DesignID != Guid.Empty) { var cutFillDesign = siteModel.Designs.Locate(requestArgument.ReferenceDesign.DesignID); if (cutFillDesign == null) { throw new ArgumentException($"Design {requestArgument.ReferenceDesign.DesignID} not a recognized design in project {requestArgument.ProjectID}"); } cutFillDesignWrapper = new DesignWrapper(requestArgument.ReferenceDesign, cutFillDesign); } var existenceMap = siteModel.ExistenceMap; var utilities = DIContext.Obtain <IRequestorUtilities>(); var requestors = utilities.ConstructRequestors(null, siteModel, requestArgument.Overrides, requestArgument.LiftParams, utilities.ConstructRequestorIntermediaries(siteModel, requestArgument.Filters, true, GridDataType.CellProfile), AreaControlSet.CreateAreaControlSet(), existenceMap); // Obtain the primary partition map to allow this request to determine the elements it needs to process bool[] primaryPartitionMap = ImmutableSpatialAffinityPartitionMap.Instance().PrimaryPartitions(); SubGridTreeBitmapSubGridBits cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); foreach (var point in requestArgument.Points) { // Determine the on-the-ground cell siteModel.Grid.CalculateIndexOfCellContainingPosition(point.Easting, point.Northing, out int OTGCellX, out int OTGCellY); var thisSubGridOrigin = new SubGridCellAddress(OTGCellX, OTGCellY); if (!primaryPartitionMap[thisSubGridOrigin.ToSpatialPartitionDescriptor()]) { continue; } // Get the sub grid relative cell location int cellX = OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask; int cellY = OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask; // Reach into the sub-grid request layer and retrieve an appropriate sub-grid cellOverrideMask.Clear(); cellOverrideMask.SetBit(cellX, cellY); requestors[0].CellOverrideMask = cellOverrideMask; // using the cell address get the index of cell in clientGrid var requestSubGridInternalResult = requestors[0].RequestSubGridInternal( thisSubGridOrigin, true, true); if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError) { Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {result}"); result.StationOffsetRows.Add(new StationOffsetRow(point.Station, point.Offset, point.Northing, point.Easting)); continue; } var hydratedPoint = ExtractRequiredValues(cutFillDesignWrapper, point, requestSubGridInternalResult.clientGrid as ClientCellProfileLeafSubgrid, cellX, cellY); result.StationOffsetRows.Add(hydratedPoint); } result.ResultStatus = RequestErrorStatus.OK; return(result); }
/// <summary> /// Executor that implements requesting and rendering sub grid information to create the cell datum /// </summary> public async Task <CellPassesResponse> ExecuteAsync(CellPassesRequestArgument_ClusterCompute arg, SubGridSpatialAffinityKey key) { Log.LogInformation($"Performing Execute for DataModel:{arg.ProjectID}"); var result = new CellPassesResponse { ReturnCode = CellPassesReturnCode.Error }; var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID); if (siteModel == null) { Log.LogError($"Failed to locate site model {arg.ProjectID}"); return(result); } var existenceMap = siteModel.ExistenceMap; var utilities = DIContext.Obtain <IRequestorUtilities>(); var requestors = utilities.ConstructRequestors(null, siteModel, arg.Overrides, arg.LiftParams, utilities.ConstructRequestorIntermediaries(siteModel, arg.Filters, true, GridDataType.CellPasses), AreaControlSet.CreateAreaControlSet(), existenceMap); // Get the sub grid relative cell location var cellX = arg.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask; var cellY = arg.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask; // Reach into the sub-grid request layer and retrieve an appropriate sub-grid var cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); cellOverrideMask.SetBit(cellX, cellY); requestors[0].CellOverrideMask = cellOverrideMask; var thisSubGridOrigin = new SubGridCellAddress(arg.OTGCellX, arg.OTGCellY); var requestSubGridInternalResult = requestors[0].RequestSubGridInternal(thisSubGridOrigin, true, true); if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError) { if (requestSubGridInternalResult.requestResult == ServerRequestResult.SubGridNotFound) { result.ReturnCode = CellPassesReturnCode.NoDataFound; } else { Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {requestSubGridInternalResult.requestResult}"); } return(result); } if (!(requestSubGridInternalResult.clientGrid is ClientCellProfileAllPassesLeafSubgrid grid)) { Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed due the grid return type being incorrect. Expected {typeof(ClientCellProfileAllPassesLeafSubgrid).Name}, but got {requestSubGridInternalResult.clientGrid.GetType().Name}"); return(result); } var cell = grid.Cells[cellX, cellY]; if (cell.TotalPasses > 0) { result.ReturnCode = CellPassesReturnCode.DataFound; for (var idx = 0; idx < cell.TotalPasses; idx++) { var cellPass = cell.CellPasses[idx]; result.CellPasses.Add(cellPass); } } else { result.ReturnCode = CellPassesReturnCode.NoDataFound; } return(result); }
/// <summary> /// Computes a bitmask used to sieve out only the cells that will be used in the query context. /// The sieved cells are the only cells processed and returned. All other cells will be null values, /// even if data is present for them that matches filtering and other conditions /// </summary> /// <param name="subGridMoniker"></param> /// <param name="areaControlSet"></param> /// <param name="siteModelCellSize"></param> /// <param name="sieveBitmask"></param> /// <param name="subGridWorldOriginX"></param> /// <param name="subGridWorldOriginY"></param> /// <returns></returns> public static bool ComputeSieveBitmaskInteger(double subGridWorldOriginX, double subGridWorldOriginY, string subGridMoniker, AreaControlSet areaControlSet, double siteModelCellSize, out SubGridTreeBitmapSubGridBits sieveBitmask) { const int kMaxStepSize = 10000; sieveBitmask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); /* TODO - add configuration item for VLPDPSNode_UseSkipStepComputationForWMSSubGridRequests * if (!VLPDSvcLocations.VLPDPSNode_UseSkipStepComputationForWMSSubGridRequests) * return false; */ if (areaControlSet.PixelXWorldSize < siteModelCellSize && areaControlSet.PixelYWorldSize < siteModelCellSize) { return(false); } // Progress through the cells in the grid, starting from the southern most // row in the grid and progressing from the western end to the eastern end // (ie: bottom to top, left to right) ///////////////// CalculateParameters; START double stepsPerPixelX = areaControlSet.PixelXWorldSize / siteModelCellSize; double stepsPerPixelY = areaControlSet.PixelYWorldSize / siteModelCellSize; // Note: integers int stepX = Math.Min(kMaxStepSize, Math.Max(1, (int)Math.Truncate(stepsPerPixelX))); int stepY = Math.Min(kMaxStepSize, Math.Max(1, (int)Math.Truncate(stepsPerPixelY))); double stepXIncrement = stepX * siteModelCellSize; double stepYIncrement = stepY * siteModelCellSize; double stepXIncrementOverTwo = stepXIncrement / 2; double stepYIncrementOverTwo = stepYIncrement / 2; ///////////////// CalculateParameters; END if (stepX < 2 && stepY < 2) { return(false); } if (stepX >= SubGridTreeConsts.SubGridTreeDimension && stepY >= SubGridTreeConsts.SubGridTreeDimension) { Log.LogDebug($"Skip value of {stepX}/{stepY} chosen for {subGridMoniker}"); } sieveBitmask.Clear(); // Calculate the world coordinate location of the origin (bottom left corner) of this sub grid //subGrid.CalculateWorldOrigin(out double subGridWorldOriginX, out double subGridWorldOriginY); // Skip-Iterate through the cells marking those cells that require values // calculate for them in the bitmask double temp = subGridWorldOriginY / stepYIncrement; double currentNorth = (Math.Truncate(temp) * stepYIncrement) - stepYIncrementOverTwo; int northRow = (int)Math.Floor((currentNorth - subGridWorldOriginY) / siteModelCellSize); while (northRow < 0) { northRow += stepY; } while (northRow < SubGridTreeConsts.SubGridTreeDimension) { temp = subGridWorldOriginX / stepXIncrement; double currentEast = (Math.Truncate(temp) * stepXIncrement) - stepXIncrementOverTwo; int eastCol = (int)Math.Floor((currentEast - subGridWorldOriginX) / siteModelCellSize); while (eastCol < 0) { eastCol += stepX; } while (eastCol < SubGridTreeConsts.SubGridTreeDimension) { sieveBitmask.SetBit(eastCol, northRow); eastCol += stepX; } northRow += stepY; } return(true); }
public void ProcessElevationInformationForSubGrid(int cellOriginX, int cellOriginY, float[,] baseSubGrid, float[,] topSubGrid) { // FCellArea is a handy place to store the cell area, rather than calculate it all the time (value wont change); var cellArea = CellSize * CellSize; var bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); CellsScanned += SubGridTreeConsts.SubGridTreeCellsPerSubGrid; for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++) { for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++) { var topZ = topSubGrid[i, j]; var baseZ = baseSubGrid[i, j]; if (baseZ != Consts.NullHeight && topZ != Consts.NullHeight) { CellsUsed++; // Note the fact we have processed this cell in the coverage map bits.SetBit(i, j); var cellUsedInVolumeCalc = (topZ - baseZ >= FillTolerance) || (baseZ - topZ >= CutTolerance); // Accumulate volumes if (cellUsedInVolumeCalc) { var volumeDifference = cellArea * (topZ - baseZ); // Accumulate the 'surplus' volume. Ie: the simple summation of // all cuts and fills. Volume += volumeDifference; // Accumulate the cuts and fills into discrete cut and fill quantities if (topZ < baseZ) { CellsUsedCut++; CutFillVolume.AddCutVolume(Math.Abs(volumeDifference)); } else { CellsUsedFill++; CutFillVolume.AddFillVolume(Math.Abs(volumeDifference)); } } else { // Note the fact there was no volume change in this cell // NoChangeMap.Cells[BaseScanSubGrid.OriginX + I, BaseScanSubGrid.OriginY + J] := True; } } else { CellsDiscarded++; } } } // Record the bits for this sub grid in the coverage map by requesting the whole sub grid // of bits from the leaf level and setting it in one operation under an exclusive lock if (!bits.IsEmpty()) { var coverageMapSubGrid = CoverageMap.ConstructPathToCell(cellOriginX, cellOriginY, SubGridPathConstructionType.CreateLeaf); ((SubGridTreeLeafBitmapSubGrid)coverageMapSubGrid).Bits = bits; } }
protected void ProcessVolumeInformationForSubGrid(ClientHeightLeafSubGrid baseScanSubGrid, ClientHeightLeafSubGrid topScanSubGrid) { _log.LogDebug("In ProcessVolumeInformationForSubGrid"); try { // DesignHeights represents all the valid spot elevations for the cells in the // sub grid being processed (IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult profilerRequestResult)getDesignHeightsResult = (null, DesignProfilerRequestResult.UnknownError); // FCellArea is a handy place to store the cell area, rather than calculate it all the time (value wont change); var cellArea = CellSize * CellSize; // Query the patch of elevations from the surface model for this sub grid if (ActiveDesign?.Design != null) { _log.LogDebug("About to call ActiveDesign.Design.GetDesignHeightsViaLocalCompute()"); getDesignHeightsResult = ActiveDesign.Design.GetDesignHeightsViaLocalCompute(SiteModel, ActiveDesign.Offset, baseScanSubGrid.OriginAsCellAddress(), CellSize); if (getDesignHeightsResult.profilerRequestResult != DesignProfilerRequestResult.OK && getDesignHeightsResult.profilerRequestResult != DesignProfilerRequestResult.NoElevationsInRequestedPatch) { _log.LogError($"Design profiler sub grid elevation request for {baseScanSubGrid.OriginAsCellAddress()} failed with error {getDesignHeightsResult.profilerRequestResult}"); return; } } var bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); // ReSharper disable once CompareOfFloatsByEqualityOperator var standardVolumeProcessing = LiftParams.TargetLiftThickness == Consts.NullHeight || LiftParams.TargetLiftThickness <= 0; var localCellsScanned = 0; var localCellsUsed = 0; var localCellsDiscarded = 0; var localCellsUsedCut = 0; var localCellsUsedFill = 0; var localVolume = 0.0d; var localCutFillVolume = new CutFillVolume(0, 0); // If we are interested in standard volume processing use this cycle if (standardVolumeProcessing) { localCellsScanned += SubGridTreeConsts.SubGridTreeCellsPerSubGrid; for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++) { for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++) { float topZ; var baseZ = baseScanSubGrid.Cells[i, j]; // If the user has configured a first pass thickness, then we need to subtract this height // difference from the BaseZ retrieved from the current cell if this measured height was // the first pass made in the cell. if (LiftParams.FirstPassThickness > 0) { baseZ -= LiftParams.FirstPassThickness; } if (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.BetweenDesignAndFilter) { topZ = getDesignHeightsResult.designHeights?.Cells[i, j] ?? Consts.NullHeight; if (VolumeType == VolumeComputationType.BetweenDesignAndFilter) { MinMax.Swap(ref baseZ, ref topZ); } } else { topZ = topScanSubGrid.Cells[i, j]; } switch (VolumeType) { case VolumeComputationType.None: break; case VolumeComputationType.AboveLevel: { // ReSharper disable once CompareOfFloatsByEqualityOperator if (baseZ != Consts.NullHeight) { localCellsUsed++; if (baseZ > BaseLevel) { localVolume += cellArea * (baseZ - BaseLevel); } } else { localCellsDiscarded++; } break; } case VolumeComputationType.Between2Levels: { // ReSharper disable once CompareOfFloatsByEqualityOperator if (baseZ != Consts.NullHeight) { localCellsUsed++; if (baseZ > BaseLevel) { localVolume += cellArea * (baseZ < TopLevel ? (baseZ - BaseLevel) : (TopLevel - BaseLevel)); } } else { localCellsDiscarded++; } break; } case VolumeComputationType.AboveFilter: case VolumeComputationType.Between2Filters: case VolumeComputationType.BetweenFilterAndDesign: case VolumeComputationType.BetweenDesignAndFilter: { // ReSharper disable once CompareOfFloatsByEqualityOperator if (baseZ != Consts.NullHeight && // ReSharper disable once CompareOfFloatsByEqualityOperator topZ != Consts.NullHeight) { localCellsUsed++; // Note the fact we have processed this cell in the coverage map bits.SetBit(i, j); var cellUsedInVolumeCalc = (topZ - baseZ >= FillTolerance) || (baseZ - topZ >= CutTolerance); // Accumulate volumes if (cellUsedInVolumeCalc) { var volumeDifference = cellArea * (topZ - baseZ); // Accumulate the 'surplus' volume. Ie: the simple summation of // all cuts and fills. localVolume += volumeDifference; // Accumulate the cuts and fills into discrete cut and fill quantities if (topZ < baseZ) { localCellsUsedCut++; localCutFillVolume.AddCutVolume(Math.Abs(volumeDifference)); } else { localCellsUsedFill++; localCutFillVolume.AddFillVolume(Math.Abs(volumeDifference)); } } else { // Note the fact there was no volume change in this cell // NoChangeMap.Cells[BaseScanSubGrid.OriginX + I, BaseScanSubGrid.OriginY + J] := True; } } else { localCellsDiscarded++; } } break; default: _log.LogError($"Unknown volume type {VolumeType} in ProcessVolumeInformationForSubGrid()"); break; } } } } // ReSharper disable once CompareOfFloatsByEqualityOperator var targetLiftThicknessCalculationsRequired = LiftParams.TargetLiftThickness != Consts.NullHeight && LiftParams.TargetLiftThickness > 0; //If we are interested in thickness calculations do them if (targetLiftThicknessCalculationsRequired) { var belowToleranceToCheck = LiftParams.TargetLiftThickness - LiftParams.BelowToleranceLiftThickness; var aboveToleranceToCheck = LiftParams.TargetLiftThickness + LiftParams.AboveToleranceLiftThickness; SubGridUtilities.SubGridDimensionalIterator((i, j) => { var baseZ = baseScanSubGrid.Cells[i, j]; var topZ = topScanSubGrid.Cells[i, j]; // ReSharper disable once CompareOfFloatsByEqualityOperator if (baseZ != Consts.NullHeight || // ReSharper disable once CompareOfFloatsByEqualityOperator topZ != Consts.NullHeight) { localCellsScanned++; } //Test if we don't have NULL values and carry on // ReSharper disable once CompareOfFloatsByEqualityOperator if (baseZ != Consts.NullHeight && // ReSharper disable once CompareOfFloatsByEqualityOperator topZ != Consts.NullHeight) { bits.SetBit(i, j); double elevationDiff = topZ - baseZ; if (elevationDiff <= aboveToleranceToCheck && elevationDiff >= belowToleranceToCheck) { localCellsUsed++; } else if (elevationDiff > aboveToleranceToCheck) { localCellsUsedFill++; } else if (elevationDiff < belowToleranceToCheck) { localCellsUsedCut++; } } else { localCellsDiscarded++; } }); } // Update the quantities in the aggregator proper // Note: the lock is not asynchronous as this will be highly non-contended _lock.Wait(); try { CellsScanned += localCellsScanned; CellsUsed += localCellsUsed; CellsDiscarded += localCellsDiscarded; CellsUsedCut += localCellsUsedCut; CellsUsedFill += localCellsUsedFill; Volume += localVolume; CutFillVolume.AddCutFillVolume(localCutFillVolume.CutVolume, localCutFillVolume.FillVolume); // Record the bits for this sub grid in the coverage map by requesting the whole sub grid // of bits from the leaf level and setting it in one operation under an exclusive lock if (!bits.IsEmpty()) { var coverageMapSubGrid = CoverageMap.ConstructPathToCell(baseScanSubGrid.OriginX, baseScanSubGrid.OriginY, SubGridPathConstructionType.CreateLeaf); ((SubGridTreeLeafBitmapSubGrid)coverageMapSubGrid).Bits = bits; } } finally { _lock.Release(); } } catch (Exception e) { _log.LogError(e, "Exception thrown by ProcessVolumeInformationForSubGrid - rethrowing"); throw; } finally { _log.LogDebug("Out ProcessVolumeInformationForSubGrid"); } }
/// <summary> /// Builds a fully analyzed vector of profiled cells from the list of cell passed to it /// </summary> public override bool Analyze(List <SummaryVolumeProfileCell> profileCells, ISubGridSegmentCellPassIterator cellPassIterator) { Log.LogDebug($"Analyze Summary Volume ProfileCells. Processing {profileCells.Count}"); var CurrentSubgridOrigin = new SubGridCellAddress(int.MaxValue, int.MaxValue); ISubGrid SubGrid = null; IServerLeafSubGrid _SubGridAsLeaf = null; profileCell = null; // Construct the set of requestors to query elevation sub grids needed for the summary volume calculations. var filterSet = FilterUtilities.ConstructFilters(FilterSet, VolumeType); IntermediaryFilterRequired = filterSet.Filters.Length == 3; var utilities = DIContext.Obtain <IRequestorUtilities>(); Requestors = utilities.ConstructRequestors(null, SiteModel, Overrides, LiftParams, utilities.ConstructRequestorIntermediaries(SiteModel, filterSet, true, GridDataType.HeightAndTime), AreaControlSet.CreateAreaControlSet(), PDExistenceMap); var cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); for (int I = 0; I < profileCells.Count; I++) { profileCell = profileCells[I]; // get sub grid origin for cell address var thisSubgridOrigin = new SubGridCellAddress(profileCell.OTGCellX >> SubGridTreeConsts.SubGridIndexBitsPerLevel, profileCell.OTGCellY >> SubGridTreeConsts.SubGridIndexBitsPerLevel); if (!CurrentSubgridOrigin.Equals(thisSubgridOrigin)) // if we have a new sub grid to fetch { // if we have an existing sub grid and a change in sub grid detected process the current sub grid profile cell list if (SubGrid != null) { ProcessSubGroup(new SubGridCellAddress(CurrentSubgridOrigin.X << SubGridTreeConsts.SubGridIndexBitsPerLevel, CurrentSubgridOrigin.Y << SubGridTreeConsts.SubGridIndexBitsPerLevel), PDExistenceMap[CurrentSubgridOrigin.X, CurrentSubgridOrigin.Y], cellOverrideMask); cellOverrideMask.Clear(); } SubGrid = null; cellCounter = 0; // Does the sub grid tree contain this node in it's existence map? if so get sub grid if (PDExistenceMap[thisSubgridOrigin.X, thisSubgridOrigin.Y]) { SubGrid = SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining (SiteModel.PrimaryStorageProxy, SiteModel.Grid, profileCell.OTGCellX, profileCell.OTGCellY, SiteModel.Grid.NumLevels, false, false); } _SubGridAsLeaf = SubGrid as ServerSubGridTreeLeaf; if (_SubGridAsLeaf == null) { continue; } CurrentSubgridOrigin = thisSubgridOrigin; // all good to proceed with this sub grid } profileCellList[cellCounter++] = profileCell; // add cell to list to process for this sub grid cellOverrideMask.SetBit(profileCell.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask, profileCell.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask); } if (cellCounter > 0 && SubGrid != null) // Make sure we process last list { ProcessSubGroup(new SubGridCellAddress(CurrentSubgridOrigin.X << SubGridTreeConsts.SubGridIndexBitsPerLevel, CurrentSubgridOrigin.Y << SubGridTreeConsts.SubGridIndexBitsPerLevel), PDExistenceMap[CurrentSubgridOrigin.X, CurrentSubgridOrigin.Y], cellOverrideMask); } return(true); }