• Path.js

  • ¶

    Path of points

    Example use

    var points = [
      new Vec3(-1.5, -1.0, 0),
      new Vec3(-0.5, -0.7, 0),
      new Vec3( 0.5,  0.7, 0),
      new Vec3( 1.5,  1.0, 0)
    ]
    
    var path = new Path(points)
    

    Reference

    var Vec3 = require('./Vec3');
  • ¶

    Path ( points, closed )

    points - Array of points { Array of Vec3 }
    closed - is it a closed path or not? { Boolean }

    function Path(points, closed) {
      this.points = points || [];
      this.dirtyLength = true;
      this.closed = closed || false;
      this.samplesCount = 1000;
    }
  • ¶

    addPoint ( p )

    p - point as a { Vec3 }
    returns

    Path.prototype.addPoint = function(p) {
      return this.points.push(p);
  • ¶

    shouldnt this return this?

    };
  • ¶

    getPoint ( t, debug )

    t -
    debug - what is this lol
    returns point as a { Vec3 }

    Path.prototype.getPoint = function(t, debug) {
      var point = t * (this.points.length - 1);
      var intPoint = Math.floor(point);
      var weight = point - intPoint;
      var c0 = intPoint;
      var c1 = intPoint + 1;
      if (intPoint === this.points.length - 1) {
        c0 = intPoint;
        c1 = intPoint;
      }
      var vec = new Vec3();
      vec.x = this.points[c0].x + (this.points[c1].x - this.points[c0].x) * weight;
      vec.y = this.points[c0].y + (this.points[c1].y - this.points[c0].y) * weight;
      vec.z = this.points[c0].z + (this.points[c1].z - this.points[c0].z) * weight;
      return vec;
    };
  • ¶

    getPointAt ( d )

    d - ?
    returns point as a { Vec3 }

    Path.prototype.getPointAt = function(d) {
      if (!this.closed) {
        d = Math.max(0, Math.min(d, 1));
      }
      if (this.dirtyLength) {
        this.precalculateLength();
      }
      var k = 0;
      for (var i=0; i<this.accumulatedLengthRatios.length; i++) {
        if (this.accumulatedLengthRatios[i] > d - 1/this.samplesCount) {
          k = this.accumulatedRatios[i];
          break;
        }
      }
      return this.getPoint(k, true);
    };
  • ¶

    naive implementation

    getClosestPoint ( point )

    Finds closest point to given point
    point - point as a { Vec3 }
    returns point as a { Vec3 }

    Path.prototype.getClosestPoint = function(point) {
      if (this.dirtyLength) {
        this.precalculateLength();
      }
      var closesPoint = this.precalculatedPoints.reduce(function(best, p) {
        var dist = point.squareDistance(p);
        if (dist < best.dist) {
          return { dist: dist, point: p };
        }
        else return best;
      }, { dist: Infinity, point: null });
      return closesPoint.point;
    }
  • ¶

    getClosestPointRatio ( point )

    point - point as a { Vec3 }
    returns

    Path.prototype.getClosestPointRatio = function(point) {
      if (this.dirtyLength) {
        this.precalculateLength();
      }
      var closesPoint = this.precalculatedPoints.reduce(function(best, p, pIndex) {
        var dist = point.squareDistance(p);
        if (dist < best.dist) {
          return { dist: dist, point: p, index: pIndex };
        }
        else return best;
      }, { dist: Infinity, point: null, index: -1 });
      return this.accumulatedLengthRatios[closesPoint.index];
    }
  • ¶

    close ()

    Path.prototype.close = function() {
      return this.closed = true;
    };
  • ¶

    isClosed ()

    returns { Boolean }

    Path.prototype.isClosed = function() {
      return this.closed;
    };
  • ¶

    reverse ()

    Path.prototype.reverse = function() {
      this.points = this.points.reverse();
      return this.dirtyLength = true;
    };
  • ¶

    precalculateLength ()

    Path.prototype.precalculateLength = function() {
      this.accumulatedRatios = [];
      this.accumulatedLengthRatios = [];
      this.accumulatedLengths = [];
      this.precalculatedPoints = [];
    
      var step = 1 / this.samplesCount;
      var k = 0;
      var totalLength = 0;
      var point = null;
      var prevPoint = null;
    
      for (var i=0; i<this.samplesCount; i++) {
        prevPoint = point;
        point = this.getPoint(k);
        if (i > 0) {
          totalLength += point.dup().sub(prevPoint).length();;
        }
        this.accumulatedRatios.push(k);
        this.accumulatedLengths.push(totalLength);
        this.precalculatedPoints.push(point);
        k += step;
      }
      for (var i=0; i<this.accumulatedLengths.length - 1; i++) {
        this.accumulatedLengthRatios.push(this.accumulatedLengths[i] / totalLength);
      }
      this.length = totalLength;
      return this.dirtyLength = false;
    };
    
    module.exports = Path;