Exemple #1
0
        public void ProcessElevationInformationForSubGrid(int cellOriginX, int cellOriginY, float[,] baseSubGrid, float[,] topSubGrid)
        {
            // FCellArea is a handy place to store the cell area, rather than calculate it all the time (value wont change);
            var cellArea = CellSize * CellSize;

            var bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            CellsScanned += SubGridTreeConsts.SubGridTreeCellsPerSubGrid;

            for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++)
            {
                for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++)
                {
                    var topZ  = topSubGrid[i, j];
                    var baseZ = baseSubGrid[i, j];

                    if (baseZ != Consts.NullHeight && topZ != Consts.NullHeight)
                    {
                        CellsUsed++;

                        //  Note the fact we have processed this cell in the coverage map
                        bits.SetBit(i, j);

                        var cellUsedInVolumeCalc = (topZ - baseZ >= FillTolerance) || (baseZ - topZ >= CutTolerance);

                        // Accumulate volumes
                        if (cellUsedInVolumeCalc)
                        {
                            var volumeDifference = cellArea * (topZ - baseZ);

                            // Accumulate the 'surplus' volume. Ie: the simple summation of
                            // all cuts and fills.
                            Volume += volumeDifference;

                            // Accumulate the cuts and fills into discrete cut and fill quantities
                            if (topZ < baseZ)
                            {
                                CellsUsedCut++;
                                CutFillVolume.AddCutVolume(Math.Abs(volumeDifference));
                            }
                            else
                            {
                                CellsUsedFill++;
                                CutFillVolume.AddFillVolume(Math.Abs(volumeDifference));
                            }
                        }
                        else
                        {
                            // Note the fact there was no volume change in this cell
                            // NoChangeMap.Cells[BaseScanSubGrid.OriginX + I, BaseScanSubGrid.OriginY + J] := True;
                        }
                    }
                    else
                    {
                        CellsDiscarded++;
                    }
                }
            }

            // Record the bits for this sub grid in the coverage map by requesting the whole sub grid
            // of bits from the leaf level and setting it in one operation under an exclusive lock
            if (!bits.IsEmpty())
            {
                var coverageMapSubGrid = CoverageMap.ConstructPathToCell(cellOriginX, cellOriginY, SubGridPathConstructionType.CreateLeaf);
                ((SubGridTreeLeafBitmapSubGrid)coverageMapSubGrid).Bits = bits;
            }
        }
Exemple #2
0
        protected void ProcessVolumeInformationForSubGrid(ClientHeightLeafSubGrid baseScanSubGrid,
                                                          ClientHeightLeafSubGrid topScanSubGrid)
        {
            _log.LogDebug("In ProcessVolumeInformationForSubGrid");

            try
            {
                // DesignHeights represents all the valid spot elevations for the cells in the
                // sub grid being processed
                (IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult profilerRequestResult)getDesignHeightsResult = (null, DesignProfilerRequestResult.UnknownError);

                // FCellArea is a handy place to store the cell area, rather than calculate it all the time (value wont change);
                var cellArea = CellSize * CellSize;

                // Query the patch of elevations from the surface model for this sub grid
                if (ActiveDesign?.Design != null)
                {
                    _log.LogDebug("About to call ActiveDesign.Design.GetDesignHeightsViaLocalCompute()");

                    getDesignHeightsResult = ActiveDesign.Design.GetDesignHeightsViaLocalCompute(SiteModel, ActiveDesign.Offset, baseScanSubGrid.OriginAsCellAddress(), CellSize);

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

                var bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

                // ReSharper disable once CompareOfFloatsByEqualityOperator
                var standardVolumeProcessing = LiftParams.TargetLiftThickness == Consts.NullHeight || LiftParams.TargetLiftThickness <= 0;

                var localCellsScanned   = 0;
                var localCellsUsed      = 0;
                var localCellsDiscarded = 0;
                var localCellsUsedCut   = 0;
                var localCellsUsedFill  = 0;
                var localVolume         = 0.0d;
                var localCutFillVolume  = new CutFillVolume(0, 0);

                // If we are interested in standard volume processing use this cycle
                if (standardVolumeProcessing)
                {
                    localCellsScanned += SubGridTreeConsts.SubGridTreeCellsPerSubGrid;

                    for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++)
                    {
                        for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++)
                        {
                            float topZ;
                            var   baseZ = baseScanSubGrid.Cells[i, j];

                            // If the user has configured a first pass thickness, then we need to subtract this height
                            // difference from the BaseZ retrieved from the current cell if this measured height was
                            // the first pass made in the cell.
                            if (LiftParams.FirstPassThickness > 0)
                            {
                                baseZ -= LiftParams.FirstPassThickness;
                            }

                            if (VolumeType == VolumeComputationType.BetweenFilterAndDesign ||
                                VolumeType == VolumeComputationType.BetweenDesignAndFilter)
                            {
                                topZ = getDesignHeightsResult.designHeights?.Cells[i, j] ?? Consts.NullHeight;

                                if (VolumeType == VolumeComputationType.BetweenDesignAndFilter)
                                {
                                    MinMax.Swap(ref baseZ, ref topZ);
                                }
                            }
                            else
                            {
                                topZ = topScanSubGrid.Cells[i, j];
                            }

                            switch (VolumeType)
                            {
                            case VolumeComputationType.None:
                                break;

                            case VolumeComputationType.AboveLevel:
                            {
                                // ReSharper disable once CompareOfFloatsByEqualityOperator
                                if (baseZ != Consts.NullHeight)
                                {
                                    localCellsUsed++;
                                    if (baseZ > BaseLevel)
                                    {
                                        localVolume += cellArea * (baseZ - BaseLevel);
                                    }
                                }
                                else
                                {
                                    localCellsDiscarded++;
                                }

                                break;
                            }

                            case VolumeComputationType.Between2Levels:
                            {
                                // ReSharper disable once CompareOfFloatsByEqualityOperator
                                if (baseZ != Consts.NullHeight)
                                {
                                    localCellsUsed++;

                                    if (baseZ > BaseLevel)
                                    {
                                        localVolume += cellArea * (baseZ < TopLevel ? (baseZ - BaseLevel) : (TopLevel - BaseLevel));
                                    }
                                }
                                else
                                {
                                    localCellsDiscarded++;
                                }

                                break;
                            }

                            case VolumeComputationType.AboveFilter:
                            case VolumeComputationType.Between2Filters:
                            case VolumeComputationType.BetweenFilterAndDesign:
                            case VolumeComputationType.BetweenDesignAndFilter:
                            {
                                // ReSharper disable once CompareOfFloatsByEqualityOperator
                                if (baseZ != Consts.NullHeight &&
                                    // ReSharper disable once CompareOfFloatsByEqualityOperator
                                    topZ != Consts.NullHeight)
                                {
                                    localCellsUsed++;

                                    //  Note the fact we have processed this cell in the coverage map
                                    bits.SetBit(i, j);

                                    var cellUsedInVolumeCalc = (topZ - baseZ >= FillTolerance) || (baseZ - topZ >= CutTolerance);

                                    // Accumulate volumes
                                    if (cellUsedInVolumeCalc)
                                    {
                                        var volumeDifference = cellArea * (topZ - baseZ);

                                        // Accumulate the 'surplus' volume. Ie: the simple summation of
                                        // all cuts and fills.
                                        localVolume += volumeDifference;

                                        // Accumulate the cuts and fills into discrete cut and fill quantities
                                        if (topZ < baseZ)
                                        {
                                            localCellsUsedCut++;
                                            localCutFillVolume.AddCutVolume(Math.Abs(volumeDifference));
                                        }
                                        else
                                        {
                                            localCellsUsedFill++;
                                            localCutFillVolume.AddFillVolume(Math.Abs(volumeDifference));
                                        }
                                    }
                                    else
                                    {
                                        // Note the fact there was no volume change in this cell
                                        // NoChangeMap.Cells[BaseScanSubGrid.OriginX + I, BaseScanSubGrid.OriginY + J] := True;
                                    }
                                }
                                else
                                {
                                    localCellsDiscarded++;
                                }
                            }
                            break;

                            default:
                                _log.LogError($"Unknown volume type {VolumeType} in ProcessVolumeInformationForSubGrid()");
                                break;
                            }
                        }
                    }
                }

                // ReSharper disable once CompareOfFloatsByEqualityOperator
                var targetLiftThicknessCalculationsRequired = LiftParams.TargetLiftThickness != Consts.NullHeight && LiftParams.TargetLiftThickness > 0;

                //If we are interested in thickness calculations do them
                if (targetLiftThicknessCalculationsRequired)
                {
                    var belowToleranceToCheck = LiftParams.TargetLiftThickness - LiftParams.BelowToleranceLiftThickness;
                    var aboveToleranceToCheck = LiftParams.TargetLiftThickness + LiftParams.AboveToleranceLiftThickness;

                    SubGridUtilities.SubGridDimensionalIterator((i, j) =>
                    {
                        var baseZ = baseScanSubGrid.Cells[i, j];
                        var topZ  = topScanSubGrid.Cells[i, j];

                        // ReSharper disable once CompareOfFloatsByEqualityOperator
                        if (baseZ != Consts.NullHeight ||
                            // ReSharper disable once CompareOfFloatsByEqualityOperator
                            topZ != Consts.NullHeight)
                        {
                            localCellsScanned++;
                        }

                        //Test if we don't have NULL values and carry on
                        // ReSharper disable once CompareOfFloatsByEqualityOperator
                        if (baseZ != Consts.NullHeight &&
                            // ReSharper disable once CompareOfFloatsByEqualityOperator
                            topZ != Consts.NullHeight)
                        {
                            bits.SetBit(i, j);
                            double elevationDiff = topZ - baseZ;

                            if (elevationDiff <= aboveToleranceToCheck && elevationDiff >= belowToleranceToCheck)
                            {
                                localCellsUsed++;
                            }
                            else if (elevationDiff > aboveToleranceToCheck)
                            {
                                localCellsUsedFill++;
                            }
                            else if (elevationDiff < belowToleranceToCheck)
                            {
                                localCellsUsedCut++;
                            }
                        }
                        else
                        {
                            localCellsDiscarded++;
                        }
                    });
                }

                // Update the quantities in the aggregator proper
                // Note: the lock is not asynchronous as this will be highly non-contended
                _lock.Wait();
                try
                {
                    CellsScanned   += localCellsScanned;
                    CellsUsed      += localCellsUsed;
                    CellsDiscarded += localCellsDiscarded;
                    CellsUsedCut   += localCellsUsedCut;
                    CellsUsedFill  += localCellsUsedFill;
                    Volume         += localVolume;
                    CutFillVolume.AddCutFillVolume(localCutFillVolume.CutVolume, localCutFillVolume.FillVolume);

                    // Record the bits for this sub grid in the coverage map by requesting the whole sub grid
                    // of bits from the leaf level and setting it in one operation under an exclusive lock
                    if (!bits.IsEmpty())
                    {
                        var coverageMapSubGrid = CoverageMap.ConstructPathToCell(baseScanSubGrid.OriginX, baseScanSubGrid.OriginY, SubGridPathConstructionType.CreateLeaf);
                        ((SubGridTreeLeafBitmapSubGrid)coverageMapSubGrid).Bits = bits;
                    }
                }
                finally
                {
                    _lock.Release();
                }
            }
            catch (Exception e)
            {
                _log.LogError(e, "Exception thrown by ProcessVolumeInformationForSubGrid - rethrowing");
                throw;
            }
            finally
            {
                _log.LogDebug("Out ProcessVolumeInformationForSubGrid");
            }
        }
Exemple #3
0
        protected void Scan_triangle_line(int _y, double x1, double x2, ref int NumImportUpdates)
        {
            int _x;
            SubGridTreeLeafBitmapSubGrid ExistenceBitMask;
            bool YOrdinateIsASeedVertexRow;
            int  BitMaskCacheSubgridIndex;

            void GetInUseExistenceMap()
            {
                if (CachedInUseMaps[BitMaskCacheSubgridIndex].TriangleScanInvocationNumber == TriangleScanInvocationNumber)
                {
                    ExistenceBitMask = CachedInUseMaps[BitMaskCacheSubgridIndex].InUseMap;
                }
                else
                {
                    ExistenceBitMask = (SubGridTreeLeafBitmapSubGrid)IsUsed.ConstructPathToCell(_x, _y, SubGridPathConstructionType.ReturnExistingLeafOnly);
                    CachedInUseMaps[BitMaskCacheSubgridIndex].InUseMap = ExistenceBitMask;
                    CachedInUseMaps[BitMaskCacheSubgridIndex].TriangleScanInvocationNumber = TriangleScanInvocationNumber;
                }
            }

            int startx = (int)Math.Ceiling(Math.Min(x1, x2));
            int endx   = (int)Math.Floor(Math.Max(x1, x2));

            if (startx > endx)
            {
                return;
            }

            double z0 = Zplane.Evaluate(startx, _y);
            double dz = Zplane.a;

            _x = startx;

            int BitMaskIndexX = _x & SubGridTreeConsts.SubGridLocalKeyMask;
            int BitMaskIndexY = _y & SubGridTreeConsts.SubGridLocalKeyMask;

            // Get the initial ExistenceBitMask from the bitmask cache
            BitMaskCacheSubgridIndex = startx / SubGridTreeConsts.SubGridTreeDimension - InUse_MinXTriangleScanRange / SubGridTreeConsts.SubGridTreeDimension;
            GetInUseExistenceMap();

            YOrdinateIsASeedVertexRow = _y % YSeedIntervalStep == 0;

            int NumElevationsToScan = endx - startx + 1;

            if (NumElevationsToScan > Elevations.Length)
            {
                Array.Resize(ref Elevations, NumElevationsToScan + 100);
            }

            GetHeightForTriangleScan(startx, _y, false, NumElevationsToScan, Elevations);

            for (int I = 0; I < NumElevationsToScan; I++)
            {
                if (ExistenceBitMask == null || !ExistenceBitMask.Bits.BitSet(BitMaskIndexX, BitMaskIndexY))
                {
                    double _z = Elevations[I];

                    // If the 'z' at this location is the null elevation then do not include it as a potential candidate
                    if (_z != NullVertexHeight)
                    {
                        double Diff = Math.Abs(_z - z0);

                        // Note: There is a final 'IsUsed' check to make sure this point is not one of the
                        // initial seed points placed into the TIN surface
                        if (Diff > Candidate.Import)
                        {
                            if (!YOrdinateIsASeedVertexRow || _x % XSeedIntervalStep != 0)
                            {
                                Candidate.Import = Diff;
                                Candidate.X      = _x;
                                Candidate.Y      = _y;
                                Candidate.Z      = _z;
                                NumImportUpdates++;
                            }
                        }
                    }
                }

                z0 += dz;
                _x++;

                BitMaskIndexX++;
                if (BitMaskIndexX == SubGridTreeConsts.SubGridTreeDimension && I != NumElevationsToScan - 1)
                {
                    BitMaskCacheSubgridIndex++;
                    GetInUseExistenceMap();
                    BitMaskIndexX = 0;
                }
            }
        }