// 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: G4TouchableHistory.icc,v 1.2.2.1 1999/12/07 20:48:41 gunter Exp $
// GEANT4 tag $Name: geant4-01-00 $
//
// 
// class G4TouchableHistory inline implementation

inline G4TouchableHistory::G4TouchableHistory()
  : fhistory()
{
  ftlate= G4ThreeVector(0.,0.,0.);
  frot= G4RotationMatrix();
}

inline G4TouchableHistory::G4TouchableHistory(const G4NavigationHistory &history)
  : fhistory(history)
{
  G4AffineTransform tf(fhistory.GetTopTransform().Inverse());
  ftlate=tf.NetTranslation();
  frot=tf.NetRotation();
}

inline 
void  G4TouchableHistory::UpdateYourself(     G4VPhysicalVolume*   pPhysVol,
			   const G4NavigationHistory* pHistory) 
{
  fhistory= *pHistory;  
  G4AffineTransform tf(fhistory.GetTopTransform().Inverse());
  if( pPhysVol == 0 ){
    // This means that the track has left the World Volume.
    // Since the Navigation History does not already reflect this,
    // we must correct this problem here. John A. (--> K. Amako)
    fhistory.SetFirstEntry(pPhysVol);
  }
  ftlate=tf.NetTranslation();
  frot=tf.NetRotation();
}

G4int
inline G4TouchableHistory::CalculateHistoryIndex(G4int stackDepth) const
{
  return (fhistory.GetDepth()-stackDepth); // was -1
}

inline G4VPhysicalVolume* G4TouchableHistory::GetVolume(G4int depth) const
{
  return fhistory.GetVolume(CalculateHistoryIndex(depth));
}

inline G4VSolid* G4TouchableHistory::GetSolid(G4int depth) const
{
  return fhistory.GetVolume(CalculateHistoryIndex(depth))->GetLogicalVolume()->GetSolid();
}

inline G4int   G4TouchableHistory::GetReplicaNumber(G4int depth) const
{
  // return this->GetHistory()->GetTopReplicaNo();
  return fhistory.GetReplicaNo(CalculateHistoryIndex(depth));
}

inline G4int  G4TouchableHistory::GetHistoryDepth()  const
{
  return  fhistory.GetDepth();
}

inline G4int  G4TouchableHistory::MoveUpHistory( G4int num_levels )
{
  G4NavigationHistory* nHistory= &fhistory;
  G4int maxLevelsMove=  nHistory->GetDepth();
  G4int minLevelsMove=  0;                      // Cannot redescend today!
				        // Soon it will be possible
					// by adding a data member here
				        //     fCurrentDepth;

  if( num_levels > maxLevelsMove ){
      num_levels = maxLevelsMove;
  }
  else if( num_levels < minLevelsMove ){
      num_levels = minLevelsMove;
  }

  nHistory->BackLevel( num_levels ); 

  return num_levels;
}

inline const G4NavigationHistory* G4TouchableHistory::GetHistory() const
{
  return &fhistory;
}
