there exist uniform, centripedal and chordal variants.
# evaluate a uniform Catmull-Rom spline segment at t in [0, 1] catmull_rom = (p0, p1, p2, p3, t) -> a0 = [] a1 = [] a2 = [] a3 = [] for i in [0...p1.length] # cubic polynomial coefficients for each dimension a0[i] = -0.5 * p0[i] + 1.5 * p1[i] - 1.5 * p2[i] + 0.5 * p3[i] a1[i] = p0[i] - 2.5 * p1[i] + 2 * p2[i] - 0.5 * p3[i] a2[i] = -0.5 * p0[i] + 0.5 * p2[i] a3[i] = p1[i] point = [] for i in [0...p1.length] # evaluate cubic polynomial point[i] = ((a0[i] * t + a1[i]) * t + a2[i]) * t + a3[i] point # generate interpolated path through given control points catmull_rom_path = (points, resolution) -> path = [] n = points.length for i in [0...n - 1] # duplicate endpoints as needed for interpolation at boundaries p0 = if i is 0 then points[0] else points[i - 1] p1 = points[i] p2 = if i + 1 < n then points[i + 1] else points[n - 1] p3 = if i + 2 < n then points[i + 2] else points[n - 1] # sample points on spline segment from p1 to p2 for j in [0...resolution] t = j / resolution path.push catmull_rom p0, p1, p2, p3, t if i < n - 1 or j is 0 path
example usage
example_points = [[-0.72, -0.3], [0, 0], [1, 0.8], [1.1, 0.5], [2.7, 1.2], [3.4, 0.27]] path = catmull_rom_path example_points, 100 for p in path console.log "#{p[0]} #{p[1]}"