/// <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; * */ }
/// <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); */ }
public BlurCompiler(BlurFunctionHandler filter, double accuracy = 1D) { _compileItem = Compile(filter, accuracy); }
/// <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)); }
public CompileItem(double[] arrayRadius, double[] arrayVolumes, BlurFunctionHandler filter) { ArrayRadius = arrayRadius; ArrayVolumes = arrayVolumes; Filter = filter; }
public CurveBlurFilter(IEnumerable <Point3D> curve, BlurFunctionHandler filter, ExtrapolationMode mode = ExtrapolationMode.Mirror) { _blurCompiler = new BlurCompiler(filter); _linearCompiler = new CurveInterpolationCompiler(curve, mode); }
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); }