Published
Edited
Feb 4, 2021
Importers
4 stars
Insert cell
Insert cell
values = [[0, 1.5], [2, 2], [3, 1], [4, 0.5], [5, 1], [6, 2], [7, 3]]
Insert cell
f = interpolateCatmullRom.alpha(0.5)(values)
Insert cell
Insert cell
values.map((_, i) => f(i / (values.length - 1)))
Insert cell
Insert cell
Insert cell
Insert cell
interpolateCatmullRom([3, 1, 5, 9, 8, 7, 8])(0.5) // returns the central control point
Insert cell
Insert cell
interpolateCatmullRom([[0, 3], [1, 1], [2, 5], [3, 9], [4, 8], [5, 7], [6, 8]])(
0.5
) // returns the central control point
Insert cell
Insert cell
interpolateCatmullRom([
[0, 3, 4],
[1, 1, 8],
[2, 5, 3],
[3, 9, 1],
[4, 8, 3],
[5, 7, 8],
[6, 8, 7]
])(0.5) // returns the central control point
Insert cell
interpolateCatmullRom = {
// adapted from d3.interpolateBasis: https://github.com/d3/d3-interpolate/blob/master/src/basis.js

function deltaT(u, v, alpha) {
let sum = 0;
for (let i = 0; i < u.length; i++) {
sum += (u[i] - v[i]) * (u[i] - v[i]);
}
return Math.pow(sum, alpha / 2);
}
function sum(fu, u, fv, v, div = 1) {
return u.map((ui, i) => (fu * ui + fv * v[i]) / div);
}
function catmullRom(tt, v0, v1, v2, v3, alpha) {
var t0 = 0,
t1 = deltaT(v1, v0, alpha / 2) + t0,
t2 = deltaT(v2, v1, alpha / 2) + t1,
t3 = deltaT(v3, v2, alpha / 2) + t2,
t = (1 - tt) * t1 + tt * t2,
a1 = sum(t1 - t, v0, t - t0, v1, t1 - t0),
a2 = sum(t2 - t, v1, t - t1, v2, t2 - t1),
a3 = sum(t3 - t, v2, t - t2, v3, t3 - t2),
b1 = sum(t2 - t, a1, t - t0, a2, t2 - t0),
b2 = sum(t3 - t, a2, t - t1, a3, t3 - t1),
c = sum(t2 - t, b1, t - t1, b2, t2 - t1);
return c;
}

return (function custom(alpha) {
function interpolateCatmullRom(values) {
// values must be an array of arrays of equal length (2 for 2D, 3 for 3D)
// we accept scalars for 1D, in that case we return a scalar
const scalar = !Array.isArray(values[0]);
const arr = scalar ? u => [u] : u => u;
const unarr = scalar ? u => u[0] : u => u;
var n = values.length - 1;
return function(t) {
var i =
t <= 0 ? (t = 0) : t >= 1 ? ((t = 1), n - 1) : Math.floor(t * n),
v1 = arr(values[i]),
v2 = arr(values[i + 1]),
// should we throw if v1.length !== v2.length?
v0 = i > 0 ? arr(values[i - 1]) : sum(2, v1, -1, v2),
v3 = i < n - 1 ? arr(values[i + 2]) : sum(2, v2, -1, v1);
return unarr(catmullRom((t - i / n) * n, v0, v1, v2, v3, alpha));
};
}

interpolateCatmullRom.alpha = function(alpha) {
return custom(+alpha);
};

return interpolateCatmullRom;
})(0.5);
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more