//   Geometry handling class 
//        R. Ansari , G. Le Meur   2000
// DAPNIA/SPP (Saclay) / CEA    LAL - IN2P3/CNRS  (Orsay)

#ifndef CIRCLE_H_SEEN
#define CIRCLE_H_SEEN

#include <math.h>
#include <iostream>
#include "vector3d.h"
#include "unitvector.h"
#include "utilgeom.h"
#include "geometry.h"

namespace SOPHYA {  

class Circle : public Geometry
{
  
 public:

  Circle();
  Circle(double theta, double phi, double aperture);
  Circle(double x, double y, double z, double aperture);
  Circle(const Vector3d& v, double aperture=M_PI/2.);
  Circle(const Circle& c);
  virtual ~Circle() {}

  void SetCircle(const UnitVector&, double);
  void SetSpinAxis(double theta, double phi);
  void SetSpinAxis(const Vector3d&);
  void SetSpinAxis(double x, double y, double z);
  void SetApertureAngle(double aperture);
  void SetApertureAngle(const Circle&);
  
  // psi contient les 4 valeurs des angles d intersection. -1 si les cercles ne se coupent pas
  // voir la numerotation dans le .cc
  /*   psi contains  4 values of the intersection  angles. 
    -1 if  circles do not intersect
    psi[0]=psi(i,j,0)
    psi[1]=psi(i,j,1)
    psi[2]=psi(j,i,0)
    psi[3]=psi(j,i,1)
  */

  bool Intersection(const Circle&, double*) const;
  bool Intersection(const Circle&) const;

  // donne le UnitVector correspondant a une position donnee sur le cercle
  /*!    Return UnitVector corresponding to a given position donnee on the circle
   */
  UnitVector ConvToSphere(double psi) const;

  // donne le UnitVector correspondant la tangente au cercle en une position donnee sur le cercle
  /*!    Return UnitVector corresponding to the tangent to the circle */
//    at given position on the circle.
  UnitVector TanOnCircle(double psi) const;

  // donne le vecteur tangent dans le plan (xy) a la sphere en une position donnee sur le cercle
  /*!    Return the  vector  tangent to the sphere in the plane (xy) 
    at a given position on the circle.
  */
  UnitVector EPhi(double psi) const;

  // donne l autre vecteur tangent (orthogonal a EPhi)
  /*!    Return the other tangent  vector( orthogonal to EPhi)-- 
    see previous method
  */
  UnitVector ETheta(double psi) const;

   // donne l angle de separation dans [0,2Pi] en une position donnee sur le cercle et EPhi
  /*!   Return separation angle in [0,2Pi] at a given position on the 
    circle and EPhi
  */
  double SepAngleTanEPhi02PI(double psi) const;

  double Theta() const {return _spinaxis.Theta();}
  double Phi() const {return _spinaxis.Phi();}
  double ApertureAngle() const {return _angouv;}
  Vector3d Omega() const {return _spinaxis;}
  virtual void Print(ostream&) const;
  Circle& operator=(const Circle&);
  bool operator==(const Circle&) const;
  bool operator!=(const Circle&) const;

 private:

  Vector3d _spinaxis;
  UnitVector _spinunitaxis;
  double _angouv;
  double _theta,_phi;
  double _x,_y,_z;

  double _cangouv;
  double _sangouv;
  double _ctheta;
  double _stheta;
  double _cphi;
  double _sphi;
};

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

} // namespace SOPHYA

#endif
