예제 #1
0
        public void Test_SubGridTreeBitmapSubGridBitsTests_SetBitValue()
        {
            // Test setting a bit on and off, at two corners to test boundary conditions
            SubGridTreeBitmapSubGridBits bits = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            bits.SetBitValue(0, 0, true);

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

            bits.SetBitValue(0, 0, false);

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

            bits.SetBitValue(31, 31, true);

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

            bits.SetBitValue(31, 31, false);

            Assert.Equal(0U, bits.Bits[31]);
            Assert.Equal(0, bits.CountBits());
        }
예제 #2
0
        /// <summary>
        /// Computes a filter patch for a sub grid with respect to the alignment and a station/offset range over the alignment.
        /// Note: This is a CPU intensive operation. TRex currently uses an approach of polygonal spatial filtering with a boundary
        /// computed from the alignment geometry and station/offset bounds.
        /// </summary>
        public override bool ComputeFilterPatch(double startStn, double endStn, double leftOffset, double rightOffset,
                                                SubGridTreeBitmapSubGridBits mask, SubGridTreeBitmapSubGridBits patch,
                                                double originX, double originY, double cellSize, double offset)
        {
            var leftOffsetValue  = -leftOffset;
            var rightOffsetValue = rightOffset;

            if (leftOffsetValue > rightOffsetValue)
            {
                MinMax.Swap(ref leftOffsetValue, ref rightOffsetValue);
            }

            //   SIGLogMessage.PublishNoODS(Self, Format('Constructing filter patch for Stn:%.3f-%.3f, Ofs:%.3f-%.3f, originX:%.3f, originY:%.3f',
            //   [startStn, endStn, LeftOffsetValue, RightOffsetValue, originX, originY]));

            if (_data == null)
            {
                _log.LogError("No data element provided to SVL filter patch calculation");
                return(false);
            }

            patch.Clear();

            // Check the corners of the sub grid. If all are out of the offset range then assume
            // none of the cells are applicable. All four corners need to be on the same side of the
            // alignment in terms of offset to fail the sub grid.
            var cornersOutOfOffsetRange     = 0;
            var cornersOutOfOffsetRangeSign = 0;

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

            for (var i = 0; i < _corners.Length; i++)
            {
                _data.ComputeStnOfs(originXPlusHalfCellSize + _corners[i].X * cellSize, originYPlusHalfCellSize + _corners[i].Y * cellSize, out var stn, out var ofs);

                if (!(stn != Consts.NullDouble && ofs != Consts.NullDouble && Range.InRange(stn, startStn, endStn)) &&
                    !Range.InRange(ofs, leftOffsetValue, rightOffsetValue))
                {
                    if (i == 0)
                    {
                        cornersOutOfOffsetRangeSign = Math.Sign(ofs);
                    }

                    if (cornersOutOfOffsetRangeSign == Math.Sign(ofs))
                    {
                        cornersOutOfOffsetRange++;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (cornersOutOfOffsetRange == _corners.Length)
            {
                // Return success with the empty patch
                //SIGLogMessage.PublishNoODS(Self, 'All corners of patch exceed stn:ofs boundary');
                return(true);
            }

            // Iterate across the cells in the mask computing and checking the stn:ofs of
            // each point using the previously successful element as a hint for the next
            // computation
            for (var i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++)
            {
                for (var j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++)
                {
                    if (!mask.BitSet(i, j))
                    {
                        continue;
                    }

                    // Force element to be nil for all calculation until we resolve the issue
                    // of an in appropriate element 'capturing' the focus and then being used to
                    // calculate inappropriate offsets due to it's station range covering the
                    // points being computed.

                    NFFStationedLineworkEntity element = null;

                    _data.ComputeStnOfs(originXPlusHalfCellSize + i * cellSize, originYPlusHalfCellSize + j * cellSize,
                                        out var stn, out var ofs, ref element);

                    if (stn != Consts.NullDouble && ofs != Consts.NullDouble)
                    {
                        patch.SetBitValue(i, j, Range.InRange(stn, startStn, endStn) && Range.InRange(ofs, leftOffsetValue, rightOffsetValue));
                    }
                }
            }

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

            return(true);
        }