mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-26 17:54:52 +02:00
89 lines
2.3 KiB
JavaScript
89 lines
2.3 KiB
JavaScript
// https://github.com/thibauts/b-spline
|
|
export default 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;
|
|
}
|
|
}
|
|
|
|
// closed curve?
|
|
if (weights.length < points.length) {
|
|
weights = weights.concat(weights.slice(0, degree));
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
// closed curve?
|
|
if (knots.length === points.length) {
|
|
knots = knots.concat(knots.slice(0, degree));
|
|
}
|
|
|
|
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;
|
|
}
|