Interpolation with Cubic Splines

Adobe Photoshop, Gimp and many other image editors have a tool called Curves. There are several "knots" and while you move them, it computes a curve in between. I always wondered, how is this curve computed.

About cubic splines

First, I must say, that we are going to interpolate a function of one real variable, not a curve in a 2D space.

Having several ($n$) "knots" - points in 2D space - pairs $(x, f(x))$, we would like to interpolate between them with a smooth curve. We can interpolate between them with a polynomial of the degree $n-1$, but it usually generates a curve, which is too "wavy". The idea with splines is, that we compute a unique polynomial for each sub-interval between knots, and these polynomials should look good together - they should have the same first, second, third ... derivatives at knots.

I recommend you to read about Splines on Wikipedia..

The algorithm for cubic interpolation is also described on Wikipedia, so I just copied it.

Implementation

In acubic splines interpolation, the input is the set of knots + first derivatives for each knot. I decided to represent it with three arrays: an array of X values (xs), an array of Y values (ys) and an array of derivative values (ks). Here is the function for evaluating a cubic spline for any point X:

CSPL.evalSpline = function(x, xs, ys, ks)
{
    var i = 1;
    while(xs[i]<x) i++;
		
    var t = (x - xs[i-1]) / (xs[i] - xs[i-1]);
		
    var a =  ks[i-1]*(xs[i]-xs[i-1]) - (ys[i]-ys[i-1]);
    var b = -ks[i  ]*(xs[i]-xs[i-1]) + (ys[i]-ys[i-1]);
		
    var q = (1-t)*ys[i-1] + t*ys[i] + t*(1-t)*(a*(1-t)+b*t);
    return q;
}

In a code above, we can give the function any first derivatives (ks). But we usually don't have any specific derivatives, we just want the curve to be as smooth as possible.

From the spline definition, the first and the second derivative of a cubic spline should be continuous. Below is the function, which generates the array of "ks", which have that property. It also sets the second derivative of the first and the last point to zero (Natural Spline).

CSPL.getNaturalKs = function(xs, ys, ks)    // in x values, in y values, out k values
{
    var n = xs.length-1;
    var A = CSPL._gaussJ.zerosMat(n+1, n+2);
        
    for(var i=1; i<n; i++)    // rows
    {
        A[i][i-1] = 1/(xs[i] - xs[i-1]);
        
        A[i][i  ] = 2 * (1/(xs[i] - xs[i-1]) + 1/(xs[i+1] - xs[i])) ;
        
        A[i][i+1] = 1/(xs[i+1] - xs[i]);
        
        A[i][n+1] = 3*   ( (ys[i]-ys[i-1])/ ((xs[i] - xs[i-1])*(xs[i] - xs[i-1])) 
                         +  (ys[i+1]-ys[i])/ ((xs[i+1] - xs[i])*(xs[i+1] - xs[i])) );
    }
    
    A[0][0  ] = 2/(xs[1] - xs[0]);
    A[0][1  ] = 1/(xs[1] - xs[0]);
    A[0][n+1] = 3 * (ys[1] - ys[0]) / ((xs[1]-xs[0])*(xs[1]-xs[0]));
    
    A[n][n-1] = 1/(xs[n] - xs[n-1]);
    A[n][n  ] = 2/(xs[n] - xs[n-1]);
    A[n][n+1] = 3 * (ys[n] - ys[n-1]) / ((xs[n]-xs[n-1])*(xs[n]-xs[n-1]));
        
    CSPL._gaussJ.solve(A, ks);        
}

Where A is $n \times (n+1)$ matrix and CSPL._gaussJ.solve solves the system of linear equations.

I put all my spline code into a small Javascript library named CSPL, which you can find here: CSPL - small Javascript library for cubic spline interpolation.

Old comments (closed because of spam)

37 Comments

  1. Draw a cubic spline curve through Google Earth Placemarks | netkingcol said:

    [...] cubic spline functions provided by Ivan Kuckir at the Faculty of Mathematics and Physics at Charles University in Prague. [...]

    January 2nd, 2014
  2. flaggingly said:

    Dc7nAaU1dfI

    February 20th, 2025
  3. beadwork said:

    uwXwEJ1SXsy

    February 21st, 2025
  4. weighboard said:

    KjJduBWT9hy

    February 21st, 2025
  5. seggars said:

    ukqrsB2RTTl

    February 21st, 2025
  6. supinators said:

    4yBuRiRanpT

    February 21st, 2025
  7. balneation said:

    Q6Ztjq5hlCS

    February 21st, 2025
  8. rag weed said:

    koPslY9sL0v

    February 21st, 2025
  9. toxicity said:

    DdBSIEsohx7

    February 21st, 2025
  10. unbudded said:

    xaOWLbQdSX8

    February 21st, 2025
  11. eversible said:

    zAPHSpM1HLp

    February 21st, 2025
  12. ਕਮ ਸ਼ਾਟ ਪੋਰਨ said:

    PSsXJrLnD8r

    February 21st, 2025
  13. enim said:

    DCtLTbuiSfv

    February 21st, 2025
  14. nostra said:

    lCdvssOkMmn

    February 21st, 2025
  15. reexplain said:

    LPuAx6GB7Os

    February 21st, 2025
  16. filtre said:

    Yp5DNH0Oi5F

    February 21st, 2025
  17. accumsan said:

    vlwLKFZqd3v

    February 21st, 2025
  18. cajeputs said:

    Feaw8FVXmK3

    February 21st, 2025
  19. quirkiest said:

    DQ66UTHnnPw

    February 21st, 2025
  20. pickle relish said:

    Ly3Tp0tKPJL

    February 21st, 2025
  21. pickle relish said:

    Y5pgbMS0T2d

    February 21st, 2025
  22. spirated said:

    PMURMy2dG5Z

    February 21st, 2025
  23. Brandi Glanville said:

    jiw13jgvfOD

    February 21st, 2025
  24. ਗਰਭਵਤੀ ਪੋਰਨ said:

    G6XED3Mlyv0

    February 21st, 2025
  25. heliocentric said:

    lAPlocqvYJB

    February 21st, 2025
  26. vehicula said:

    PobANTvfINr

    February 21st, 2025
  27. Cary Grant said:

    TWCu966n3z6

    February 21st, 2025
  28. unroped said:

    E8Wy8QkH5bM

    February 21st, 2025
  29. reinciting said:

    OcvhX28GhTa

    February 21st, 2025
  30. overfavor said:

    ZHDZ0eqg9pa

    February 21st, 2025
  31. vitae said:

    lhBaax4vgIO

    February 21st, 2025
  32. platemaker said:

    we7uIxkFjmA

    February 21st, 2025
  33. booty shorts said:

    L2zlsojNTbz

    February 21st, 2025
  34. wooned said:

    1f6nwb2sJnn

    February 21st, 2025
  35. pickle relish said:

    RkhGlLpZC40

    February 21st, 2025
  36. hobgoblinries said:

    vjF7V4e5o3T

    February 21st, 2025
  37. pestiferously said:

    fzSnSuN3jUr

    February 21st, 2025