code: public final void interpolate(Quaternion q1, double alpha) {
  		// From "Advanced Animation and Rendering Techniques"
  		// by Watt and Watt pg. 364, function as implemented appeared to be 
  		// incorrect.  Fails to choose the same quaternion for the double
  		// covering. Resulting in change of direction for rotations.
  		// Fixed function to negate the first quaternion in the case that the
  		// dot product of q1 and this is negative. Second case was not needed. 
  
  		double dot,s1,s2,om,sinom;
  
  		dot = this.x*q1.x + this.y*q1.y + this.z*q1.z + this.w*q1.w;
  
  		if ( dot < 0 ) {
  			// negate quaternion
  			q1.x = -q1.x;  q1.y = -q1.y;  q1.z = -q1.z;  q1.w = -q1.w;
  			dot = -dot;
  		}
  
  		if ( (1.0 - dot) > EPS ) {
  			om = Math.acos(dot);
  			sinom = Math.sin(om);
  			s1 = Math.sin((1.0-alpha)*om)/sinom;
  			s2 = Math.sin( alpha*om)/sinom;
  		} else{
  			s1 = 1.0 - alpha;
  			s2 = alpha;
  		}
  
  		this.w = (s1*this.w + s2*q1.w);
  		this.x = (s1*this.x + s2*q1.x);
  		this.y = (s1*this.y + s2*q1.y);
  		this.z = (s1*this.z + s2*q1.z);
  	}
docs: Performs a great circle interpolation between this quaternion
  and the quaternion parameter and places the result into this
  quaternion.
  @param q1  the other quaternion
  @param alpha  the alpha interpolation parameter