Example #1
0
        /// <summary>
        /// Заполняет вспомогательные данные методом многочленов deg-степени.
        /// </summary>
        /// <param name="filter">Фильтр-функция</param>
        /// <param name="accuracy"></param>
        private static CompileItem Compile(BlurFunctionHandler filter, double accuracy = 1D)
        {
            return(CompileImplementation(filter, accuracy));



            /*
             * CompileItem result = CompileItemsCache[deg];
             *
             * if (result == null)
             * {
             *  if (deg >= 0 && deg <= 8)
             *  {
             *      CompileItemsCache[deg] = result = CompileImplementation(filter, deg);
             *  }
             *  else
             *  {
             *      throw new ArgumentException("Значение deg должно быть от 0 до 8");
             *  }
             *
             * }
             *
             * return result;
             * */
        }
Example #2
0
        /// <summary>
        /// Вычисляет площадь кривой вокруг точки center.
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="center"></param>
        /// <param name="dr"></param>
        /// <returns></returns>
        private static double GetArea(BlurFunctionHandler filter, double center, double dr)
        {
            //Степень многочлена которым будем аппроксимировать исходную функцию
            const int deg = 8;

            //Метод многочленов deg-степени
            var points = new PointD[deg + 1];

            //Левая граница
            var rm = center - dr;

            for (var i = 0; i <= deg; i++)
            {
                var x = i * 2D * dr / deg;
                points[i] = new PointD(i, filter(rm + x));
            }

            //Строим многочлен deg-степени проходящий через заданные точки
            var polynom = Polynomial.GetPolynomial(points);

            //Вычисляем площадь фигуры ограниченной полиномом
            return(polynom.GetArea(0, deg) * 2D * dr / deg);



            /*
             * const int deg = 8;
             *
             * //Метод многочленов deg-степени
             * PointD[] points = new Point2D[deg + 1];
             *
             * double rm = center - dr / 2D;
             *
             * for (int i = 0; i <= deg; i++)
             * {
             *  double x = i * dr / deg;
             *  points[i] = new PointD(x, filter(rm + x));
             * }
             *
             * return Polynomial.Resolve(points).GetArea(0, dr);
             */
        }
Example #3
0
 public BlurCompiler(BlurFunctionHandler filter, double accuracy = 1D)
 {
     _compileItem = Compile(filter, accuracy);
 }
Example #4
0
        /// <summary>
        /// Заполняет вспомогательные данные методом многочленов deg-степени.
        /// </summary>
        /// <param name="filter">Фильтр-функция</param>
        /// <param name="accuracy"></param>
        private static CompileItem CompileImplementation(BlurFunctionHandler filter, double accuracy = 1D)
        {
            //var tick = TickCounter.TickCount;

            //for (int m = 100000; m > 0.1; m--)
            //for (int s = 100; s >= 1; s--)
            //{

            #region Начальные значения

            var          drStart      = 0.18256D * accuracy;
            const double drMultiplier = 1.16D;

            var listRadius  = new List <double>();
            var listVolumes = new List <double>();

            //Начальные значение радиуса
            double r = 0;

            //Начальное значение ширины сектора
            var dr = drStart / 2D;

            //Будем собирать сумму
            double vSum = 0;

            #endregion

            #region Вычисляем и заполняем площади

            var volume = GetArea(filter, r, dr);

            vSum += volume;

            //Сохраняем параметры текущей итерации
            listRadius.Add(0);
            listVolumes.Add(volume);

            var limit = 1E-50D * filter(0);

            do
            {
                //Предыдущее значение
                var saveDr = dr;

                //Текущее значение
                dr *= drMultiplier;

                r += saveDr + dr;

                //Метод многочленов
                volume = GetArea(filter, r, dr);

                vSum += 2 * volume;

                //Сохраняем параметры текущей итерации
                listRadius.Add(r);
                listVolumes.Add(volume);

                if (volume < limit)
                {
                    break;
                }
                if (listRadius.Count > 1000)
                {
                    throw new Exception("Функция не сходится либо сходится очень медленно");
                }
            } while (true);

            #endregion

            if (vSum.Equals(1D))
            {
                //MessageBox.Show(drStart + " " + drMultiplier);
            }


            #region Нормируем объемы

            if (!vSum.Equals(1D))
            {
                for (var i = 0; i < listVolumes.Count; i++)
                {
                    listVolumes[i] /= vSum;
                }
            }

            #endregion
            //}
            //tick = TickCounter.TickCount - tick;
            //MessageBox.Show(tick.ToString());


            //return null;
            return(new CompileItem(listRadius.ToArray(), listVolumes.ToArray(), filter));
        }
Example #5
0
 public CompileItem(double[] arrayRadius, double[] arrayVolumes, BlurFunctionHandler filter)
 {
     ArrayRadius  = arrayRadius;
     ArrayVolumes = arrayVolumes;
     Filter       = filter;
 }
Example #6
0
 public CurveBlurFilter(IEnumerable <Point3D> curve, BlurFunctionHandler filter, ExtrapolationMode mode = ExtrapolationMode.Mirror)
 {
     _blurCompiler   = new BlurCompiler(filter);
     _linearCompiler = new CurveInterpolationCompiler(curve, mode);
 }
Example #7
0
 public CurveBlurFilter2(Point3D[] curve, BlurFunctionHandler filter, ExtrapolationMode mode = ExtrapolationMode.Mirror)
 {
     _blurCompiler   = new BlurCompiler(filter);
     _linearCompiler = new CurveInterpolationCompiler(curve, mode);
     BuildCorners();
 }
        /// <summary>
        /// Заполняет параметрами фильтра.
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="arrayRadius"></param>
        /// <param name="arrayVolumes"></param>
        /// <param name="arraySectors"></param>
        private static void PrepareBlur(BlurFunctionHandler filter, out double[] arrayRadius, out double[] arrayVolumes, out int[] arraySectors)
        {
            //Начальное значение ширины сектора
            const double drStart = 0.01D;

            //Мультипликатор для dr
            const double drMultiplier = 1.5D;

            //Предельный радиус
            const double rMax = 3;

            double vSum = 0;

            var listRadius  = new List <double>();
            var listVolumes = new List <double>();
            var listSectors = new List <int>();

            //Начальные значение радиуса
            double r = 0;

            //Начальное значение ширины сектора
            var dr = drStart;

            var volume = filter(0) * Pi * dr * dr / 4D;

            vSum += volume;

            //Сохраняем параметры текущей итерации
            listRadius.Add(0);
            listVolumes.Add(volume);
            listSectors.Add(1);

            //double tick = TickCounter.TickCount;

            do
            {
                //Предыдущее значение
                var saveDr = dr;

                //Текущее значение
                dr *= drMultiplier;

                r += (saveDr + dr) / 2D;

                //Количество делений угла в зависимости от радиуса и от шага радиуса
                var aCount = (int)(Tau * r / dr + 1);

                //Гауссовский объем

                //Первый способ (метод прямоугольников)
                volume = filter(r) * Tau * r * dr;
                vSum  += volume;

                //Второй способ (метод трапеций)
                //volume = (filter(r - dr / 2) + filter(r + dr / 2)) * Math.Pi * r * dr;
                //vSum += volume;

                //Сохраняем параметры текущей итерации
                listRadius.Add(r);
                listVolumes.Add(volume / aCount);
                listSectors.Add(aCount);
            }while (r < rMax);

            //MessageBox.Show((TickCounter.TickCount - tick).ToString() + "!!!");

            //Нормируем объемы
            for (var i = 0; i < listVolumes.Count; i++)
            {
                listVolumes[i] /= vSum;
            }

            arrayRadius  = listRadius.ToArray();
            arraySectors = listSectors.ToArray();
            arrayVolumes = listVolumes.ToArray();
        }
 public SurfaceBlurFilter(BlurFunctionHandler filter, Func <double, double, double> function)
 {
     _function = function;
     PrepareBlur(filter, out _arrayRadius, out _arrayVolumes, out _arraySectors);
 }
 public SurfaceBlurFilter(BlurFunctionHandler filter)
 {
     PrepareBlur(filter, out _arrayRadius, out _arrayVolumes, out _arraySectors);
 }