/*
 * Author: Paul Koshevoy
 * v3x1.java  Wed, Jan 14 1998, 11:30:00 1998
 */

public class v3x1
{
public double x;
public double y;
public double z;

public v3x1(double x_, double y_, double z_)
    {
	x = x_;
	y = y_;
	z = z_;
    }

public v3x1(double x0, double y0, double z0, double x1, double y1, double z1)
    {
	x = x1 - x0;
	y = y1 - y0;
	z = z1 - z0;
    }

public v3x1(double x_[], double y_[], double z_[], int a, int b)
    {
	x = x_[b] - x_[a];
	y = y_[b] - y_[a];
	z = z_[b] - z_[a];
    }

// cross product constructor
public v3x1(double x_[], double y_[], double z_[])
    {
	double M[][] = new double[3][3];
	M[1][0] = x_[1]-x_[0];
	M[1][1] = y_[1]-y_[0];
	M[1][2] = z_[1]-z_[0];
	M[2][0] = x_[2]-x_[0];
	M[2][1] = y_[2]-y_[0];
	M[2][2] = z_[2]-z_[0];
	
	x = M[1][1]*M[2][2] - M[1][2]*M[2][1];
	y = M[1][2]*M[2][0] - M[1][0]*M[2][2];
	z = M[1][0]*M[2][1] - M[2][0]*M[1][1];
    }

// cross product constructor, expects 3D points
public v3x1(v3x1 v0, v3x1 v1, v3x1 v2)
    {
	x = (v1.y - v0.y)*(v2.z - v0.z) - (v1.z - v0.z)*(v2.y - v0.y);
	y = (v1.z - v0.z)*(v2.x - v0.x) - (v1.x - v0.x)*(v2.z - v0.z);
	z = (v1.x - v0.x)*(v2.y - v0.y) - (v2.x - v0.x)*(v1.y - v0.y);
    }

// cross product constructor, expects directional vectors
public static v3x1 cross(v3x1 a, v3x1 b)
    {
	double x = a.y*b.z - a.z*b.y;
	double y = a.z*b.x - a.x*b.z;
	double z = a.x*b.y - b.x*a.y;
	return (new v3x1(x, y, z));
    }

// copy constructor with offset
public v3x1(v3x1 v, v3x1 off)
    {
	x = v.x + off.x;
	y = v.y + off.y;
	z = v.z + off.z;
    }

// copy constructor
public v3x1(v3x1 v)
    {
	x = v.x;
	y = v.y;
	z = v.z;
    }

public void reverse()
    {
	x = -x;
	y = -y;
	z = -z;
    }
    
public void dump()
    {
	System.out.print("[ ");
	System.out.print(x);
	System.out.print(" ");
	System.out.print(y);
	System.out.print(" ");
	System.out.print(z);
	System.out.println("]T");
    }
    
// M[row][col]  is expected as input, where row==3, col==3
public static double det3x3(double M[][])
    {
	return (M[0][0]*(M[1][1]*M[2][2] - M[1][2]*M[2][1]) -
		M[0][1]*(M[1][0]*M[2][2] - M[1][2]*M[2][0]) +
		M[0][2]*(M[1][0]*M[2][1] - M[2][0]*M[1][1]));
//	double d1 = M[0][0]*det2x2(M[1][1], M[1][2], M[2][1], M[2][2]);
//	double d2 = M[0][1]*det2x2(M[1][0], M[1][2], M[2][0], M[2][2]);
//	double d3 = M[0][2]*det2x2(M[1][0], M[1][1], M[2][0], M[2][1]);
//	System.out.print(d1);
//	System.out.print(" - ");
//	System.out.print(d2);
//	System.out.print(" + ");
//	System.out.print(d3);
//	System.out.print(" = ");
//	System.out.println(d1-d2+d3);
//	return d1-d2+d3;
    }

public static double det2x2(double a1, double a2, double b1, double b2)
    {
	return a1*b2-a2*b1;
    }

public static double dot(v3x1 a, v3x1 b)
    {
//	System.out.println(a.x*b.x + a.y*b.y + a.z*b.z);
	return (a.x*b.x + a.y*b.y + a.z*b.z);
    }

public double magnitude()
    {
	return (double)(Math.sqrt(v3x1.dot(this, this)));
    }
    
public double mag_squared()
    {
	return v3x1.dot(this, this);
    }
    
public static v3x1 unit(v3x1 v)
    {
	double mag = (double)(Math.sqrt(v3x1.dot(v, v)));
	if(mag == 0)
	    {
		System.out.print("trying to normalize a zero vector: [");
		System.out.print(v.x);
		System.out.print(" ");
		System.out.print(v.y);
		System.out.print(" ");
		System.out.print(v.z);
		System.out.println("]T");
		return null;
	    }
	return (new v3x1(v.x/mag, v.y/mag, v.z/mag));
    }
    
public static v3x1 add(v3x1 a, v3x1 b)
    {
	return (new v3x1(a.x+b.x, a.y+b.y, a.z+b.z));
    }
    
public v3x1 plus(v3x1 b)
    {
	return (new v3x1(x+b.x, y+b.y, z+b.z));
    }

public v3x1 minus(v3x1 b)
    {
	return (new v3x1(x-b.x, y-b.y, z-b.z));
    }

public v3x1 times(double f)
    {
	return (new v3x1(x*f, y*f, z*f));
    }

public static v3x1 subtract(v3x1 a, v3x1 b)
    {
	return (new v3x1(a.x-b.x, a.y-b.y, a.z-b.z));
    }

public static v3x1 subtract(v3x1 a, int x_, int y_, int z_)
    {	
	return (new v3x1(a.x-x_, a.y-y_, a.z-z_));
    }

public static v3x1 subtract(v3x1 a, double x_, double y_, double z_)
    {	
	return (new v3x1(a.x-x_, a.y-y_, a.z-z_));
    }

public static v3x1 add(v3x1 a, double d)
    {
	return (new v3x1(a.x+d, a.y+d, a.z+d));
    }

public void add(double d)
    {
	x = x+d;
	y = y+d;
	z = z+d;
    }

public void add(v3x1 v)
    {
	x = x+v.x;
	y = y+v.y;
	z = z+v.z;
    }

public static v3x1 mult(v3x1 a, double d)
    {
	return (new v3x1(a.x*d, a.y*d, a.z*d));
    }

public static v3x1 squared(v3x1 a)
    {
	return (new v3x1(a.x*Math.abs(a.x), a.y*Math.abs(a.y), a.z*Math.abs(a.z)));
    }

public void mult(double d)
    {
	x = x*d;
	y = y*d;
	z = z*d;
    }

public static v3x1 divide(v3x1 a, double d)
    {
	return (new v3x1(a.x/d, a.y/d, a.z/d));
    }

public static v3x1 negate(v3x1 v)
    {
	return (new v3x1(-v.x, -v.y, -v.z));
    }
    
public void neg()
    {
	x = -x;
	y = -y;
	z = -z;
    }

public boolean equal(v3x1 v)
    {
	if((x==v.x) && (y==v.y) && (z==v.z))
	    return true;
	return false;
    }
}


