-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathindex.js
83 lines (66 loc) · 1.93 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
function interpolate(t, degree, points, knots, weights, result) {
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
];
// remap t to the domain where the spline is defined
var low = knots[domain[0]];
var high = knots[domain[1]];
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;
}
module.exports = interpolate;