title: Motion paths using cardinal splines
body: <p>I reformatted some code I found to use cardinal splines and draw a curve given a set of points to work with my Canvas library, which works quite nicely, but then I wanted to also use said technique to move objects along a given set of points -- a path. SO had several questions pertaining to my problem, and I've tried to implement the last answer of <a href="https://stackoverflow.com/questions/17083580/i-want-to-do-animation-of-an-object-along-a-particular-path">this</a> question, but I honestly have no idea what half the variables in his code mean. Here's my <a href="https://github.com/khanfusiion3/ArtJS/blob/master/art.js" rel="nofollow noreferrer">library</a>, and the <a href="https://jsfiddle.net/khanfused/dbj9hfjz/" rel="nofollow noreferrer">curve object</a> by itself:</p>
  
  <pre><code>Art.prototype.modules.display.Base.extend({
    constructor: function (options) {
  
      // Declare variables for brevity.
  
      var extend = Art.prototype.modules.utility.extend,
        defaults = {
          points: [],
          tension: 0.5,
          closed: false
        };
  
      // Extend the object with the defaults overwritten by the options.
  
      extend(this, extend(defaults, options));
  
    },
    id: 'curve',
    draw: function () {
  
      // Declare variables for brevity.
  
      var t = this,
        graphics = Art.prototype.modules.display.curve.core.graphics,
        controls = [],
        n = t.points.length,
        getControlPoints = function (a, b, c, d, e, f, tension) {
          var x = {
            x: Math.sqrt(Math.pow(c - a, 2) + Math.pow(d - b, 2)),
            y: Math.sqrt(Math.pow(e - c, 2) + Math.pow(f - d, 2))
          };
          var y = {
            x: tension * x.x / (x.x + x.y)
          };
          y.y = tension - y.x;
          var z = {
            x: c + y.x * (a - e),
            y: d + y.x * (b - f)
          };
          var $z = {
            x: c - y.y * (a - e),
            y: d - y.y * (b - f)
          };
          return [z.x, z.y, $z.x, $z.y];
        };
  
      graphics.strokeStyle = t.stroke;
  
      graphics.lineWidth = t.lineWidth;
  
      if (t.closed) {
        t.points.push(t.points[0], t.points[1], t.points[2], t.points[3]);
        t.points.unshift(t.points[n - 1]);
        t.points.unshift(t.points[n - 1]);
        for (var p = 0; p &lt; n; p += 2) {
          controls = controls.concat(getControlPoints(t.points[p], t.points[p + 1], t.points[p + 2], t.points[p + 3], t.points[p + 4], t.points[p + 5], t.tension));
        }
        controls = controls.concat(controls[0], controls[1]);
        for (var $p = 2; $p &lt; n + 2; $p += 2) {
          graphics.beginPath();
          graphics.moveTo(t.points[$p], t.points[$p + 1]);
          graphics.bezierCurveTo(controls[2 * $p - 2], controls[2 * $p - 1], controls[2 * $p], controls[2 * $p + 1], t.points[$p + 2], t.points[$p + 3]);
          graphics.stroke();
          graphics.closePath();
        }
      } else {
        for (var p = 0; p &lt; n - 4; p += 2) {
          controls = controls.concat(getControlPoints(t.points[p], t.points[p + 1], t.points[p + 2], t.points[p + 3], t.points[p + 4], t.points[p + 5], t.tension));
        }
        for (var $p = 2; $p &lt; t.points.length - 5; $p += 2) {
          graphics.beginPath();
          graphics.moveTo(t.points[$p], t.points[$p + 1]);
          graphics.bezierCurveTo(controls[2 * $p - 2], controls[2 * $p - 1], controls[2 * $p], controls[2 * $p + 1], t.points[$p + 2], t.points[$p + 3]);
          graphics.stroke();
          graphics.closePath();
        }
        graphics.beginPath();
        graphics.moveTo(t.points[0], t.points[1]);
        graphics.quadraticCurveTo(controls[0], controls[1], t.points[2], t.points[3]);
        graphics.stroke();
        graphics.closePath();
        graphics.beginPath();
        graphics.moveTo(t.points[n - 2], t.points[n - 1]);
        graphics.quadraticCurveTo(controls[2 * n - 10], controls[2 * n - 9], t.points[n - 4], t.points[n - 3]);
        graphics.stroke();
        graphics.closePath();
      }
  
      return this;
  
    }
  });
  </code></pre>
  
  <p>I don't necessarily want the code handed to me on a silver platter (although... that would be nice) -- rather, I want to learn the math involved, but preferably in psuedocode and in relatively simple terms. An explanation of the SO answer I linked to would be especially helpful, as it works nicely.</p>