//public SectionDescription(PointD in_p0, DenseVector in_direction, bool in_fromMarginToMargin)
        //{
        //    fromMarginToMargin = in_fromMarginToMargin;
        //    p0 = in_p0;
        //    direction = in_direction;
        //}



        public SectionDescription TransformTillMargins(Rectangle imageMarginsRect)
        {
            LineDescription2D lDesc  = new LineDescription2D(p0, direction);
            Vector2D          vHoriz = new Vector2D(1.0d, 0.0d); // DenseVector.Create(2, i => ((i == 0) ? (1.0d) : (0.0d)));
            Vector2D          vVert  = new Vector2D(0.0d, 1.0d); // DenseVector.Create(2, i => ((i == 0) ? (0.0d) : (1.0d)));
            //return new SectionDescription(p1, p2, fromMarginToMargin);
            LineDescription2D rectLtop = new LineDescription2D(new PointD(imageMarginsRect.Left, imageMarginsRect.Top),
                                                               vHoriz);
            LineDescription2D rectLleft = new LineDescription2D(new PointD(imageMarginsRect.Left, imageMarginsRect.Top),
                                                                vVert);
            LineDescription2D rectLright = new LineDescription2D(new PointD(imageMarginsRect.Right, imageMarginsRect.Top),
                                                                 vVert);
            LineDescription2D rectLbottom = new LineDescription2D(new PointD(imageMarginsRect.Left, imageMarginsRect.Bottom),
                                                                  vHoriz);

            List <PointD> ptCross  = new List <PointD>();
            PointD        pcTop    = LineDescription2D.CrossPoint(rectLtop, lDesc);
            PointD        pcBottom = LineDescription2D.CrossPoint(rectLbottom, lDesc);
            PointD        pcLeft   = LineDescription2D.CrossPoint(rectLleft, lDesc);
            PointD        pcRight  = LineDescription2D.CrossPoint(rectLright, lDesc);

            if ((pcTop.X >= imageMarginsRect.Left) && (pcTop.X <= imageMarginsRect.Right))
            {
                ptCross.Add(pcTop);
            }
            if ((pcBottom.X >= imageMarginsRect.Left) && (pcBottom.X <= imageMarginsRect.Right))
            {
                ptCross.Add(pcBottom);
            }
            if ((pcLeft.Y >= imageMarginsRect.Top) && (pcLeft.Y <= imageMarginsRect.Bottom))
            {
                ptCross.Add(pcLeft);
            }
            if ((pcRight.Y >= imageMarginsRect.Top) && (pcRight.Y <= imageMarginsRect.Bottom))
            {
                ptCross.Add(pcRight);
            }

            return(new SectionDescription(ptCross[0], ptCross[1], true));
        }
        /// <summary>
        /// Gets the local minimums distribution.
        /// </summary>
        /// <param name="dmFieldData">The dm field data.</param>
        /// <param name="dimensionNumber">The dimension number:
        /// 1 - rows (angle)
        /// 2 - columns (distance)
        /// </param>
        /// <returns>DenseMatrix.</returns>
        //public static DenseMatrix GetLocalMinimumsDistribution(DenseMatrix dmFieldData, PointD sunCenterPoint, PointD imageCenterPoint, double imageRadius, int imageHeight, double imageCircleCropFactor = 0.9d, int dimensionNumber = 1)
        public static List <Point3D> GetLocalMinimumsDistribution(DenseMatrix dmFieldData, RoundData sunDiskData, RoundData imageRoundData, int imageHeight, double imageCircleCropFactor = 0.9d)
        {
            // DenseMatrix dmFieldminimumsData = DenseMatrix.Create(dmFieldData.RowCount, dmFieldData.ColumnCount, 0.0d);
            List <Point3D> lRetPoints = new List <Point3D>();

            double     imageRadius      = imageRoundData.DRadius;
            PointD     imageCenterPoint = imageRoundData.pointDCircleCenter();
            PointPolar imageCenterPointRelatedToSunCenter = new PointPolar(imageCenterPoint - sunDiskData.pointDCircleCenter(), true);
            double     distanceSunCenterToImageCenter     = PointD.Distance(imageCenterPoint, sunDiskData.pointDCircleCenter());


            #region // obsolete
            //if (dimensionNumber == 1)
            //{
            #endregion // obsolete
            for (int i = 0; i < dmFieldData.RowCount; i++)
            {
                bool itsTheCropCase = false;
                //если направлени на кроп кадра - то не берем в расмотрение
                double currentAngle = ((double)i / (double)(dmFieldData.RowCount - 1)) * 2.0d * Math.PI;

                LineDescription2D line, lineMargin;
                if (currentAngle < Math.PI)
                {
                    //верхняя половина, смотрим направление на y=0.0d
                    line = new LineDescription2D(sunDiskData.pointDCircleCenter(),
                                                 new Vector2D(Math.Cos(currentAngle), -Math.Sin(currentAngle)));
                    lineMargin = new LineDescription2D(new PointD(0.0d, 0.0d), new Vector2D(1.0d, 0.0d));
                }
                else
                {
                    line = new LineDescription2D(sunDiskData.pointDCircleCenter(),
                                                 new Vector2D(Math.Cos(currentAngle), Math.Sin(currentAngle)));
                    lineMargin = new LineDescription2D(new PointD(0.0d, imageHeight), new Vector2D(1.0d, 0.0d));
                }

                PointD crossPointD = LineDescription2D.CrossPoint(line, lineMargin);
                if (crossPointD.Distance(imageCenterPoint) < imageRadius)
                {
                    itsTheCropCase = true;
                }

                #region // obsolete
                //double yMargin = 0.0d;
                //double xMargin = sunCenterPoint.X + (yMargin - sunCenterPoint.Y) / Math.Tan(currentAngle);
                //double dx = xMargin - imageCenterPoint.X;
                //double dy = yMargin - imageCenterPoint.Y;
                //if (Math.Sqrt(dx * dx + dy * dy) < imageRadius) itsTheCropCase = true;
                #endregion // obsolete

                #region    //obsolete
                //else
                //{
                //    //нижняя половина, смотрим направление на y=imageHeight
                //    double yMargin = (double)imageHeight;
                //    double xMargin = sunCenterPoint.X + (yMargin - sunCenterPoint.Y) / Math.Tan(currentAngle);
                //    double dx = xMargin - imageCenterPoint.X;
                //    double dy = yMargin - imageCenterPoint.Y;
                //    if (Math.Sqrt(dx * dx + dy * dy) < imageRadius) itsTheCropCase = true;
                //}
                #endregion //obsolete
                //Если слишком близко к краю изображения - тоже исключаем. Минимум должен лежать не ближе, например, 1/15



                //DenseMatrix dmSlicedDataMatrix = (DenseMatrix)dmFieldData.SubMatrix(i, 1, 0, dmFieldData.ColumnCount);
                DenseVector dvRowDataVector = (DenseVector)dmFieldData.EnumerateRows().ElementAt(i);
                #region // debug plotting
                //dvRowDataVector.SaveVectorDataAsImagePlot(
                //    "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" +
                //    i.ToString("D03") + "-step1.png");
                #endregion // debug plotting
                dvRowDataVector.MapIndexedInplace((idx, x) => ((x == 0.0d) || (idx < sunDiskData.DRadius * 1.5d)) ? (1.0d) : (x));
                #region    // debug plotting
                //dvRowDataVector.SaveVectorDataAsImagePlot(
                //    "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" +
                //    i.ToString("D03") + "-step2.png");
                #endregion // debug plotting
                double phiFromImageCenterToDirection = imageCenterPointRelatedToSunCenter.Phi - currentAngle;
                double distanceToImageMargin         = distanceSunCenterToImageCenter * Math.Cos(phiFromImageCenterToDirection) +
                                                       Math.Sqrt(imageRadius * imageRadius -
                                                                 distanceSunCenterToImageCenter * distanceSunCenterToImageCenter *
                                                                 Math.Sin(phiFromImageCenterToDirection) *
                                                                 Math.Sin(phiFromImageCenterToDirection));
                dvRowDataVector.MapIndexedInplace(
                    (idx, x) => ((double)idx / distanceToImageMargin >= imageCircleCropFactor) ? (1.0d) : (x));
                #region // debug plotting
                //dvRowDataVector.SaveVectorDataAsImagePlot(
                //    "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" +
                //    i.ToString("D03") + "-step3.png");
                #endregion // debug plotting
                double minValue      = dvRowDataVector.Minimum();
                int    minValueIndex = dvRowDataVector.MinimumIndex();

                //if (!itsTheCropCase) dmFieldminimumsData[i, minValueIndex] = minValue;
                if ((!itsTheCropCase) && ((double)minValueIndex > sunDiskData.DRadius))
                {
                    lRetPoints.Add(new Point3D(currentAngle, minValueIndex, minValue));
                }
                else
                {
                    continue;
                }
            }

            #region // obsolete
            //}
            //else if (dimensionNumber == 2)
            //{
            //    for (int i = 0; i < dmFieldData.ColumnCount; i++)
            //    {
            //        DenseMatrix dmSlicedDataMatrix = (DenseMatrix)dmFieldData.SubMatrix(0, dmFieldData.RowCount, i, 1);
            //        DenseVector dvSlicedDataVector = DenseVector.OfEnumerable(dmSlicedDataMatrix.Values);
            //        dvSlicedDataVector.MapInplace(new Func<double, double>(x => (x == 0.0d) ? (1.0d) : (x)));
            //        double minValue = dvSlicedDataVector.Minimum();
            //        int minValueIndex = dvSlicedDataVector.MinimumIndex();
            //        dmFieldminimumsData[minValueIndex, i] = minValue;
            //    }
            //}
            #endregion // obsolete

            //return dmFieldminimumsData;
            return(lRetPoints);
        }
        private void btnGetFuncAlongSection_Click(object sender, EventArgs e)
        {
            foreach (SectionDescription sectionDescription in sectionsList)
            {
                PointD p1 = sectionDescription.p1;
                PointD p2 = sectionDescription.p2;
                bool   fromMarginToMargin = false;

                SectionDescription currSection = new SectionDescription(p1, p2, true);

                LineDescription2D l1 = currSection.SectionLine;

                DenseMatrix dmValues         = (DenseMatrix)currImgData.DmSourceData.Clone();
                DenseMatrix dmDistanceToLine = (DenseMatrix)currImgData.DmSourceData.Clone();
                dmDistanceToLine.MapIndexedInplace((row, col, dVal) =>
                {
                    PointD currPt = new PointD(col, row);

                    double dist = currPt.DistanceToLine(l1);
                    return(dist);
                });

                List <Tuple <PointD, double> > dataArray = new List <Tuple <PointD, double> >();
                for (int row = 0; row < dmValues.RowCount; row++)
                {
                    for (int col = 0; col < dmValues.ColumnCount; col++)
                    {
                        if (dmDistanceToLine[row, col] <= sectionGapWidth)
                        {
                            dataArray.Add(new Tuple <PointD, double>(new PointD(col, row), dmValues[row, col]));
                        }
                    }
                }

                List <Tuple <double, double> > dataArrayRotated = dataArray.ConvertAll((tpl) =>
                {
                    Vector2D pointVector = l1.p0.ToVector2D(tpl.Item1);
                    double projection    = pointVector * l1.directionVector;
                    return(new Tuple <double, double>(projection, tpl.Item2));
                });


                double arrayMinPosition = dataArrayRotated.Min <Tuple <double, double> >(tpl1 => tpl1.Item1);
                double arrayMaxPosition = dataArrayRotated.Max <Tuple <double, double> >(tpl1 => tpl1.Item1);
                if (!fromMarginToMargin)
                {
                    Vector2D pointVector      = l1.p0.ToVector2D(p2);
                    double   projection       = pointVector * l1.directionVector;
                    double   p2DoublePosition = projection;

                    arrayMinPosition = Math.Min(0.0d, p2DoublePosition);
                    arrayMaxPosition = Math.Max(0.0d, p2DoublePosition);
                    dataArrayRotated.RemoveAll(tpl => ((tpl.Item1 < arrayMinPosition) || (tpl.Item1 > arrayMaxPosition)));
                }

                dataArrayRotated =
                    dataArrayRotated.ConvertAll <Tuple <double, double> >(
                        tpl => new Tuple <double, double>(tpl.Item1 - arrayMinPosition, tpl.Item2));

                dataArrayRotated.Sort((tpl1, tpl2) => tpl1.Item1.CompareTo(tpl2.Item1));

                FunctionRepresentationForm form1 = new FunctionRepresentationForm();
                form1.dvScatterXSpace     = DenseVector.OfEnumerable(dataArrayRotated.ConvertAll <double>(tpl => tpl.Item1));
                form1.dvScatterFuncValues =
                    DenseVector.OfEnumerable(dataArrayRotated.ConvertAll <double>(tpl => tpl.Item2));

                if ((rtbMinValuesLimit.Text != "") && (rtbMaxValuesLimit.Text != ""))
                {
                    form1.ForcedFuncMinValue = Convert.ToDouble(rtbMinValuesLimit.Text.Replace(".", ","));
                    form1.ForcedFuncMaxValue = Convert.ToDouble(rtbMaxValuesLimit.Text.Replace(".", ","));
                    form1.ForceFuncLimits    = true;
                }


                if (rbtnShowByDots.Checked)
                {
                    form1.scatterFuncDrawingVariant = SequencesDrawingVariants.circles;
                }
                else if (rbtnShowByLine.Checked)
                {
                    form1.scatterFuncDrawingVariant = SequencesDrawingVariants.polyline;
                }

                form1.Show();
                form1.Represent();
            }
        }