namespace Yw.Curve { /// /// 样条曲线(二次拟合)B=0 /// public class TwinRelateCurve2B0 : IFitPoint { /// /// /// public TwinRelateCurve2B0(CurveExpress express) { _express = express; } /// /// /// public TwinRelateCurve2B0(List points) { if (points == null || points.Count < 3) { throw new Exception("出现数值计算问题, 无法解出二次拟合曲线(B=0)!"); } _express = BuildCurveExpress(points); } //曲线表达式 private CurveExpress _express = null; /// /// 获取拟合点Y /// public double GetFitPointY(double x) { if (_express == null) { return default; } return _express.Index2 * x * x + _express.Index0; } /// /// 获取拟合点列表 /// public List GetFitPoints(int pointNumber) { if (_express == null) { return default; } return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber); } /// /// 通过X区间获取拟合点列表 /// 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 = GetFitPointY(x); points.Add(new CurvePoint(x, y)); } return points; } /// /// 创建曲线表达式 /// public static CurveExpress BuildCurveExpress(List points) { if (points == null || points.Count < 3) { return default; } points = points.OrderBy(x => x.X).ToList(); var count = points.Count; var express = new CurveExpress { FitType = eFitType.ConicCurveB0, DefinePoints = points.Select(x => new CurvePoint(x)).ToList(), Min = points.First().X, Max = points.Last().X }; double rTotalH = 0.0; double rTotalHQ2 = 0.0; double rTotalQ2 = 0.0; double rTotalQ4 = 0.0; for (int i = 0; i < count; i++) { rTotalH = rTotalH + points[i].Y; rTotalHQ2 = rTotalHQ2 + points[i].Y * points[i].X * points[i].X; rTotalQ2 = rTotalQ2 + points[i].X * points[i].X; rTotalQ4 = rTotalQ4 + Math.Pow(points[i].X, 4); } express.Index2 = (rTotalH * rTotalQ2 - count * rTotalHQ2) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4); express.Index0 = (rTotalQ2 * rTotalHQ2 - rTotalQ4 * rTotalH) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4); return express; } } }