    // @(#)root/star:$Name:  $:$Id: TTable3Points.cxx,v 1.2 2003/01/27 20:41:37 brun Exp $
    // Author: Valery Fine   10/05/99  (E-mail: fine@bnl.gov)

    #include "TTable3Points.h"

    ///////////////////////////////////////////////////////////////////////////////////
    //
    //   TTable3Points class is to create 3D view of any 3 columns of the TTable objects
    //   with one and the same "key column value".
    //
    //   For example all values of the column "x[0]" "x[1]" "x[2]" of the

g2t_tpc_hit

     table
    //   from the rows with one and same "track_id" column value will be regarded
    //   as an image of one and the same "track".
    //   The last means all those points will be painted with one and the same 3D
    //   attributes like "color", "size", "style", "light","markers", "connections"  etc.
    //
    //   The original TTable object must be pre-sorted by "key column" via TTableSorter
    //   class
    //
    // void   CreatePoints(Tg2t_tpc_hit *points)
    // {
    //   g2t_tpc_hit_st *p = points->GetTable();
    //
    //  TTable3Points *track = 0;
    //  TString tr;
    //  tr = "track_p";
    //  TTable &ttt = *((TTable *)points);
    //  // Track2Line MUST be on heap otherwise 3D view will crash just code leaves this
    //  // subroutine
    //  We will assemble all points by its "track_p" field.
    //
    //  TTableSorter *Track2Line = new TTableSorter (ttt,"track_p");
    //
    //  Int_t i = 0;
    //  Char_t buffer[10];
    //  Int_t ntracks = 0;
    //  const Int_t maxtracks = 5;
    ////---------------------------- Fill tracks -------------------
    //  long currentId = -1;
    //  long newId =  0;
    //  g2t_tpc_hit_st *hitPoint = 0;
    //  TVolume *thisTrack[7] = {0,0,0,0,0,0,0}; // seven volumes for 7 different colors
    //  Int_t  MaxRowtoCount = 5000; // 5000;
    //  Int_t  MaxTracks = Track2Line->CountKeys();
    //  MaxTracks = 100;
    //  for (i=0;i<Track2Line->GetNRows() && ntracks <  MaxTracks ;i++)
    //  {
    //   hitPoint = p + Track2Line->GetIndex(i);
    //   newId =  hitPoint->track_p;
    //   if (newId != currentId)  { // The hit for the new track has been found
    //
    //     const Char_t *xName = "x[0]";
    //     const Char_t *yName = "x[1]";
    //     const Char_t *zName = "x[2]";
    //
    //     track =  new TTable3Points(Track2Line,(const void *)&newId,xName,yName,zName);
    //
    //     // Create a shape for this node
    //     TPolyLineShape *trackShape  =  new TPolyLineShape(track);
    //     trackShape->SetVisibility(1);
    //     Int_t colorIndx = ntracks%7;
    //     trackShape->SetColorAttribute(colorIndx+kGreen);
    //     trackShape->SetLineStyle(1);
    //     trackShape->SetSizeAttribute(2);
    //     // Create a node to hold it
    //     if (!thisTrack[colorIndx])  {
    //         thisTrack[colorIndx] = new TVolume("hits","hits",trackShape);
    //         thisTrack[colorIndx]->Mark();
    //         thisTrack[colorIndx]->SetVisibility();
    //         TVolumePosition *pp = hall->Add(thisTrack[colorIndx]);
    //         if (!pp) printf(" no position %d\n",ntrack);
    //     }
    //     else
    //       thisTrack[colorIndx]->Add(trackShape);
    //     currentId = newId;
    //     ntracks++;
    //   }
    // }
    //
    ///////////////////////////////////////////////////////////////////////////////////

    ClassImp(TTable3Points)

    //________________________________________________________________________________
     TTable3Points::TTable3Points():fColumnOffset(0)
    {
    }

    //________________________________________________________________________________
     TTable3Points::TTable3Points(TTableSorter *sorter,const void *key,
                           const Char_t *xName, const Char_t *yName, const Char_t *zName
                          ,Option_t *opt)
                    : TTablePoints(sorter,key,opt)

    {
      fColumnOffset =  new ULong_t [kTotalSize];
      SetXColumn(xName);  SetYColumn(yName);  SetZColumn(zName);
    }

    //________________________________________________________________________________
     TTable3Points::TTable3Points(TTableSorter *sorter,Int_t keyIndex,
                           const Char_t *xName, const Char_t *yName, const Char_t *zName
                          ,Option_t *opt)
                    : TTablePoints(sorter,keyIndex,opt)

    {
      fColumnOffset =  new ULong_t [kTotalSize];
      SetXColumn(xName);  SetYColumn(yName);  SetZColumn(zName);
    }

    //________________________________________________________________________________
     TTable3Points::~TTable3Points()
    {
      SafeDelete(fColumnOffset);
    }

    //________________________________________________________________________________
     Float_t TTable3Points::GetAnyPoint(Int_t idx, EPointDirection xAxis) const
    {
     Float_t point  = 0;
     TTable  *table = 0;
     if (fTableSorter) table = fTableSorter->GetTable();
     if (table) {
        const Char_t *tablePtr = ((Char_t *)table->At(Indx(idx))) + fColumnOffset[xAxis] ;
        point = *((Float_t *)tablePtr);
     }
     return point;
    }

    //____________________________________________________________________________
     void TTable3Points::SetAnyColumn(const Char_t *anyName, EPointDirection indx)
    {
       fColumnOffset[indx] = fTableSorter->GetTable()->GetOffset(anyName);
       if (fColumnOffset[indx] == ULong_t(-1))  MakeZombie();
    }

    //____________________________________________________________________________
     Float_t *TTable3Points::GetXYZ(Float_t *xyz,Int_t idx, Int_t num) const
    {
      if (xyz) {
        Int_t size = TMath::Min(idx+num,Size());
        Int_t j=0;
        for (Int_t i=idx;i<size;i++) {
          xyz[j++] = GetX(i);
          xyz[j++] = GetY(i);
          xyz[j++] = GetZ(i);
        }
      }
      return xyz;
    }