UNPKG

splines

Version:

Convenient and efficient B-splines.

57 lines (54 loc) 2.24 kB
var assert = require('assert'); // TODO: This could probably be a little bit more efficient by explicitly working out (programmatically!) the computation for each i. module.exports.bspline = function (n, period) { assert(n>=0 && n==n|0, "splines: B-spline order must be a non-negative integer."); assert(period===undefined || period>=n+1, "splines: Periodic B-spline must have period larger than or equal to order+1."); // TODO: This condition could be lifted, but it does make things a little complicated. var j, k, text = [], gammaAccu = 1; text.push("var t=x+" + ((n+1)/2) +";"); if (period!==undefined) { text.push("t-=Math.floor(t*" + (1/period) + ")*" + period + ";"); } text.push("var i=Math.floor(t);"); text.push("if (i<0 || i>" + n + ") return 0;"); for(j=0; j<=n; j++) { text.push("var A0_" + j + "=0;"); } setA0(0,n); /*for(j=0; j<=n; j++) { text.push("var A0_" + j + "=0;"); } text.push("switch(i) {"); for(j=0; j<=n; j++) { text.push("case " + j + ": A0_" + j + "=1; break;"); } text.push("default: return 0;"); text.push("}");*/ /*text.push("if (i<0 || i>" + n + ") return 0;"); for(j=0; j<=n; j++) { text.push("var A0_" + j + "= i==" + j + " ? 1 : 0;"); }*/ text.push("var alpha0=t-i;"); for(j=1; j<=n-1; j++) { text.push("var alpha" + j + "=alpha0+" + j + ";"); } for(k=1; k<=n; k++) { gammaAccu *= (n+1-k); for(j=0; j<=n-k; j++) { text.push("var A" + k + "_" + j + "=" + (n+1-k) + "*A" + (k-1) + "_" + (j+1) + "+alpha" + j + "*(A" + (k-1) + "_" + j + "-A" + (k-1) + "_" + (j+1) + ");"); } } text.push("return A" + n + "_0*" + (1/gammaAccu) + ";"); return new Function("x", text.join('\n')); function setA0(A,B) { // Find the A0 component to set within the range [A,B] if (A==B) { text.push("A0_" + A + "=1;"); } else { var mid = (A+B)>>1; text.push("if (i<=" + mid + ") {"); setA0(A,mid); text.push("} else {"); setA0(mid+1,B); text.push("}"); } } };