// @(#)root/geom:$Name:  $:$Id: TGeoPatternFinder.cxx,v 1.10 2004/02/10 08:56:20 brun Exp $
// Author: Andrei Gheata   30/10/01

/*************************************************************************
 * TGeoPatternFinder - base finder class for patterns. A pattern is specifying 
 *   a division type
 *************************************************************************/

#include "TObject.h"
#include "TGeoMatrix.h"
#include "TGeoPara.h"
#include "TGeoArb8.h"
#include "TGeoNode.h"
#include "TGeoManager.h"

#include "TGeoPatternFinder.h"

ClassImp(TGeoPatternFinder)
ClassImp(TGeoPatternX)
ClassImp(TGeoPatternY)
ClassImp(TGeoPatternZ)
ClassImp(TGeoPatternParaX)
ClassImp(TGeoPatternParaY)
ClassImp(TGeoPatternParaZ)
ClassImp(TGeoPatternTrapZ)
ClassImp(TGeoPatternCylR)
ClassImp(TGeoPatternCylPhi)
ClassImp(TGeoPatternSphR)
ClassImp(TGeoPatternSphTheta)
ClassImp(TGeoPatternSphPhi)
ClassImp(TGeoPatternHoneycomb)
   

//-----------------------------------------------------------------------------
TGeoPatternFinder::TGeoPatternFinder()
{
// Default constructor
   fMatrix     = 0;
   fCurrent    = -1;
   fNdivisions = 0;
   fDivIndex   = 0;
   fStep       = 0;
   fStart      = 0;
   fEnd        = 0;
   fVolume     = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternFinder::TGeoPatternFinder(TGeoVolume *vol, Int_t ndiv)
{
// Default constructor
   fVolume     = vol;
   fMatrix     = 0;
   fCurrent    = -1;
   fNdivisions = ndiv;
   fDivIndex   = 0;
   fStep       = 0;
   fStart      = 0;
   fEnd        = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternFinder::~TGeoPatternFinder()
{
// Destructor
}

/*************************************************************************
 * TGeoPatternX - a X axis divison pattern
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternX::TGeoPatternX()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dx = ((TGeoBBox*)vol->GetShape())->GetDX();
   fStart = -dx;
   fEnd = dx;
   fStep = 2*dx/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dx = ((TGeoBBox*)vol->GetShape())->GetDX();
   fStart = -dx;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternX::~TGeoPatternX()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternX::FindNode(Double_t *point)
{
// get the node division containing the query point
   TGeoNode *node = 0;
   Int_t ind = (Int_t)((point[0]-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternY - a Y axis divison pattern
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternY::TGeoPatternY()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dy = ((TGeoBBox*)vol->GetShape())->GetDY();
   fStart = -dy;
   fEnd = dy;
   fStep = 2*dy/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dy = ((TGeoBBox*)vol->GetShape())->GetDY();
   fStart = -dy;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternY::~TGeoPatternY()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternY::FindNode(Double_t *point)
{
// find the node containing the query point
   TGeoNode *node = 0;
   Int_t ind = (Int_t)((point[1]-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternZ - a Z axis divison pattern
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternZ::TGeoPatternZ()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dz = ((TGeoBBox*)vol->GetShape())->GetDZ();
   fStart = -dz;
   fEnd = dz;
   fStep = 2*dz/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dz = ((TGeoBBox*)vol->GetShape())->GetDZ();
   fStart = -dz;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternZ::~TGeoPatternZ()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternZ::FindNode(Double_t *point)
{
// find the node containing the query point
   TGeoNode *node = 0;
   Int_t ind = (Int_t)((point[2]-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   //node = GetNodeOffset(ind);
   //node = fVolume->GetNode(fDivIndex+ind);
   //cd(ind);
   node = (TGeoNode*)fVolume->GetNodes()->UncheckedAt(fDivIndex+ind);
   fCurrent = ind;
   ((TGeoTranslation*)fMatrix)->SetDz(fStart+ind*fStep+fStep/2);
   return node;
}

/*************************************************************************
 * TGeoPatternParaX - a X axis divison pattern for PARA shape
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternParaX::TGeoPatternParaX()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dx = ((TGeoPara*)vol->GetShape())->GetX();
   fStart = -dx;
   fEnd = dx;
   fStep = 2*dx/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t dx = ((TGeoPara*)vol->GetShape())->GetX();
   fStart = -dx;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaX::~TGeoPatternParaX()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternParaX::FindNode(Double_t *point)
{
// get the node division containing the query point
   TGeoNode *node = 0;
   Double_t txy = ((TGeoPara*)fVolume->GetShape())->GetTxy();
   Double_t txz = ((TGeoPara*)fVolume->GetShape())->GetTxz();
   Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
   Double_t xt = point[0]-txz*point[2]-txy*(point[1]-tyz*point[2]);
   Int_t ind = (Int_t)((xt-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternParaY - a Y axis divison pattern for PARA shape
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternParaY::TGeoPatternParaY()
{
// Default constructor
   fTxy = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
   Double_t dy = ((TGeoPara*)vol->GetShape())->GetY();
   fStart = -dy;
   fEnd = dy;
   fStep = 2*dy/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
   Double_t dy = ((TGeoPara*)vol->GetShape())->GetY();
   fStart = -dy;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaY::~TGeoPatternParaY()
{
// Destructor
}
//-----------------------------------------------------------------------------
void TGeoPatternParaY::cd(Int_t idiv)
{
   fCurrent = idiv;
   Double_t dy = fStart+idiv*fStep+fStep/2;
   ((TGeoTranslation*)fMatrix)->SetDx(fTxy*dy);
   ((TGeoTranslation*)fMatrix)->SetDy(dy);
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternParaY::FindNode(Double_t *point)
{
// get the node division containing the query point
   TGeoNode *node = 0;
   Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
   Double_t yt = point[1]-tyz*point[2];
   Int_t ind = (Int_t)((yt-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternParaZ - a Z axis divison pattern for PARA shape
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternParaZ::TGeoPatternParaZ()
{
// Default constructor
   fTxz = 0;
   fTyz = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
   fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
   Double_t dz = ((TGeoPara*)vol->GetShape())->GetZ();
   fStart = -dz;
   fEnd = dz;
   fStep = 2*dz/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
   fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
   Double_t dz = ((TGeoPara*)vol->GetShape())->GetZ();
   fStart = -dz;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
   fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternParaZ::~TGeoPatternParaZ()
{
// Destructor
}
//-----------------------------------------------------------------------------
void TGeoPatternParaZ::cd(Int_t idiv)
{
   fCurrent = idiv;
   Double_t dz = fStart+idiv*fStep+fStep/2;
   ((TGeoTranslation*)fMatrix)->SetDx(fTxz*dz);
   ((TGeoTranslation*)fMatrix)->SetDy(fTyz*dz);
   ((TGeoTranslation*)fMatrix)->SetDz(dz);
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternParaZ::FindNode(Double_t *point)
{
// get the node division containing the query point
   TGeoNode *node = 0;
   Double_t zt = point[2];
   Int_t ind = (Int_t)((zt-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternTrapZ - a Z axis divison pattern for TRAP or GTRA shapes
 *   
 *************************************************************************/


//-----------------------------------------------------------------------------
TGeoPatternTrapZ::TGeoPatternTrapZ()
{
// Default constructor
   fTxz = 0;
   fTyz = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
   Double_t phi   = ((TGeoTrap*)vol->GetShape())->GetPhi();
   fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
   fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
   Double_t dz = ((TGeoArb8*)vol->GetShape())->GetDz();
   fStart = -dz;
   fEnd = dz;
   fStep = 2*dz/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
   Double_t phi   = ((TGeoTrap*)vol->GetShape())->GetPhi();
   fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
   fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
   Double_t dz = ((TGeoArb8*)vol->GetShape())->GetDz();
   fStart = -dz;
   fEnd = fStart + ndivisions*step;
   fStep       = step;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
             :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
   Double_t phi   = ((TGeoTrap*)vol->GetShape())->GetPhi();
   fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
   fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = new TGeoTranslation(0,0,0);
   fMatrix->RegisterYourself();
}
//-----------------------------------------------------------------------------
TGeoPatternTrapZ::~TGeoPatternTrapZ()
{
// Destructor
}
//-----------------------------------------------------------------------------
void TGeoPatternTrapZ::cd(Int_t idiv)
{
   fCurrent = idiv;
   Double_t dz = fStart+idiv*fStep+fStep/2;
   ((TGeoTranslation*)fMatrix)->SetDx(fTxz*dz);
   ((TGeoTranslation*)fMatrix)->SetDy(fTyz*dz);
   ((TGeoTranslation*)fMatrix)->SetDz(dz);
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternTrapZ::FindNode(Double_t *point)
{
// get the node division containing the query point
   TGeoNode *node = 0;
   Double_t zt = point[2];
   Int_t ind = (Int_t)((zt-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}


/*************************************************************************
 * TGeoPatternCylR - a cylindrical R divison pattern
 *   
 *************************************************************************/
 


//-----------------------------------------------------------------------------
TGeoPatternCylR::TGeoPatternCylR()
{
// Default constructor
   fMatrix = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fMatrix     = gGeoIdentity;
// compute step, start, end
}
//-----------------------------------------------------------------------------
TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions, Double_t step)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStep       = step;
   fMatrix     = gGeoIdentity;
// compute start, end
}
//-----------------------------------------------------------------------------
TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
   fMatrix     = gGeoIdentity;
}
//-----------------------------------------------------------------------------
TGeoPatternCylR::~TGeoPatternCylR()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternCylR::FindNode(Double_t *point)
{
// find the node containing the query point
   if (!fMatrix) fMatrix = gGeoIdentity;
   TGeoNode *node = 0;
   Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
   Int_t ind = (Int_t)((r-fStart+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}
/*************************************************************************
 * TGeoPatternCylPhi - a cylindrical phi divison pattern
 *   
 *************************************************************************/
 


//-----------------------------------------------------------------------------
TGeoPatternCylPhi::TGeoPatternCylPhi()
{
// Default constructor
   fSinCos = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
// compute step, start, end
   fStart = 0;
   fEnd = 0;
   fStep = 0;
   fMatrix = 0;
   fSinCos = 0;
}
//-----------------------------------------------------------------------------
TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions, Double_t step)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStep       = step;
   fSinCos = 0;
// compute start, end
}
//-----------------------------------------------------------------------------
TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   if (fStart<0) fStart+=360;
   fEnd        = end;
   if (fEnd<0) fEnd+=360;
   if ((end-start)<0)
      fStep       = (end-start+360)/ndivisions;
   else
      fStep       = (end-start)/ndivisions;
   fMatrix     = new TGeoRotation();
   fMatrix->RegisterYourself();
   fSinCos     = new Double_t[2*ndivisions];
   for (Int_t idiv = 0; idiv<ndivisions; idiv++) {
      fSinCos[2*idiv] = TMath::Sin(TMath::DegToRad()*(start+fStep/2+idiv*fStep));
      fSinCos[2*idiv+1] = TMath::Cos(TMath::DegToRad()*(start+fStep/2+idiv*fStep));
   }
}
//-----------------------------------------------------------------------------
TGeoPatternCylPhi::~TGeoPatternCylPhi()
{
// Destructor
   if (fSinCos) delete [] fSinCos;
}
//-----------------------------------------------------------------------------
void TGeoPatternCylPhi::cd(Int_t idiv)
{
   fCurrent = idiv;
   if (!fSinCos) {
      fSinCos     = new Double_t[2*fNdivisions];
      for (Int_t i = 0; i<fNdivisions; i++) {
         fSinCos[2*i] = TMath::Sin(TMath::DegToRad()*(fStart+fStep/2+i*fStep));
         fSinCos[2*i+1] = TMath::Cos(TMath::DegToRad()*(fStart+fStep/2+i*fStep));
      }
   }   
   
   ((TGeoRotation*)fMatrix)->FastRotZ(&fSinCos[2*idiv]);
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternCylPhi::FindNode(Double_t *point)
{
// find the node containing the query point
   TGeoNode *node = 0;
   Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
   if (phi<0) phi += 360;
//   Double_t dphi = fStep*fNdivisions;
   Double_t ddp = phi - fStart;
   if (ddp<0) ddp+=360;
//   if (ddp>360) ddp-=360;
   Int_t ind = (Int_t)((ddp+fStep)/fStep)-1;
   if ((ind<0) || (ind>=fNdivisions)) return node; 
   node = GetNodeOffset(ind);
   cd(ind);
   return node;
}

/*************************************************************************
 * TGeoPatternSphR - a spherical R divison pattern
 *   
 *************************************************************************/




//-----------------------------------------------------------------------------
TGeoPatternSphR::TGeoPatternSphR()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
// compute step, start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions, Double_t step)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStep       = step;
// compute start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
                :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
}
//-----------------------------------------------------------------------------
TGeoPatternSphR::~TGeoPatternSphR()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternSphR::FindNode(Double_t * /*point*/)
{
// find the node containing the query point
   return 0;
}

/*************************************************************************
 * TGeoPatternSphTheta - a spherical theta divison pattern
 *   
 *************************************************************************/




//-----------------------------------------------------------------------------
TGeoPatternSphTheta::TGeoPatternSphTheta()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions)
                    :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
// compute step, start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions, Double_t step)
                    :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStep       = step;
// compute start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
                    :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
}
//-----------------------------------------------------------------------------
TGeoPatternSphTheta::~TGeoPatternSphTheta()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternSphTheta::FindNode(Double_t * /*point*/)
{
// find the node containing the query point
   return 0;
}

/*************************************************************************
 * TGeoPatternSphPhi - a spherical phi divison pattern
 *   
 *************************************************************************/




//-----------------------------------------------------------------------------
TGeoPatternSphPhi::TGeoPatternSphPhi()
{
// Default constructor
}
//-----------------------------------------------------------------------------
TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
// compute step, start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions, Double_t step)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStep       = step;
// compute start, end
}
//-----------------------------------------------------------------------------
TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
                  :TGeoPatternFinder(vol, ndivisions)
{   
// constructor
   fStart      = start;
   fEnd        = end;
   fStep       = (end - start)/ndivisions;
}
//-----------------------------------------------------------------------------
TGeoPatternSphPhi::~TGeoPatternSphPhi()
{
// Destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternSphPhi::FindNode(Double_t * /*point*/)
{
// find the node containing the query point
   return 0;
}

/*************************************************************************
 * TGeoPatternHoneycomb - a divison pattern specialized for honeycombs
 *   
 *************************************************************************/

   

//-----------------------------------------------------------------------------
TGeoPatternHoneycomb::TGeoPatternHoneycomb()
{
// Default constructor
   fNrows       = 0;                 
   fAxisOnRows  = 0;            
   fNdivisions  = 0;             
   fStart       = 0;                 
}
//-----------------------------------------------------------------------------
TGeoPatternHoneycomb::TGeoPatternHoneycomb(TGeoVolume *vol, Int_t nrows)
                     :TGeoPatternFinder(vol, nrows)
{
// Default constructor
   fNrows = nrows;
// compute everything else
}
//-----------------------------------------------------------------------------
TGeoPatternHoneycomb::~TGeoPatternHoneycomb()
{
// destructor
}
//-----------------------------------------------------------------------------
TGeoNode *TGeoPatternHoneycomb::FindNode(Double_t * /*point*/)
{
// find the node containing the query point
   return 0;
}
