Esempio n. 1
0
        public void BuildLiftsForSinglePassCell_CMVPercentChange(float[] heights, short[] cmvs)
        {
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();
            var baseTime  = DateTime.UtcNow;

            var cellPasses = new[]
            {
                new CellPass
                {
                    Time   = baseTime,
                    Height = heights[0],
                    CCV    = cmvs[0]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(1),
                    Height = heights[1],
                    CCV    = cmvs[1]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(2),
                    Height = heights[2],
                    CCV    = cmvs[2]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(3),
                    Height = heights[3],
                    CCV    = cmvs[3]
                }
            };

            DITAGFileAndSubGridRequestsFixture.AddSingleCellWithPasses
                (siteModel, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset, cellPasses);

            IClientLeafSubGrid clientGrid = ClientLeafSubGridFactoryFactory.CreateClientSubGridFactory().GetSubGrid(GridDataType.CCVPercentChange) as ClientCMVLeafSubGrid;

            var serverGrid = TRex.SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining(
                siteModel.PrimaryStorageProxy, siteModel.Grid,
                SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                siteModel.Grid.NumLevels, false, false) as IServerLeafSubGrid;

            var builder = new CellLiftBuilder(siteModel, GridDataType.CCVPercentChange, new FilteredValuePopulationControl(),
                                              new FilterSet(new CombinedFilter()), new CellPassFastEventLookerUpper(siteModel));

            var cell = new ProfileCell();

            var segmentIterator  = new SubGridSegmentIterator(serverGrid, serverGrid.Directory, siteModel.PrimaryStorageProxy);
            var cellPassIterator = new SubGridSegmentCellPassIterator_NonStatic(segmentIterator);

            var filteredValueAssignmentContext = new FilteredValueAssignmentContext();

            builder.Build(cell, new LiftParameters(), clientGrid, filteredValueAssignmentContext, cellPassIterator, true).Should().BeTrue();

            cell.Layers.Count().Should().Be(1);
            cell.Layers[0].PassCount.Should().Be(4);
            filteredValueAssignmentContext.FilteredValue.FilteredPassData.FilteredPass.CCV.Should().Be(cmvs[cmvs.Length - 1]);
            filteredValueAssignmentContext.PreviousFilteredValue.FilteredPassData.FilteredPass.CCV.Should().Be(cmvs[cmvs.Length - 2]);
        }
Esempio n. 2
0
        public override bool PerformHeightAnnotation(SubGridTreeBitmapSubGridBits processingMap, IList filteredSurveyedSurfaces, bool returnEarliestFilteredCellPass,
                                                     IClientLeafSubGrid surfaceElevationsSource, Func <int, int, float, bool> elevationRangeFilterLambda)
        {
            if (!(surfaceElevationsSource is ClientHeightAndTimeLeafSubGrid surfaceElevations))
            {
                _log.LogError($"{nameof(ClientHeightAndTimeLeafSubGrid)}.{nameof(PerformHeightAnnotation)} not supplied a ClientHeightAndTimeLeafSubGrid instance, but an instance of {surfaceElevationsSource?.GetType().FullName}");
                return(false);
            }

            // For all cells we wanted to request a surveyed surface elevation for,
            // update the cell elevation if a non null surveyed surface of appropriate time was computed
            // Note: The surveyed surface will return all cells in the requested sub grid, not just the ones indicated in the processing map
            // IE: It is unsafe to test for null top indicate not-filtered, use the processing map iterators to cover only those cells required
            processingMap.ForEachSetBit((x, y) =>
            {
                var surveyedSurfaceCellHeight = surfaceElevations.Cells[x, y];

                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (surveyedSurfaceCellHeight == Consts.NullHeight)
                {
                    return;
                }

                // If we got back a surveyed surface elevation...
                var surveyedSurfaceCellTime = surfaceElevations.Times[x, y];
                var prodHeight = Cells[x, y];
                var prodTime   = Times[x, y];

                // Determine if the elevation from the surveyed surface data is required based on the production data elevation being null, and
                // the relative age of the measured surveyed surface elevation compared with a non-null production data height
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (!(prodHeight == Consts.NullHeight || (returnEarliestFilteredCellPass ? surveyedSurfaceCellTime <prodTime : surveyedSurfaceCellTime> prodTime)))
                {
                    // We didn't get a surveyed surface elevation, so clear the bit in the processing map to indicate there is no surveyed surface information present for it
                    processingMap.ClearBit(x, y);
                    return;
                }

                // Check if there is an elevation range filter in effect and whether the surveyed surface elevation data matches it
                if (elevationRangeFilterLambda != null)
                {
                    if (!elevationRangeFilterLambda(x, y, surveyedSurfaceCellHeight))
                    {
                        // We didn't get a surveyed surface elevation, so clear the bit in the processing map to indicate there is no surveyed surface information present for it
                        processingMap.ClearBit(x, y);
                        return;
                    }
                }

                Cells[x, y] = surveyedSurfaceCellHeight;
                Times[x, y] = surveyedSurfaceCellTime;
            });

            //        if (ClientGrid_is_TICClientSubGridTreeLeaf_HeightAndTime)
            //          ClientGridAsHeightAndTime.SurveyedSurfaceMap.Assign(ProcessingMap);
            return(true);
        }
Esempio n. 3
0
        /// <summary>
        /// Determines if the leaf content of this subgrid is equal to 'other'
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public override bool LeafContentEquals(IClientLeafSubGrid other)
        {
            bool result = true;

            IGenericClientLeafSubGrid <MachineSpeedExtendedRecord> _other = (IGenericClientLeafSubGrid <MachineSpeedExtendedRecord>)other;

            ForEach((x, y) => result &= Cells[x, y].Equals(_other.Cells[x, y]));

            return(result);
        }
Esempio n. 4
0
        public IClientLeafSubGrid ExtractFromCachedItem(IClientLeafSubGrid cachedItem, SubGridTreeBitmapSubGridBits map, SurveyedSurfacePatchType patchType)
        {
            var resultItem = _clientLeafSubGridFactory.GetSubGridEx
                                 (patchType == SurveyedSurfacePatchType.CompositeElevations ? GridDataType.CompositeHeights : GridDataType.HeightAndTime,
                                 cachedItem.CellSize, cachedItem.Level, cachedItem.OriginX, cachedItem.OriginY);

            resultItem.AssignFromCachedPreProcessedClientSubGrid(cachedItem, map);

            return(resultItem);
        }
Esempio n. 5
0
        /// <summary>
        /// Determines if the leaf content of this sub grid is equal to 'other'
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public override bool LeafContentEquals(IClientLeafSubGrid other)
        {
            bool result = true;

            IGenericClientLeafSubGrid <ushort> _other = (IGenericClientLeafSubGrid <ushort>)other;

            ForEach((x, y) => result &= Cells[x, y] == _other.Cells[x, y]);

            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Determines if the leaf content of this subgrid is equal to 'other'
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public override bool LeafContentEquals(IClientLeafSubGrid other)
        {
            bool result = true;

            IGenericClientLeafSubGrid <SubGridCellPassDataMDPEntryRecord> _other = (IGenericClientLeafSubGrid <SubGridCellPassDataMDPEntryRecord>)other;

            ForEach((x, y) => result &= Cells[x, y].Equals(_other.Cells[x, y]));

            return(result);
        }
Esempio n. 7
0
        public override bool LeafContentEquals(IClientLeafSubGrid other)
        {
            bool result = true;

            IGenericClientLeafSubGrid <ClientCellProfileAllPassesLeafSubgridRecord> _other = (IGenericClientLeafSubGrid <ClientCellProfileAllPassesLeafSubgridRecord>)other;

            ForEach((x, y) => result &= Cells[x, y].Equals(_other.Cells[x, y]));

            return(result);
        }
Esempio n. 8
0
        public override bool LeafContentEquals(IClientLeafSubGrid other)
        {
            var result = true;

            // ReSharper disable once InconsistentNaming
            var _other = (IGenericClientLeafSubGrid <ClientCellProfileLeafSubgridRecord>)other;

            ForEach((x, y) => result &= Cells[x, y].Equals(_other.Cells[x, y]));

            return(result);
        }
Esempio n. 9
0
        /// <summary>
        /// Assigns the state of one client leaf sub grid to this client leaf sub grid
        /// Note: The cell values are explicitly NOT copied in this operation
        /// </summary>
        public void Assign(IClientLeafSubGrid source)
        {
            level   = source.Level;
            originX = source.OriginX;
            originY = source.OriginY;

            // Grid data type is never assigned from one client grid to another...
            //GridDataType = source.GridDataType;

            CellSize          = source.CellSize;
            IndexOriginOffset = source.IndexOriginOffset;
            ProdDataMap.Assign(source.ProdDataMap);
            FilterMap.Assign(source.FilterMap);
        }
Esempio n. 10
0
        public void BuildLiftsForMultiplePassCell(float height1, float height2, float height3, float first, float last, float lowest, float heighest)
        {
            var siteModel  = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();
            var baseTime   = DateTime.UtcNow;
            var cellPasses = new[]
            {
                new CellPass
                {
                    Time   = baseTime,
                    Height = height1
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(1),
                    Height = height2
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(2),
                    Height = height3
                }
            };

            DITAGFileAndSubGridRequestsFixture.AddSingleCellWithPasses
                (siteModel, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset, cellPasses);

            IClientLeafSubGrid clientGrid = ClientLeafSubGridFactoryFactory.CreateClientSubGridFactory().GetSubGrid(GridDataType.Height) as ClientHeightLeafSubGrid;

            var serverGrid = TRex.SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining(
                siteModel.PrimaryStorageProxy, siteModel.Grid,
                SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                siteModel.Grid.NumLevels, false, false) as IServerLeafSubGrid;

            var builder = new CellLiftBuilder(siteModel, GridDataType.Height, new FilteredValuePopulationControl(),
                                              new FilterSet(new CombinedFilter()), new CellPassFastEventLookerUpper(siteModel));

            var cell = new ProfileCell();

            var segmentIterator  = new SubGridSegmentIterator(serverGrid, serverGrid.Directory, siteModel.PrimaryStorageProxy);
            var cellPassIterator = new SubGridSegmentCellPassIterator_NonStatic(segmentIterator);

            builder.Build(cell, new LiftParameters(), clientGrid, new FilteredValueAssignmentContext(), cellPassIterator, false).Should().BeTrue();

            cell.Layers.Count().Should().Be(1);
            cell.Layers[0].PassCount.Should().Be(3);
            cell.Layers[0].MinimumPassHeight.Should().Be(lowest);
            cell.Layers[0].MaximumPassHeight.Should().Be(heighest);
            cell.Layers[0].FirstPassHeight.Should().Be(first);
            cell.Layers[0].LastPassHeight.Should().Be(last);
        }
Esempio n. 11
0
        public void Test_SubGridClientLeafFactory_Creation()
        {
            IClientLeafSubGridFactory factory = new ClientLeafSubGridFactory();

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightLeaf = factory.GetSubGrid(Types.GridDataType.Height);

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightAndTimeLeaf = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            Assert.NotNull(factory);
        }
Esempio n. 12
0
        /// <summary>
        /// Construct a concrete instance of a sub grid implementing the IClientLeafSubGrid interface based
        /// on the role it should play according to the grid data type requested. All aspects of leaf ownership
        /// by a sub grid tree, parentage, level, cell size, index origin offset are delegated responsibilities
        /// of the caller or a derived factory class
        /// </summary>
        /// <returns>An appropriate instance derived from ClientLeafSubGrid</returns>
        public IClientLeafSubGrid GetSubGrid(GridDataType gridDataType)
        {
            IClientLeafSubGrid result = null;

            //* TODO: Don't use repatriated sub grids for now...
            //    if (!ClientLeaves[(int) gridDataType].TryTake(out IClientLeafSubGrid result))
            //    {
            if (_typeMap[(int)gridDataType] != null)
            {
                result = _typeMap[(int)gridDataType]();
            }
            //    }

            result?.Clear();
            return(result);
        }
Esempio n. 13
0
        public void Test_SubGridClientLeafFactory_Recycling()
        {
            IClientLeafSubGridFactory factory = new ClientLeafSubGridFactory();

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightLeaf = factory.GetSubGrid(Types.GridDataType.Height);

            factory.ReturnClientSubGrid(ref HeightLeaf);

            Assert.Null(HeightLeaf);

            IClientLeafSubGrid HeightAndTimeLeaf = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            factory.ReturnClientSubGrid(ref HeightAndTimeLeaf);

            Assert.Null(HeightAndTimeLeaf);
        }
Esempio n. 14
0
        /// <summary>
        /// Return a client grid previous obtained from the factory so it may reuse it
        /// </summary>
        public void ReturnClientSubGrid(ref IClientLeafSubGrid clientGrid)
        {
            // TODO: Don't accept any repatriated sub grids for now

            /*
             * if (clientGrid == null)
             * return;
             *
             * // Make sure the type of the client grid being returned matches it's advertised grid type
             * // if (!typeMap[(int)clientGrid.GridDataType].Equals(clientGrid.GetType()))
             * // {
             * //    throw new TRexException("Type of client grid being returned does not match advertised grid data type.");
             * // }
             *
             * ClientLeaves[(int) clientGrid.GridDataType].Add(clientGrid);
             */
            clientGrid = null;
        }
Esempio n. 15
0
        // creates an array of NEE for a sub grid
        //  which is sent to Coordinate service
        //  to resolve into a list of LHH (in same order)
        // Note: only adds entry where cellPassCount exists, so may not be 1024 entries
        private XYZ[] SetupLLPositions(string csibName, IClientLeafSubGrid subGrid)
        {
            var indexIntoNEECoords = 0;
            var NEECoords          = new XYZ[1024];
            var subGridProfile     = subGrid as ClientCellProfileLeafSubgrid;

            subGrid.CalculateWorldOrigin(out double subGridWorldOriginX, out double subGridWorldOriginY);
            SubGridUtilities.SubGridDimensionalIterator((x, y) =>
            {
                var cell = subGridProfile.Cells[x, y];
                if (cell.PassCount == 0) // Nothing for us to do, as cell is empty
                {
                    return;
                }
                var easting  = subGridWorldOriginX + (x + 0.5) * subGridProfile.CellSize;
                var northing = subGridWorldOriginY + (y + 0.5) * subGridProfile.CellSize;
                NEECoords[indexIntoNEECoords] = new XYZ(easting, northing, cell.Height);
                indexIntoNEECoords++;
            });

            return(_convertCoordinates.NEEToLLH(csibName, NEECoords.ToCoreX_XYZ()).ToTRex_XYZ());
        }
Esempio n. 16
0
        public void Test_SubGridClientLeafFactory_Reuse()
        {
            IClientLeafSubGridFactory factory = ClientLeafSubGridFactoryFactory.CreateClientSubGridFactory();

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightLeaf = factory.GetSubGrid(Types.GridDataType.Height);

            factory.ReturnClientSubGrid(ref HeightLeaf);

            IClientLeafSubGrid HeightAndTimeLeaf = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            factory.ReturnClientSubGrid(ref HeightAndTimeLeaf);

            IClientLeafSubGrid HeightLeaf2 = factory.GetSubGrid(Types.GridDataType.Height);

            Assert.NotNull(HeightLeaf2);
            Assert.Equal(Types.GridDataType.Height, HeightLeaf2.GridDataType);

            IClientLeafSubGrid HeightAndTimeLeaf2 = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            Assert.NotNull(HeightAndTimeLeaf2);
            Assert.Equal(Types.GridDataType.HeightAndTime, HeightAndTimeLeaf2.GridDataType);
        }
Esempio n. 17
0
        /// <summary>
        /// Decorates the base sub grid request logic with additional requirements for progressive requests
        /// </summary>
        public override ServerRequestResult RetrieveSubGrid(IClientLeafSubGrid clientGrid,
                                                            SubGridTreeBitmapSubGridBits cellOverrideMask,
                                                            out bool sieveFilterInUse,
                                                            Func <ServerRequestResult> computeSpatialFilterMaskAndClientProdDataMap)
        {
            // Establish the expected number of height layers in the client sub grid
            if (!(clientGrid is IClientProgressiveHeightsLeafSubGrid subGrid))
            {
                throw new ArgumentException($"Supplied client {clientGrid.Moniker()} is not a {nameof(IClientProgressiveHeightsLeafSubGrid)}");
            }

            _progressiveClientSubGrid = subGrid;

            var numHeightLayers = (int)((EndDate.Ticks - StartDate.Ticks) / Interval.Ticks);

            if ((EndDate.Ticks - StartDate.Ticks) % Interval.Ticks == 0)
            {
                numHeightLayers++;
            }

            _progressiveClientSubGrid.NumberOfHeightLayers = numHeightLayers;

            return(base.RetrieveSubGrid(clientGrid, cellOverrideMask, out sieveFilterInUse, computeSpatialFilterMaskAndClientProdDataMap));
        }
Esempio n. 18
0
        /// <summary>
        /// Populate requested elevation information into the sub grid result
        /// </summary>
        /// <param name="subGrid"></param>
        public override void Populate(IClientLeafSubGrid subGrid)
        {
            //========================================================================================
            byte BytesForRangeExcludingNull(uint range) => range < byte.MaxValue ? ONE_BYTE : range < ushort.MaxValue ? TWO_BYTES : FOUR_BYTES;

            //========================================================================================

            base.Populate(subGrid);

            ClientHeightAndTimeLeafSubGrid elevSubGrid = (ClientHeightAndTimeLeafSubGrid)subGrid;
            var elevations = elevSubGrid.Cells;
            var times      = elevSubGrid.Times;

            IsNull = true;

            subGrid.CalculateWorldOrigin(out var worldOriginX, out var worldOriginY);
            SubGridOriginX = worldOriginX;
            SubGridOriginY = worldOriginY;

            if (elevSubGrid.Cells != null)
            {
                // Determine the minimum/maximum non-null elevation/time in the sub grid
                double minElevation = DOUBLE_VALUE;
                double maxElevation = -DOUBLE_VALUE;
                uint   minTime      = TIME_MAXIMUM_VALUE;
                uint   maxTime      = TIME_MINIMUM_VALUE;

                SubGridUtilities.SubGridDimensionalIterator((x, y) =>
                {
                    var valueHeight = elevations[x, y];

                    if (Math.Abs(valueHeight - CellPassConsts.NullHeight) > Consts.TOLERANCE_DIMENSION)
                    {
                        if (valueHeight < minElevation)
                        {
                            minElevation = valueHeight;
                        }
                        if (valueHeight > maxElevation)
                        {
                            maxElevation = valueHeight;
                        }

                        long valueTime = times[x, y];

                        if (valueTime < minTime)
                        {
                            minTime = (uint)valueTime;
                        }
                        if (valueTime > maxTime)
                        {
                            minTime = (uint)valueTime;
                        }
                    }
                });

                if (Math.Abs(minElevation - CellPassConsts.NullHeight) >= Consts.TOLERANCE_DIMENSION)
                {
                    var minElevationAsMM = (uint)Math.Floor(minElevation * ELEVATION_OFFSET_FACTOR + ELEVATION_OFFSET_TOLERANCE);
                    var maxElevationAsMM = (uint)Math.Floor(maxElevation * ELEVATION_OFFSET_FACTOR + ELEVATION_OFFSET_TOLERANCE);

                    // Set the appropriate values into the result
                    Data   = new PatchOffsetsRecord[SubGridTreeConsts.SubGridTreeDimension, SubGridTreeConsts.SubGridTreeDimension];
                    IsNull = false;

                    ElevationOrigin     = (float)minElevation;
                    ElevationOffsetSize = BytesForRangeExcludingNull(maxElevationAsMM - minElevationAsMM);

                    TimeOrigin     = minTime;
                    TimeOffsetSize = BytesForRangeExcludingNull(minTime - maxTime);

                    SubGridUtilities.SubGridDimensionalIterator((x, y) =>
                    {
                        var valueHeight = elevations[x, y];
                        var valueTime   = (uint)times[x, y];

                        if (Math.Abs(valueHeight - CellPassConsts.NullHeight) < Consts.TOLERANCE_DIMENSION)
                        {
                            Data[x, y] = new PatchOffsetsRecord(uint.MaxValue, uint.MaxValue);
                        }
                        else
                        {
                            Data[x, y] = new PatchOffsetsRecord((uint)Math.Floor((valueHeight - minElevation) * ELEVATION_OFFSET_FACTOR + ELEVATION_OFFSET_TOLERANCE),
                                                                valueTime - minTime);
                        }
                    });
                }
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Processes a response containing a set of sub grids from the sub grid processor for a request
        /// </summary>
        private void ProcessResponse(ISerialisedByteArrayWrapper message)
        {
            var sw            = Stopwatch.StartNew();
            int responseCount = 0;

            using (var MS = new MemoryStream(message.Bytes))
            {
                using (var reader = new BinaryReader(MS, Encoding.UTF8, true))
                {
                    // Read the number of sub grid present in the stream
                    responseCount = reader.ReadInt32();

                    //Log.LogDebug($"Sub grid listener processing a collection of {responseCount} sub grid results");

                    // Create a single instance of the client grid. The approach here is that TransferResponse does not move ownership
                    // to the called context (it may clone the passed in client grid if desired)
                    var clientGrids = new IClientLeafSubGrid[responseCount][];

                    try
                    {
                        for (var i = 0; i < responseCount; i++)
                        {
                            var subGridCount = reader.ReadInt32();
                            clientGrids[i] = new IClientLeafSubGrid[subGridCount];

                            for (var j = 0; j < subGridCount; j++)
                            {
                                clientGrids[i][j] = _clientLeafSubGridFactory.GetSubGrid(TRexTask.GridDataType);

                                // Check if the returned sub grid is null
                                if (reader.ReadBoolean())
                                {
                                    clientGrids[i][j].Read(reader);
                                }
                                // else  - Remove to reduce unwanted log traffic
                                //   Log.LogWarning($"Sub grid at position [{i},{j}] in sub grid response array is null");
                            }
                        }

                        // Log.InfoFormat("Transferring response#{0} to processor (from thread {1})", thisResponseCount, System.Threading.Thread.CurrentThread.ManagedThreadId);

                        // Send the decoded grid to the PipelinedTask, but ensure sub grids are serialized into the TRexTask
                        // (no assumption of thread safety within the TRexTask itself)
                        try
                        {
                            lock (TRexTask)
                            {
                                for (var i = 0; i < responseCount; i++)
                                {
                                    var thisResponseCount = ++responseCounter;

                                    if (TRexTask.TransferResponse(clientGrids[i]))
                                    {
                                        // Log.DebugFormat("Processed response#{0} (from thread {1})", thisResponseCount, System.Threading.Thread.CurrentThread.ManagedThreadId);
                                    }
                                    else
                                    {
                                        _log.LogInformation($"Processing response#{thisResponseCount} FAILED (from thread {Thread.CurrentThread.ManagedThreadId})");
                                    }
                                }
                            }
                        }
                        finally
                        {
                            // Tell the pipeline that a set of sub grid have been completely processed
                            TRexTask.PipeLine.SubGridsProcessed(responseCount);
                        }
                    }
                    finally
                    {
                        // Return the client grid to the factory for recycling now its role is complete here... when using SimpleConcurrentBag
                        _clientLeafSubGridFactory.ReturnClientSubGrids(clientGrids, responseCount);
                    }
                }
            }

            _log.LogDebug($"Sub grid listener processed a collection of {responseCount} sub grid results in {sw.Elapsed}");
        }
Esempio n. 20
0
        private void ValidateSurveyedSurfaceSuGridResult(ISiteModel siteModel, GridDataType expectedGridType,
                                                         SurveyedSurfacePatchType patchType, IClientLeafSubGrid result)
        {
            result.Should().NotBeNull();
            result.CellSize.Should().Be(siteModel.CellSize);
            result.IndexOriginOffset.Should().Be(SubGridTreeConsts.DefaultIndexOriginOffset);
            result.Level.Should().Be(SubGridTreeConsts.SubGridTreeLevels);
            result.WorldExtents().Should().BeEquivalentTo(new BoundingWorldExtent3D(0, 0, SubGridTreeConsts.SubGridTreeDimension * siteModel.CellSize, SubGridTreeConsts.SubGridTreeDimension * siteModel.CellSize));

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

            result.CountNonNullCells().Should().Be(903);
        }
Esempio n. 21
0
 /// <summary>
 /// Populates base class information from the supplied client leaf sub grid
 /// </summary>
 /// <param name="subGrid"></param>
 public virtual void Populate(IClientLeafSubGrid subGrid)
 {
     CellOriginX = (int)subGrid.OriginX;
     CellOriginY = (int)subGrid.OriginY;
 }
Esempio n. 22
0
 public CacheContextAdditionResult Add(IClientLeafSubGrid clientResult, long subGridInvalidationVersion)
 {
     return(_cache.Add(_context, clientResult, subGridInvalidationVersion));
 }
Esempio n. 23
0
 public abstract bool LeafContentEquals(IClientLeafSubGrid other);
Esempio n. 24
0
 public virtual bool PerformHeightAnnotation(SubGridTreeBitmapSubGridBits processingMap, IList filteredSurveyedSurfaces, bool returnEarliestFilteredCellPass,
                                             IClientLeafSubGrid surfaceElevationsSource, Func <int, int, float, bool> elevationRangeFilter)
 {
     return(false);
 }
Esempio n. 25
0
        /// <summary>
        /// Orchestrates the mainline work of analyzing cell and cell pass information to create a client sub grid (heights, CMV, MDP etc)
        /// based on filter and other information established in the class
        /// </summary>
        /// <param name="clientGrid"></param>
        /// <param name="cellOverrideMask"></param>
        /// <returns></returns>
        public virtual ServerRequestResult RetrieveSubGrid(IClientLeafSubGrid clientGrid,
                                                           SubGridTreeBitmapSubGridBits cellOverrideMask,
                                                           out bool sieveFilterInUse,
                                                           Func <ServerRequestResult> computeSpatialFilterMaskAndClientProdDataMap)
        {
            sieveFilterInUse = false;

            if (!Utilities.DerivedGridDataTypesAreCompatible(_gridDataType, clientGrid.GridDataType))
            {
                throw new TRexSubGridProcessingException($"Grid data type of client leaf sub grid [{clientGrid.GridDataType}] is not compatible with the grid data type of retriever [{_gridDataType}]");
            }

            var result = ServerRequestResult.UnknownError;

            //  SIGLogMessage.PublishNoODS(Nil, Format('In RetrieveSubGrid: Active pass filters = %s, Active cell filters = %s', [PassFilter.ActiveFiltersText, CellFilter.ActiveFiltersText]));

            // Set up class local state for other methods to access
            _clientGrid       = clientGrid;
            _clientGridAsLeaf = clientGrid as ClientLeafSubGrid;

            _canUseGlobalLatestCells &=
                !(_gridDataType == GridDataType.CCV ||
                  _gridDataType == GridDataType.CCVPercent) &&
                _liftParams.CCVSummaryTypes != CCVSummaryTypes.None &&
                !(_gridDataType == GridDataType.MDP ||
                  _gridDataType == GridDataType.MDPPercent) &&
                _liftParams.MDPSummaryTypes != MDPSummaryTypes.None &&
                !(_gridDataType == GridDataType.CCA || _gridDataType == GridDataType.CCAPercent) &&
                !(_gridDataType == GridDataType.CellProfile ||
                  _gridDataType == GridDataType.PassCount ||
                  _gridDataType == GridDataType.CellPasses ||
                  _gridDataType == GridDataType.MachineSpeed ||
                  _gridDataType == GridDataType.CCVPercentChange ||
                  _gridDataType == GridDataType.MachineSpeedTarget ||
                  _gridDataType == GridDataType.CCVPercentChangeIgnoredTopNullValue);

            // Support for lazy construction of any required profiling infrastructure
            if (_clientGrid.WantsLiftProcessingResults() && _profiler == null)
            {
                // Some display types require lift processing to be able to select the
                // appropriate cell pass containing the filtered value required.

                _profiler = DIContext.Obtain <IProfilerBuilder <ProfileCell> >();

                //TODO: should referenceDesignWrapper be null here or be passed through from args?
                _profiler.Configure(ProfileStyle.CellPasses, _siteModel, _pdExistenceMap, _gridDataType, new FilterSet(_filter),
                                    null, _populationControl, new CellPassFastEventLookerUpper(_siteModel), VolumeComputationType.None, _overrides, _liftParams);

                _cellProfile = new ProfileCell();

                // Create and configure the assignment context which is used to contain
                // a filtered pass and its attendant machine events and target values
                // prior to assignment to the client sub grid.
                _assignmentContext.CellProfile = _cellProfile;
            }

            try
            {
                // Ensure pass type filter is set correctly
                if (_filter.AttributeFilter.HasPassTypeFilter)
                {
                    if ((_filter.AttributeFilter.PassTypeSet & (PassTypeSet.Front | PassTypeSet.Rear)) == PassTypeSet.Front)
                    {
                        _filter.AttributeFilter.PassTypeSet |= PassTypeSet.Rear; // these two types go together as half passes
                    }
                }
                // ... unless we can use the last pass grid to satisfy the query
                if (_canUseGlobalLatestCells &&
                    !_filter.AttributeFilter.HasElevationRangeFilter &&
                    !_clientGrid.WantsLiftProcessingResults() &&
                    !_filter.AttributeFilter.HasElevationMappingModeFilter &&
                    !(_filter.AttributeFilter.HasElevationTypeFilter &&
                      (_filter.AttributeFilter.ElevationType == ElevationType.Highest ||
                       _filter.AttributeFilter.ElevationType == ElevationType.Lowest)) &&
                    !(_gridDataType == GridDataType.PassCount || _gridDataType == GridDataType.Temperature ||
                      _gridDataType == GridDataType.CellProfile || _gridDataType == GridDataType.CellPasses ||
                      _gridDataType == GridDataType.MachineSpeed))
                {
                    _useLastPassGrid = true;
                }

                // First get the sub grid we are interested in
                // SIGLogMessage.PublishNoODS(Nil, Format('Begin LocateSubGridContaining at %dx%d', [clientGrid.OriginX, clientGrid.OriginY]));

                _subGrid = SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining(_storageProxy, _siteModel.Grid, clientGrid.OriginX, clientGrid.OriginY, _siteModel.Grid.NumLevels, false, false);

                //  SIGLogMessage.PublishNoODS(Nil, Format('End LocateSubGridContaining at %dx%d', [clientGrid.OriginX, clientGrid.Origin]));

                if (_subGrid == null) // This should never really happen, but we'll be polite about it
                {
                    Log.LogWarning(
                        $"Sub grid address (CellX={clientGrid.OriginX}, CellY={clientGrid.OriginY}) passed to LocateSubGridContaining() from RetrieveSubGrid() did not match an existing sub grid in the data model. Returning SubGridNotFound as response with a null sub grid reference.");
                    return(ServerRequestResult.SubGridNotFound);
                }

                // Now process the contents of that sub grid into the sub grid to be returned to the client.

                if (!_subGrid.IsLeafSubGrid())
                {
                    Log.LogInformation("Requests of node sub grids in the server sub grid are not yet supported");
                    return(result);
                }

                if (!(_subGrid is IServerLeafSubGrid))
                {
                    Log.LogError($"_SubGrid {_subGrid.Moniker()} is not a server grid leaf node");
                    return(result);
                }

                // SIGLogMessage.PublishNoODS(Nil, Format('Getting sub grid leaf at %dx%d', [clientGrid.OriginX, clientGrid.OriginY]));

                _subGridAsLeaf     = (IServerLeafSubGrid)_subGrid;
                _globalLatestCells = _subGridAsLeaf.Directory.GlobalLatestCells;

                if (PruneSubGridRetrievalHere())
                {
                    return(ServerRequestResult.NoError);
                }

                // SIGLogMessage.PublishNoODS(Nil, Format('Setup for stripe iteration at %dx%d', [clientGrid.OriginX, clientGrid.OriginY]));

                SetupForCellPassStackExamination();

                // Determine if a sieve filter is required for the sub grid where the sieve matches
                // the X and Y pixel world size (used for WMS tile computation)
                _subGrid.CalculateWorldOrigin(out var subGridWorldOriginX, out var subGridWorldOriginY);

                sieveFilterInUse = _areaControlSet.UseIntegerAlgorithm
          ? GridRotationUtilities.ComputeSieveBitmaskInteger(subGridWorldOriginX, subGridWorldOriginY, _subGrid.Moniker(), _areaControlSet, _siteModel.CellSize, out _sieveBitmask)
          : GridRotationUtilities.ComputeSieveBitmaskFloat(subGridWorldOriginX, subGridWorldOriginY, _areaControlSet, _siteModel.CellSize, _assignmentContext, out _sieveBitmask);

                //if (Debug_ExtremeLogSwitchC) Log.LogDebug($"Performing stripe iteration at {clientGrid.OriginX}x{clientGrid.OriginY}");

                if (computeSpatialFilterMaskAndClientProdDataMap != null)
                {
                    _clientGrid.ProdDataMap.Assign(_subGridAsLeaf.Directory.GlobalLatestCells.PassDataExistenceMap);
                    var innerResult = computeSpatialFilterMaskAndClientProdDataMap();
                    if (innerResult != ServerRequestResult.NoError)
                    {
                        return(innerResult);
                    }
                }

                // Before iterating over stripes of this sub grid, compute a scan map detailing to the best of our current
                // knowledge, which cells need to be visited so that only cells the filter wants and which are actually
                // present in the data set are requested. If the intent is to store the result in a cache then ensure the
                // entire content is requested for the sub grid.
                if (_prepareGridForCacheStorageIfNoSieving)
                {
                    _aggregatedCellScanMap.Fill();
                }
                else
                {
                    _aggregatedCellScanMap.OrWith(_globalLatestCells.PassDataExistenceMap);

                    if (sieveFilterInUse)
                    {
                        _aggregatedCellScanMap.AndWith(_sieveBitmask);             // ... and which are required by any sieve mask
                    }
                    _aggregatedCellScanMap.AndWith(_clientGridAsLeaf.ProdDataMap); // ... and which are in the required production data map
                    _aggregatedCellScanMap.AndWith(_clientGridAsLeaf.FilterMap);   // ... and which are in the required filter map
                }

                // Iterate over the stripes in the sub grid processing each one in turn.
                for (byte i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++)
                {
                    RetrieveSubGridStripe(i);
                }

                //if Debug_ExtremeLogSwitchC then Log.LogDebug($"Stripe iteration complete at {clientGrid.OriginX}x{clientGrid.OriginY}");

                result = ServerRequestResult.NoError;
            }
            catch (Exception e)
            {
                Log.LogError(e, $"Exception occurred in {nameof(RetrieveSubGrid)}");
                throw;
            }

            return(result);
        }
Esempio n. 26
0
        /// <summary>
        /// Responsible for coordinating the retrieval of production data for a sub grid from a site model and also annotating it with
        /// surveyed surface information for requests involving height data.
        /// </summary>
        public (ServerRequestResult requestResult, IClientLeafSubGrid clientGrid) RequestSubGridInternal(
            SubGridCellAddress subGridAddress,
            bool prodDataRequested,
            bool surveyedSurfaceDataRequested)
        {
            (ServerRequestResult requestResult, IClientLeafSubGrid clientGrid)result = (ServerRequestResult.UnknownError, null);

            if (!(prodDataRequested || surveyedSurfaceDataRequested))
            {
                result.requestResult = ServerRequestResult.MissingInputParameters;
                return(result);
            }

            _prodDataRequested            = prodDataRequested;
            _surveyedSurfaceDataRequested = surveyedSurfaceDataRequested;

            // if <config>.Debug_ExtremeLogSwitchB then Log.LogDebug("About to call RetrieveSubGrid()");

            result.clientGrid = ClientLeafSubGridFactory.GetSubGridEx(
                Utilities.IntermediaryICGridDataTypeForDataType(_gridDataType, subGridAddress.SurveyedSurfaceDataRequested),
                _siteModel.CellSize, SubGridTreeConsts.SubGridTreeLevels,
                subGridAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask,
                subGridAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask);

            _clientGrid = result.clientGrid;

            if (ShouldInitialiseFilterContext() && !InitialiseFilterContext())
            {
                result.requestResult = ServerRequestResult.FilterInitialisationFailure;
                ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                return(result);
            }

            _haveComputedSpatialFilterMaskAndClientProdDataMap = false;

            if (_prodDataRequested)
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Performing data extraction");
                }

                if ((result.requestResult = PerformDataExtraction()) != ServerRequestResult.NoError)
                {
                    ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    return(result);
                }
            }

            if (_surveyedSurfaceDataRequested)
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Performing height annotation");
                }

                if ((result.requestResult = PerformHeightAnnotation()) != ServerRequestResult.NoError)
                {
                    ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    return(result);
                }
            }

            // Reassign _clientGrid to result as its reference may have been changed as a result of caching.
            result.clientGrid = _clientGrid;

            return(result);
        }
Esempio n. 27
0
        /// <summary>
        /// Calculates a cut/fill sub grid from a production data elevation sub grid and an elevation sub grid computed from a referenced design,
        /// replacing the elevations in the first sub grid with the resulting cut fill values
        /// </summary>
        public static (bool executionResult, DesignProfilerRequestResult profilerRequestResult) ComputeCutFillSubGrid(ISiteModel siteModel, IClientLeafSubGrid SubGrid, IDesignWrapper designWrapper)
        {
            (bool executionResult, DesignProfilerRequestResult profilerRequestResult)result = (false, DesignProfilerRequestResult.UnknownError);

            if (designWrapper?.Design == null)
            {
                return(result);
            }

            var getDesignHeightsResult = designWrapper.Design.GetDesignHeightsViaLocalCompute(siteModel, designWrapper.Offset, SubGrid.OriginAsCellAddress(), SubGrid.CellSize);

            result.profilerRequestResult = getDesignHeightsResult.errorCode;

            if (result.profilerRequestResult != DesignProfilerRequestResult.OK && result.profilerRequestResult != DesignProfilerRequestResult.NoElevationsInRequestedPatch)
            {
                _log.LogError($"Design profiler sub grid elevation request for {SubGrid.OriginAsCellAddress()} failed with error {result.profilerRequestResult}");
                return(result);
            }

            ComputeCutFillSubGrid((IClientHeightLeafSubGrid)SubGrid, getDesignHeightsResult.designHeights);

            result.executionResult = true;
            return(result);
        }
Esempio n. 28
0
        /// <summary>
        /// // Note: There is an assumption you have already checked on a existence map that there is a sub grid for this address
        /// </summary>
        private ServerRequestResult PerformDataExtraction()
        {
            // If there is a cache context for this sub grid, but the sub grid does not support assignation then complain
            var assignationSupported = ClientLeafSubGrid.SupportsAssignationFromCachedPreProcessedClientSubGrid[(int)_clientGrid.GridDataType];

            var subGridCacheContext = _subGridCacheContexts?.FirstOrDefault(x => x.GridDataType == _clientGrid.GridDataType);

            if (subGridCacheContext != null && !assignationSupported)
            {
                throw new TRexException($"Client sub grid of type {_clientGrid.GridDataType} does not support assignation from cached sub grids but has a cache context enabled for it.");
            }

            if (subGridCacheContext != null && assignationSupported)
            {
                if (subGridCacheContext != null && _clientGrid.GridDataType != subGridCacheContext.GridDataType)
                {
                    _log.LogWarning($"Client grid data type {_clientGrid.GridDataType} does not match type of sub grid cache context {subGridCacheContext.GridDataType}");
                }

                // Determine if there is a suitable pre-calculated result present in the general sub grid result cache.
                // If there is, then apply the filter mask to the cached data and copy it to the client grid
                var cachedSubGrid = (IClientLeafSubGrid)_subGridCache?.Get(subGridCacheContext, _clientGrid.CacheOriginX, _clientGrid.CacheOriginY);

                // If there was a cached sub grid located, assign its contents according the client grid mask into the client grid and return it
                if (cachedSubGrid != null)
                {
                    // Log.LogInformation($"Acquired sub grid {CachedSubGrid.Moniker()} for client sub grid {ClientGrid.Moniker()} in data model {SiteModel.ID} from result cache");

                    // Check the cache supplied a tpe of sub grid we can use. If not (due to an issue), ignore the returned item and request the result directly
                    if (_clientGrid.SupportsAssignationFrom(cachedSubGrid.GridDataType))
                    {
                        _clientGrid.ProdDataMap.Assign(cachedSubGrid.ProdDataMap);
                        var innerResult = ComputeSpatialFilterMaskAndClientProdDataMap();
                        if (innerResult != ServerRequestResult.NoError)
                        {
                            return(innerResult);
                        }

                        // Use the filter mask to copy the relevant cells from the cache to the client sub grid
                        _clientGrid.AssignFromCachedPreProcessedClientSubGrid(cachedSubGrid, _clientGrid.FilterMap);

                        return(ServerRequestResult.NoError);
                    }

                    _log.LogError($"Sub grid retrieved from cache is not valid for assigning into client grid. Ignoring. Client sub grid = {_clientGrid.Moniker()}/{_clientGrid.GridDataType}. Cache sub grid = {cachedSubGrid.Moniker()}/{cachedSubGrid.GridDataType}");
                }
            }

            var result = _retriever.RetrieveSubGrid(_clientGrid, CellOverrideMask, out var sieveFilterInUse, ComputeSpatialFilterMaskAndClientProdDataMap);

            // If a sub grid was retrieved and this is a supported data type in the cache then add it to the cache
            // If the sub grid does not support assignation from a precomputed sub grid then just return the result with
            // no reference to the cache.
            if (result == ServerRequestResult.NoError && assignationSupported)
            {
                // Determine if this sub grid is suitable for storage in the cache
                // Don't add sub grids computed using a non-trivial WMS sieve to the general sub grid cache
                var shouldBeCached = subGridCacheContext != null && !sieveFilterInUse && (_clientGrid.GridDataType == subGridCacheContext.GridDataType);

                var subGridInvalidationVersion = shouldBeCached ? subGridCacheContext.InvalidationVersion : 0;

                var clientGrid2 = ClientLeafSubGridFactory.GetSubGrid(_clientGrid.GridDataType);
                clientGrid2.Assign(_clientGrid);
                clientGrid2.AssignFromCachedPreProcessedClientSubGrid(_clientGrid, _clientGrid.FilterMap);

                if (shouldBeCached)
                {
                    //Log.LogInformation($"Adding sub grid {ClientGrid.Moniker()} in data model {SiteModel.ID} to result cache");

                    // Add the newly computed client sub grid to the cache by creating a clone of the client and adding it...
                    if (_subGridCache.Add(subGridCacheContext, _clientGrid, subGridInvalidationVersion) != CacheContextAdditionResult.Added)
                    {
                        _log.LogWarning($"Failed to add sub grid {clientGrid2.Moniker()}, data model {_siteModel.ID} to sub grid result cache context [FingerPrint:{subGridCacheContext.FingerPrint}], returning sub grid to factory as not added to cache");
                        ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    }
                }

                _clientGrid = clientGrid2;
            }

            //if <config>.Debug_ExtremeLogSwitchB then  SIGLogMessage.PublishNoODS(Nil, 'Completed call to RetrieveSubGrid()');

            return(result);
        }