Cubic spline interpolation. Call Fit (or use the corrector constructor) to compute spline coefficients, then Eval to evaluate the spline at other X coordinates.

This is implemented based on the wikipedia article: http://en.wikipedia.org/wiki/Spline_interpolation I'm not sure I have the right to include a copy of the article so the equation numbers referenced in comments will end up being wrong at some point.

This is not optimized, and is not MT safe. This can extrapolate off the ends of the splines. You must provide points in X sort order.

Example #1
0
 /// <summary>
 /// Static all-in-one method to fit the splines and evaluate at X coordinates.
 /// </summary>
 /// <param name="x">Input. X coordinates to fit.</param>
 /// <param name="y">Input. Y coordinates to fit.</param>
 /// <param name="xs">Input. X coordinates to evaluate the fitted curve at.</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>
 /// <returns>The computed y values for each xs.</returns>
 public static float[] Compute(float[] x, float[] y, float[] xs, float startSlope = float.NaN, float endSlope = float.NaN, bool debug = false)
 {
     CubicSpline spline = new CubicSpline();
     return spline.FitAndEval(x, y, xs, startSlope, endSlope, debug);
 }
Example #2
0
        /// <summary>
        /// Fit the input x,y points using a 'geometric' strategy so that y does not have to be a single-valued
        /// function of x.
        /// </summary>
        /// <param name="x">Input x coordinates.</param>
        /// <param name="y">Input y coordinates, do not need to be a single-valued function of x.</param>
        /// <param name="nOutputPoints">How many output points to create.</param>
        /// <param name="xs">Output (interpolated) x values.</param>
        /// <param name="ys">Output (interpolated) y values.</param>
        public static void FitGeometric(float[] x, float[] y, float[] directions, int nOutputPoints, out float[] xs, out float[] ys)
        {
            // Compute distances
            int n = x.Length;
            float[] dists = new float[n]; // cumulative distance
            dists[0] = 0;
            float totalDist = 0;

            for (int i = 1; i < n; i++)
            {
                float dx = x[i] - x[i - 1];
                float dy = y[i] - y[i - 1];
                float dist = (float)Math.Sqrt(dx * dx + dy * dy);
                totalDist += dist;
                dists[i] = totalDist;
            }

            // Create 'times' to interpolate to
            float dt = totalDist / (nOutputPoints - 1);
            float[] times = new float[nOutputPoints];
            times[0] = 0;

            for (int i = 1; i < nOutputPoints; i++)
            {
                times[i] = times[i - 1] + dt;
            }

            var deg45 = (float) Math.PI/4;
            var deg90 = (float)Math.PI / 2;
            var deg180 = (float)Math.PI;

            // Spline fit both x and y to times
            CubicSpline xSpline = new CubicSpline();
            xs = xSpline.FitAndEval(dists, x, times, directions.FirstOrDefault(), directions.LastOrDefault());

            CubicSpline ySpline = new CubicSpline();
            ys = ySpline.FitAndEval(dists, y, times, directions.FirstOrDefault(), directions.LastOrDefault());
        }
Example #3
0
        /// <summary>
        /// Static all-in-one method to fit the splines and evaluate at X coordinates.
        /// </summary>
        /// <param name="x">Input. X coordinates to fit.</param>
        /// <param name="y">Input. Y coordinates to fit.</param>
        /// <param name="xs">Input. X coordinates to evaluate the fitted curve at.</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>
        /// <returns>The computed y values for each xs.</returns>
        public static float[] Compute(float[] x, float[] y, float[] xs, float startSlope = float.NaN, float endSlope = float.NaN, bool debug = false)
        {
            CubicSpline spline = new CubicSpline();

            return(spline.FitAndEval(x, y, xs, startSlope, endSlope, debug));
        }