/*
* This code is released under the GNU General Public License.  See COPYING for 
* details.  Copyright 2003 John Spray: spray_john@users.sourceforge.net
*/



//Vector.c : function definitions for the "vector" class

#include "Vector.h"
#include <stdlib.h>
#include <math.h>

Vector::Vector()
{
	*this=0;
}

int Vector::InCube(Vector p1,Vector p2)
{
	if((x-p1.x)*(x-p2.x)>0)
					return 0;
	if((y-p1.y)*(y-p2.y)>0)
					return 0;
	if((z-p1.z)*(z-p2.z)>0)
					return 0;
	
	return 1;
}

void Vector::Unitize()
{
	float mag;
	mag=this->Mag();
	if(mag==0) return;
	x/=mag;
	y/=mag;
	z/=mag;
	return;
}

void Vector::Randomize()
{
	x=2;y=2;z=2;
	while(x*x+y*y+z*z>1){
		x=(float)rand()/(float)RAND_MAX-0.5f;
		y=(float)rand()/(float)RAND_MAX-0.5f;
		z=(float)rand()/(float)RAND_MAX-0.5f;
	}
}

void Vector::Scalef(float xs,float ys,float zs)
{
	x*=xs;
	y*=ys;
	z*=zs;
	return;
}

void Vector::Set3f(float xnew,float ynew, float znew)
{
	x=xnew;
	y=ynew;
	z=znew;
}

float Vector::Mag()
{
	return sqrt(x*x+y*y+z*z);
}

float Vector::Mag2()
{
	return x*x+y*y+z*z;
}

const Vector operator+(const Vector& left,const Vector& right)
{
	Vector retval;
	retval.x=left.x+right.x;
	retval.y=left.y+right.y;
	retval.z=left.z+right.z;
	return retval;
}

const Vector operator-(const Vector& left,const Vector& right)
{
	Vector retval;
	retval.x=left.x-right.x;
	retval.y=left.y-right.y;
	retval.z=left.z-right.z;
	return retval;
}

const Vector operator-(const Vector& original)
{
	Vector retval;
	retval.x=-original.x;
	retval.y=-original.y;
	retval.z=-original.z;
	return retval;
}

const Vector operator*(const float& left,const Vector& right)
{
	Vector retval;
	retval.x=left*right.x;
	retval.y=left*right.y;
	retval.z=left*right.z;
	return retval;
}

const Vector operator*(const Vector& left,const float& right)
{
	Vector retval;
	retval.x=right*left.x;
	retval.y=right*left.y;
	retval.z=right*left.z;
	return retval;
}

const Vector operator/(const Vector& left,const float& right)
{
	Vector retval;
	retval.x=left.x/right;
	retval.y=left.y/right;
	retval.z=left.z/right;
	return retval;  
}

const Vector operator*(const Vector& left,const Vector& right)
{
	Vector retval;
	retval.x=left.x*right.x;
	retval.y=left.y*right.y;
	retval.z=left.z*right.z;
	return retval;
}

//cross product
const Vector operator^(const Vector& left,const Vector& right)
{
	Vector retval;
	retval.x=left.y*right.z-left.z*right.y;
	retval.y=-left.x*right.z+left.z*right.x;
	retval.z=left.x*right.y-left.y*right.x;
	return retval;
}

//dot product
const float operator|(const Vector&left,const Vector& right)
{
	float retval=0;
	retval+=left.x*right.x;
	retval+=left.y*right.y;
	retval+=left.z*right.z;
	return retval;
}

//angle-between
const float operator%(Vector& left,Vector& right)
{
	float retval=0;
	retval=left|right;
	retval/=left.Mag();
	retval/=right.Mag();
	retval=acos(retval);
	return retval;
}


int operator==(const Vector& left,const Vector& right)
{
	if(
	left.x==right.x&&
	left.y==right.y&&
	left.z==right.z)
		return 1;
	else
		return 0;
}


int operator>(Vector& left,Vector& right)
{
	if(left.Mag2()>right.Mag2())
		return 1;
	else
		return 0;
}


int operator<(Vector& left,Vector& right)
{
	if(left.Mag2()<right.Mag2())
		return 1;
	else
		return 0;
}


Vector& operator+=(Vector& left,const Vector& right)
{
	left.x+=right.x;
	left.y+=right.y;
	left.z+=right.z;
	return left;
}


Vector& operator-=(Vector& left,const Vector& right)
{
	left.x-=right.x;
	left.y-=right.y;
	left.z-=right.z;
	return left;
}

Vector& operator*=(Vector& left,const Vector& right)
{
	left.x=left.x*right.x;
	left.y=left.y*right.y;
	left.z=left.z*right.z;
	return left;
}

Vector& operator*=(Vector& left,const float& right)
{
	left.x=left.x*right;
	left.y=left.y*right;
	left.z=left.z*right;
	return left;
}

const Vector PerpLinePoint(Vector l1,Vector l2,Vector p)
{
  Vector retval,v;
  float lambda;
  
  v=l1-l2;
  lambda=((l1-p)|v)/v.Mag2();
  retval=-lambda*v+l1;

  return retval;
}

const int PointOnLine(Vector l1,Vector l2,Vector p)
{
	Vector v=l2-l1;
	float len2=v.Mag2();
	v.Unitize();

	Vector d=p-l1;

	if(d.Mag2()<len2 && (d|v) > 0.0f)
		return 1;
	else
		return 0;

}

const float Absf(float x)
{
	if(x<0.0f)
		return x*-1.0f;
	else
		return x;
}

