using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra.Double; namespace PBS.WinFrmUI.Hydro { public class CurveFitHelper { public DenseVector coefficients; private int degree; private double xMax; private double xMin; private List data; private bool isFitted; public CurveFitHelper(List data, int degree = 2) { this.degree = degree; this.data = data; double[] array = data.Select(((Yw.Geometry.Point2d p) => p.X)).ToArray(); if (data.Count > 2) { coefficients = Fit.Polynomial(array, (data).Select((Yw.Geometry.Point2d p) => p.Y).ToArray(), 2); isFitted = true; } else if (data.Count == 2) { var tuple = Fit.Line(array, data.Select((Yw.Geometry.Point2d p) => p.Y).ToArray()); coefficients = new DenseVector(new double[2] { tuple.Item1, tuple.Item2 }); isFitted = true; } else if (data.Count == 1) { coefficients = new DenseVector(new double[1] { data[0].Y }); isFitted = true; } else { coefficients = new DenseVector(new double[1]); isFitted = true; } List source = array.ToList(); xMax = source.Max(); xMin = source.Min(); } public double Evaluate(double x) { if (!isFitted) { return double.NaN; } double num = 0.0; for (int i = 0; i < coefficients.Count; i++) { num += (double)(float)(coefficients[i] * Math.Pow(x, i)); } return num; } public List GetFitCurve(int count) { List list = new List(); for (double num = xMin; num <= xMax; num += (xMax - xMin) / (double)count) { if (list.Count >= count) { break; } double num2 = Evaluate(num); list.Add(new Yw.Geometry.Point2d((float)num, (float)num2)); } return list; } public List> GetConfidenceCurve(int count) { List list = new List(); List list2 = new List(); List list3 = new List(); double num = 0.0; double num2 = 0.0; double x; for (x = xMin; x < xMax; x += (xMax - xMin) / (double)count) { List list4 = ((IEnumerable)data.FindAll((Yw.Geometry.Point2d p) => x - (xMax - xMin) / (double)count / 2.0 <= (double)p.X && (double)p.X < x + (xMax - xMin) / (double)count / 2.0)).Select((Func)((Yw.Geometry.Point2d p) => p.Y)).ToList(); if (list4.Count >= 3) { double[] confidenceRange = GetConfidenceRange(list4, 95.0); double num3 = x; if (confidenceRange[0] != double.NaN && confidenceRange[1] != double.NaN) { list2.Add(new Yw.Geometry.Point2d((float)num3, (float)confidenceRange[0])); list.Add(new Yw.Geometry.Point2d((float)num3, (float)confidenceRange[1])); num = x; num2 = (confidenceRange[0] + confidenceRange[1]) / 2.0; list3.Add(new Yw.Geometry.Point2d((float)num3, (float)num2)); } } else if (list4.Count == 2) { double num4 = x; list2.Add(new Yw.Geometry.Point2d((float)num4, (float)list4.Min())); list.Add(new Yw.Geometry.Point2d((float)num4, (float)list4.Max())); num = x; num2 = (list4.Min() + list4.Max()) / 2.0; list3.Add(new Yw.Geometry.Point2d((float)num4, (float)num2)); } else if (list4.Count == 1) { double num5 = x; list2.Add(new Yw.Geometry.Point2d((float)num5, (float)list4[0])); list.Add(new Yw.Geometry.Point2d((float)num5, (float)list4[0])); num = x; num2 = list4[0]; list3.Add(new Yw.Geometry.Point2d((float)num5, (float)num2)); } else if (list4.Count == 0) { list2.Add(new Yw.Geometry.Point2d((float)num, (float)num2)); list.Add(new Yw.Geometry.Point2d((float)num, (float)num2)); list3.Add(new Yw.Geometry.Point2d((float)num, (float)num2)); } } return new List> { list2, list, list3 }; } public static double[] GetConfidenceRange(List data, double confidenceLevel = 90.0, bool mode = true) { if (mode) { data.Sort(); int num = (int)Math.Round((double)data.Count * confidenceLevel / 100.0); int num2 = (int)Math.Round((double)data.Count * (1.0 - confidenceLevel / 100.0)); if (num == data.Count) { num = data.Count - 1; } if (num2 < 0) { num2 = 0; } return new double[2] { data[num2], data[num] }; } double num3 = double.MaxValue; double num4 = double.MinValue; foreach (double datum in data) { if (datum < num3) { num3 = datum; } if (datum > num4) { num4 = datum; } } double num5 = 0.0; foreach (double datum2 in data) { num5 += datum2; } double num6 = num5 / (double)data.Count; double num7 = 0.0; foreach (double datum3 in data) { num7 += Math.Pow(datum3 - num6, 2.0); } double num8 = Math.Sqrt(num7 / (double)(data.Count - 1)); double num9 = GetZValueOneTail((1.0 - confidenceLevel / 100.0) / 2.0) * num8; double num10 = num6 - num9; double num11 = num6 + num9; return new double[2] { num10, num11 }; } private static double GetZValueOneTail(double alpha) { if (alpha == 0.5) { return 0.0; } if (alpha > 0.5) { return 0.0 - GetZValueOneTail(1.0 - alpha); } double[] array = new double[6] { 0.1, 0.05, 0.025, 0.01, 0.005, 0.001 }; double[] array2 = new double[6] { 1.28, 1.645, 1.96, 2.33, 2.575, 3.09 }; int num = array.Length; int i; for (i = 0; i < num && alpha < array[i]; i++) { } if (i == 0) { return 0.0; } if (i == num) { return array2[num - 1]; } double num2 = array[i - 1]; double num3 = array[i]; double num4 = array2[i - 1]; return (array2[i] - num4) / (num3 - num2) * (alpha - num2) + num4; } private static bool isValid(double value) { if (value == (double)(int)value && value < 0.0) { return false; } if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } } }