/** * Computes the polynomial coefficients for the Hermite cubic spline interpolation * for a set of (x,y) value pairs and their derivatives. This is modeled off of * the InterpolateHermiteSorted method in the Math.NET CubicSpline class. * * @param xVals * x values for interpolation. * @param yVals * y values for interpolation. * @param firstDerivatives * First derivative values of the function. * @returns * Polynomial coefficients of the segments. */ static List <float>[] computeHermitePolyCoefficients(float[] xVals, float[] yVals, float[] firstDerivatives) { if (xVals.Length != yVals.Length || xVals.Length != firstDerivatives.Length) { Debug.Log("[LogLabel.Easing] Dimension mismatch"); } if (xVals.Length < 2) { Debug.Log("[LogLabel.Easing] Not enough points."); } int n = xVals.Length - 1; // number of segments List <float>[] segmentCoeffs = new List <float> [n]; for (int i = 0; i < n; i++) { float w = xVals[i + 1] - xVals[i]; float w2 = w * w; float yv = yVals[i]; float yvP = yVals[i + 1]; float fd = firstDerivatives[i]; float fdP = firstDerivatives[i + 1]; float[] coeffs = new float[4]; coeffs[0] = yv; coeffs[1] = firstDerivatives[i]; coeffs[2] = (3 * (yvP - yv) / w - 2 * fd - fdP) / w; coeffs[3] = (2 * (yv - yvP) / w + fd + fdP) / w2; segmentCoeffs[i] = PolynomialRoutines.trimPoly(coeffs).ToList(); } return(segmentCoeffs); }
/** * An univariate numeric function. */ //static System.Func<float, float> UniFunction; /// <summary> /// Returns a function that computes a cubic spline interpolation for the data /// set using the Akima algorithm, as originally formulated by Hiroshi Akima in /// his 1970 paper "A New Method of Interpolation and Smooth Curve Fitting Based /// on Local Procedures." /// J. ACM 17, 4 (October 1970), 589-602. DOI=10.1145/321607.321609 /// http://doi.acm.org/10.1145/321607.321609 /// /// This implementation is based on the Akima implementation in the CubicSpline /// class in the Math.NET Numerics library. The method referenced is /// CubicSpline.InterpolateAkimaSorted. /// /// Returns a polynomial spline function consisting of n cubic polynomials, /// defined over the subintervals determined by the x values, /// x[0] < x[1] < ... < x[n-1]. /// The Akima algorithm requires that n >= 5. /// /// @param xVals /// The arguments of the interpolation points. /// @param yVals /// The values of the interpolation points. /// @returns /// A function which interpolates the dataset. /// </summary> public static System.Func <float, float> createAkimaSplineInterpolator(float[] xVals, float[] yVals) { List <float>[] segmentCoeffs = computeAkimaPolyCoefficients(xVals, yVals); float[] xValsCopy = new float[xVals.Length]; xVals.CopyTo(xValsCopy, 0); // clone to break dependency on passed values return((float x) => { return PolynomialRoutines.evaluatePolySegment(xValsCopy, segmentCoeffs, x); }); }