package math.matrix;

import exception.IllegalDimensionException;

/**
 * 3D vector of real numbers, v<sub>i</sub>&isin;&#x211D;.
 * @author Daniel Weschke
 */
public class Vector3D extends Vector{
	
	/**
	 * UID
	 */
	private static final long serialVersionUID = 1904780583446397290L;
	
	public Vector3D(){
		super(3);
	}

	/**
	 * Create vector with given x, y and z value
	 * @param x
	 * @param y
	 * @param z
	 */
	public Vector3D(double x, double y, double z){
		super(x, y, z);
	}

	/**
	 * Create vector with given array
	 * @param data array
	 */
	public Vector3D(double... data){
		super(data);
	}
	
	/**
	 * Copy vector
	 * @param v vector
	 */
	public Vector3D(Vector v){
		super(v);
	}
    
    /**
     * Cross product v x v.
     * A x B = (a<sub>2</sub>b<sub>3</sub> - a<sub>3</sub>b<sub>2</sub>,
     * a<sub>3</sub>b<sub>1</sub> - a<sub>1</sub>b<sub>3</sub>,
     * a<sub>1</sub>b<sub>2</sub> - a<sub>2</sub>b<sub>1</sub>)<sup>T</sup>;
     * a vector quantity
     * @param a vector
     * @return vector
     * @throws IllegalDimensionException
     */
    public Vector3D cross(Vector3D a){
    	Vector3D c = new Vector3D();
    	c.set(0, get(1)*a.get(2) - get(2)*a.get(1));
    	c.set(1, get(2)*a.get(0) - get(0)*a.get(2));
    	c.set(2, get(0)*a.get(1) - get(1)*a.get(0));
    	return c;
    }
    
    /**
     * Scalar triple product.
     * A • (B x C); a scalar quantity
     * @param b vector
     * @param c vector
     * @return scalar
     * @throws IllegalDimensionException
     */
    public double scalTrip(Vector3D b, Vector3D c){
        try {
			return dot(b.cross(c));
		} catch (IllegalDimensionException e) {
			e.printStackTrace();
			return Double.NaN;
		}
    }

    /**
     * Vector triple product.
     * A x (B x C); a vector quantity
     * @param b vector
     * @param c vector
     * @return vector
     * @throws IllegalDimensionException
     */
    public Vector3D vecTrip(Vector3D b, Vector3D c) {
        return this.cross(b.cross(c));
    }
    
    /**
     * cosine between this and given vector
     * @param a vector
     * @return cos&theta;
     */
    public double cos(Vector3D a){
    	try {
			return dot(a)/(norm()*a.norm());
		} catch (IllegalDimensionException e) {
			e.printStackTrace();
			return Double.NaN;
		}
    }
    
    /**
     * sine between this and given vector
     * @param a vector
     * @return sin&theta;
     */
    public double sin(Vector3D a){
    	return cross(a).norm()/(norm()*a.norm());
    }

	public static void main(String[] args) {
		Vector3D u = new Vector3D(3,3,0);
		Vector3D v = new Vector3D(0,2,2);
		System.out.println("cos = " + u.cos(v) + " : " + (u.cos(v)==0.5));
		System.out.println("|w| = " + u.cross(v).norm() + " : " +
				((u.cross(v).norm())==(6*Math.sqrt(3))));
	}

}
