// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4FieldTrack.icc,v 1.1.10.1 1999/12/07 20:48:00 gunter Exp $
// GEANT4 tag $Name: geant4-01-00 $
//
#include "PhysicalConstants.h"

inline G4FieldTrack& 
G4FieldTrack::SetCurvePnt( const G4ThreeVector& pPosition, 
			  const G4ThreeVector& pVelocity,  // Can be Unit
			  const G4double       s_curve )
{
  SixVector[0] = pPosition.x(); 
  SixVector[1] = pPosition.y(); 
  SixVector[2] = pPosition.z(); 

  SixVector[3] = pVelocity.x(); 
  SixVector[4] = pVelocity.y(); 
  SixVector[5] = pVelocity.z(); 

  fMomentumDir = pVelocity.unit();

  fDistanceAlongCurve= s_curve;

  return *this;
} 

inline
G4FieldTrack::G4FieldTrack( const G4ThreeVector& pPosition, 
			    const G4ThreeVector& pVelocity,    // Can be unit
			    const G4double       curve_length, 
			    const G4double       pEnergy,
			    const G4double       pLabortTimeOfFlight,
			    const G4double       pProperTimeOfFlight,
			    const G4ThreeVector* pSpin) :
  fEnergy(pEnergy),
  fLabTimeOfFlight(pLabortTimeOfFlight), 
  fProperTimeOfFlight(pProperTimeOfFlight)
{
  SetCurvePnt( pPosition, pVelocity, curve_length );
  if(pSpin){ fSpin= *pSpin; }
  fMomentumDir = pVelocity.unit();
}

inline
G4FieldTrack::G4FieldTrack( const G4FieldTrack&  rStVec  ) :
  fEnergy( rStVec.fEnergy ),
  fLabTimeOfFlight( rStVec.fLabTimeOfFlight ), 
  fProperTimeOfFlight( rStVec.fProperTimeOfFlight ), 
  fMomentumModulus( rStVec.fMomentumModulus ),
  fMomentumDir( rStVec.fMomentumDir ),
  fSpin( rStVec.fSpin ), 
  fDistanceAlongCurve( rStVec.fDistanceAlongCurve)
{
  SixVector[0]= rStVec.SixVector[0];
  SixVector[1]= rStVec.SixVector[1];
  SixVector[2]= rStVec.SixVector[2];
  SixVector[3]= rStVec.SixVector[3];
  SixVector[4]= rStVec.SixVector[4];
  SixVector[5]= rStVec.SixVector[5];
 // Old code:
  // SetCurvePnt(rStVec.GetPosition(), 
  //	      rStVec.GetMomentumDir(), 
  // 	      rStVec.GetCurveLength() );   // Slow, so changed it
}

// Destructor 
inline G4FieldTrack::~G4FieldTrack(){}

inline G4ThreeVector  G4FieldTrack::GetPosition() const
{
   G4ThreeVector myPosition( SixVector[0], SixVector[1], SixVector[2] );
   return myPosition;
} 

inline void G4FieldTrack::SetPosition( G4ThreeVector pPosition) 
{
   SixVector[0] = pPosition.x(); 
   SixVector[1] = pPosition.y(); 
   SixVector[2] = pPosition.z(); 
} 

// Older ... obsolete 
inline G4ThreeVector  G4FieldTrack::Position() const
{
   return this->GetPosition();
}

inline const G4ThreeVector& G4FieldTrack::GetMomentumDir() const 
{
   // G4ThreeVector myVelocity( SixVector[3], SixVector[4], SixVector[5] );
   // return myVelocity;
   return fMomentumDir;
} 

inline G4double  G4FieldTrack::GetCurveLength() const 
{
     return  fDistanceAlongCurve;  
}

inline G4double  G4FieldTrack::CurveS() const 
{
     return  this->GetCurveLength();
}

inline void G4FieldTrack::SetCurveLength(G4double nCurve_s)
{
     fDistanceAlongCurve= nCurve_s;  
}

inline void  G4FieldTrack::SetCurveS(G4double new_curve_s) 
{
     this->SetCurveLength(new_curve_s);
}

#ifdef ENERGY_OK
inline G4double  G4FieldTrack::GetEnergy() const
{ return fEnergy;}
#endif

inline void G4FieldTrack::SetEnergy(G4double nEnergy)
{ fEnergy=nEnergy;}
inline G4ThreeVector  G4FieldTrack::GetSpin()   const
{ return fSpin;}
inline void G4FieldTrack::SetSpin(G4ThreeVector nSpin)
{ fSpin=nSpin; }

inline G4double  G4FieldTrack::GetLabTimeOfFlight() const
{ return fLabTimeOfFlight; }
inline void G4FieldTrack::SetLabTimeOfFlight(G4double nTOF)
{ fLabTimeOfFlight=nTOF;}

inline G4double  G4FieldTrack::GetProperTimeOfFlight() const
{ return fProperTimeOfFlight; }
inline void G4FieldTrack::SetProperTimeOfFlight(G4double nTOF)
{ fProperTimeOfFlight=nTOF;}

inline G4double G4FieldTrack::GetMomentumModulus() const
{ return fMomentumModulus;}
inline void G4FieldTrack::SetMomentumModulus(G4double nMomentumMod)
{ fMomentumModulus= nMomentumMod ;}         // does not modify energy

inline void G4FieldTrack::SetMomentumDir(G4ThreeVector newMomDir)
{ fMomentumDir= newMomDir; }

inline G4ThreeVector G4FieldTrack::GetVelocity() const 
{ return G4ThreeVector( SixVector[3], SixVector[4], SixVector[5] ); } 

inline void G4FieldTrack::SetVelocity(G4ThreeVector pVelocity)
{
  SixVector[3] = pVelocity.x(); 
  SixVector[4] = pVelocity.y(); 
  SixVector[5] = pVelocity.z(); 

  fMomentumDir = pVelocity.unit(); 
}

// Dump values to array
//  
//   note that momentum direction is not saved 

inline
void G4FieldTrack::DumpToArray(G4double valArr[ncompSVEC] ) const
{
  valArr[0]=SixVector[0];
  valArr[1]=SixVector[1];
  valArr[2]=SixVector[2];
  valArr[3]=SixVector[3];
  valArr[4]=SixVector[4];
  valArr[5]=SixVector[5];

  G4ThreeVector Velocity(valArr[3],valArr[4],valArr[5]);
  G4double      velocity_mag_sq = Velocity.mag2();

  G4double mass_in_Kg;
  mass_in_Kg = fEnergy / velocity_mag_sq * (1-velocity_mag_sq/c_squared);
  valArr[6]= mass_in_Kg;

  // valArr[6]=fEnergy;  // When it is integrated over, do this ...
  valArr[7]=fLabTimeOfFlight;
  valArr[8]=fProperTimeOfFlight;
  valArr[9]=fSpin.x();
  valArr[10]=fSpin.y();
  valArr[11]=fSpin.z();
  // valArr[13]=fMomentumDir.x(); 
  // valArr[14]=fMomentumDir.y();
  // valArr[15]=fMomentumDir.z();
  // valArr[]=fDistanceAlongCurve; 
}

// Load values from array
//  
//   note that momentum direction must-be/is normalised

inline
void G4FieldTrack::LoadFromArray( const G4double valArr[ncompSVEC] )
{
  SixVector[0]=valArr[0];
  SixVector[1]=valArr[1];
  SixVector[2]=valArr[2];
  SixVector[3]=valArr[3];
  SixVector[4]=valArr[4];
  SixVector[5]=valArr[5];

  G4ThreeVector Velocity(valArr[3],valArr[4],valArr[5]);
  G4double      velocity_mag_sq = Velocity.mag2();

  // fEnergy=valArr[6]; // When it is integrated over, do this ...

  G4double mass_in_Kg=valArr[6];
  fEnergy= mass_in_Kg * velocity_mag_sq / (1-velocity_mag_sq/c_squared);
                                                            // sqr(c_light)
  fMomentumDir= Velocity.unit();

  fLabTimeOfFlight=valArr[7];
  fProperTimeOfFlight=valArr[8];
  fSpin=G4ThreeVector(valArr[9],valArr[10],valArr[11]);
  // fMomentumDir=G4ThreeVector(valArr[13],valArr[14],valArr[15]);
  // fDistanceAlongCurve= valArr[]; 
}
  
inline
G4FieldTrack & G4FieldTrack::operator = ( const G4FieldTrack& rStVec )
{
  // SetCurvePnt(rStVec.GetPosition(), 
  //	      rStVec.GetMomentumDir(), 
  //	      rStVec.GetCurveLength() );
  SixVector[0]= rStVec.SixVector[0];
  SixVector[1]= rStVec.SixVector[1];
  SixVector[2]= rStVec.SixVector[2];
  SixVector[3]= rStVec.SixVector[3];
  SixVector[4]= rStVec.SixVector[4];
  SixVector[5]= rStVec.SixVector[5];
  SetCurveLength( rStVec.GetCurveLength() );

  SetEnergy(  rStVec.fEnergy );
  SetLabTimeOfFlight( rStVec.GetLabTimeOfFlight()  ); 
  SetProperTimeOfFlight( rStVec.GetProperTimeOfFlight()  ); 
  SetSpin( rStVec.GetSpin() );
  SetMomentumModulus( rStVec.GetMomentumModulus());
  SetMomentumDir( rStVec.fMomentumDir );

  return *this;
}
     


