#ifndef VECTOR3D_H_SEEN
#define VECTOR3D_H_SEEN

#include <math.h>
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#ifdef __MWERKS__
   #include "mwerksmath.h"
//   #include "unixmac.h"
#endif
#include "longlat.h"

/*
  Geometrie en dimension 3. 
  Tous les calculs sont faits en radians 
  et en coordonnees spheriques theta,phi
  pour les rotations (angles d'Euler) ma source est 
  "Classical Mechanics" 2nd edition, H. Goldstein, Addison Wesley
*/
/*!    3-D geometry. 

    All computations are made with angles in radians and with spherical
    coordinates theta, phi.

    Concerning Euler's angles, the reference is :
 
    "Classical Mechanics" 2nd edition, H. Goldstein, Addison Wesley
*/

class Vector3d 
{

 public:
  
  Vector3d();
  Vector3d(double x, double y, double z);
  Vector3d(double theta, double phi);
  Vector3d(const LongLat&);
  Vector3d(const Vector3d&);

//   To manipulate the vector
  virtual void Setxyz(double x, double y, double z);
  virtual void SetThetaPhi(double theta,  double phi);
  virtual void ThetaPhi2xyz();
  virtual void xyz2ThetaPhi();

// Acces to coordinates
  inline double Theta() const {return _theta;}
  inline double Phi() const {return _phi;}
  inline double X() const {return _x;}
  inline double Y() const {return _y;}
  inline double Z() const {return _z;}

  virtual Vector3d& Normalize();
  virtual double Norm() const;

  // produit scalaire
  virtual double Psc(const Vector3d&) const;

  // ecart angulaire entre 2 vecteurs dans [0,Pi]
  /*!   angular gap between 2 vectors in [0,Pi] */
  virtual double SepAngle(const Vector3d&) const;

  // produit vectoriel
  /*!    vector product */
  virtual Vector3d Vect(const Vector3d&) const;

  // vecteur perpendiculaire de meme phi
  /*!    perpendicular vector, with equal phi */
  virtual Vector3d VperpPhi() const;

  // vecteur perpendiculaire de meme theta
  /*!    perpendicular vector with equal theta */
  virtual Vector3d VperpTheta() const;

  virtual Vector3d ETheta() const;
  virtual Vector3d EPhi() const;

  // rotations d'Euler
  /*!    Euler's rotations */
  // rotations d Euler
  virtual Vector3d Euler(double, double, double) const;

  // rotation inverse
  /*!    inverse rotation */
  Vector3d InvEuler(double, double, double) const;

  // rotation d'angle phi autour d'un axe omega (regle du tire-bouchon)
  /*!    rotation of angle phi around an axis omega (Maxwell's rule) */
  Vector3d Rotate(const Vector3d& omega,double phi);

  virtual Vector3d& operator=(const Vector3d&);
  virtual Vector3d& operator+=(const Vector3d&);
  virtual Vector3d& operator-=(const Vector3d&);
  virtual Vector3d operator+(const Vector3d&) const;
  virtual Vector3d operator-(const Vector3d&) const;

  virtual Vector3d& operator+=(double);
  virtual Vector3d& operator/=(double);
  virtual Vector3d& operator*=(double);

  virtual Vector3d operator+(double) const;
  virtual Vector3d operator-(double) const;
  virtual Vector3d operator*(double) const;
  virtual Vector3d operator/(double) const;

  /*!    vector product */
  virtual Vector3d operator^(const Vector3d&) const; // produit vectoriel
  /*!    dot product */
  virtual double operator*(const Vector3d&) const; // produit scalaire

  bool operator==(const Vector3d&);
  
  virtual void Print(ostream& os) const;

 protected:

  double _x;
  double _y;
  double _z;
  double _theta;
  double _phi;

};

inline ostream& operator<<(ostream& s, const Vector3d& v) 
{  
  v.Print(s);  
  return s;  
}

// fonctions globales

inline Vector3d operator*(double d, const Vector3d& v) 
{
  return v*d;
}

inline Vector3d operator+(double d, const Vector3d& v) 
{
  return v+d;
}

#endif


