public void Test_SubGridTreeBitmapSubGridBitsTests_ForEach_Function() { // Test iteration function for empty, full and arbitrary masks SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); bits.ForEach((x, y) => { return(true); }); Assert.Equal(bits.CountBits(), SubGridTreeConsts.CellsPerSubGrid); bits.Clear(); bits.ForEach((x, y) => { return(x < 16); }); Assert.Equal(bits.CountBits(), SubGridTreeConsts.CellsPerSubGrid / 2); bits.Clear(); bits.ForEach((x, y) => { return((x == 1) && (y == 1)); }); Assert.Equal(1, bits.CountBits()); }
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"); }
public void Test_SubGridTreeBitmapSubGridBitsTests_Clear() { SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled); Assert.True(bits.IsFull(), "Bits not full"); bits.Clear(); Assert.True(bits.IsEmpty(), "Bits not empty after performing a Clear()"); }
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()); }
/// <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_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); }
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 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> /// Computes a filter patch for a sub grid with respect to the alignment and a station/offset range over the alignment. /// Note: This is a CPU intensive operation. TRex currently uses an approach of polygonal spatial filtering with a boundary /// computed from the alignment geometry and station/offset bounds. /// </summary> public override bool ComputeFilterPatch(double startStn, double endStn, double leftOffset, double rightOffset, SubGridTreeBitmapSubGridBits mask, SubGridTreeBitmapSubGridBits patch, double originX, double originY, double cellSize, double offset) { var leftOffsetValue = -leftOffset; var rightOffsetValue = rightOffset; if (leftOffsetValue > rightOffsetValue) { MinMax.Swap(ref leftOffsetValue, ref rightOffsetValue); } // SIGLogMessage.PublishNoODS(Self, Format('Constructing filter patch for Stn:%.3f-%.3f, Ofs:%.3f-%.3f, originX:%.3f, originY:%.3f', // [startStn, endStn, LeftOffsetValue, RightOffsetValue, originX, originY])); if (_data == null) { _log.LogError("No data element provided to SVL filter patch calculation"); return(false); } patch.Clear(); // Check the corners of the sub grid. If all are out of the offset range then assume // none of the cells are applicable. All four corners need to be on the same side of the // alignment in terms of offset to fail the sub grid. var cornersOutOfOffsetRange = 0; var cornersOutOfOffsetRangeSign = 0; var originXPlusHalfCellSize = originX + cellSize / 2; var originYPlusHalfCellSize = originY + cellSize / 2; for (var i = 0; i < _corners.Length; i++) { _data.ComputeStnOfs(originXPlusHalfCellSize + _corners[i].X * cellSize, originYPlusHalfCellSize + _corners[i].Y * cellSize, out var stn, out var ofs); if (!(stn != Consts.NullDouble && ofs != Consts.NullDouble && Range.InRange(stn, startStn, endStn)) && !Range.InRange(ofs, leftOffsetValue, rightOffsetValue)) { if (i == 0) { cornersOutOfOffsetRangeSign = Math.Sign(ofs); } if (cornersOutOfOffsetRangeSign == Math.Sign(ofs)) { cornersOutOfOffsetRange++; } else { break; } } } if (cornersOutOfOffsetRange == _corners.Length) { // Return success with the empty patch //SIGLogMessage.PublishNoODS(Self, 'All corners of patch exceed stn:ofs boundary'); return(true); } // Iterate across the cells in the mask computing and checking the stn:ofs of // each point using the previously successful element as a hint for the next // computation for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++) { for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++) { if (!mask.BitSet(i, j)) { continue; } // Force element to be nil for all calculation until we resolve the issue // of an in appropriate element 'capturing' the focus and then being used to // calculate inappropriate offsets due to it's station range covering the // points being computed. NFFStationedLineworkEntity element = null; _data.ComputeStnOfs(originXPlusHalfCellSize + i * cellSize, originYPlusHalfCellSize + j * cellSize, out var stn, out var ofs, ref element); if (stn != Consts.NullDouble && ofs != Consts.NullDouble) { patch.SetBitValue(i, j, Range.InRange(stn, startStn, endStn) && Range.InRange(ofs, leftOffsetValue, rightOffsetValue)); } } } // SIGLogMessage.PublishNoODS(Self, Format('Filter patch construction successful with %d bits', [patch.CountBits])); return(true); }
/// <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); }
/// <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); }