/// <summary>
        /// Resizing the <paramref name="idx"/> layer (0 is top most layer) to have new length of <paramref name="newLength"/>
        /// </summary>
        /// <param name="idx">zero-based. 0 is on top, regardless annotation direction</param>
        /// <param name="newLength">in meteres</param>
        /// <param name="fromButtomToUp"></param>
        public void SetLayerLength(int idx, double newLength, AnnotationDirection direction)
        {
            double[] newDepthBoundaries = LayerLengthEditWithShift(depthBoundaries, idx, newLength, direction);
            if (newDepthBoundaries.Length < depthBoundaries.Length)
            {
                //layer removals is required (as they are pushed out)
                int toRemove = depthBoundaries.Length - newDepthBoundaries.Length;
                switch (direction)
                {
                case AnnotationDirection.UpToBottom:
                    for (int i = 0; i < toRemove; i++)
                    {
                        RemoveLayer(depthBoundaries.Length - 2, FreeSpaceAccepter.UpperLayer);
                    }
                    break;

                case AnnotationDirection.BottomToUp:
                    for (int i = 0; i < toRemove; i++)
                    {
                        RemoveLayer(0, FreeSpaceAccepter.LowerLayer);
                    }
                    break;

                default:
                    throw new NotSupportedException("unexpected annotation direction");
                }
            }
            //now appling new depths
            System.Diagnostics.Debug.Assert(depthBoundaries.Length == newDepthBoundaries.Length);
            depthBoundaries = newDepthBoundaries;
            ResetAllcolumns();
        }
Esempio n. 2
0
 /// <param name="wpfHeight">The column height in WPF units</param>
 public LayerBoundaryEditorVM(double wpfHeight, int maxRank, AnnotationDirection annotationDirection)
 {
     Boundaries = new LayerBoundary[] {
         new LayerBoundary(0.0, maxRank),
         new LayerBoundary(wpfHeight, maxRank)
     };
     AnnotationDirection = annotationDirection;
 }
Esempio n. 3
0
        /// <summary>
        /// Fills in Number array of each boundary with respect to the annotation direction
        /// </summary>
        /// <param name="boundaries">Including outer boundaries of the first and last layer</param>
        /// <returns></returns>
        public static void RecalcBoundaryNumbers(LayerBoundary[] boundaries, AnnotationDirection direction)
        {
            if (boundaries.Length == 0)
            {
                return;
            }

            //asserting conditions
            int maxRank = boundaries.Select(b => b.Rank).Max();

            if (boundaries[0].Rank != maxRank)
            {
                new ArgumentException("the first boundary must be outer boundaries having the max rank");
            }
            if (boundaries[boundaries.Length - 1].Rank != maxRank)
            {
                new ArgumentException("the last boundary must be outer boundaries having the max rank");
            }

            int N = boundaries.Length;

            int[] recentNumbers = Enumerable.Repeat(0, maxRank + 1).ToArray();

            switch (direction)
            {
            case AnnotationDirection.UpToBottom:
                for (int i = 0; i < N; i++)
                {
                    LayerBoundary lb = boundaries[i];
                    int           maxIdxToAccount = lb.Rank;

                    //updating recent numbers
                    recentNumbers[maxIdxToAccount]++;     //highest rank number increases
                    for (int j = 0; j < maxIdxToAccount; j++)
                    {
                        recentNumbers[j] = 1;     //lower numbers reset ot 1
                    }
                    //now copying the part of the recentNumbers to the lb.Number
                    lb.Numbers = recentNumbers.Take(maxIdxToAccount + 1).ToArray();
                }
                break;

            case AnnotationDirection.BottomToUp:

                for (int i = N - 1; i >= 0; i--)
                {
                    LayerBoundary lb = boundaries[i];

                    if (i == N - 1)
                    {
                        //lower boundary always contains all zeros, thus skipping it
                        lb.Numbers = recentNumbers.ToArray();
                        continue;
                    }

                    int maxIdxToAccount = lb.Rank;

                    //updating recent numbers
                    for (int j = 0; j <= maxIdxToAccount; j++)
                    {
                        recentNumbers[j]++;
                    }

                    //coping updated recent to the boundary
                    lb.Numbers = recentNumbers.Take(maxIdxToAccount + 1).ToArray();

                    //reseting lower rank recent numbers
                    for (int j = 0; j < maxIdxToAccount; j++)
                    {
                        recentNumbers[j] = 0;
                    }
                }

                break;

            default:
                throw new NotSupportedException();
                break;
            }

            return;
        }
        /// <summary>
        /// Forms a table by filling it with supplied data
        /// </summary>
        /// <param name="intervals"></param>
        /// <param name="boundaries">including the "outer boundaries" of bounding layer</param>
        /// <param name="layers"></param>
        /// <param name="isDepthIncreases">true if depth increases (other parameter arrays are sorted so the depth increases)</param>
        /// <param name="samples">All samples in the project</param>
        /// <returns></returns>
        public static CSV.ReportTable GenerateCVSTableContents(
            Intervals.BoreIntervalVM[] intervals,
            RTF.LayerBoundary[] boundaries,
            RTF.LayerDescrition[] layers,
            string[] rankNames,
            RTF.Sample[] samples,
            AnnotationDirection annotationDirection,
            AnnotationPlane.Template.Property[] allProperties,
            string[] genRankNames
            )
        {
            List <KeyValuePair <double, int> > intBounds = new List <KeyValuePair <double, int> >();

            for (int i = 0; i < intervals.Length; i++)
            {
                Intervals.BoreIntervalVM interval = intervals[i];
                if (interval.LowerDepth < interval.UpperDepth)
                {
                    throw new ArgumentException("The upper bound is lower than lower bound");
                }
                intBounds.Add(new KeyValuePair <double, int>(interval.UpperDepth, 1));
                intBounds.Add(new KeyValuePair <double, int>(interval.LowerDepth, -1));
            }
            double[] keys = intBounds.Select(kvp => kvp.Key).ToArray();
            foreach (int key in keys)
            {
                int curKeyValsSum = intBounds.Where(kvp => kvp.Key == key).Sum(kvp => kvp.Value);
                if (curKeyValsSum == 0)
                {
                    intBounds = intBounds.Where(kvp => kvp.Key != key).ToList();
                }
            }

            int[] events = intBounds.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).ToArray();
            int   sum    = 0;

            for (int i = 0; i < events.Length; i++)
            {
                sum += events[i];
                if (Math.Abs(sum) > 1)
                {
                    throw new InvalidOperationException("You've passed intersecting intervals");
                }
            }


            List <CSV.ReportRow> rows = new List <CSV.ReportRow>();

            if (boundaries.Length - 1 != layers.Length)
            {
                throw new ArgumentException("Layers count must be exactly one more than boundary count");
            }

            string directionString = string.Empty;

            switch (annotationDirection)
            {
            case AnnotationDirection.UpToBottom:
                directionString = "сверху вниз";
                break;

            case AnnotationDirection.BottomToUp:
                directionString = "снизу вверх";
                break;
            }

            List <string> allColumnsList = new List <string>();

            allColumnsList.Add("№ " + genRankNames[0]);
            allColumnsList.Add("№ " + genRankNames[1]);
            allColumnsList.Add("№ " + genRankNames[2]);
            allColumnsList.Add("Верхняя граница слоя (м)");
            allColumnsList.Add("Нижняя граница слоя (м)");

            foreach (AnnotationPlane.Template.Property prop in allProperties)
            {
                allColumnsList.Add(string.IsNullOrEmpty(prop.Name) ? prop.Name : prop.ID);
            }

            CSV.ReportRow header = new CSV.ReportRow(allColumnsList.ToArray());
            rows.Add(header);

            int reportedInIndex;
            int inIndex;
            int laIndex;
            int layerOrderNum;
            int group_number = 1;
            int pack_number  = 1;

            switch (annotationDirection)
            {
            case AnnotationDirection.UpToBottom:
                intervals = intervals.OrderBy(i => i.UpperDepth).ToArray();
                for (int i = 0; i < boundaries.Length - 1; i++)
                {
                    if (boundaries[i + 1].Depth < boundaries[i].Depth)
                    {
                        throw new NotSupportedException("Boundary depths must increase");
                    }
                }

                reportedInIndex = -1;
                inIndex         = 0;
                laIndex         = 0;
                layerOrderNum   = 1;
                while (inIndex < intervals.Length && laIndex < layers.Length)
                {
                    if (reportedInIndex != inIndex)
                    {
                        reportedInIndex = inIndex;
                    }
                    RTF.LayerBoundary upperLabound = boundaries[laIndex];
                    double            curLaUpper   = upperLabound.Depth;
                    double            curLaLower   = boundaries[laIndex + 1].Depth;
                    double            curIntUpper  = intervals[inIndex].UpperDepth;
                    double            curIntLower  = intervals[inIndex].UpperDepth + intervals[inIndex].ExtractedLength;
                    bool doInInc       = false;
                    bool doLaInc       = false;
                    bool skipReporting = false;

                    if (curIntLower >= curLaLower)
                    {
                        if (curIntUpper > curLaLower)
                        {
                            skipReporting = true;
                        }
                        else
                        {
                            if (curIntUpper > curLaUpper)
                            {
                                curLaUpper = curIntUpper;
                            }
                        }
                        doLaInc = true;
                    }
                    else
                    {
                        curLaLower = curIntLower;
                        if (curIntUpper > curLaUpper)
                        {
                            curLaUpper = curIntUpper;
                        }

                        doInInc = true;
                    }

                    List <int> group_pack = GetGroupPackNumbersForUpperLaBound(upperLabound, laIndex, boundaries, curIntLower, rankNames);

                    switch (upperLabound.Rank)
                    {
                    case 2:
                        group_number  = group_pack[0];
                        pack_number   = 1;
                        layerOrderNum = 1;
                        break;

                    case 1:
                        pack_number   = group_pack[0];
                        layerOrderNum = 1;
                        break;

                    default:
                        break;
                    }

                    if (!skipReporting)
                    {
                        var layerSamples = samples.Where(s => (s.Depth > curLaUpper) && (s.Depth < curLaLower)).ToArray();
                        rows.Add(GetLayerDescrRow(layerOrderNum++, curLaLower, curLaUpper, layers[laIndex], layerSamples, group_number, pack_number, allProperties));
                    }
                    if (doLaInc)
                    {
                        laIndex++;
                    }
                    if (doInInc)
                    {
                        inIndex++;
                    }
                }
                break;

            case AnnotationDirection.BottomToUp:
                intervals = intervals.OrderBy(i => i.UpperDepth).ToArray();
                for (int i = boundaries.Length - 2; i >= 0; i--)
                {
                    if (boundaries[i + 1].Depth < boundaries[i].Depth)
                    {
                        throw new NotSupportedException("Boundary depths must increase");
                    }
                }

                reportedInIndex = intervals.Length;
                inIndex         = intervals.Length - 1;
                laIndex         = layers.Length - 1;
                layerOrderNum   = 1;
                while (inIndex >= 0 && laIndex >= 0)
                {
                    if (reportedInIndex != inIndex)
                    {
                        reportedInIndex = inIndex;
                    }
                    RTF.LayerBoundary upperLabound = boundaries[laIndex];
                    RTF.LayerBoundary lowerLaBound = boundaries[laIndex + 1];
                    double            curLaUpper   = upperLabound.Depth;
                    double            curLaLower   = boundaries[laIndex + 1].Depth;
                    double            curIntUpper  = intervals[inIndex].UpperDepth;
                    double            curIntLower  = intervals[inIndex].UpperDepth + intervals[inIndex].ExtractedLength;
                    bool doInDec       = false;
                    bool doLaDec       = false;
                    bool skipReporting = false;

                    if (curIntUpper <= curLaUpper)
                    {
                        if (curIntLower < curLaUpper)
                        {
                            skipReporting = true;
                        }
                        else
                        {
                            if (curIntLower < curLaLower)
                            {
                                curLaLower = curIntLower;
                            }
                        }
                        doLaDec = true;
                    }
                    else
                    {
                        curLaUpper = curIntUpper;
                        if (curIntLower < curLaLower)
                        {
                            curLaLower = curIntLower;
                        }

                        doInDec = true;
                    }

                    if (!skipReporting)
                    {
                        List <int> group_pack = GetGroupPackNumbersForLowerLaBound(lowerLaBound, laIndex, boundaries, curIntUpper, rankNames);

                        switch (lowerLaBound.Rank)
                        {
                        case 2:
                            group_number  = group_pack[0];
                            pack_number   = group_pack[1];
                            layerOrderNum = 1;
                            break;

                        case 1:
                            pack_number   = group_pack[0];
                            layerOrderNum = 1;
                            break;

                        default:
                            break;
                        }

                        var layerSamples = samples.Where(s => (s.Depth > curLaUpper) && (s.Depth < curLaLower)).ToArray();
                        rows.Add(GetLayerDescrRow(layerOrderNum++, curLaLower, curLaUpper, layers[laIndex], layerSamples, group_number, pack_number, allProperties));
                    }
                    if (doLaDec)
                    {
                        laIndex--;
                    }
                    if (doInDec)
                    {
                        inIndex--;
                    }
                }
                break;

            default:
                throw new NotSupportedException();
            }

            return(new CSV.ReportTable(rows.ToArray()));
        }
        /// <summary>
        /// Forms a table by filling it with supplied data
        /// </summary>
        /// <param name="boundaries">including the "outer boundaries" of bounding layer</param>
        /// <param name="layers"></param>
        /// <param name="isDepthIncreases">true if depth increases (other parameter arrays are sorted so the depth increases)</param>
        /// <returns></returns>
        public static CSV.ReportTable GenerateCVSTableContents(
            RTF.LayerBoundary[] boundaries,
            RTF.LayerDescrition[] layers,
            AnnotationDirection annotationDirection,
            AnnotationPlane.Template.Property[] allProperties,
            string[] genRankNames
            )
        {
            List <CSV.ReportRow> rows = new List <CSV.ReportRow>();

            if (boundaries.Length - 1 != layers.Length)
            {
                throw new ArgumentException("Layers count must be exactly one more than boundary count");
            }

            List <string> allColumnsList = new List <string>();

            for (int i = genRankNames.Length - 1; i >= 0; i--)
            {
                allColumnsList.Add(string.Format("№ {0}", genRankNames[i]));
            }
            allColumnsList.Add("Верхняя граница слоя (м)");
            allColumnsList.Add("Нижняя граница слоя (м)");

            foreach (AnnotationPlane.Template.Property prop in allProperties)
            {
                allColumnsList.Add(string.IsNullOrEmpty(prop.Name) ? prop.Name : prop.ID);
            }

            CSV.ReportRow header = new CSV.ReportRow(allColumnsList.ToArray());
            rows.Add(header);

            int[] ranksNumbers = Enumerable.Repeat(1, genRankNames.Length).ToArray();

            switch (annotationDirection)
            {
            case AnnotationDirection.UpToBottom:
                for (int i = 0; i < layers.Length; i++)
                {
                    for (int j = 0; j < boundaries[i].OrderNumbers.Length; j++)
                    {
                        ranksNumbers[j] = boundaries[i].OrderNumbers[j];
                    }
                    rows.Add(GetLayerDescrRow(boundaries[i + 1].Depth, boundaries[i].Depth, layers[i], ranksNumbers, allProperties));
                }


                break;

            case AnnotationDirection.BottomToUp:
                for (int i = layers.Length - 1; i >= 0; i--)
                {
                    rows.Add(GetLayerDescrRow(boundaries[i + 1].Depth, boundaries[i].Depth, layers[i], ranksNumbers, allProperties));
                    ranksNumbers[boundaries[i].OrderNumbers.Length - 1] = boundaries[i].OrderNumbers[boundaries[i].OrderNumbers.Length - 1] + 1;
                    for (int j = 0; j < boundaries[i].OrderNumbers.Length - 1; j++)
                    {
                        ranksNumbers[j] = 1;
                    }
                }
                break;

            default:
                throw new NotSupportedException();
            }

            return(new CSV.ReportTable(rows.ToArray()));
        }
Esempio n. 6
0
        /// <summary>
        /// Forms a table by filling it with supplied data
        /// </summary>
        /// <param name="boundaries">including the "outer boundaries" of bounding layer</param>
        /// <param name="samples">All samples in the project</param>
        /// <returns></returns>
        public static ReportTable GenerateTableContents(
            Intervals.BoreIntervalVM[] intervals,
            LayerBoundary[] boundaries,
            LayerDescrition[] layers,
            string[] rankNames,
            Sample[] samples,
            AnnotationDirection annotationDirection)
        {
            //asserting intervals
            //lower - upper bounds order
            //intersection check
            List <KeyValuePair <double, int> > intBounds = new List <KeyValuePair <double, int> >();

            for (int i = 0; i < intervals.Length; i++)
            {
                Intervals.BoreIntervalVM interval = intervals[i];
                if (interval.LowerDepth < interval.UpperDepth)
                {
                    throw new ArgumentException("The upper bound is lower than lower bound");
                }
                intBounds.Add(new KeyValuePair <double, int>(interval.UpperDepth, 1));  // +1 opens the interval
                intBounds.Add(new KeyValuePair <double, int>(interval.LowerDepth, -1)); // -1 closes the interval
            }
            // detecting intervals with touching bounds; removing these bounds
            double[] keys = intBounds.Select(kvp => kvp.Key).ToArray();
            foreach (int key in keys)
            {
                int curKeyValsSum = intBounds.Where(kvp => kvp.Key == key).Sum(kvp => kvp.Value);
                if (curKeyValsSum == 0)
                {
                    intBounds = intBounds.Where(kvp => kvp.Key != key).ToList();
                }
            }

            int[] events = intBounds.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).ToArray();
            int   sum    = 0;

            for (int i = 0; i < events.Length; i++)
            {
                sum += events[i];
                if (Math.Abs(sum) > 1)
                {
                    throw new InvalidOperationException("You've passed intersecting intervals");
                }
            }


            List <ReportRow> rows = new List <ReportRow>();

            if (boundaries.Length - 1 != layers.Length)
            {
                throw new ArgumentException("Layers count must be exactly one more than boundary count");
            }

            string directionString = string.Empty;

            switch (annotationDirection)
            {
            case AnnotationDirection.UpToBottom:
                directionString = "сверху вниз";
                break;

            case AnnotationDirection.BottomToUp:
                directionString = "снизу вверх";
                break;
            }

            ReportRow header = new ReportRow(
                new TextCell[] {
                new TextCell(
                    string.Format("Описание керна {0}.\nИнтервал / выход керна в м.", directionString),
                    LeftColWidth, horizontalAlignement: TextAlignement.Centered, isBold: true),
                new TextCell("место отбора от начала керна, м; описание", RightcolWidth, horizontalAlignement: TextAlignement.Centered, isBold: true)
            });

            rows.Add(header);

            int reportedInIndex;
            int inIndex;
            int laIndex;
            int layerOrderNum;

            //for now works with increasing depths order
            switch (annotationDirection)
            {
            case AnnotationDirection.UpToBottom:
                intervals = intervals.OrderBy(i => i.UpperDepth).ToArray();
                for (int i = 0; i < boundaries.Length - 1; i++)
                {
                    if (boundaries[i + 1].Depth < boundaries[i].Depth)
                    {
                        throw new NotSupportedException("Boundary depths must increase");
                    }
                }

                reportedInIndex = -1;
                inIndex         = 0;
                laIndex         = 0;
                layerOrderNum   = 1;
                while (inIndex < intervals.Length && laIndex < layers.Length)
                {
                    if (reportedInIndex != inIndex)
                    {
                        //adding row depicting interval start
                        rows.Add(GetIntervalRow(intervals[inIndex].UpperDepth, intervals[inIndex].LowerDepth, intervals[inIndex].ExtractedLength));
                        reportedInIndex = inIndex;
                    }
                    LayerBoundary upperLabound  = boundaries[laIndex];
                    double        curLaUpper    = upperLabound.Depth;
                    double        curLaLower    = boundaries[laIndex + 1].Depth; //boundraies array always contains one more element than layers
                    double        curIntUpper   = intervals[inIndex].UpperDepth;
                    double        curIntLower   = intervals[inIndex].UpperDepth + intervals[inIndex].ExtractedLength;
                    bool          doInInc       = false;
                    bool          doLaInc       = false;
                    bool          skipReporting = false;

                    //analysing the relative position of the interval and the layer
                    if (curIntLower >= curLaLower)
                    {
                        //the interval includes the end of the layer or interval is entirly below the layer
                        if (curIntUpper > curLaLower)
                        {
                            //the entire interal is below the layer
                            skipReporting = true;     //the layer is not reported
                        }
                        else
                        {
                            if (curIntUpper > curLaUpper)
                            {
                                //coersing layer upper bound to match interval
                                curLaUpper = curIntUpper;
                            }
                        }
                        doLaInc = true;
                    }
                    else
                    {
                        //the layer includes the end of the interval
                        curLaLower = curIntLower;     //coersing layer lower bound to match interval
                        if (curIntUpper > curLaUpper)
                        {
                            //coersing layer upper bound to match interval
                            curLaUpper = curIntUpper;
                        }

                        doInInc = true;
                    }

                    if (!skipReporting)
                    {
                        if (upperLabound.Rank > 0)
                        {
                            //we need to add rank row
                            for (int rank = upperLabound.Rank; rank > 0; rank--)
                            {
                                double length = 0.0;
                                //calculating total length. starting from cur bound till the next bound of the same rank or higher
                                for (int i = laIndex + 1; i < boundaries.Length; i++)
                                {
                                    int curRank = boundaries[i].Rank;
                                    length += boundaries[i].Depth - boundaries[i - 1].Depth;
                                    if (curRank >= rank)
                                    {
                                        break;
                                    }
                                }

                                length = Math.Min(length, curIntLower - upperLabound.Depth);
                                rows.Add(GetRankDescrRow(upperLabound.OrderNumbers[rank], rankNames[rank], length));
                            }
                            layerOrderNum = 1;     //ranks higher than 0 reset the numbering of layers
                        }
                        var layerSamples = samples.Where(s => (s.Depth > curLaUpper) && (s.Depth < curLaLower)).ToArray();
                        rows.Add(GetLayerDescrRow(layerOrderNum++, curLaLower - curLaUpper, layers[laIndex], layerSamples));
                    }
                    if (doLaInc)
                    {
                        laIndex++;
                    }
                    if (doInInc)
                    {
                        inIndex++;
                    }
                }
                break;

            case AnnotationDirection.BottomToUp:
                intervals = intervals.OrderBy(i => i.UpperDepth).ToArray();
                for (int i = boundaries.Length - 2; i >= 0; i--)
                {
                    if (boundaries[i + 1].Depth < boundaries[i].Depth)
                    {
                        throw new NotSupportedException("Boundary depths must increase");
                    }
                }

                reportedInIndex = intervals.Length;
                inIndex         = intervals.Length - 1;
                laIndex         = layers.Length - 1;
                layerOrderNum   = 1;
                //while (inIndex < intervals.Length && laIndex < layers.Length)
                while (inIndex >= 0 && laIndex >= 0)
                {
                    if (reportedInIndex != inIndex)
                    {
                        //adding row depicting interval start
                        rows.Add(GetIntervalRow(intervals[inIndex].UpperDepth, intervals[inIndex].LowerDepth, intervals[inIndex].ExtractedLength));
                        reportedInIndex = inIndex;
                    }
                    LayerBoundary upperLabound  = boundaries[laIndex];
                    LayerBoundary lowerLaBound  = boundaries[laIndex + 1];
                    double        curLaUpper    = upperLabound.Depth;
                    double        curLaLower    = boundaries[laIndex + 1].Depth; //boundraies array always contains one more element than layers
                    double        curIntUpper   = intervals[inIndex].UpperDepth;
                    double        curIntLower   = intervals[inIndex].UpperDepth + intervals[inIndex].ExtractedLength;
                    bool          doInDec       = false;
                    bool          doLaDec       = false;
                    bool          skipReporting = false;

                    //analysing the relative position of the interval and the layer
                    //if (curIntLower >= curLaLower)
                    if (curIntUpper <= curLaUpper)
                    {
                        //the interval includes the end of the layer or interval is entirly alte the layer

                        //if (curIntUpper > curLaLower)
                        if (curIntLower < curLaUpper)
                        {
                            //the entire interal is after the layer
                            skipReporting = true;     //the layer is not reported
                        }
                        else
                        {
                            //if (curIntUpper > curLaUpper)
                            if (curIntLower < curLaLower)
                            {
                                //coersing layer lower bound to match interval

                                //curLaUpper = curIntUpper;
                                curLaLower = curIntLower;
                            }
                        }
                        doLaDec = true;
                    }
                    else
                    {
                        //the layer includes the end of the interval
                        //curLaLower = curIntLower; //coersing layer lower bound to match interval
                        curLaUpper = curIntUpper;     //coersing layer upper bound to match interval
                        //if (curIntUpper > curLaUpper)
                        if (curIntLower < curLaLower)
                        {
                            //coersing layer lower bound to match interval

                            //curLaUpper = curIntUpper;
                            curLaLower = curIntLower;
                        }

                        doInDec = true;
                    }

                    if (!skipReporting)
                    {
                        //if (upperLabound.Rank > 0)
                        if (lowerLaBound.Rank > 0)
                        {
                            //we need to add rank row
                            for (int rank = lowerLaBound.Rank; rank > 0; rank--)
                            {
                                double length = 0.0;
                                //calculating total length. starting from cur bound till the next bound of the same rank or higher
                                //for (int i = laIndex + 1; i < boundaries.Length; i++)
                                for (int i = laIndex; i >= 0; i--)
                                {
                                    int curRank = boundaries[i].Rank;
                                    //length += boundaries[i].Depth - boundaries[i - 1].Depth;
                                    length += boundaries[i + 1].Depth - boundaries[i].Depth;
                                    if (curRank >= rank)
                                    {
                                        break;
                                    }
                                }

                                //length = Math.Min(length, curIntLower - upperLabound.Depth);
                                length = Math.Min(length, lowerLaBound.Depth - curIntUpper);
                                if (rank == lowerLaBound.Rank)
                                {
                                    //as the lower boundary contains passed order number, we need to repot the next numbe (incremented by one)
                                    rows.Add(GetRankDescrRow(lowerLaBound.OrderNumbers[rank] + 1, rankNames[rank], length));
                                }
                                else
                                {
                                    //passing hight rank bundary means that lower rank numberings reset
                                    rows.Add(GetRankDescrRow(1, rankNames[rank], length));
                                }
                            }
                            layerOrderNum = 1;     //ranks higher than 0 reset the numbering of layers
                        }
                        var layerSamples = samples.Where(s => (s.Depth > curLaUpper) && (s.Depth < curLaLower)).ToArray();
                        rows.Add(GetLayerDescrRow(layerOrderNum++, curLaLower - curLaUpper, layers[laIndex], layerSamples));
                    }
                    if (doLaDec)
                    {
                        laIndex--;
                    }
                    if (doInDec)
                    {
                        inIndex--;
                    }
                }
                break;

            default:
                throw new NotSupportedException();
                break;
            }

            return(new ReportTable(rows.ToArray()));
        }
        /// <param name="idx">layer index. zero based. zero index is always the upper one</param>
        /// <returns>new depths</returns>
        public static double[] LayerLengthEditWithShift(double[] depths, int idx, double newLength, AnnotationDirection direction)
        {
            double[] results;
            if (newLength < 0)
            {
                throw new ArgumentException("newLength must be non-negative");
            }
            if ((idx < 0) || (idx >= depths.Length - 1))
            {
                throw new IndexOutOfRangeException("layer index");
            }
            if (newLength == 0.0)
            {
                newLength = MinLayerLength;
            }

            switch (direction)
            {
            case AnnotationDirection.UpToBottom:
                if (idx == depths.Length - 2)
                {     //the last layer length can't be edited
                    results = depths.ToArray();
                    return(results);
                }

                double oldLength = depths[idx + 1] - depths[idx];

                int    initialBoundaryCount = depths.Length;
                double lowerDepth           = depths[initialBoundaryCount - 1];

                double addition = newLength - oldLength;

                int    toRemove            = 0;
                double removedLayersLength = 0.0;
                while (
                    (depths.Length - 2 - toRemove > idx) &&     //do not proceed further corrected layer (affect the layers befor the idx)
                    (depths[depths.Length - 1 - toRemove] - depths[depths.Length - 2 - toRemove] + removedLayersLength <= addition))
                {
                    removedLayersLength += depths[depths.Length - 1 - toRemove] - depths[depths.Length - 2 - toRemove];
                    toRemove++;
                }
                System.Diagnostics.Trace.WriteLine("{0} layers to remove");

                results = depths.Take(initialBoundaryCount - toRemove).ToArray();
                for (int i = idx + 1; i < initialBoundaryCount - toRemove - 1; i++)
                {
                    results[i] += addition;
                }
                results[initialBoundaryCount - toRemove - 1] = lowerDepth;
                break;

            case AnnotationDirection.BottomToUp:
                if (idx == 0)
                {
                    //the last layer length can't be edited
                    results = depths.ToArray();
                    return(results);
                }
                oldLength = depths[idx + 1] - depths[idx];

                initialBoundaryCount = depths.Length;
                double upperDepth = depths[0];

                double substraction = newLength - oldLength;

                toRemove            = 0;
                removedLayersLength = 0.0;
                while ((idx - toRemove - 1 >= 0) && (depths[idx - toRemove] - depths[idx - toRemove - 1] + removedLayersLength <= substraction))
                {
                    removedLayersLength += depths[idx - toRemove] - depths[idx - toRemove - 1];
                    toRemove++;
                }
                System.Diagnostics.Trace.WriteLine("{0} layers to remove");

                results = depths.Skip(toRemove).ToArray();
                for (int i = idx - toRemove; i > 0; i--)
                {
                    results[i] -= substraction;
                }
                results[0] = upperDepth;
                break;

            default:
                throw new NotSupportedException("unexpected annotatiuon direction");
            }

            return(results);
        }