1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-02-24 17:42:43 +01:00
BezierInfo-2/lib/spline.js
2016-09-11 17:55:42 -07:00

83 lines
2.0 KiB
JavaScript

// https://github.com/thibauts/b-spline
module.exports = function interpolate(t, degree, points, knots, weights, result, scaled) {
var i,j,s,l; // function-scoped iteration variables
var n = points.length; // points count
var d = points[0].length; // point dimensionality
if(degree < 1) throw new Error('degree must be at least 1 (linear)');
if(degree > (n-1)) throw new Error('degree must be less than or equal to point count - 1');
if(!weights) {
// build weight vector of length [n]
weights = [];
for(i=0; i<n; i++) {
weights[i] = 1;
}
}
if(!knots) {
// build knot vector of length [n + degree + 1]
var knots = [];
for(i=0; i<n+degree+1; i++) {
knots[i] = i;
}
} else {
if(knots.length !== n+degree+1) throw new Error('bad knot vector length');
}
var domain = [
degree,
knots.length-1 - degree
];
var low = knots[domain[0]];
var high = knots[domain[1]];
// remap t to the domain where the spline is defined
if (!scaled) {
t = t * (high - low) + low;
}
if(t < low || t > high) throw new Error('out of bounds');
// find s (the spline segment) for the [t] value provided
for(s=domain[0]; s<domain[1]; s++) {
if(t >= knots[s] && t <= knots[s+1]) {
break;
}
}
// convert points to homogeneous coordinates
var v = [];
for(i=0; i<n; i++) {
v[i] = [];
for(j=0; j<d; j++) {
v[i][j] = points[i][j] * weights[i];
}
v[i][d] = weights[i];
}
// l (level) goes from 1 to the curve degree + 1
var alpha;
for(l=1; l<=degree+1; l++) {
// build level l of the pyramid
for(i=s; i>s-degree-1+l; i--) {
alpha = (t - knots[i]) / (knots[i+degree+1-l] - knots[i]);
// interpolate each component
for(j=0; j<d+1; j++) {
v[i][j] = (1 - alpha) * v[i-1][j] + alpha * v[i][j];
}
}
}
// convert back to cartesian and return
var result = result || [];
for(i=0; i<d; i++) {
result[i] = v[s][i] / v[s][d];
}
return result;
};