/****************************************************************************
 * cartesian.cpp
 *    Shared stuff for dealing with Cartesian coordinates
 *		Also contains quaternion structures and operations
 *
 *    Cartesian point of doubles: cPt
 *    Cartesian point of integers: iPt
 *    Vector of doubles: vectorPt
 *    Color of doubles:   colorPt
 *    Quaternion: Quaternion
 *
 *    Can be accessed as cPt.x, cPt[X], colorPt[GREEN], iPt[I], etc.
 *
 *
 * W. Michael Brown
 * 5/26/03
 ****************************************************************************/

#include "cartesian.h"


// ------------------------ TwoD Stuff

template<class numtyp>
TwoD<numtyp>::TwoD() {
}

// Assign both x and y the value
template<class numtyp>
TwoD<numtyp>::TwoD(numtyp in) {
  x=in;
  y=in;
}

// Assignment Constructor
template<class numtyp>
TwoD<numtyp>::TwoD(numtyp cx, numtyp cy) {
	x=cx;
	y=cy;
}

// Type conversion
template<class numtyp>
TwoD<numtyp>::TwoD(const TwoD<float> &two) {
	x=numtyp(two.x);
	y=numtyp(two.y);
}

// Ball projection (onto xy-plane)
template<class numtyp>
TwoD<numtyp>::TwoD(const Ball<float> &ball) {
  x=numtyp(cos(ball.theta));
  y=numtyp(sin(ball.theta));
}  

template<class numtyp>
numtyp & TwoD<numtyp>::operator[](unsigned i) {
	switch(i) {
   case X: return x;
   case Y: return y;
  }
  return x;
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator + (const TwoD<numtyp> &two) const {
	return TwoD(x+two.x, y+two.y);
}

template<class numtyp>
void TwoD<numtyp>::operator += (const TwoD<numtyp> &two) {
  x+=two.x;
  y+=two.y;
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator + (const numtyp two) const {
	return TwoD(x+two, y+two);
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator - (const TwoD<numtyp> &two) const {
	return TwoD(x-two.x, y-two.y);
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator - (const numtyp two) const {
	return TwoD(x-two, y-two);
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator * (const numtyp two) const {
	return TwoD(x*two, y*two);
}

template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::operator * (const TwoD<numtyp> &two) const {
	return TwoD<numtyp>(x*two.x,y*two.y);
}

template<class numtyp>
void TwoD<numtyp>::operator /= (const numtyp two) {
  x/=two;
  y/=two;
}

template<class numtyp>
bool TwoD<numtyp>::operator != (const TwoD<numtyp> &two) const {
  if (x!=two.x || y!=two.y)
  	return true;
  return false;
}

// Move coordinates into array
template<class numtyp>
void TwoD<numtyp>::to_array(numtyp *array) {
  *array=x;
  array++;
  *array=y;
}
  
// Set coordinates from array
template<class numtyp>
void TwoD<numtyp>::from_array(numtyp *array) {
  x=*array;
  array++;
  y=*array;
}

// Dot Product
template<class numtyp>
numtyp TwoD<numtyp>::dot(const TwoD<numtyp> &two) const {
	return x*two.x+y*two.y;
}

// Returns one of two normals to a line represented by vector
template<class numtyp>
TwoD<numtyp> TwoD<numtyp>::normal() {
	return TwoD(y,x*numtyp(-1));
}

template<class numtyp>
numtyp TwoD<numtyp>::dist2(const TwoD<numtyp> &two) const {
	TwoD diff=*this-two;
	return diff.dot(diff);
}

// Returns two
template<class numtyp>
unsigned TwoD<numtyp>::dimensionality() {
  return 2;
}

// Returns the index of *this (for unsigned) in a square 3D array
/* s_size[0]=1Dsize */
template<class numtyp>
numtyp TwoD<numtyp>::array_index(vector<unsigned> &s_size) {
  return y+x*s_size[0];
}

// Increment a 3D index from min to max (same as nested for)
template <>
bool TwoD<unsigned>::increment_index(TwoD &minp,TwoD &maxp) {
  x++;
  if (x!=maxp.x)
    return true;
  x=minp.x;
  y++;
  if (y!=maxp.y)
    return true;
  return false;
}

// Return false if x or y is not within the inclusive range
template<class numtyp>
bool TwoD<numtyp>::check_bounds(numtyp minp,numtyp maxp) {
  if (x<minp || y<minp || x>maxp || y>maxp)
    return false;
  return true;
}

template<class numtyp>
ostream & operator<<(ostream &out, const TwoD<numtyp> &t) {
	out << t.x << " " << t.y;
	return out;
}

template<class numtyp>
istream & operator>>(istream &in, TwoD<numtyp> &t) {
	in >> t.x >> t.y;
	return in;
}

// ------------------------ ThreeD Stuff

// Assignment Constructor
template<class numtyp>
ThreeD<numtyp>::ThreeD(numtyp cx, numtyp cy, numtyp cz) {
	x=cx; y=cy; z=cz;
}

// Assignment Constructor
template<class numtyp>
ThreeD<numtyp>::ThreeD(numtyp in) {
	x=in; y=in; z=in;
}

// Type Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const ThreeD<unsigned>& in) {
  x=numtyp(in.x);  y=numtyp(in.y);  z=numtyp(in.z);
}

// Type Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const ThreeD<int>& in) {
  x=numtyp(in.x);  y=numtyp(in.y);  z=numtyp(in.z);
}

// Type Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const ThreeD<float>& in) {
  x=numtyp(in.x);  y=numtyp(in.y);  z=numtyp(in.z);
}

// Type Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const ThreeD<double>& in) {
  x=numtyp(in.x);  y=numtyp(in.y);  z=numtyp(in.z);
}

// TwoD with (z-coordinate set to zero)
template<class numtyp>
ThreeD<numtyp>::ThreeD(const TwoD<float>& in) {
  x=numtyp(in.x);  y=numtyp(in.y);  z=0;
}

// Spherical Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const Ball<double>& ball) {
  double sp=sin(ball.phi);
  x=numtyp(sp*cos(ball.theta));
  y=numtyp(sp*sin(ball.theta));
  z=numtyp(cos(ball.phi));
}

// Spherical Conversion
template<class numtyp>
ThreeD<numtyp>::ThreeD(const Ball<float>& ball) {
  double sp=sin(ball.phi);
  x=numtyp(sp*cos(ball.theta));
  y=numtyp(sp*sin(ball.theta));
  z=numtyp(cos(ball.phi));
}

template<class numtyp>
ThreeD<numtyp>::ThreeD() {
}

template<class numtyp>
void ThreeD<numtyp>::operator = (const ThreeD &two) {
  #ifdef NANCHECK
  //assert(a::not_nan(two.x) && a::not_nan(two.y) && a::not_nan(two.z));
  #endif
  x=two.x; y=two.y; z=two.z;
}

template<class numtyp>
bool ThreeD<numtyp>::operator == (const ThreeD<numtyp> &two) const {
  if (x!=two.x || y!=two.y || z!=two.z)
    return false;
  return true;
}

template<class numtyp>
bool ThreeD<numtyp>::operator != (const ThreeD<numtyp> &two) const {
  if (x!=two.x || y!=two.y || z!=two.z)
    return true;
  return false;
}

template<class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator + (const ThreeD<numtyp> &two) const {
  return (ThreeD<numtyp>(x+two.x,y+two.y,z+two.z));
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator + (const numtyp &two) const {
  return (ThreeD<numtyp>(x+two,y+two,z+two));
}

template<class numtyp>
void ThreeD<numtyp>::operator += (const numtyp &two) {
  x+=two; y+=two; z+=two;
}

template<class numtyp>
void ThreeD<numtyp>::operator += (const ThreeD &two) {
  x+=two.x; y+=two.y; z+=two.z;
}

template<class numtyp>
void ThreeD<numtyp>::operator -= (const ThreeD &two) {
  x-=two.x; y-=two.y; z-=two.z;
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator - (const ThreeD<numtyp> &two) const {
  return (ThreeD<numtyp>(x-two.x,y-two.y,z-two.z));
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator - (const numtyp &two) const {
  return (ThreeD<numtyp>(x-two,y-two,z-two));
}

template<class numtyp>
void ThreeD<numtyp>::operator -= (const numtyp &two) {
  x-=two; y-=two; z-=two;
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator * (const numtyp &two) const {
  return (ThreeD<numtyp>(x*two,y*two,z*two));
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator * (const ThreeD<numtyp> &two) const {
	return ThreeD<numtyp>(x*two.x,y*two.y,z*two.z);
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator / (const ThreeD<numtyp> &two) const {
	return ThreeD<numtyp>(x/two.x,y/two.y,z/two.z);
}

// Dot Product
template <class numtyp>
numtyp ThreeD<numtyp>::dot(const ThreeD<numtyp> &two) const {
	return (x*two.x+y*two.y+z*two.z);
}

// Move coordinates into array
template<class numtyp>
void ThreeD<numtyp>::to_array(numtyp *array) {
  *array=x;
  array++;
  *array=y;
  array++;
  *array=z;
}

// Set coordinates from array
template<class numtyp>
void ThreeD<numtyp>::from_array(numtyp *array) {
  x=*array;
  array++;
  y=*array;
  array++;
  z=*array;
}


// Return the cross product of *this and two
template<class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::cross(const ThreeD<numtyp> &two) const {
	return ThreeD<numtyp> (y*two.z-z*two.y, z*two.x-x*two.z, x*two.y-y*two.x);
}

// Return the angle between two vectors
template<class numtyp>
numtyp ThreeD<numtyp>::angle(const ThreeD<numtyp> &two) const {
	#ifdef NANCHECK
	//assert(fabs(double((*this*two)/(norm()*two.norm())))<=1);
	#endif
	return(numtyp(acos( double(dot(two)/(norm()*two.norm())) )));
}

// Returns an arbitrary vector that is perpendicular to the input
template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::perpendicular() {
  ThreeD<numtyp> two=*this;
	if (y==0 && z==0)
		two.y+=1;
	else
		two.x+=1;
	return cross(two);
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::rotatey(double t) const {
	ThreeD<numtyp> two;
  numtyp sint=numtyp(sin(t));
  numtyp cost=numtyp(cos(t));
	two.x=(x*cost)-(z*sint);
	two.z=(x*sint)+(z*cost);
	two.y=y;
	return two;
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::rotatez(double t) const {
	ThreeD<numtyp> two;
  numtyp sint=numtyp(sin(t));
  numtyp cost=numtyp(cos(t));
	two.x=(x*cost)-(y*sint);
	two.y=(x*sint)+(y*cost);
	two.z=z;
	return two;
}

template <class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::operator / (const numtyp &two) const {
  return (ThreeD<numtyp>(x/two,y/two,z/two));
}

template<class numtyp>
void ThreeD<numtyp>::operator /= (const numtyp &two) {
  x/=two; y/=two; z/=two;
}

// Magnitude of vector
template <class numtyp>
numtyp ThreeD<numtyp>::hypot() const {
  return norm();
}

// Return the norm of a vector
template<class numtyp>
numtyp ThreeD<numtyp>::norm() const {
  numtyp xi=x*x; numtyp yi=y*y; numtyp zi=z*z;
  return numtyp(sqrt(double(xi+yi+zi)));
}

// Return the squared norm of a vector
template<class numtyp>
numtyp ThreeD<numtyp>::norm2() const {
  return x*x+y*y+z*z;
}

template <class numtyp>
numtyp ThreeD<numtyp>::dist2(const ThreeD<numtyp> &two) {
	ThreeD diff=*this-two;
	return diff.dot(diff);
}

// Return unit vector
template<class numtyp>
ThreeD<numtyp> ThreeD<numtyp>::unit() {
	ThreeD<numtyp> unit=*this;
	unit.normalize();
	return unit;
}

/// Returns 3
template<class numtyp>
unsigned ThreeD<numtyp>::dimensionality() {
  return 3;
}

template<class numtyp>
c2DPt ThreeD<numtyp>::projz() {
	return c2DPt(x,y);
}

template<class numtyp>
ostream & operator<< (ostream &out, const ThreeD<numtyp> &t) {
	out << t.x << " " << t.y << " " << t.z;
	return out;
}

template<class numtyp>
istream & operator>>(istream &in, ThreeD<numtyp> &t) {
	in >> t.x >> t.y >> t.z;
	return in;
}

template<class numtyp>
ThreeD<numtyp> operator+ (const numtyp one, const ThreeD<numtyp> &two) {
	return ThreeD<numtyp>(one+two.x,one+two.y,one+two.z);
}

template<class numtyp>
ThreeD<numtyp> operator- (const numtyp one, const ThreeD<numtyp> &two) {
	return ThreeD<numtyp>(one-two.x,one-two.y,one-two.z);
}

template<class numtyp>
ThreeD<numtyp> operator* (const numtyp one, const ThreeD<numtyp> &two) {
	return ThreeD<numtyp>(one*two.x,one*two.y,one*two.z);
}

template<class numtyp>
ThreeD<numtyp> operator/ (const numtyp one, const ThreeD<numtyp> &two) {
	return ThreeD<numtyp>(one/two.x,one/two.y,one/two.z);
}

// Set this to be the max of one and two for each dimension
template<class numtyp>
void ThreeD<numtyp>::max(ThreeD<numtyp> &one, ThreeD<numtyp> &two) {
	x=am::max(one.x,two.x);
	y=am::max(one.y,two.y);
	z=am::max(one.z,two.z);
}

// Set this to be the max of one and two for each dimension
template<class numtyp>
void ThreeD<numtyp>::min(ThreeD<numtyp> &one, ThreeD<numtyp> &two) {
	x=am::min(one.x,two.x);
	y=am::min(one.y,two.y);
	z=am::min(one.z,two.z);
}

// Returns the index of *this (for unsigned) in a square 3D array
/* s_size[0]=1Dsize, and s_size[1]=1D size*1Dsize */
template<class numtyp>
numtyp ThreeD<numtyp>::array_index(vector<unsigned> &s_size) {
  return z+y*s_size[0]+x*s_size[1];
}

// Increment a 3D index from min to max (same as nested for)
template <>
bool ThreeD<unsigned>::increment_index(ThreeD &minp,ThreeD &maxp) {
  x++;
  if (x!=maxp.x)
    return true;
  x=minp.x;
  y++;
  if (y!=maxp.y)
    return true;
  y=minp.y;
  z++;
  if (z!=maxp.z)
    return true;
  return false;
}

// Return false if x,y, or z is not within the inclusive range
template<class numtyp>
bool ThreeD<numtyp>::check_bounds(numtyp minp,numtyp maxp) {
  if (x<minp || y<minp || z<minp || x>maxp || y>maxp || z>maxp)
    return false;
  return true;
}

// --------------------- Quaternion Stuff -----------------------

Quaternion::Quaternion() {
	#ifdef NANCHECK
	w=0; i=0; j=0; k=0;
	#endif
}

Quaternion::~Quaternion() {
}

Quaternion::Quaternion(const Quaternion &two) {
  #ifdef NANCHECK
  //assert(a::not_nan(two.w) && a::not_nan(two.i) && a::not_nan(two.j) &&
  //			 a::not_nan(two.k));
  #endif
	w=two.w; i=two.i; j=two.j; k=two.k;
}

Quaternion::Quaternion(double inw, double ini, double inj, double ink) {
  #ifdef NANCHECK
  //assert(a::not_nan(inw) && a::not_nan(ini) && a::not_nan(inj) &&
  //			 a::not_nan(ink));
  #endif
	w=inw; i=ini; j=inj; k=ink;
}

// Set the quaterion according to axis-angle (must be a UNIT vector)
Quaternion::Quaternion(const vectorPt &v, double angle) {
  double halfa=angle/2;
	double sina=sin(halfa);
	w=cos(halfa);
	i=v.x*sina;
	j=v.y*sina;
	k=v.z*sina;
  #ifdef NANCHECK
  //assert(a::not_nan(w) && a::not_nan(i) && a::not_nan(j) && a::not_nan(k));
  #endif
}

// Set the quaterion according to rotation from vector 1 to vector 2
//    The input vectors do not need to be normalized
Quaternion::Quaternion(const vectorPt &v1, const vectorPt &v2) {
	double angle=acos( v1.dot(v2)/(v1.norm()*v2.norm()) );
	vectorPt axis=v1.cross(v2);
  double norm=axis.norm();
  if (norm<EPS) {
    *this=NOROTATE;
    return;
  }    
    
	axis/=norm;
  double halfa=angle/2;
	double s=sin(halfa);

	w=cos(halfa);
	i=axis.x*s;
	j=axis.y*s;
	k=axis.z*s;
  #ifdef NANCHECK
  //assert(a::not_nan(w) && a::not_nan(i) && a::not_nan(j) && a::not_nan(k));
  #endif
}

// From Euler angles
Quaternion::Quaternion(const EulerRot &erot) {
  double c1 = cos(erot.theta/2);
  double s1 = sin(erot.theta/2);
  double c2 = cos(erot.psi/2);
  double s2 = sin(erot.psi/2);
  double c3 = cos(erot.phi/2);
  double s3 = sin(erot.phi/2);
  double c1c2 = c1*c2;
  double s1s2 = s1*s2;
  w =c1c2*c3 - s1s2*s3;
  i =c1c2*s3 + s1s2*c3;
	j =s1*c2*c3 + c1*s2*s3;
	k =c1*s2*c3 - s1*c2*s3;
}

double & Quaternion::operator[](unsigned index) {
	switch(index) {
	 case I: return i;
   case J: return j;
   case K: return k;
   case W: return w;
  }
  return w;
}

Quaternion operator + (const Quaternion one, const Quaternion two) {
	Quaternion q(one.w+two.w,one.i+two.i,one.j+two.j,one.k+two.k);
	return q;
}

void Quaternion::operator += (const Quaternion &two) {
  w+=two.w; i+=two.i; j+=two.j; k+=two.k;
}

Quaternion Quaternion::operator* (const Quaternion &two) const {
	Quaternion q;
	q.w=two.w*w-two.i*i-two.j*j-two.k*k;
	q.i=two.w*i+two.i*w+two.j*k-two.k*j;
	q.j=two.w*j-two.i*k+two.j*w+two.k*i;
	q.k=two.w*k+two.i*j-two.j*i+two.k*w;

	return (q);
}

void Quaternion::operator*=(const Quaternion &two) {
	(*this)=(*this)*two;
}

Quaternion Quaternion::operator* (const double two) const {
	Quaternion q;
	q.w=two*w;
	q.i=two*i;
	q.j=two*j;
	q.k=two*k;

	return (q);
}

void Quaternion::operator*=(const double two) {
  w*=two;
  i*=two;
  j*=two;
  k*=two;
}

void Quaternion::operator = (const Quaternion &two) {
  #ifdef NANCHECK
  //assert(a::not_nan(two.w) && a::not_nan(two.i) && a::not_nan(two.j) &&
  //			 a::not_nan(two.k));
  #endif
  w=two.w; i=two.i; j=two.j; k=two.k; return;
}

bool Quaternion::operator == (const Quaternion &two) const {
  if (w!=two.w || i!=two.i || j!=two.j || k!=two.k)
		return false;
  return true;
}

Quaternion Quaternion::conj() const {
	Quaternion q;
	q.w=w; q.i=i*-1.0; q.j=j*-1.0; q.k=k*-1.0;
	return q;
}

double Quaternion::norm() {
  return (sqrt(w*w+i*i+j*j+k*k));
}

void Quaternion::normalize() {
  double temp=norm();

  if (temp!=0) {
    w/=temp; i/=temp; j/=temp; k/=temp;
  } else {
    w=1; i=0; j=0; k=0;
  }
}

Quaternion Quaternion::unit() {
	Quaternion unit=*this;
	unit.normalize();
	return unit;
}

ostream & operator<<(ostream &out, const Quaternion &q) {
	out << q.w << " " << q.i << " " << q.j << " " << q.k << " ";
	return out;
}

istream & operator>>(istream &in, Quaternion &q) {
	in >> q.w >> q.i >> q.j >> q.k;
	return in;
}

// ------------------- RotMat Stuff
RotMat::RotMat() {
}

RotMat::RotMat(const Quaternion &q) {
	set(q);
}

void RotMat::set(const Quaternion &q) {
 	// x'=x(w^2+i^2-k^2-j^2)+y(2ij-2kw)+z(2jw+2ik)
	// y'=x(2ij+2kw)+y(j^2-k^2+w^2-i^2)+z(2jk-2iw)
	// z'=x(2ik-2jw)+y(2jk+2iw)+z(k^2-j^2-i^2+w^2)
	double w2=q.w*q.w;
	double i2=q.i*q.i;
	double j2=q.j*q.j;
	double k2=q.k*q.k;
  double twoij=2.0*q.i*q.j;
  double twoik=2.0*q.i*q.k;
  double twojk=2.0*q.j*q.k;
  double twoiw=2.0*q.i*q.w;
  double twojw=2.0*q.j*q.w;
  double twokw=2.0*q.k*q.w;

  x_x=w2+i2-j2-k2;
  x_y=twoij-twokw;
  x_z=twojw+twoik;

  y_x=twoij+twokw;
  y_y=w2-i2+j2-k2;
	y_z=twojk-twoiw;

	z_x=twoik-twojw;
	z_y=twojk+twoiw;
	z_z=w2-i2-j2+k2;
}

cPt RotMat::operator*(const cPt &in) const {
  cPt out;
  out.x=x_x*in.x+x_y*in.y+x_z*in.z;
  out.y=y_x*in.x+y_y*in.y+y_z*in.z;
  out.z=z_x*in.x+z_y*in.y+z_z*in.z;
  return out;
}

void RotMat::proper() {
  double det=x_x*y_y*z_z-x_x*y_z*z_y-x_y*y_x*z_z+x_y*y_z*z_x+x_z*y_x*z_y-x_z*
             x_y*z_x;
  if (det<0) {
    x_x*=-1.0;
    x_y*=-1.0;
    x_z*=-1.0;
    y_x*=-1.0;
    y_y*=-1.0;
    y_z*=-1.0;
    z_x*=-1.0;
    z_y*=-1.0;
    z_z*=-1.0;
  }
}

EulerRot::EulerRot() {
}

EulerRot::EulerRot(double theta_i,double psi_i,double phi_i) {
	theta=theta_i;
 	psi=psi_i;
 	phi=phi_i;
}

// Rotate the rotation axis by a given rotation matrix
void EulerRot::rotate_axis(const RotMat &rotmat) {
	double c1=cos(theta/2.0);
  double s1=sin(theta/2.0);
	double c2=cos(psi/2.0);
	double s2=sin(psi/2.0);
	double c3=cos(phi/2.0);
	double s3=sin(phi/2.0);
	double c1c2=c1*c2;
	double s1s2=s1*s2;
  double w=c1c2*c3 - s1s2*s3;

  vectorPt axis;
	axis.x=c1c2*s3 + s1s2*c3;
	axis.y=s1*c2*c3 + c1*s2*s3;
	axis.z=c1*s2*c3 - s1*c2*s3;

  double angle=2.0*acos(w);
	double norm = axis.norm();
	if (norm < 0.00000001)
    return; // No rotation
  axis/=norm;

  axis=rotmat*axis;

  double s=sin(angle);
	double c=cos(angle);
	double t=1.0-c;
	if ((axis.x*axis.y*t + axis.z*s) > 0.998) { // north pole singularity detected
		theta = 2.0*atan2(axis.x*sin(angle/2.0),cos(angle/2.0));
		psi = PI/2.0;
		phi = 0;
		return;
	}
	if ((axis.x*axis.y*t + axis.z*s) < -0.998) { // south pole singularity detected
		theta = -2.0*atan2(axis.x*sin(angle/2.0),cos(angle/2.0));
		psi = -PI/2.0;
		phi = 0;
		return;
	}

  theta = atan2(axis.y*s-axis.x*axis.z*t, 1-(axis.y*axis.y+axis.z*axis.z)*t);
	psi = asin(axis.x*axis.y*t+axis.z*s) ;
	phi = atan2(axis.x*s-axis.y*axis.z*t, 1-(axis.x*axis.x+axis.z*axis.z)*t);
}


void EulerRot::operator= (const EulerRot &two) {
	theta=two.theta;
	psi=two.psi;
	phi=two.phi;
}

ostream & operator<<(ostream &out, const EulerRot &rot) {
	out << rot.theta << " " << rot.psi << " " << rot.phi;
	return out;
}

// ------------------- Global functions

// Find the point on the line in the direction of v closest to an outside point
//   The point v_point is known to lie on the line
cPt c::point_to_line(const vectorPt &v, const cPt &v_point, const cPt &point){
	vectorPt u=point-v_point;
	double uTv=u.dot(v);
	double vTv=v.dot(v);
	double qT=uTv/vTv;

	return ( (v*qT)+v_point);
}

// Return the closest distance between two line segments input as end points
double c::closest_approach(const cPt &l1_1, const cPt &l1_2, const cPt &l2_1,
													 const cPt &l2_2) {
  vectorPt u = l1_2 - l1_1;
  vectorPt v = l2_2 - l2_1;
  vectorPt w = l1_1-l2_1;
  double a = u.dot(u);
  double b = u.dot(v);
  double c = v.dot(v);
  double d = u.dot(w);
  double e = v.dot(w);
  double D = a*c - b*b;       
  double sc, sN, sD = D;      
  double tc, tN, tD = D;      

  // compute the closest points between the two lines
  if (D < 0.00000000001) { // parallel lines
    sN = 0.0; sD = 1.0; tN = e; tD = c;
  } else {  // get the closest points on the infinite lines
    sN = (b*e - c*d);
    tN = (a*e - b*d);
    if (sN < 0.0) {       
      sN = 0.0; tN = e; tD = c;
    } else if (sN > sD) {  
			sN = sD; tN = e + b; tD = c;
		}
  }

  if (tN < 0.0) {
    tN = 0.0;
    if (-d < 0.0)
      sN = 0.0;
    else if (-d > a)
      sN = sD;
    else {
      sN = -d; sD = a;
    }
  } else if (tN > tD) {   
    tN = tD;
    if ((-d + b) < 0.0)
      sN = 0;
    else if ((-d + b) > a)
      sN = sD;
    else {
      sN = (-d + b); sD = a;
    }
  }

	sc=sN/sD;
	tc=tN/tD;

  // vector connecting points
  vectorPt dP=w+(u*sc)-(v*tc); 

  return dP.norm();
}

void c::closest_approach_points(const cPt &l1_1, const cPt &l1_2,
																const cPt &l2_1, const cPt &l2_2,
																cPt &close_l1, cPt &close_l2) {
  vectorPt u = l1_2 - l1_1;
  vectorPt v = l2_2 - l2_1;
  vectorPt w = l1_1-l2_1;
  double a = u.dot(u);
  double b = u.dot(v);
  double c = v.dot(v);
  double d = u.dot(w);
  double e = v.dot(w);
  double D = a*c - b*b;
  double sc, sN, sD = D;
  double tc, tN, tD = D;

  // compute the closest points between the two lines
  if (D < 0.00000000001) { // parallel lines
    sN = 0.0; sD = 1.0; tN = e; tD = c;
  } else {  // get the closest points on the infinite lines
    sN = (b*e - c*d);
    tN = (a*e - b*d);
    if (sN < 0.0) {
      sN = 0.0; tN = e; tD = c;
    } else if (sN > sD) {
			sN = sD; tN = e + b; tD = c;
		}
  }

  if (tN < 0.0) {
    tN = 0.0;
    if (-d < 0.0)
      sN = 0.0;
    else if (-d > a)
      sN = sD;
    else {
      sN = -d; sD = a;
    }
  } else if (tN > tD) {
    tN = tD;
    if ((-d + b) < 0.0)
      sN = 0;
    else if ((-d + b) > a)
      sN = sD;
    else {
      sN = (-d + b); sD = a;
    }
  }

	sc=sN/sD;
	tc=tN/tD;

  close_l1=u*sc+l1_1;
  close_l2=v*tc+l2_1;

  return;
}

// Returns true if two line segments intersect
bool c::intersect(const c2DPt &line1_start, const c2DPt &line1_end,
									const c2DPt &line2_start, const c2DPt &line2_end) {
  // Check segment1, line2 intersection
	if (!sline_intersect(line1_start,line1_end,(line2_end-line2_start).normal(),
											 line2_start))
	  return false;

  // Check segment2, line1 intersection
	if (!sline_intersect(line2_start,line2_end,(line1_end-line1_start).normal(),
											 line1_start))
	  return false;

	return true;
}  
							 
// Liang-Barsky Intersection between line segment and line
bool c::sline_intersect(const c2DPt &line1_start, const c2DPt &line1_end,
												const c2DPt &line2normal, const c2DPt &line2_point) {
	double denom=(line1_end-line1_start).dot(line2normal);
	if (fabs(denom)<am::epsilon(denom))
		return false; // Parallel lines
	double numerator=(line1_start-line2_point).dot(line2normal)*-1.0;
	double t=numerator/denom;
	if (t<0 || t>1)
		return false;
	return true;
}

/// Average position
cPt c::mean(vector<cPt> &vec) {
  cPt average(vec[0]);
  for (unsigned i=1; i<vec.size(); i++) 
    average+=vec[i];
  return average/vec.size();
}

template class TwoD<double>;
template class TwoD<float>;
template class TwoD<unsigned>;
template ostream & operator<< <double>(ostream &out, const TwoD<double> &t);
template ostream & operator<< <float>(ostream &out, const TwoD<float> &t);
template istream & operator>> <double>(istream &in, TwoD<double> &t);
template istream & operator>> <float>(istream &in, TwoD<float> &t);
template class ThreeD<int>;
template class ThreeD<float>;
template class ThreeD<double>;
template class ThreeD<unsigned>;
template ostream & operator<< <float>(ostream &out, const ThreeD<float> &t);
template istream & operator>> <float>(istream &in, ThreeD<float> &t);
template ostream & operator<< <double>(ostream &out, const ThreeD<double> &t);
template istream & operator>> <double>(istream &in, ThreeD<double> &t);
template ostream & operator<< <unsigned>(ostream &out, const ThreeD<unsigned> &t);
template istream & operator>> <unsigned>(istream &in, ThreeD<unsigned> &t);
template ThreeD<unsigned> operator+ (const unsigned one,
																		 const ThreeD<unsigned> &two);
template ThreeD<double> operator+(const double one, const ThreeD<double> &two);
template ThreeD<unsigned> operator- (const unsigned one,
																		 const ThreeD<unsigned> &two);
template ThreeD<double> operator-(const double one, const ThreeD<double> &two);
template ThreeD<unsigned> operator* (const unsigned one,
																		 const ThreeD<unsigned> &two);
template ThreeD<double> operator*(const double one, const ThreeD<double> &two);
template ThreeD<unsigned> operator/ (const unsigned one,
																		 const ThreeD<unsigned> &two);
template ThreeD<double> operator/(const double one, const ThreeD<double> &two);


