Пример #1
0
        public void Test_SubGridTreeBitmapSubGridBitsTests_ClearBit()
        {
            // Test setting a bit on and off, at two corners to test boundary conditions
            SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            bits.SetBit(0, 0);

            Assert.NotEqual(0U, bits.Bits[0]);
            Assert.Equal(1, bits.CountBits());

            bits.ClearBit(0, 0);

            Assert.Equal(0U, bits.Bits[0]);
            Assert.Equal(0, bits.CountBits());

            bits.SetBit(31, 31);

            Assert.NotEqual(0U, bits.Bits[31]);
            Assert.Equal(1, bits.CountBits());

            bits.ClearBit(31, 31);

            Assert.Equal(0U, bits.Bits[31]);
            Assert.Equal(0, bits.CountBits());
        }
Пример #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);
        }
Пример #3
0
        public override bool UpdateProcessingMapForSurveyedSurfaces(SubGridTreeBitmapSubGridBits processingMap, IList filteredSurveyedSurfaces, bool returnEarliestFilteredCellPass)
        {
            if (!(filteredSurveyedSurfaces is ISurveyedSurfaces surveyedSurfaces))
            {
                return(false);
            }

            processingMap.Assign(FilterMap);

            // If we're interested in a particular cell, but we don't have any surveyed surfaces later (or earlier)
            // than the cell production data pass time (depending on PassFilter.ReturnEarliestFilteredCellPass)
            // then there's no point in asking the Design Profiler service for an elevation

            processingMap.ForEachSetBit((x, y) =>
            {
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (Cells[x, y] != Consts.NullHeight &&
                    !(returnEarliestFilteredCellPass ? surveyedSurfaces.HasSurfaceEarlierThan(Times[x, y]) : surveyedSurfaces.HasSurfaceLaterThan(Times[x, y])))
                {
                    processingMap.ClearBit(x, y);
                }
            });

            return(true);
        }
Пример #4
0
        public override bool ComputeFilterPatch(double startStn, double endStn, double leftOffset, double rightOffset,
                                                SubGridTreeBitmapSubGridBits mask,
                                                SubGridTreeBitmapSubGridBits patch,
                                                double originX, double originY,
                                                double cellSize,
                                                double offset)
        {
            var Heights = new float[SubGridTreeConsts.SubGridTreeDimension, SubGridTreeConsts.SubGridTreeDimension];

            if (InterpolateHeights(Heights, originX, originY, cellSize, offset))
            {
                mask.ForEachSetBit((x, y) =>
                {
                    if (Heights[x, y] == Common.Consts.NullHeight)
                    {
                        mask.ClearBit(x, y);
                    }
                });
                patch.Assign(mask);

                //SIGLogMessage.PublishNoODS(Self, Format('Filter patch construction successful with %d bits', [patch.CountBits]), ...);

                return(true);
            }

            //SIGLogMessage.PublishNoODS(Self, Format('Filter patch construction failed...', []), ...);
            return(false);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        public void Test_SubGridTreeBitmapSubGridBitsTests_Operators_AND()
        {
            SubGridTreeBitmapSubGridBits bits1 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled);
            SubGridTreeBitmapSubGridBits bits2 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            Assert.Equal((bits1 & bits2), bits2);

            bits1.ClearBit(1, 1);
            Assert.NotEqual((bits1 & bits2), bits1);
        }
Пример #7
0
        public void Test_SubGridTreeBitmapSubGridBitsTests_Operators_NOT()
        {
            SubGridTreeBitmapSubGridBits bits1 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled);
            SubGridTreeBitmapSubGridBits bits2 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            Assert.Equal(~bits1, bits2);
            Assert.Equal(bits1, ~bits2);

            bits1.ClearBit(1, 1);
            Assert.True((~bits1).BitSet(1, 1), "NOTing single bit did not flip it");
        }
Пример #8
0
        public void Test_SubGridTreeBitmapSubGridBitsTests_Operators_OR()
        {
            SubGridTreeBitmapSubGridBits bits1 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled);
            SubGridTreeBitmapSubGridBits bits2 = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            Assert.Equal((bits1 | bits2), bits1);

            bits1.ClearBit(1, 1);
            Assert.Equal((bits1 | bits2), bits1);

            bits2.SetBit(1, 1);
            Assert.True((bits1 | bits2).IsFull(), "ORing after clearing/setting bits did not return full mask");
        }
Пример #9
0
        public static bool ConstructSubGridCellFilterMask(ILeafSubGrid SubGridAsLeaf,
                                                          ISiteModel SiteModel,
                                                          ICombinedFilter Filter,
                                                          SubGridTreeBitmapSubGridBits CellOverrideMask,
                                                          bool AHasOverrideSpatialCellRestriction,
                                                          BoundingIntegerExtent2D AOverrideSpatialCellRestriction,
                                                          SubGridTreeBitmapSubGridBits PDMask,
                                                          SubGridTreeBitmapSubGridBits FilterMask)
        {
            ConstructSubgridSpatialAndPositionalMask(SubGridAsLeaf, SiteModel, Filter,
                                                     AHasOverrideSpatialCellRestriction, AOverrideSpatialCellRestriction,
                                                     PDMask, FilterMask);

            // Apply any override mask supplied by the caller. If all bits are required in the override,
            // then a filled mask should be supplied...
            PDMask.AndWith(CellOverrideMask);

            // 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 (Filter != null && Filter.SpatialFilter.HasAlignmentDesignMask())
            {
                if (Filter.SpatialFilter.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 {Filter.SpatialFilter.AlignmentDesignMaskDesignUID}");
                }

                // Go over set bits and determine if they are in Design fence boundary
                FilterMask.ForEachSetBit((X, Y) =>
                {
                    SiteModel.Grid.GetCellCenterPosition(SubGridAsLeaf.OriginX + X, SubGridAsLeaf.OriginY + Y, out var CX, out var CY);
                    if (!Filter.SpatialFilter.AlignmentFence.IncludesPoint(CX, CY))
                    {
                        FilterMask.ClearBit(X, Y); // remove interest as its not in design boundary
                    }
                });
            }

            PDMask.AndWith(FilterMask);

            return(true);
        }
Пример #10
0
        public static void ConstructSubgridSpatialAndPositionalMask(ILeafSubGrid SubGridAsLeaf,
                                                                    ISiteModel SiteModel,
                                                                    ICombinedFilter Filter,
                                                                    bool AHasOverrideSpatialCellRestriction,
                                                                    BoundingIntegerExtent2D AOverrideSpatialCellRestriction,
                                                                    SubGridTreeBitmapSubGridBits PDMask,
                                                                    SubGridTreeBitmapSubGridBits FilterMask)
        {
            if (Filter == null || !Filter.SpatialFilter.HasSpatialOrPositionalFilters)
            {
                PDMask.Fill();
                FilterMask.Fill();
                return;
            }

            var originX = SubGridAsLeaf.OriginX;
            var originY = SubGridAsLeaf.OriginY;

            var cellSize = SiteModel.CellSize;

            // Get the world location of the origin position
            SiteModel.Grid.GetCellCenterPosition(originX, originY, out var OX, out var OY);

            var SpatialFilter = Filter.SpatialFilter;

            // Attempt to satisfy the calculation below on the basis of the sub grid wholly residing in the override and filter spatial restrictions
            if (SpatialFilter.Fence.IncludesExtent(new BoundingWorldExtent3D(OX, OY,
                                                                             OX + cellSize * SubGridTreeConsts.SubGridTreeDimension,
                                                                             OY + cellSize * SubGridTreeConsts.SubGridTreeDimension)))
            {
                // The extent of the sub grid is wholly contained in the filter, therefore there is no need to iterate though all the cells
                // individually...

                FilterMask.Fill();

                // ... unless there is an override spatial cell restriction that does not enclose the extent of the sub grid
                if (AHasOverrideSpatialCellRestriction &&
                    !AOverrideSpatialCellRestriction.Encloses(new BoundingIntegerExtent2D((int)originX, (int)originY,
                                                                                          (int)originX + SubGridTreeConsts.SubGridTreeDimension,
                                                                                          (int)originY + SubGridTreeConsts.SubGridTreeDimension)))
                {
                    for (byte I = 0; I < SubGridTreeConsts.SubGridTreeDimension; I++)
                    {
                        for (byte J = 0; J < SubGridTreeConsts.SubGridTreeDimension; J++)
                        {
                            if (!AOverrideSpatialCellRestriction.Includes(originX + I, originY + J))
                            {
                                FilterMask.ClearBit(I, J);
                            }
                        }
                    }
                }
            }
            else
            {
                // Perform the calculation the long hand way
                // ... Idea: Invert row and column order of calculation below to get and set bits based on an entire column of bits

                FilterMask.Clear();

                // Construct the filter mask based on the spatial and location (square/circle/polygonal) filtering
                double CX = OX;

                for (byte I = 0; I < SubGridTreeConsts.SubGridTreeDimension; I++)
                {
                    int    OriginXPlusI = originX + I;
                    double CY           = OY; // Set to the first row in the column about to be processed

                    for (byte J = 0; J < SubGridTreeConsts.SubGridTreeDimension; J++)
                    {
                        if (AHasOverrideSpatialCellRestriction && !AOverrideSpatialCellRestriction.Includes((int)OriginXPlusI, (int)(originY + J)))
                        {
                            // Do nothing
                        }
                        else
                        {
                            // SiteModel.Grid.GetCellCenterPosition(OriginXPlusI, originY + J, out CX, out CY);
                            if (SpatialFilter.IsCellInSelection(CX, CY))
                            {
                                FilterMask.SetBit(I, J);
                            }
                        }

                        CY += cellSize; // Move to next row
                    }

                    CX += cellSize; // Move to next column
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Performs the donkey work of the elevation patch calculation
        /// </summary>
        public IClientLeafSubGrid Execute(ISiteModel siteModel, int otgCellBottomLeftX, int otgCellBottomLeftY, double cellSize, SurveyedSurfacePatchType patchType,
                                          Guid[] includedSurveyedSurfaces, IDesignFiles designs, ISurveyedSurfaces surveyedSurfaces, SubGridTreeBitmapSubGridBits processingMap)
        {
            var calcResult = DesignProfilerRequestResult.UnknownError;

            try
            {
                if (!Enum.IsDefined(typeof(SurveyedSurfacePatchType), patchType))
                {
                    _log.LogError($"Unknown SurveyedSurfacePatchType: {patchType}, returning null");
                    return(null);
                }

                if (includedSurveyedSurfaces == null)
                {
                    _log.LogError("Included surveyed surfaces list is null, returning null");
                    return(null);
                }

                if (processingMap == null)
                {
                    _log.LogError("Supplied processing map is null, returning null");
                    return(null);
                }

                var patch = _clientLeafSubGridFactory.GetSubGridEx(
                    patchType == SurveyedSurfacePatchType.CompositeElevations ? GridDataType.CompositeHeights : GridDataType.HeightAndTime,
                    cellSize, SubGridTreeConsts.SubGridTreeLevels,
                    otgCellBottomLeftX, otgCellBottomLeftY);

                // Assign
                var patchSingle = patchType != SurveyedSurfacePatchType.CompositeElevations
          ? patch as ClientHeightAndTimeLeafSubGrid
          : null;

                var patchComposite = patchType == SurveyedSurfacePatchType.CompositeElevations
          ? patch as ClientCompositeHeightsLeafSubgrid
          : null;

                patch.CalculateWorldOrigin(out var originX, out var originY);

                var halfCellSize            = cellSize / 2;
                var originXPlusHalfCellSize = originX + halfCellSize;
                var originYPlusHalfCellSize = originY + halfCellSize;

                // Work down through the list of surfaces in the time ordering provided by the caller
                foreach (var surveyedSurfaceUid in includedSurveyedSurfaces)
                {
                    if (processingMap.IsEmpty())
                    {
                        break;
                    }

                    var thisSurveyedSurface = surveyedSurfaces.Locate(surveyedSurfaceUid);
                    if (thisSurveyedSurface == null)
                    {
                        _log.LogError($"Surveyed surface {surveyedSurfaceUid} not found in site model, returning null");
                        calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                        return(null);
                    }

                    // Lock & load the design
                    var design = designs.Lock(thisSurveyedSurface.DesignDescriptor.DesignID, siteModel, cellSize, out _);

                    if (design == null)
                    {
                        _log.LogError($"Failed to lock design file {thisSurveyedSurface.DesignDescriptor} in {nameof(CalculateSurfaceElevationPatch)}");
                        calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile;
                        return(null);
                    }

                    try
                    {
                        if (!design.HasElevationDataForSubGridPatch(
                                otgCellBottomLeftX >> SubGridTreeConsts.SubGridIndexBitsPerLevel,
                                otgCellBottomLeftY >> SubGridTreeConsts.SubGridIndexBitsPerLevel))
                        {
                            continue;
                        }

                        var asAtDate = thisSurveyedSurface.AsAtDate.Ticks;
                        var hint     = -1;

                        // Walk across the sub grid checking for a design elevation for each appropriate cell
                        // based on the processing bit mask passed in
                        processingMap.ForEachSetBit((x, y) =>
                        {
                            // If we can interpolate a height for the requested cell, then update the cell height
                            // and decrement the bit count so that we know when we've handled all the requested cells

                            if (design.InterpolateHeight(ref hint,
                                                         originXPlusHalfCellSize + cellSize * x, originYPlusHalfCellSize + cellSize * y,
                                                         0, out var z))
                            {
                                // Check for composite elevation processing
                                if (patchType == SurveyedSurfacePatchType.CompositeElevations)
                                {
                                    // Set the first elevation if not already set
                                    if (patchComposite.Cells[x, y].FirstHeightTime == 0)
                                    {
                                        patchComposite.Cells[x, y].FirstHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].FirstHeight     = (float)z;
                                    }

                                    // Always set the latest elevation (surfaces ordered by increasing date)
                                    patchComposite.Cells[x, y].LastHeightTime = asAtDate;
                                    patchComposite.Cells[x, y].LastHeight     = (float)z;

                                    // Update the lowest height
                                    if (patchComposite.Cells[x, y].LowestHeightTime == 0 ||
                                        patchComposite.Cells[x, y].LowestHeight > z)
                                    {
                                        patchComposite.Cells[x, y].LowestHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].LowestHeight     = (float)z;
                                    }

                                    // Update the highest height
                                    if (patchComposite.Cells[x, y].HighestHeightTime == 0 ||
                                        patchComposite.Cells[x, y].HighestHeight > z)
                                    {
                                        patchComposite.Cells[x, y].HighestHeightTime = asAtDate;
                                        patchComposite.Cells[x, y].HighestHeight     = (float)z;
                                    }
                                }
                                else // earliest/latest singular value processing
                                {
                                    patchSingle.Times[x, y] = asAtDate;
                                    patchSingle.Cells[x, y] = (float)z;
                                }
                            }

                            // Only clear the processing bit if earliest or latest information is wanted from the surveyed surfaces
                            if (patchType != SurveyedSurfacePatchType.CompositeElevations)
                            {
                                processingMap.ClearBit(x, y);
                            }

                            return(true);
                        });
                    }
                    finally
                    {
                        designs.UnLock(thisSurveyedSurface.DesignDescriptor.DesignID, design);
                    }
                }

                calcResult = DesignProfilerRequestResult.OK;

                return(patch);
            }
            catch (Exception e)
            {
                _log.LogError(e, $"Exception occurred calculating surveyed surface patch, calcResult = {calcResult}");
                return(null);
            }
        }