Catmull-Rom to Bézier

Drawing a curve through points by interpreting a Bézier curve (for canvas bezierCurveTo) from a Catmull-Rom spline.

HTML

<canvas id="canvas" width="500" height="500"></canvas>

JavaScript

var TWO_PI = Math.PI * 2;

var points = [];
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;

function drawPoints(points, ctx) {
    
    ctx.strokeStyle = 'rgba(0,0,0,0.25)';
    
    for (var i = 0, n = points.length, p; i < n; i++) {
        p = points[i];
        ctx.beginPath();
        ctx.arc(p.x, p.y, 3, 0, TWO_PI, false);
        ctx.closePath();
        ctx.stroke();
        ctx.fillText('p' + i, p.x + 6, p.y + 2);
    }
}

function generatePoints(list, count) {
    for (var i = 0; i < count; i++) {
        list.push({
            x: (width * 0.1) + Math.random() * (width * 0.8),
            y: (height * 0.1) + Math.random() * (height * 0.8)
        });
    }
}

function curveThroughPoints(points, ctx) {
    
    ctx.beginPath();
    
    var p0, p1, p2, p3, i6 = 1 / 6;
    
    for (var i = 3, n = points.length; i < n; i++) {
        
        p0 = points[i - 3];
        p1 = points[i - 2];
        p2 = points[i - 1];
        p3 = points[i];
        
        if (i === 3) {
            ctx.moveTo(p1.x, p1.y);
        }
        
        ctx.bezierCurveTo(
            (p2.x * i6) + p1.x + (p0.x * -i6),
            p2.y * i6 + p1.y + p0.y * -i6,
            p3.x * -i6 + p2.x + p1.x * i6,
            p3.y * -i6 + p2.y + p1.y * i6,
            p2.x,
            p2.y
        );
    }
    
    ctx.lineWidth = 1;
    ctx.strokeStyle = 'rgba(255,0,255,0.8)';
    ctx.stroke();
}

generatePoints(points, 10);
curveThroughPoints(points, context);
drawPoints(points, context);