//-*-c++-*-
#ifndef TULIP_COORD_H
#define TULIP_COORD_H

#include <cassert>
///
class Coord {
  friend Coord operator +(const Coord &c1,const Coord &c2);
  friend Coord operator -(const Coord &c1,const Coord &c2);
  friend Coord operator ^(const Coord &c1,const Coord &c2);
  friend Coord operator /(const Coord &c1,const float scalaire);
  friend Coord operator *(const Coord &c1,const float scalaire);
  friend float operator*(const Coord &c1,const Coord &c2);

private:
  float v[3];
public:
  inline Coord(const float=0,const float=0,const float=0);
  ///
  inline void set(const float=0,const float=0,const float=0);
  ///
  inline void set(const Coord&);
  ///
  inline void setX(float);
  ///
  inline void setY(float);
  ///
  inline  void setZ(float);
  ///
  float getX() const {return v[0];}
  ///
  float getY() const {return v[1];}
  ///
  float getZ() const {return v[2];}
  ///
  float norm() const;
  ///
  float dist(const Coord&) const;
  ///
  inline Coord & operator *=(const Coord&);
  ///
  inline Coord & operator *=(const float);
  ///
  inline Coord & operator /=(const Coord&);
  ///
  inline Coord & operator /=(const float);
  ///
  inline Coord & operator -=(const Coord&);
  ///
  inline Coord & operator -=(const float);
  ///
  inline Coord & operator +=(const Coord&);
  ///
  inline Coord & operator +=(const float);
  ///
  inline void get(float &, float &, float &) const;
  ///
  inline bool operator ==(const Coord &) const;
  //
  inline bool operator !=(const Coord &) const;
  //
  inline float& operator[](const unsigned int);
  //
  inline float operator[](const unsigned int) const;
};

inline Coord operator +(const Coord &c1,const Coord &c2);
inline Coord operator -(const Coord &c1,const Coord &c2);
inline Coord operator ^(const Coord &c1,const Coord &c2);
inline Coord operator /(const Coord &coord,const float scalaire);
inline Coord operator *(const Coord &coord,const float scalaire);
inline float operator *(const Coord &c1,const Coord &c2);

Coord::Coord(const float xx, const float yy, const float zz){v[0]=xx;v[1]=yy,v[2]=zz;}
void Coord::set(const float xx,const float yy,const float zz){v[0]=xx;v[1]=yy,v[2]=zz;}
void Coord::set(const Coord &c){for (int i=0;i<3;++i) v[i]=c.v[i];}
void Coord::get(float &xx,float &yy,float &zz) const {xx=v[0];yy=v[1];zz=v[2];}
void Coord::setX(const float xx) {v[0]=xx;}
void Coord::setY(const float yy) {v[1]=yy;}
void Coord::setZ(const float zz) {v[2]=zz;}
Coord & Coord::operator *=(const Coord &c){for (int i=0;i<3;++i) v[i]*=c.v[i];return *this;}
Coord & Coord::operator *=(const float d){for (int i=0;i<3;++i) v[i]*=d;return *this;}
Coord & Coord::operator /=(const Coord &c){for (int i=0;i<3;++i) v[i]/=c.v[i];return *this;}
Coord & Coord::operator /=(const float d){for (int i=0;i<3;++i) v[i]/=d;return *this;}
Coord & Coord::operator -=(const Coord &c){for (int i=0;i<3;++i) v[i]-=c.v[i];return *this;}
Coord & Coord::operator -=(const float d){for (int i=0;i<3;++i) v[i]-=d;return *this;}
Coord & Coord::operator +=(const Coord &c){for (int i=0;i<3;++i) v[i]+=c.v[i];return *this;}
Coord & Coord::operator +=(const float d){for (int i=0;i<3;++i) v[i]+=d;return *this;}
bool Coord::operator ==(const Coord &c) const {return ((v[0] == c.v[0]) && (v[1] == c.v[1]) && (v[2] == c.v[2]));}
bool Coord::operator !=(const Coord &c) const {return !((*this)==c);}
float& Coord::operator[](const unsigned int i) {
  assert (i>=0 && i<3);
  return(v[i]);
}
float Coord::operator[](const unsigned int i) const {
  assert (i>=0 && i<3);
  return(v[i]);
}
//External operators
Coord operator +(const Coord &c1,const Coord &c2){return Coord(c1.v[0]+c2.v[0],c1.v[1]+c2.v[1],c1.v[2]+c2.v[2]);}
float operator *(const Coord &c1,const Coord &c2){return (c1.v[0]*c2.v[0]+c1.v[1]*c2.v[1]+c1.v[2]*c2.v[2]);}
Coord operator -(const Coord &c1,const Coord &c2){return Coord(c1.v[0]-c2.v[0],c1.v[1]-c2.v[1],c1.v[2]-c2.v[2]);}
Coord operator ^(const Coord &c1,const Coord &c2){return Coord(c1.v[1]*c2.v[2]-c1.v[2]*c2.v[1],c1.v[2]*c2.v[0]-c1.v[0]*c2.v[2],c1.v[0]*c2.v[1]-c1.v[1]*c2.v[0]);}
Coord operator /(const Coord &coord,const float scalaire){return Coord(coord.v[0]/scalaire,coord.v[1]/scalaire,coord.v[2]/scalaire);} 
Coord operator *(const Coord &coord,const float scalaire){return Coord(coord.v[0]*scalaire,coord.v[1]*scalaire,coord.v[2]*scalaire);}


#endif
