C#使用MathNet库来对进行曲线拟合
阅读原文时间:2023年07月09日阅读:1

下面是用来求取一条直线和一条拟合曲线交点的代码

    /// <summary>  
    /// 拟合曲线所筛选的点的个数  
    /// </summary>  
    const int CurveNums = 10;

    /// <summary>  
    /// 拟合曲线的阶数  
    /// </summary>  
    public int m =2;

    /// <summary>  
    /// 取直线上的点的个数  
    /// </summary>  
    const int XNums = 50;  
    /// <summary>  
    ///  最小二乘法拟合曲线  
    /// </summary>  
    /// <param name="X">X轴数组</param>  
    /// <param name="Y">Y轴数组</param>  
    /// <param name="m">阶数</param>  
    /// <returns>返回曲线方程的各阶系数(由高阶到低阶,一般m=2)</returns>  
    public double\[\] FittingCurveByLeastSquare(double\[\] X, double\[\] Y, int m = 2)  
    {  
        /// https://blog.csdn.net/qq\_23062949/article/details/119700640?spm=1001.2101.3001.6650.3&utm\_medium=distribute.pc\_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.no\_search\_link&depth\_1-utm\_source=distribute.pc\_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.no\_search\_link  
        double\[\] res = new double\[m + 1\];  
        if (X.Length > m && Y.Length > m)  
        {  
            res = Fit.Polynomial(X, Y, m);  
        }  
        return res;  
    }

    /// <summary>  
    /// 计算直线方程  
    /// </summary>  
    /// <param name="StartPoint">直线起点</param>  
    /// <param name="angle">直线的角度</param>  
    /// <returns>返回k,b的数组</returns>  
    public double\[\] CalculateLine(Point StartPoint, double angle)  
    {  
        double k = Math.Tan(angle / 180 \* Math.PI);  
        double b = StartPoint.Y - k \* StartPoint.X;  
        return new double\[\] { k, b };  
    }

    /// <summary>  
    /// 计算交点  
    /// </summary>  
    /// <param name="LineResult">直线的k,b</param>  
    /// <param name="CurveResult">拟合曲线的系数数组</param>  
    /// <param name="LineX">直线上的点的X坐标</param>  
    /// <param name="m">阶数</param>  
    /// <returns></returns>  
    public EPoint CalculateInterPoint(double\[\] LineResult, double\[\] CurveResult, double\[\] LineX, int m)  
    {  
        EPoint InterPoint = new EPoint();  
        if (LineResult.Length == 2 && CurveResult.Length == (m + 1))  
        {  
            double k = LineResult\[0\];  
            double b = LineResult\[1\];  
            for (int i = 0; i < LineX.Count(); i++)  
            {  
                double x = LineX\[i\];  
                double y\_Line = k \* x + b;  
                double y\_Curve = 0;  
                for (int n = 0; n <= m; n++)  
                {  
                    y\_Curve += CurveResult\[n\] \* Math.Pow(x, n);  
                }  
                bool IsSuccessFind = false;  
                for (int t = 1; t <= 50; t++)  
                {  
                    if (Math.Abs(y\_Line - y\_Curve) < 5)  
                    {  
                        InterPoint = new EPoint((int)x, (int)y\_Line);  
                        IsSuccessFind = true;  
                        break;//跳出内循环  
                    }  
                }  
                if (IsSuccessFind)  
                {  
                    break;//跳出外循环  
                }  
            }  
        }  
        return InterPoint;  
    }

    /// <summary>  
    /// 计算R^2,R^2这个值越接近1,说明拟合出来的曲线跟原曲线就越接近  
    /// </summary>  
    /// <param name="Y">实际的Y</param>  
    /// <param name="Ytest">代入拟合曲线方程得到的Y</param>  
    /// <returns>返回R^2</returns>  
    public double CalculateRSquared(double\[\] Y, double\[\] Ytest)  
    {  
        double RSquared = GoodnessOfFit.RSquared(Y, Ytest);  
        return RSquared;  
    }