Skip to content

Instantly share code, notes, and snippets.

@nicholaswmin
Created September 7, 2015 12:49
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save nicholaswmin/c2661eb11cad5671d816 to your computer and use it in GitHub Desktop.
Save nicholaswmin/c2661eb11cad5671d816 to your computer and use it in GitHub Desktop.
Catmull Rom Fitting Algorithm in Javascript through a series of X/Y Points
/**
* Interpolates a Catmull-Rom Spline through a series of x/y points
* Converts the CR Spline to Cubic Beziers for use with SVG items
*
* If 'alpha' is 0.5 then the 'Centripetal' variant is used
* If 'alpha' is 1 then the 'Chordal' variant is used
*
*
* @param {Array} data - Array of points, each point in object literal holding x/y values
* @return {String} d - SVG string with cubic bezier curves representing the Catmull-Rom Spline
*/
var catmullRomFitting = function (data,alpha) {
if (alpha == 0 || alpha === undefined) {
return false;
} else {
var p0, p1, p2, p3, bp1, bp2, d1, d2, d3, A, B, N, M;
var d3powA, d2powA, d3pow2A, d2pow2A, d1pow2A, d1powA;
var d = Math.round(data[0].x) + ',' + Math.round(data[0].y) + ' ';
var length = data.length;
for (var i = 0; i < length - 1; i++) {
p0 = i == 0 ? data[0] : data[i - 1];
p1 = data[i];
p2 = data[i + 1];
p3 = i + 2 < length ? data[i + 2] : p2;
d1 = Math.sqrt(Math.pow(p0.x - p1.x, 2) + Math.pow(p0.y - p1.y, 2));
d2 = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
d3 = Math.sqrt(Math.pow(p2.x - p3.x, 2) + Math.pow(p2.y - p3.y, 2));
// Catmull-Rom to Cubic Bezier conversion matrix
// A = 2d1^2a + 3d1^a * d2^a + d3^2a
// B = 2d3^2a + 3d3^a * d2^a + d2^2a
// [ 0 1 0 0 ]
// [ -d2^2a /N A/N d1^2a /N 0 ]
// [ 0 d3^2a /M B/M -d2^2a /M ]
// [ 0 0 1 0 ]
d3powA = Math.pow(d3, alpha);
d3pow2A = Math.pow(d3, 2 * alpha);
d2powA = Math.pow(d2, alpha);
d2pow2A = Math.pow(d2, 2 * alpha);
d1powA = Math.pow(d1, alpha);
d1pow2A = Math.pow(d1, 2 * alpha);
A = 2 * d1pow2A + 3 * d1powA * d2powA + d2pow2A;
B = 2 * d3pow2A + 3 * d3powA * d2powA + d2pow2A;
N = 3 * d1powA * (d1powA + d2powA);
if (N > 0) {
N = 1 / N;
}
M = 3 * d3powA * (d3powA + d2powA);
if (M > 0) {
M = 1 / M;
}
bp1 = { x: (-d2pow2A * p0.x + A * p1.x + d1pow2A * p2.x) * N,
y: (-d2pow2A * p0.y + A * p1.y + d1pow2A * p2.y) * N };
bp2 = { x: (d3pow2A * p1.x + B * p2.x - d2pow2A * p3.x) * M,
y: (d3pow2A * p1.y + B * p2.y - d2pow2A * p3.y) * M };
if (bp1.x == 0 && bp1.y == 0) {
bp1 = p1;
}
if (bp2.x == 0 && bp2.y == 0) {
bp2 = p2;
}
d += 'C' + bp1.x + ',' + bp1.y + ' ' + bp2.x + ',' + bp2.y + ' ' + p2.x + ',' + p2.y + ' ';
}
return d;
}
};
@sivakrishna551
Copy link

Hello nicholaswmin,
Is this js having any opensource license like(MIT) OR any copy rights ?
OR
can we use this for commercial purpose directly ?

@nicholaswmin
Copy link
Author

@sivakrishna551 - it's MIT from me.

I've chopped some parts of the code from somewhere else that I can't remember (was somekind of chart-drawing library). I think it was MIT licensed as well but I'm not 100% positive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment