1 /**
  2  * Constructs a default position constraint using the <tt>fix</tt> attribute.
  3  * An optional position function can be specified to determine how the fixed
  4  * position per-particle is determined.
  5  *
  6  * @class Constraints particles to a fixed position. The fixed position per
  7  * particle is determined using a given position function, which defaults to
  8  * <tt>function(d) d.fix</tt>.
  9  *
 10  * <p>If the position function returns null, then no position constraint is
 11  * applied to the given particle. Otherwise, the particle's position is set to
 12  * the returned position, as expressed by a {@link pv.Vector}. (Note: the
 13  * position does not need to be an instance of <tt>pv.Vector</tt>, but simply an
 14  * object with <tt>x</tt> and <tt>y</tt> attributes.)
 15  *
 16  * <p>This constraint also supports a configurable alpha parameter, which
 17  * defaults to 1. If the alpha parameter is in the range [0,1], then rather than
 18  * setting the particle's new position directly to the position returned by the
 19  * supplied position function, the particle's position is interpolated towards
 20  * the fixed position. This results is a smooth (exponential) drift towards the
 21  * fixed position, which can increase the stability of the physics simulation.
 22  * In addition, the alpha parameter can be decayed over time, relaxing the
 23  * position constraint, which helps to stabilize on an optimal solution.
 24  *
 25  * @param {function} [f] the position function.
 26  */
 27 pv.Constraint.position = function(f) {
 28   var a = 1, // default alpha
 29       constraint = {};
 30 
 31   if (!arguments.length) /** @ignore */ f = function(p) { return p.fix; };
 32 
 33   /**
 34    * Sets or gets the alpha parameter for position interpolation. If the alpha
 35    * parameter is in the range [0,1], then rather than setting the particle's
 36    * new position directly to the position returned by the supplied position
 37    * function, the particle's position is interpolated towards the fixed
 38    * position.
 39    *
 40    * @function
 41    * @name pv.Constraint.position.prototype.alpha
 42    * @param {number} x the new alpha parameter, in the range [0,1].
 43    * @returns {pv.Constraint.position} this.
 44    */
 45   constraint.alpha = function(x) {
 46     if (arguments.length) {
 47       a = Number(x);
 48       return constraint;
 49     }
 50     return a;
 51   };
 52 
 53   /**
 54    * Applies this constraint to the specified particles.
 55    *
 56    * @function
 57    * @name pv.Constraint.position.prototype.apply
 58    * @param {pv.Particle} particles particles to which to apply this constraint.
 59    */
 60   constraint.apply = function(particles) {
 61     for (var p = particles; p; p = p.next) {
 62       var v = f(p);
 63       if (v) {
 64         p.x += (v.x - p.x) * a;
 65         p.y += (v.y - p.y) * a;
 66         p.fx = p.fy = p.vx = p.vy = 0;
 67       }
 68     }
 69   };
 70 
 71   return constraint;
 72 };
 73