// -*- C++ -*-

#ifndef SPACEVECTOR_H
#define SPACEVECTOR_H

#include "ZMutility/ZMenvironment.h"

#ifndef HEP_THREEVECTOR_H
#  include "CLHEP/Vector/ThreeVector.h"
#endif

ZM_BEGIN_NAMESPACE( zmpv )      /*  namespace zmpv  {  */

typedef double Scalar;

struct ZMpvDEGREES_t; 
struct ZMpvRADIANS_t; 
struct ZMpvETA_t;     

		// Note - inheriting from Hep3Vector is "dangerous"
		// because there is no virtual destructor.  Therefore,
		// SpaceVector obeys the following rules:
		//   *	It has NO additional data members.
		//   *	Any method valid for Hep3Vector is also valid
		//	for SpaceVector, treating the data memebers in
		//	identical manner.
		// This makes the inheritance safe.

class SpaceVector : public Hep3Vector {

public:

// 1 - Construct or set vectors in various coordinate systems

  // --- Cartesian coordinates (and all constructors from Hep3Vector)

  inline SpaceVector(HepDouble x = 0.0, HepDouble y = 0.0, HepDouble z = 0.0);
  // The constructor.  Constructors in polar coordinates are presented below.

  inline SpaceVector(const  Hep3Vector &);
  inline SpaceVector(const SpaceVector &);
  // The copy constructor.

  inline ~SpaceVector();
  // The destructor.  Not virtual - inheritance from this class is dangerous.

  inline void set( HepDouble x, HepDouble y, HepDouble z);
  // Set all three components in cartesian coordinate system.

  // --- Spherical coordinates ---

  // The keyword RADIANS is a ZMpvRADIANS_t
  // The keyword DEGREES is a ZMpvDEGREES_t
  // The keyword ETA     is a ZMpvETA_t
  // Use example:
  // SpaceVector v ( 10.0, 45, DEGREES, .369, RADIANS );

  inline void set    (HepDouble r, HepDouble theta, ZMpvRADIANS_t thetaUnits,
                                  HepDouble phi,   ZMpvRADIANS_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble theta, ZMpvRADIANS_t thetaUnits,
                                   HepDouble phi,   ZMpvRADIANS_t phiUnits);
  // Set or construct SpaceVector v (r, theta, RADIANS, phi, RADIANS)

  inline void set    (HepDouble r, HepDouble theta, ZMpvRADIANS_t thetaUnits,
                                   HepDouble phi,   ZMpvDEGREES_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble theta, ZMpvRADIANS_t thetaUnits,
                                   HepDouble phi,   ZMpvDEGREES_t phiUnits);
  // Set or construct SpaceVector v (r, theta, RADIANS, phi, DEGREES)

  inline void set    (HepDouble r, HepDouble theta, ZMpvDEGREES_t thetaUnits,
                                   HepDouble phi,   ZMpvRADIANS_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble theta, ZMpvDEGREES_t thetaUnits,
                                   HepDouble phi,   ZMpvRADIANS_t phiUnits);
  // Set or construct SpaceVector v (r, theta, DEGREES, phi, RADIANS)

  inline void set    (HepDouble r, HepDouble theta, ZMpvDEGREES_t thetaUnits,
                                   HepDouble phi,   ZMpvDEGREES_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble theta, ZMpvDEGREES_t thetaUnits,
                                   HepDouble phi,   ZMpvDEGREES_t phiUnits);
  // Set or construct SpaceVector v (r, theta, DEGREES, phi, DEGREES)

  // --- Polar coordinates and pseudorapidity --- 

  inline void set  ( HepDouble r, HepDouble eta,  ZMpvETA_t thetaUnits,
                                  HepDouble phi,  ZMpvRADIANS_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble eta,  ZMpvETA_t thetaUnits,
                                  HepDouble phi,  ZMpvRADIANS_t phiUnits);
  // Set or construct SpaceVector v (r, pseudorapidity, ETA, phi, RADIANS)

  inline void set  ( HepDouble r, HepDouble eta, ZMpvETA_t thetaUnits,
                                  HepDouble phi,   ZMpvDEGREES_t phiUnits);
  inline SpaceVector (HepDouble r, HepDouble eta, ZMpvETA_t thetaUnits,
                           HepDouble phi, ZMpvDEGREES_t phiUnits);
  // Set or construct SpaceVector v (r, pseudorapidity, ETA, phi, DEGREES)

  // --- Cylindrical coordinates ---

  inline void set      (HepDouble rho, HepDouble phi, ZMpvRADIANS_t phiUnits,
                        HepDouble z);
  inline SpaceVector   (HepDouble rho, HepDouble phi, ZMpvRADIANS_t phiUnits,
                        HepDouble z);
  // Set or construct SpaceVector v (rho, phi, RADIANS, z)

  inline void set      (HepDouble rho, HepDouble phi, ZMpvDEGREES_t phiUnits,
                        HepDouble z);
  inline SpaceVector   (HepDouble rho, HepDouble phi, ZMpvDEGREES_t phiUnits,
                        HepDouble z);
  // Set or construct SpaceVector v (rho, phi, DEGREES, z)

  inline void setCyl ( HepDouble rho, HepDouble phi, HepDouble theta);
  // Set by supplying perp() and azimuthal and polar angles in radians.

  inline void setCyl ( HepDouble rho, HepDouble phi,
                               HepDouble eta, ZMpvETA_t etaUnits);
  // Set by supplying perp(), and azimuthal angle in radians,
  // and pseudo-rapidity.  Example: v.setCyl (5, pi/4, 3.5, ETA)

}; // SpaceVector

#ifndef ZMPVMICROTYPES_H
struct ZMpvDEGREES_t {ZMpvDEGREES_t(int){}};
struct ZMpvRADIANS_t {ZMpvRADIANS_t(int){}};
struct ZMpvETA_t     {ZMpvETA_t    (int){}};

// Names for specifying angles are placed in the zmpv namespace.
static const ZMpvDEGREES_t DEGREES = 0;
static const ZMpvRADIANS_t RADIANS = 0;
static const ZMpvETA_t     ETA = 0;
#endif

ZM_END_NAMESPACE( zmpv )        /*  }  // namespace zmpv  */

#include "PhysicsVectors/SpaceVector.icc"

#endif /* SPACEVECTOR_H */
