package mikera.vectorz;

/**
 * Static functions for quaternion maths, implemented on Vector4 instances
 * 
 * Vector4 instance represents (x,y,z,t) tuple,
 * 
 * Where: quaternion value = x.i + y.j + z.k + t
 * 
 * @author Mike
 *
 */
public class Quaternions {

	private Quaternions(){}

	/** 
	 * Computes the conjugate of a quaternion
	 * 
	 * @param a
	 * @return
	 */
	public static Vector4 conjugate(Vector4 a) {
		return new Vector4(-a.x,-a.y,-a.z,a.t);
	}
	
	/**
	 * Computes the product of two quaternions as a new quaternion
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static Vector4 mul(Vector4 a, Vector4 b) {
		double rt=(a.t*b.t)-(a.x*b.x)-(a.y*b.y)-(a.z*b.z);
		double rx=(a.t*b.x)+(a.x*b.t)+(a.y*b.z)-(a.z*b.y);
		double ry=(a.t*b.y)-(a.x*b.z)+(a.y*b.t)+(a.z*b.x);
		double rz=(a.t*b.z)+(a.x*b.y)-(a.y*b.x)+(a.z*b.t);
		return new Vector4(rx,ry,rz,rt);
	}
	
	/**
	 * Rotates a 3D vector using the given quaternion, returning a new 3D vector
	 * @param q
	 * @param a
	 * @return
	 */
	public static Vector3 rotate(Vector4 a, Vector3 b) {
		double rx=(a.t*b.x)+(a.y*b.z)-(a.z*b.y);
		double ry=(a.t*b.y)-(a.x*b.z)+(a.z*b.x);
		double rz=(a.t*b.z)+(a.x*b.y)-(a.y*b.x);
		return new Vector3(rx,ry,rz);
	}
	
	/**
	 * Create a quaternion that represents a rotation around a given axis vector.
	 * 
	 * The axis vector need not be normalised.
	 * 
	 * @param axis
	 * @param angle
	 * @return
	 */
	public static Vector4 axisAngle(Vector3 axis, double angle) {
		double ha=angle; // 0.5*angle;
		double ca=Math.cos(ha);
		double sa=Math.sin(ha);
		double x=axis.x, y=axis.y, z=axis.z;
		double d=(x*x)+(y*y)+(z*z);
		double ff=sa;
		if ((d<(0.99999))||(d>1.00001)) {
			ff/=Math.sqrt(d);
		} else {
			ff-=(d-1.0)*0.5;
		}
		return new Vector4(ff*x,ff*y,ff*z,ca);
	}
	
	/**
	 * Normalises a quaternion
	 * 
	 * @param a
	 * @return
	 */
	public static Vector4 normalise(Vector4 a) {
		double dd=a.elementSquaredSum();
		if (dd>0.0) {
			double d=1.0/Math.sqrt(dd);
			return new Vector4(a.x*d,a.y*d,a.z*d,a.t*d);
		} else {
			return new Vector4(0,0,0,1);
		}
	}
	
	/**
	 * Inverts a quaternion
	 * 
	 * @param a
	 * @return
	 */
	public static Vector4 invert(Vector4 a) {
		double dd=a.elementSquaredSum();
		double ff=1.0/dd;
		return new Vector4(-a.x*ff,-a.y*ff,-a.z*ff,a.t*ff);
	}
 }

 

Ads help maintain this website.