コード例 #1
0
        public CubicSpline(Point[] inputPoints)
        {
            buildRanges(inputPoints);
            splines = new Polynomial[ranges.Length];
            double[] h = new double[points.Length];
            for (int i = 1; i < points.Length; i++)
            {
                h[i] = points[i].getX() - points[i - 1].getX();
            }

            TriDiagonalMatrix matrix = new TriDiagonalMatrix(points.Length - 2);

            double[] F = new double[points.Length - 2];
            // Построение системы динейных уравнений относительно coeff_c[i],  коэффициент при x^2

            for (int i = 2; i < points.Length; i++)
            {
                matrix[i - 2].a = h[i - 1];
                matrix[i - 2].c = 2 * (h[i] + h[i - 1]);
                matrix[i - 2].b = h[i];
                F[i - 2]        = 3 * ((points[i].getY() - points[i - 1].getY()) / h[i] -
                                       (points[i - 1].getY() - points[i - 2].getY()) / h[i - 1]);
            }
            matrix[0].a = 0;
            matrix[matrix.Length - 1].b = 0;

            // Находим коэффициенты 'с'
            double[] c = new double[points.Length + 1];
            c[0] = 0;
            c[1] = 0;
            double[] t = matrix.solve(F);
            Array.Copy(t, 0, c, 2, t.Length);
            c[c.Length - 1] = 0;



            // Вычисляем оставшмеся коэффициетны и создаем сплайны
            for (int i = 1; i < c.Length - 1; i++)
            {
                double a = points[i - 1].getY();                                                                // свободный коэффициент
                double d = (c[i + 1] - c[i]) / (3 * h[i]);                                                      // коэффициент при x^3
                double b = (points[i].getY() - points[i - 1].getY()) / h[i] - (2 * c[i] + c[i + 1]) * h[i] / 3; // коэффициент при x^1
                splines[i - 1] = new Polynomial(new double[] { a, b, c[i], d });
            }
        }
コード例 #2
0
ファイル: CubicSpline.cs プロジェクト: Sidd710/tempRepo
        /// <summary>
        /// Compute spline coefficients for the specified x,y points.
        /// This does the "natural spline" style for ends.
        /// This can extrapolate off the ends of the splines.
        /// You must provide points in X sort order.
        /// </summary>
        /// <param name="x">Input. X coordinates to fit.</param>
        /// <param name="y">Input. Y coordinates to fit.</param>
        /// <param name="startSlope">Optional slope constraint for the first point. Single.NaN means no constraint.</param>
        /// <param name="endSlope">Optional slope constraint for the final point. Single.NaN means no constraint.</param>
        /// <param name="debug">Turn on console output. Default is false.</param>
        public void Fit(float[] x, float[] y, float startSlope = float.NaN, float endSlope = float.NaN, bool debug = false)
        {
            if (Single.IsInfinity(startSlope) || Single.IsInfinity(endSlope))
            {
                throw new Exception("startSlope and endSlope cannot be infinity.");
            }

            // Save x and y for eval
            this.xOrig = x;
            this.yOrig = y;

            int n = x.Length;

            float[] r = new float[n]; // the right hand side numbers: wikipedia page overloads b

            var   m = new TriDiagonalMatrix(n);
            float dx1, dx2, dy1, dy2;

            // First row is different (equation 16 from the article)
            if (float.IsNaN(startSlope))
            {
                dx1    = x[1] - x[0];
                m.C[0] = 1.0f / dx1;
                m.B[0] = 2.0f * m.C[0];
                r[0]   = 3 * (y[1] - y[0]) / (dx1 * dx1);
            }
            else
            {
                m.B[0] = 1;
                r[0]   = startSlope;
            }

            // Body rows (equation 15 from the article)
            for (int i = 1; i < n - 1; i++)
            {
                dx1 = x[i] - x[i - 1];
                dx2 = x[i + 1] - x[i];

                m.A[i] = 1.0f / dx1;
                m.C[i] = 1.0f / dx2;
                m.B[i] = 2.0f * (m.A[i] + m.C[i]);

                dy1  = y[i] - y[i - 1];
                dy2  = y[i + 1] - y[i];
                r[i] = 3 * (dy1 / (dx1 * dx1) + dy2 / (dx2 * dx2));
            }

            // Last row also different (equation 17 from the article)
            if (float.IsNaN(endSlope))
            {
                dx1        = x[n - 1] - x[n - 2];
                dy1        = y[n - 1] - y[n - 2];
                m.A[n - 1] = 1.0f / dx1;
                m.B[n - 1] = 2.0f * m.A[n - 1];
                r[n - 1]   = 3 * (dy1 / (dx1 * dx1));
            }
            else
            {
                m.B[n - 1] = 1;
                r[n - 1]   = endSlope;
            }

            //if (debug) Console.WriteLine("Tri-diagonal matrix:\n{0}", m.ToDisplayString(":0.0000", "  "));
            //if (debug) Console.WriteLine("r: {0}", ArrayUtil.ToString<float>(r));

            // k is the solution to the matrix
            float[] k = m.Solve(r);
            //if (debug) Console.WriteLine("k = {0}", ArrayUtil.ToString<float>(k));

            // a and b are each spline's coefficients
            this.a = new float[n - 1];
            this.b = new float[n - 1];

            for (int i = 1; i < n; i++)
            {
                dx1      = x[i] - x[i - 1];
                dy1      = y[i] - y[i - 1];
                a[i - 1] = k[i - 1] * dx1 - dy1; // equation 10 from the article
                b[i - 1] = -k[i] * dx1 + dy1;    // equation 11 from the article
            }

            //if (debug) Console.WriteLine("a: {0}", ArrayUtil.ToString<float>(a));
            //if (debug) Console.WriteLine("b: {0}", ArrayUtil.ToString<float>(b));
        }