namespace IStation.Curve { /// /// 样条曲线(四次拟合):使用MATH.net /// public class TwinRelateCurve4M : IFitPoint { /// /// /// public TwinRelateCurve4M(CurveExpress express) { _express = express; } /// /// /// public TwinRelateCurve4M(List points) { if (points == null || points.Count < 5) { throw new Exception("出现数值计算问题 ,无法解出四次样条曲线!"); } _express = BuildCurveExpress(points); } //曲线表达式 private CurveExpress _express = null; /// /// 获取拟合点Y /// public double GetFitPointY(double x) { if (_express == null) return default; //不用减掉最小值, 和alglib有点不一样 return _express.Index4 * x * x * x * x + _express.Index3 * x * x * x + _express.Index2 * x * x + _express.Index1 * x + _express.Index0; } /// /// 获取拟合点列表 /// public List GetFitPoints(int pointNumber) { if (_express == null) return default; return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); } /// /// 通过区间获取拟合点列表 /// public List GetFitPointsByXRange(double minX, double maxX, int pointNumber) { if (_express == null) return default; if (pointNumber < 1) pointNumber = 12; if (pointNumber > 10000) pointNumber = 10000; double space = (maxX - minX) / (pointNumber - 1); if (space < 0.0001) return default; var points = new List(); for (int i = 0; i < pointNumber; i++) { double x = space * i + minX; double y = this.GetFitPointY(x); points.Add(new CurvePoint(x, y)); } return points; } /// /// 创建曲线表达式 /// public static CurveExpress BuildCurveExpress(List points) { if (points == null || points.Count < 5) return default; points = points.OrderBy(x => x.X).ToList(); CurveExpress express = new CurveExpress(); express.FitType = eFitType.FourM; express.DefinePoints = points.Select(x => new CurvePoint(x)).ToList(); express.Min = points.First().X; express.Max = points.Last().X; var X = (from x in points select x.X).ToArray(); var Y = (from x in points select x.Y).ToArray(); var res = MathNet.Numerics.Fit.Polynomial(X, Y, 4); //0次方 express.Index0 = res[0]; //1次方 express.Index1 = res[1]; //2次方 express.Index2 = res[2]; //3次方 express.Index3 = res[3]; //4次方 express.Index4 = res[4]; return express; } } }