private void DoSomethingWithAddressAsStruct(SubGridCellAddress address) { if (address.X == 123456 || address.Y == 45678) { Console.WriteLine("Ooops!"); } }
public static string GetLeafSubGridFullFileName(SubGridCellAddress cellAddress) { // Work out the cell address of the origin cell in the appropriate leaf // sub grid. We use this cell position to derive the name of the file // containing the leaf sub grid data return(ServerSubGridTreeLeaf.FileNameFromOriginPosition(new SubGridCellAddress(cellAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask, cellAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask))); }
/// <summary> /// Calculates a filter mask for a designated sub grid on this design /// </summary> public (SubGridTreeBitmapSubGridBits filterMask, DesignProfilerRequestResult errorCode) GetFilterMaskViaLocalCompute( ISiteModelBase siteModel, SubGridCellAddress originCellAddress, double cellSize) { // Calculate an elevation patch for the requested location and convert it into a bitmask detailing which cells have non-null values var patch = _designElevationCalculator.Execute(siteModel, new DesignOffset(DesignDescriptor.DesignID, 0), cellSize, originCellAddress.X, originCellAddress.Y, out var calcResult); if (patch == null) { _log.LogWarning($"Request for design elevation patch that does not exist: Project: {siteModel.ID}, design {DesignDescriptor.DesignID}, location {originCellAddress.X}:{originCellAddress.Y}, calcResult: {calcResult}"); return(null, calcResult); // Requestors should not ask for sub grids that don't exist in the design. } var mask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); var patchCells = patch.Cells; for (byte i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++) { for (byte j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++) { if (patchCells[i, j].Equals(Common.Consts.NullHeight)) { mask[i, j] = true; } } } return(mask, calcResult); }
public void Test_SubgridCellAddress_ToNormalisedInt64() { SubGridCellAddress ca = new SubGridCellAddress(1, 1); long correct = (1L << 32) | 1; Assert.Equal(ca.ToNormalisedInt64, correct); }
/// <summary> /// Cleaves all dirty segments requiring cleaving within the given sub grid /// </summary> public void PerformSegmentCleaving(IStorageProxy storageProxyForSubGridSegments, IServerLeafSubGrid subGrid, int subGridSegmentPassCountLimit = 0) { var iterator = new SubGridSegmentIterator(subGrid, storageProxyForSubGridSegments) { IterationDirection = IterationDirection.Forwards, ReturnDirtyOnly = true, RetrieveAllPasses = true }; var origin = new SubGridCellAddress(subGrid.OriginX, subGrid.OriginY); if (!iterator.MoveToFirstSubGridSegment()) { return; } do { var segment = iterator.CurrentSubGridSegment; var cleavedTimeRangeStart = segment.SegmentInfo.StartTime; var cleavedTimeRangeEnd = segment.SegmentInfo.EndTime; if (!segment.RequiresCleaving(out var totalPassCount, out var maximumPassCount)) { continue; } if (subGrid.Cells.CleaveSegment(segment, NewSegmentsFromCleaving, PersistedClovenSegments, subGridSegmentPassCountLimit)) { iterator.SegmentListExtended(); if (_segmentCleavingOperationsToLog) { _log.LogInformation( $"Info: Performed cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {ServerSubGridTree.GetLeafSubGridFullFileName(origin)}. TotalPassCount = {totalPassCount} MaximumPassCount = {maximumPassCount}"); } } else { // The segment cleave failed. While this is not a serious problem (as the sub grid will be // cleaved at some point in the future when it is modified again via tag file processing etc) // it will be noted in the log. _log.LogWarning( $"Cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {ServerSubGridTree.GetLeafSubGridFullFileName(origin)} failed. TotalPassCount = {totalPassCount} MaximumPassCount = {maximumPassCount}"); } if (_segmentCleavingOperationsToLog) { if (segment.RequiresCleaving(out totalPassCount, out maximumPassCount)) { _log.LogWarning( $"Cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {subGrid.Moniker()} failed to reduce cell pass count below maximums (max passes = {totalPassCount}/{subGridSegmentPassCountLimit}, per cell = {maximumPassCount}/{_subGridMaxSegmentCellPassesLimit})"); } } } while (iterator.MoveToNextSubGridSegment()); }
/// <summary> /// Constructs a mask using all spatial filtering elements active in the supplied filter /// </summary> public static bool ConstructSubGridCellFilterMask(ISiteModel siteModel, SubGridCellAddress currentSubGridOrigin, InterceptList intercepts, int fromProfileCellIndex, SubGridTreeBitmapSubGridBits mask, ICellSpatialFilter cellFilter, IDesign surfaceDesignMaskDesign) { ConstructSubGridSpatialAndPositionalMask(currentSubGridOrigin, intercepts, fromProfileCellIndex, mask, cellFilter, siteModel.Grid); // If the filter contains an alignment design mask filter then compute this and AND it with the // mask calculated in the step above to derive the final required filter mask if (cellFilter.HasAlignmentDesignMask()) { if (cellFilter.AlignmentFence.IsNull()) // Should have been done in ASNode but if not { throw new ArgumentException($"Spatial filter does not contained pre-prepared alignment fence for design {cellFilter.AlignmentDesignMaskDesignUID}"); } var tree = siteModel.Grid; // Go over set bits and determine if they are in Design fence boundary mask.ForEachSetBit((x, y) => { tree.GetCellCenterPosition(currentSubGridOrigin.X + x, currentSubGridOrigin.Y + y, out var cx, out var cy); if (!cellFilter.AlignmentFence.IncludesPoint(cx, cy)) { mask.ClearBit(x, y); // remove interest as its not in design boundary } }); } // If the filter contains a design mask filter then compute this and AND it with the // mask calculated in the step above to derive the final required filter mask if (surfaceDesignMaskDesign != null) { var getFilterMaskResult = surfaceDesignMaskDesign.GetFilterMaskViaLocalCompute(siteModel, currentSubGridOrigin, siteModel.CellSize); if (getFilterMaskResult.errorCode == DesignProfilerRequestResult.OK || getFilterMaskResult.errorCode == DesignProfilerRequestResult.NoElevationsInRequestedPatch) { if (getFilterMaskResult.filterMask == null) { _log.LogWarning("FilterMask null in response from surfaceDesignMaskDesign.GetFilterMask, ignoring it's contribution to filter mask"); } else { mask.AndWith(getFilterMaskResult.filterMask); } } else { _log.LogError($"Call (A2) to {nameof(ConstructSubGridCellFilterMask)} returned error result {getFilterMaskResult.errorCode} for {cellFilter.SurfaceDesignMaskDesignUid}"); return(false); } } return(true); }
/// <summary> /// Computes a unique file name for a segment within a particular sub grid /// </summary> public static string GetLeafSubGridSegmentFullFileName(SubGridCellAddress cellAddress, ISubGridCellPassesDataSegmentInfo segmentInfo) { // Work out the cell address of the origin cell in the appropriate leaf // sub grid. We use this cell position to derive the name of the file // containing the leaf sub grid data return(segmentInfo.FileName(cellAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask, cellAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask)); }
public void Test_SubgridCellAddress_Equality() { SubGridCellAddress ca = new SubGridCellAddress(1, 1); SubGridCellAddress ca2 = new SubGridCellAddress(1, 1); SubGridCellAddress ca3 = new SubGridCellAddress(3, 3); Assert.True(ca.Equals(ca2), "Equality check between identical addresses failed"); Assert.False(ca.Equals(ca3), "Inequality between different addresses failed"); }
public void Test_SubgridCellAddress_Set() { SubGridCellAddress ca = new SubGridCellAddress(); ca.Set(1, 2, true, false); // Check the simple style of creation is OK Assert.True(ca.X == 1 && ca.Y == 2 && ca.ProdDataRequested == true && ca.SurveyedSurfaceDataRequested == false, "Setting simple cell address not set properties as expected"); }
/// <summary> /// Calculates an elevation sub grid for a designated sub grid on this design /// </summary> public (IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult errorCode) GetDesignHeightsViaLocalCompute( ISiteModelBase siteModel, double offset, SubGridCellAddress originCellAddress, double cellSize) { var heightsResult = _designElevationCalculator.Execute(siteModel, new DesignOffset(DesignDescriptor.DesignID, offset), cellSize, originCellAddress.X, originCellAddress.Y, out var calcResult); return(heightsResult, calcResult); }
public void Test_SubgridCellAddress_ToSpatialPartitionDescriptor(int cellX, int cellY, int expectedPartition) { // These tests assume the default number of 1024 partitions from the configuration // Test the instance method SubGridCellAddress ca = new SubGridCellAddress(cellX, cellY); ca.ToSpatialPartitionDescriptor().Should().Be(expectedPartition); // Test the static method SubGridCellAddress.ToSpatialPartitionDescriptor(cellX, cellY).Should().Be(expectedPartition); }
public void Test_SubgridCellAddress_ToNormalisedSubgridOriginInt64() { SubGridCellAddress ca = new SubGridCellAddress(1, 1); long correct = 0; Assert.Equal(ca.ToNormalisedSubgridOriginInt64, correct); SubGridCellAddress ca2 = new SubGridCellAddress(1 << 5, 1 << 5); long correct2 = (1L << 25) | 1; Assert.Equal(ca2.ToNormalisedSubgridOriginInt64, correct2); }
public void ScanAllSetBitsAsSubGridAddresses_SingleAllocedSameStructAsStruct() { SubGridCellAddress address = new SubGridCellAddress(12, 34); for (int lots = 0; lots < 50; lots++) { for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { DoSomethingWithAddressAsStruct(address); } } } }
public void Test_SubgridCellAddress_FlagManagement() { SubGridCellAddress ca2 = new SubGridCellAddress(1, 1, true, true); // Check setting/clearing the bit flag based properties ca2.ProdDataRequested = false; Assert.False(ca2.ProdDataRequested); ca2.ProdDataRequested = true; Assert.True(ca2.ProdDataRequested); ca2.SurveyedSurfaceDataRequested = false; Assert.False(ca2.SurveyedSurfaceDataRequested); ca2.SurveyedSurfaceDataRequested = true; Assert.True(ca2.SurveyedSurfaceDataRequested); }
/// <summary> /// Given a cache key, determine which partition the cache item should reside /// </summary> public override int GetPartition(object key) { // Pull the sub grid origin location for the sub grid or segment represented in the cache key and calculate the // spatial processing division descriptor to use as the partition affinity key if (key is ISubGridSpatialAffinityKey value) { // Compute partition number against the sub grid location in the spatial affinity key return(SubGridCellAddress.ToSpatialPartitionDescriptor(value.SubGridX, value.SubGridY)); } Log.LogCritical($"Unknown key type to compute spatial affinity partition key for: [{key.GetType().FullName}] {key}. Returning partition 0 to avoid thrown exception"); return(0); //throw new ArgumentException($"Unknown key type to compute spatial affinity partition key for: [{key.GetType().FullName}] {key}"); }
public void Test_SubgridCellAddress_ToSkipInterleavedDescriptor() { SubGridCellAddress ca; long correct; ca = new SubGridCellAddress(1, 1); correct = 1; Assert.Equal(ca.ToSkipInterleavedDescriptor, correct); ca = new SubGridCellAddress(1 << 5, 1); correct = (1 << 5) | 1; Assert.Equal(ca.ToSkipInterleavedDescriptor, correct); ca = new SubGridCellAddress(1 << 5, 1 << 5); correct = 1 << 5; Assert.Equal(ca.ToSkipInterleavedDescriptor, correct); }
/// <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 ScanAllSetBitsAsSubGridAddresses_SingleAlloced() { SubGridCellAddress address = new SubGridCellAddress(); for (int lots = 0; lots < 50; lots++) { for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { address.X = i; address.Y = j; DoSomethingWithAddress(address); } } } }
/// <summary> /// Calculates a filter mask for a designated sub grid on this design /// </summary> public async Task <(SubGridTreeBitmapSubGridBits filterMask, DesignProfilerRequestResult errorCode)> GetFilterMaskViaDesignElevationService( Guid siteModelId, SubGridCellAddress originCellAddress, double cellSize) { // Query the DesignProfiler service to get the requested filter mask var filterMaskRequest = new DesignFilterSubGridMaskRequest(); var maskResponse = await filterMaskRequest.ExecuteAsync(new DesignSubGridFilterMaskArgument { CellSize = cellSize, ReferenceDesign = new DesignOffset(DesignDescriptor.DesignID, 0), OriginX = originCellAddress.X, OriginY = originCellAddress.Y, ProjectID = siteModelId }); return(maskResponse?.Bits, maskResponse?.RequestResult ?? DesignProfilerRequestResult.UnknownError); }
/// <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); } } }
/// <summary> /// Calculates an elevation sub grid for a designated sub grid on this design /// </summary> public async Task <(IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult errorCode)> GetDesignHeightsViaDesignElevationService( Guid siteModelId, double offset, SubGridCellAddress originCellAddress, double cellSize) { // Query the DesignProfiler service to get the patch of elevations calculated var elevPatchRequest = new DesignElevationPatchRequest(); var response = await elevPatchRequest.ExecuteAsync(new CalculateDesignElevationPatchArgument { CellSize = cellSize, ReferenceDesign = new DesignOffset(DesignDescriptor.DesignID, offset), OriginX = originCellAddress.X, OriginY = originCellAddress.Y, ProjectID = siteModelId }); return(response.Heights, response.CalcResult); }
public void Test_SubgridCellAddress_Creation() { SubGridCellAddress ca = new SubGridCellAddress(); // Check the simple style of creation is OK Assert.True(ca.X == 0 && ca.Y == 0 && ca.ProdDataRequested == false && ca.SurveyedSurfaceDataRequested == false, "Default simple cell address creation did not set properties as expected"); ca = new SubGridCellAddress(1, 1); // Check the simple style of creation is OK Assert.True(ca.X == 1 && ca.Y == 1 && ca.ProdDataRequested == false && ca.SurveyedSurfaceDataRequested == false, "Simple cell address creation did not set properties as expected"); SubGridCellAddress ca2 = new SubGridCellAddress(1, 1, true, true); // Check the simple style of creation is OK Assert.True(ca2.X == 1 && ca2.Y == 1 && ca2.ProdDataRequested == true && ca2.SurveyedSurfaceDataRequested == true, "Complete cell address creation did not set properties as expected"); }
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); } } }
/// <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> /// Constructs a vector of cells in profileCells along the path of the profile geometry containing in nEECoords /// </summary> public bool Build(XYZ[] nEECoords, List <T> profileCells) { NEECoords = nEECoords; ProfileCells = profileCells; CellSize = SiteModel.CellSize; CurrStationPos = 0; CurrentSubgridOrigin = new SubGridCellAddress(int.MaxValue, int.MaxValue); ReturnDesignElevation = CutFillDesignWrapper?.Design != null; DesignElevations = null; // Obtain the primary partition map to allow this request to determine the elements it needs to process bool[] primaryPartitionMap = ImmutableSpatialAffinityPartitionMap.Instance().PrimaryPartitions(); for (int loopBound = NEECoords.Length - 1, I = 0; I < loopBound; I++) { StartX = NEECoords[I].X; StartY = NEECoords[I].Y; StartStation = NEECoords[I].Z; EndX = NEECoords[I + 1].X; EndY = NEECoords[I + 1].Y; EndStation = NEECoords[I + 1].Z; if (I == 0) // Add start point of profile line to intercept list { CurrStationPos = SlicerToolUsed ? 0 : NEECoords[I].Z; // alignment profiles pass in station for more accuracy VtHzIntercepts.AddPoint(StartX, StartY, CurrStationPos); } Distance = SlicerToolUsed ? MathUtilities.Hypot(EndX - StartX, EndY - StartY) // station is not passed so compute : EndStation - StartStation; // use precise station passed if (Distance == 0) // if we have two points the same { continue; } // Get all intercepts between profile line and cell boundaries for this segment CalculateHorizontalIntercepts(CurrStationPos); // pass the distance down alignment this segment starts CalculateVerticalIntercepts(CurrStationPos); CurrStationPos += Distance; // add distance to current station } // Merge vertical and horizontal cell boundary/profile line intercepts VtHzIntercepts.MergeInterceptLists(VtIntercepts, HzIntercepts); // Add end point of profile line to intercept list VtHzIntercepts.AddPoint(EndX, EndY, CurrStationPos); // Update each intercept with it's midpoint and intercept length // i.e. the midpoint on the line between one intercept and the next one // and the length between those intercepts VtHzIntercepts.UpdateMergedListInterceptMidPoints(); if (VtHzIntercepts.Count > ProfileCells.Capacity) { ProfileCells.Capacity = VtHzIntercepts.Count; } // Iterate over all intercepts calculating the results for each cell that lies in // a subgrid handled by this node for (int i = 0; i < VtHzIntercepts.Count; i++) { if (Aborted) { return(false); } // Determine the on-the-ground cell underneath the midpoint of each intercept line SiteModel.Grid.CalculateIndexOfCellContainingPosition(VtHzIntercepts.Items[i].MidPointX, VtHzIntercepts.Items[i].MidPointY, out OTGCellX, out OTGCellY); ThisSubgridOrigin = new SubGridCellAddress(OTGCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & ~SubGridTreeConsts.SubGridLocalKeyMask); if (!CurrentSubgridOrigin.Equals(ThisSubgridOrigin)) { if (!primaryPartitionMap[ThisSubgridOrigin.ToSpatialPartitionDescriptor()]) { continue; } CurrentSubgridOrigin = ThisSubgridOrigin; if (!ProfileFilterMask.ConstructSubGridCellFilterMask(SiteModel, CurrentSubgridOrigin, VtHzIntercepts, i, FilterMask, CellFilter, SurfaceDesignMaskDesign)) { continue; } if (ReturnDesignElevation && CutFillDesignWrapper?.Design != null) // cut fill profile request then get elevation at same spot along design { var getDesignHeightsResult = CutFillDesignWrapper.Design.GetDesignHeightsViaLocalCompute(SiteModel, CutFillDesignWrapper.Offset, new SubGridCellAddress(OTGCellX, OTGCellY), CellSize); DesignElevations = getDesignHeightsResult.designHeights; DesignResult = getDesignHeightsResult.errorCode; if (DesignResult != DesignProfilerRequestResult.OK && DesignResult != DesignProfilerRequestResult.NoElevationsInRequestedPatch) { continue; } if (DesignResult == DesignProfilerRequestResult.NoElevationsInRequestedPatch) { DesignElevations = null; // force a null height to be written } } } if (FilterMask.BitSet(OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask)) { AddCellPassesDataToList(OTGCellX, OTGCellY, VtHzIntercepts.Items[i].ProfileItemIndex, VtHzIntercepts.Items[i].InterceptLength); } } Log.LogInformation($"CellProfileBuilder constructed a vector of {VtHzIntercepts.Count} vertices"); return(true); }
/// <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> /// Processes each sub grid in turn into the resulting profile. /// </summary> public void ProcessSubGroup(SubGridCellAddress address, bool prodDataAtAddress, SubGridTreeBitmapSubGridBits cellOverrideMask) { var okToProceed = false; // Execute a client grid request for each requester and create an array of the results var clientGrids = Requestors.Select(x => { x.CellOverrideMask = cellOverrideMask; // Reach into the sub grid request layer and retrieve an appropriate sub grid var requestSubGridInternalResult = x.RequestSubGridInternal(address, prodDataAtAddress, true); if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError) { Log.LogError($"Request for sub grid {address} request failed with code {requestSubGridInternalResult.requestResult}"); } return(requestSubGridInternalResult.clientGrid); }).ToArray(); // If an intermediary result was requested then merge the 'from' and intermediary sub grids now if (IntermediaryFilterRequired) { MergeIntermediaryResults(clientGrids[0] as ClientHeightAndTimeLeafSubGrid, clientGrids[1] as ClientHeightAndTimeLeafSubGrid); //... and chop out the intermediary grid clientGrids = new[] { clientGrids[0], clientGrids[2] }; } // Assign the results of the sub grid requests according to the ordering of the filter in the overall // volume type context of the request ClientHeightAndTimeLeafSubGrid heightsGrid1 = null; if (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.Between2Filters) { heightsGrid1 = clientGrids[0] as ClientHeightAndTimeLeafSubGrid; } ClientHeightAndTimeLeafSubGrid heightsGrid2 = null; if (VolumeType == VolumeComputationType.BetweenDesignAndFilter) { heightsGrid2 = clientGrids[0] as ClientHeightAndTimeLeafSubGrid; } else if (VolumeType == VolumeComputationType.Between2Filters) { heightsGrid2 = clientGrids[1] as ClientHeightAndTimeLeafSubGrid; } IClientHeightLeafSubGrid designHeights = null; if (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.BetweenDesignAndFilter) { if (svDesignWrapper?.Design != null) { var getDesignHeightsResult = svDesignWrapper.Design.GetDesignHeightsViaLocalCompute(SiteModel, svDesignWrapper.Offset, address, SiteModel.CellSize); if (getDesignHeightsResult.errorCode != DesignProfilerRequestResult.OK || getDesignHeightsResult.designHeights == null) { if (getDesignHeightsResult.errorCode == DesignProfilerRequestResult.NoElevationsInRequestedPatch) { Log.LogInformation("Call to RequestDesignElevationPatch failed due to no elevations in requested patch."); } else { Log.LogError($"Call to RequestDesignElevationPatch failed due to no TDesignProfilerRequestResult return code {getDesignHeightsResult.errorCode}."); } } else { designHeights = getDesignHeightsResult.designHeights; okToProceed = true; } } else { Log.LogError("Missing design reference. Call to request Summary Volumes Profile using design failed due to no reference design"); } } else { okToProceed = true; } if (okToProceed) { for (int I = 0; I < cellCounter; I++) { int cellX = profileCellList[I].OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask; int cellY = profileCellList[I].OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask; if (heightsGrid1 != null) { profileCellList[I].LastCellPassElevation1 = heightsGrid1.Cells[cellX, cellY]; } if (heightsGrid2 != null) { profileCellList[I].LastCellPassElevation2 = heightsGrid2.Cells[cellX, cellY]; } profileCellList[I].DesignElev = designHeights?.Cells[cellX, cellY] ?? CellPassConsts.NullHeight; } } }
/// <summary> /// Orchestrates all the activities relating to saving the state of a created or modified sub grid, including /// cleaving, saving updated elements, creating new elements and arranging for the retirement of /// elements that have been replaced in the persistent store as a result of this activity. /// </summary> public bool SaveLeafSubGrid(IServerLeafSubGrid subGrid, IStorageProxy storageProxyForSubGrids, IStorageProxy storageProxyForSubGridSegments, List <ISubGridSpatialAffinityKey> invalidatedSpatialStreams) { //Log.LogInformation($"Saving {subGrid.Moniker()} to persistent store"); try { // Perform segment cleaving as the first activity in the action of saving a leaf sub grid // to disk. This reduces the number of segment cleaving actions that would otherwise // be performed in the context of the aggregated integrator. if (_segmentCleavingOperationsToLog) { _log.LogDebug($"About to perform segment cleaving on {subGrid.Moniker()}"); } var cleaver = new SubGridSegmentCleaver(); cleaver.PerformSegmentCleaving(storageProxyForSubGridSegments, subGrid); // Calculate the cell last pass information here, immediately before it is // committed to the persistent store. The reason for this is to remove this // compute intensive operation from the critical path in TAG file processing // (which is the only writer of this information in the Raptor system). // The computer is instructed to do a partial recompute, which will recompute // all segments from the first segment marked as dirty. subGrid.ComputeLatestPassInformation(false, storageProxyForSubGridSegments); if (_segmentCleavingOperationsToLog) { _log.LogInformation($"SaveLeafSubGrid: {subGrid.Moniker()} ({subGrid.Cells.PassesData.Count} segments)"); } var modifiedOriginalSegments = new List <ISubGridCellPassesDataSegment>(100); var originAddress = new SubGridCellAddress(subGrid.OriginX, subGrid.OriginY); // The following used to be an assert/exception. However, this is may readily // happen if there are no modified segments resulting from processing a // process TAG file where the Dirty flag for the sub grid is set but no cell // passes are added to segments in that sub grid. As this is not an integrity // issue the persistence of the modified sub grid is allowed, but noted in // the log for posterity. if (subGrid.Cells.PassesData.Count == 0) { _log.LogInformation( $"Note: Saving a sub grid, {subGrid.Moniker()}, (Segments = {subGrid.Cells.PassesData.Count}, Dirty = {subGrid.Dirty}) with no cached sub grid segments to the persistent store in SaveLeafSubGrid (possible reprocessing of TAG file with no cell pass changes). " + $"SubGrid.Directory.PersistedClovenSegments.Count={cleaver.PersistedClovenSegments?.Count}, ModifiedOriginalFiles.Count={modifiedOriginalSegments.Count}, NewSegmentsFromCleaving.Count={cleaver.NewSegmentsFromCleaving.Count}"); } var iterator = new SubGridSegmentIterator(subGrid, storageProxyForSubGridSegments) { IterationDirection = IterationDirection.Forwards, ReturnDirtyOnly = true, }; //********************************************************************** //***Construct list of original segment files that have been modified*** //*** These files may be updated in-situ with no sub grid/segment *** //*** integrity issues wrt the segment directory in the sub grid *** //********************************************************************** iterator.MoveToFirstSubGridSegment(); while (iterator.CurrentSubGridSegment != null) { if (iterator.CurrentSubGridSegment.SegmentInfo.ExistsInPersistentStore && iterator.CurrentSubGridSegment.Dirty) { modifiedOriginalSegments.Add(iterator.CurrentSubGridSegment); } iterator.MoveToNextSubGridSegment(); } //********************************************************************** //*** Construct list of spatial streams that will be deleted or replaced //*** in the FS file. These will be passed to the call that saves the //*** sub grid directory file as an instruction to place them into the //*** deferred deletion list //********************************************************************** lock (invalidatedSpatialStreams) { if (cleaver.PersistedClovenSegments != null) { invalidatedSpatialStreams.AddRange(cleaver.PersistedClovenSegments); } invalidatedSpatialStreams.AddRange(modifiedOriginalSegments.Select(x => x.SegmentInfo.AffinityKey(ID))); } if (cleaver.NewSegmentsFromCleaving.Count > 0) { //********************************************************************** //*** Write new segment files generated by cleaving *** //*** File system integrity failures here will have no effect on the *** //*** sub grid/segment directory as they are not referenced by it. *** //*** At worst they become orphans they may be cleaned by in the FS *** //*** recovery phase *** //********************************************************************** if (_segmentCleavingOperationsToLog) { _log.LogInformation($"Sub grid has {cleaver.NewSegmentsFromCleaving.Count} new segments from cleaving"); } foreach (var segment in cleaver.NewSegmentsFromCleaving) { // Update the version of the segment as it is about to be written segment.SegmentInfo.Touch(); segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError); segment.Dirty = false; if (fsError == FileSystemErrorStatus.OK) { if (_segmentCleavingOperationsToLog) { _log.LogInformation($"Saved new cloven grid segment file: {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}"); } } else { _log.LogWarning($"Failed to save cloven grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}"); return(false); } } } if (modifiedOriginalSegments.Count > 0) { //********************************************************************** //*** Write modified segment files *** //*** File system integrity failures here will have no effect on the *** //*** sub grid/segment directory as the previous version of the *** //*** modified file being written will be recovered. *** //********************************************************************** if (_log.IsTraceEnabled()) { _log.LogTrace($"Sub grid has {modifiedOriginalSegments.Count} modified segments"); } foreach (var segment in modifiedOriginalSegments) { // Update the version of the segment as it is about to be written segment.SegmentInfo.Touch(); segment.Dirty = false; if (segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError)) { segment.Dirty = false; if (_log.IsTraceEnabled()) { _log.LogTrace($"Saved modified grid segment file: {segment}"); } } else { _log.LogError($"Failed to save modified original grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}"); return(false); } } } // Any remaining dirty segments in the sub grid will be due to previously empty sub grids with newly // created segments from ingest processing that have not required cleaving. These segments do not require any // special treatment are jsut saved to persistent store foreach (var segment in subGrid.Directory.SegmentDirectory.Select(x => x.Segment).Where(x => (x?.Dirty ?? false))) { if (segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError)) { segment.Dirty = false; if (_log.IsTraceEnabled()) { _log.LogTrace($"Saved new sub grid segment file: {segment}"); } } else { _log.LogError($"Failed to save new sub grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}"); return(false); } } //********************************************************************** //*** Write the sub grid directory file *** //********************************************************************** /* * There is no need to add the sub grid directory stream to the segment retirement * queue as this will be automatically replaced when the new version of the * sub grid directory is written to persistent store. * * // Add the stream representing the sub grid directory file to the list of * // invalidated streams as this stream will be replaced with the stream * // containing the updated directory information. Note: This only needs to * // be done if the sub grid has previously been read from the FS file (if not * // it has been created and not yet persisted to the store. * * if (subGrid.Directory.ExistsInPersistentStore) * { * // Include an additional invalidated spatial stream for the sub grid directory stream * lock (invalidatedSpatialStreams) * { * invalidatedSpatialStreams.Add(subGrid.AffinityKey()); * } * } */ if (subGrid.SaveDirectoryToFile(storageProxyForSubGrids, GetLeafSubGridFullFileName(originAddress))) { if (_log.IsTraceEnabled()) { _log.LogTrace($"Saved grid directory file: {GetLeafSubGridFullFileName(originAddress)}"); } } else { if (_log.IsTraceEnabled()) { _log.LogTrace($"Failed to save grid: {GetLeafSubGridFullFileName(originAddress)}"); } return(false); } //********************************************************************** //*** Reset segment dirty flags *** //********************************************************************** iterator.MoveToFirstSubGridSegment(); while (iterator.CurrentSubGridSegment != null) { iterator.CurrentSubGridSegment.Dirty = false; iterator.CurrentSubGridSegment.SegmentInfo.ExistsInPersistentStore = true; iterator.MoveToNextSubGridSegment(); } //Log.LogInformation($"Completed saving {subGrid.Moniker()} to persistent store"); return(true); } catch (Exception e) { _log.LogError(e, "Exception raised in SaveLeafSubGrid"); } return(false); }
public bool LoadLeafSubGrid(IStorageProxy storageProxy, SubGridCellAddress cellAddress, bool loadAllPasses, bool loadLatestPasses, IServerLeafSubGrid subGrid) { var fullFileName = string.Empty; var result = false; try { // Loading contents into a dirty sub grid (which should happen only on the mutable nodes), or // when there is already content in the segment directory are strictly forbidden and break immutability // rules for sub grids if (subGrid.Dirty) { throw new TRexSubGridIOException("Leaf sub grid directory loads may not be performed while the sub grid is dirty. The information should be taken from the cache instead."); } // Load the cells into it from its file // Briefly lock this sub grid just for the period required to read its contents lock (subGrid) { // If more than thread wants this sub grid then they may concurrently attempt to load it. // Make a check to see if this has happened and another thread has already loaded this sub grid directory. // If so, just return success. Previously the commented out assert was enforced causing exceptions // Debug.Assert(SubGrid.Directory?.SegmentDirectory?.Count == 0, "Loading a leaf sub grid directory when there are already segments present within it."); // Check this thread is the winner of the lock to be able to load the contents if (subGrid.Directory?.SegmentDirectory?.Count == 0) { // Ensure the appropriate storage is allocated if (loadAllPasses) { subGrid.AllocateLeafFullPassStacks(); } if (loadLatestPasses) { subGrid.AllocateLeafLatestPassGrid(); } fullFileName = GetLeafSubGridFullFileName(cellAddress); // Briefly lock this sub grid just for the period required to read its contents result = subGrid.LoadDirectoryFromFile(storageProxy, fullFileName); } else { // A previous thread has already read the directory so there is nothing more to do, return a true result. return(true); } } } finally { if (result && RecordSubGridFileReadingToLog) { _log.LogDebug($"Sub grid file {fullFileName} read from persistent store containing {subGrid.Directory.SegmentDirectory.Count} segments (Moniker: {subGrid.Moniker()}"); } } return(result); }
public FileSystemErrorStatus LoadLeafSubGridSegment(IStorageProxy storageProxy, SubGridCellAddress cellAddress, bool loadLatestData, bool loadAllPasses, IServerLeafSubGrid subGrid, ISubGridCellPassesDataSegment segment) { //Log.LogInformation($"Segment load on {cellAddress}:{Segment.SegmentInfo.StartTime}-{Segment.SegmentInfo.EndTime} beginning, loadLatestData = {loadLatestData}, loadAllPasses = {loadAllPasses}"); var needToLoadLatestData = loadLatestData && !segment.HasLatestData; var needToLoadAllPasses = loadAllPasses && !segment.HasAllPasses; if (!needToLoadLatestData && !needToLoadAllPasses) { //Log.LogInformation($"Segment load on {cellAddress} exiting as neither latest nor all passes required"); return(FileSystemErrorStatus.OK); // Nothing more to do here } // Lock the segment briefly while its contents is being loaded lock (segment) { if (!(needToLoadLatestData ^ segment.HasLatestData) && !(needToLoadAllPasses ^ segment.HasAllPasses)) { //Log.LogInformation($"Segment load on {cellAddress} leaving quietly as a previous thread has performed the load"); return(FileSystemErrorStatus.OK); // The load operation was performed on another thread. Leave quietly } // Ensure the appropriate storage is allocated if (needToLoadLatestData) { segment.AllocateLatestPassGrid(); } if (needToLoadAllPasses) { segment.AllocateFullPassStacks(); } if (!segment.SegmentInfo.ExistsInPersistentStore) { //Log.LogInformation($"Segment load on {cellAddress} exiting as segment does not exist in persistent store"); return(FileSystemErrorStatus.OK); // Nothing more to do here } // Locate the segment file and load the data from it var fullFileName = GetLeafSubGridSegmentFullFileName(cellAddress, segment.SegmentInfo); // Load the cells into it from its file var fsError = subGrid.LoadSegmentFromStorage(storageProxy, fullFileName, segment, needToLoadLatestData, needToLoadAllPasses); if (fsError != FileSystemErrorStatus.OK) { //Log.LogInformation($"Segment load on {cellAddress} failed, performing allocation cleanup activities"); // Something bad happened. Remove the segment from the list. Return failure to the caller. if (loadAllPasses) { segment.DeAllocateFullPassStacks(); } if (loadLatestData) { segment.DeAllocateLatestPassGrid(); } return(fsError); } } //Log.LogInformation($"Segment load on {cellAddress} succeeded, AllPasses?={Segment.HasAllPasses}, Segment.PassesData?Null={Segment.PassesData==null} "); return(FileSystemErrorStatus.OK); }