Per @fang's comment below. It may be beter to use Catmull-Rom Interpolating Spline instead, which both interpolates and has local control property. See more here
For stitching together cubic bezier curves that interpolate (more like natural cubic splines) see below original answer.
===================================================================
The following is javascript
-like pseudo-code that computes a series of (up to) cubic bezier curves that together combine to achieve one smooth curve passign through given points. Note bezier
in below code is assumed to be a function that computes (the polynomial form of) a cubic bezier through given control points (which is already known algorithm). Note2 below algorithm is for 1d curves it is easily adjusted for 2d curves (ie compute x and y coordinates)
function bezierThrough( knots )
{
var i, points, segments;
computePoints = function computePoints( knots ) {
var i, p1, p2, a, b, c, r, m, n = knots.length-1;
p1 = new Array(n);
p2 = new Array(n);
/*rhs vector*/
a = new Array(n);
b = new Array(n);
c = new Array(n);
r = new Array(n);
/*left most segment*/
a[0] = 0;
b[0] = 2;
c[0] = 1;
r[0] = knots[0] + 2*knots[1];
/*internal segments*/
for(i=1; i<n-1; i++)
{
a[i] = 1;
b[i] = 4;
c[i] = 1;
r[i] = 4*knots[i] + 2*knots[i+1];
}
/*right segment*/
a[n-1] = 2;
b[n-1] = 7;
c[n-1] = 0;
r[n-1] = 8*knots[n-1] + knots[n];
/*solves Ax=b with the Thomas algorithm (from Wikipedia)*/
for(i=1; i<n; i++)
{
m = a[i] / b[i-1];
b[i] = b[i] - m*c[i - 1];
r[i] = r[i] - m*r[i-1];
}
p1[n-1] = r[n-1] / b[n-1];
for(i=n-2; i>=0; --i)
p1[i] = (r[i]-c[i]*p1[i+1]) / b[i];
/*we have p1, now compute p2*/
for (i=0;i<n-1;i++)
p2[i] = 2*knots[i+1] - p1[i+1];
p2[n-1] = (knots[n]+p1[n-1])/2;
return [p1, p2];
};
if ( 1 === knots.length )
{
segments = [knots[0]];
}
else if ( 2 === knots.length )
{
segments = [bezier([knots[0], knots[1]])];
}
else
{
segments = [];
points = computePoints(knots);
for(i=0; i<knots.length-1; i++)
segments.push(bezier([knots[i], points[0][i], points[1][i], knots[i+1]]));
}
return segments;
}
see also related post
Adapted code from here