// @(#)root/star:$Name:  $:$Id: TVolumePosition.cxx,v 1.2 2003/01/27 20:41:37 brun Exp $
// Author: Valery Fine(fine@bnl.gov)   25/12/98
// $Id: TVolumePosition.cxx,v 1.2 2003/01/27 20:41:37 brun Exp $

#include "Riostream.h"

#include "TCL.h"
#include "TVolumePosition.h"
#include "TVolume.h"

#include "TROOT.h"
#include "TClass.h"
#include "TVirtualPad.h"
#include "TView.h"
#include "TGeometry.h"
#include "TRotMatrix.h"
#include "TBrowser.h"
#include "X3DBuffer.h"

#include "TPadView3D.h"

R__EXTERN  Size3D gSize3D;

ClassImp(TVolumePosition)

//______________________________________________________________________________
//*-*-*-*-*-*-*-*-* S T N O D E P O S I T I O N   description *-*-*-*-*-*-*-*-*-
//*-*               ===========================
//*-*
//*-*    A TVolumePosition object is used to build the geometry hierarchy (see TGeometry).
//*-*    A node may contain other nodes.
//*-*
//*-*    A geometry node has attributes:
//*-*      - name and title
//*-*      - pointer to the referenced shape (see TShape).
//*-*      - x,y,z offset with respect to the mother node.
//*-*      - pointer to the rotation matrix (see TRotMatrix).
//*-*
//*-*    A node can be drawn.
//*-*
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*


//______________________________________________________________________________
 TVolumePosition::TVolumePosition(TVolume *node,Double_t x, Double_t y, Double_t z, const Text_t *matrixname)
: fMatrix(0),fNode(node),fId(0)
{
//*-*-*-*-*-*-*-*-*-*-*Node normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ======================
//*-*
//*-*    name    is the name of the node
//*-*    title   is title
//*-*    x,y,z   are the offsets of the volume with respect to his mother
//*-*    matrixname  is the name of the rotation matrix
//*-*
//*-*    This new node is added into the list of sons of the current node
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   SetMatrixOwner(kFALSE);
   fX[0] = x; fX[1] =y; fX[2] = z;
   if (!node) return;
   static Int_t counter = 0;
   counter++;
   if(!(counter%1000))cout<<"TVolumePosition count="<<counter<<" name="<<node->GetName()<<endl;

   if (!gGeometry) new TGeometry;
   if (matrixname && strlen(matrixname)) fMatrix = gGeometry->GetRotMatrix(matrixname);
   if (!fMatrix) fMatrix = TVolume::GetIdentity();
}


//______________________________________________________________________________
 TVolumePosition::TVolumePosition(TVolume *node,Double_t x, Double_t y, Double_t z, TRotMatrix *matrix)
               : fMatrix(matrix),fNode(node),fId(0)
{
//*-*-*-*-*-*-*-*-*-*-*Node normal constructor*-*-*-*-*-*-*-*-*-*-*
//*-*                  ================================
//*-*
//*-*    name    is the name of the node
//*-*    title   is title
//*-*    x,y,z   are the offsets of the volume with respect to his mother
//*-*    matrix  is the pointer to the rotation matrix
//*-*
//*-*    This new node is added into the list of sons of the current node
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   SetMatrixOwner(kFALSE);
   if (!gGeometry) new TGeometry;
   fX[0] = x; fX[1] = y; fX[2] = z;
   if (!fMatrix) fMatrix = TVolume::GetIdentity();
}
//______________________________________________________________________________
 TVolumePosition::TVolumePosition(const TVolumePosition&pos): TObject()
      , fMatrix(((TVolumePosition &)pos).GetMatrix()),fNode(pos.GetNode()),fId(pos.GetId())
{
  for (int i=0;i<3;i++) fX[i] = pos.GetX(i);
  // Transferring the ownership. 
  // The last created object owns the matrix if any.
  // The source object gives up its ownership in favour of the destination object

  SetMatrixOwner(pos.IsMatrixOwner());
  // !!! We have to break the "const'ness" at this point to take the ownerships
  ((TVolumePosition &)pos).SetMatrixOwner(kFALSE);
}

//______________________________________________________________________________
 TVolumePosition::~TVolumePosition(){
   DeleteOwnMatrix();
}
//______________________________________________________________________________
 void TVolumePosition::Browse(TBrowser *b)
{
#ifndef WIN32
   Inspect();
#endif
   if (GetNode()) {
        TShape *shape = GetNode()->GetShape();
        b->Add(GetNode(),shape?shape->GetName():GetNode()->GetName());
   }
   else {
       Draw();
       gPad->Update();
   }
}

//______________________________________________________________________________
 Int_t TVolumePosition::DistancetoPrimitive(Int_t, Int_t)
{
//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a Node*-*-*-*-*-*
//*-*                  ===========================================
//*-*  Compute the closest distance of approach from point px,py to this node.
//*-*  The distance is computed in pixels units.
//*-*
//*-*
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
   return 99999;
}

//______________________________________________________________________________
 void TVolumePosition::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*-*Draw Referenced node with current parameters*-*-*-*
//*-*                   =============================================
  TVolume *node = GetNode();
  if (node) node->Draw(option);
}


//______________________________________________________________________________
 void TVolumePosition::ExecuteEvent(Int_t, Int_t, Int_t)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//*-*  This member function must be implemented to realize the action
//*-*  corresponding to the mouse click on the object in the window
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

//   if (gPad->GetView())
//             gPad->GetView()->ExecuteRotateView(event, px, py);

//   if (!gPad->GetListOfPrimitives()->FindObject(this)) gPad->SetCursor(kCross);
   gPad->SetCursor(kHand);
}

//______________________________________________________________________________
 Text_t *TVolumePosition::GetObjectInfo(Int_t, Int_t) const
{
   if (!gPad) return 0;
   if (!GetNode()) return 0;
   static char info[64];
   sprintf(info,"%s/%s, shape=%s/%s",GetNode()->GetName(),GetNode()->GetTitle(),GetNode()->GetShape()->GetName(),GetNode()->GetShape()->ClassName());
   return info;
}

//______________________________________________________________________________
 Double_t *TVolumePosition::Errmx2Master(const Double_t *localError, Double_t *masterError) const
{
  Double_t error[6];
  TCL::vzero(&error[1],4);
  error[0] = localError[0]; error[2] = localError[1]; error[5] = localError[2];
  return Cormx2Master(error, masterError);
}

//______________________________________________________________________________
 Float_t *TVolumePosition::Errmx2Master(const Float_t *localError, Float_t *masterError) const
{
  Float_t error[6];
  TCL::vzero(&error[1],4);
  error[0] = localError[0]; error[2] = localError[1]; error[5] = localError[2];
  return Cormx2Master(error, masterError);
}

//______________________________________________________________________________
 Double_t *TVolumePosition::Cormx2Master(const Double_t *localCorr, Double_t *masterCorr)const
{
  Double_t *res = 0;
  const TRotMatrix *rm = GetMatrix();
  double *m = 0;
  if (rm && ( m = ((TRotMatrix *)rm)->GetMatrix()) )
    res = TCL::trasat(m,(Double_t *)localCorr,masterCorr,3,3);
  else
    res = TCL::ucopy(localCorr,masterCorr,6);
  return res;
}

//______________________________________________________________________________
 Float_t *TVolumePosition::Cormx2Master(const Float_t *localCorr, Float_t *masterCorr) const
{
 Float_t *res = 0;
 const TRotMatrix *rm = GetMatrix();
 Double_t *m = 0;
 if (rm && (m = ((TRotMatrix *)rm)->GetMatrix()) ) {
    double corLocal[6], corGlobal[6];
    TCL::ucopy(localCorr,corLocal,6);
    TCL::trasat(m,corLocal,corGlobal,3,3);
    res =  TCL::ucopy(corGlobal,masterCorr,6);
 }
 else
    res =  TCL::ucopy(localCorr,masterCorr,6);
 return res;
}
//______________________________________________________________________________

 Double_t *TVolumePosition::Errmx2Local(const Double_t *masterError, Double_t *localError) const
{
   Double_t error[6];
   TCL::vzero(&error[1],4);
   error[0] = masterError[0]; error[2] = masterError[1]; error[5] = masterError[2];
   return Cormx2Local(error, localError);
}
//______________________________________________________________________________

 Float_t *TVolumePosition::Errmx2Local(const Float_t *masterError, Float_t *localError) const
{
   Float_t error[6];
   TCL::vzero(&error[1],4);
   error[0] = masterError[0]; error[2] = masterError[1]; error[5] = masterError[2];
   return Cormx2Local(error, localError);
}
//______________________________________________________________________________

 Double_t *TVolumePosition::Cormx2Local(const Double_t *localCorr, Double_t *masterCorr) const
{
   Double_t *res = 0;
   TRotMatrix *rm = (TRotMatrix *) GetMatrix();
   double *m = 0;
   if (rm && ( m = rm->GetMatrix()) )
      res = TCL::tratsa(m,(Double_t *)localCorr,masterCorr,3,3);
   else
      res = TCL::ucopy(localCorr,masterCorr,6);
   return res;
}

//______________________________________________________________________________

 Float_t *TVolumePosition::Cormx2Local(const Float_t *localCorr, Float_t *masterCorr) const
{
   Float_t *res = 0;
   TRotMatrix *rm = (TRotMatrix *) GetMatrix();
   Double_t *m = 0;
   if (rm && (m = rm->GetMatrix()) ) {
      double corLocal[6], corGlobal[6];
      TCL::ucopy(localCorr,corLocal,6);
      TCL::tratsa(m,corLocal,corGlobal,3,3);
      res =  TCL::ucopy(corGlobal,masterCorr,6);
   }
   else
      res =  TCL::ucopy(localCorr,masterCorr,6);
   return res;
}

//______________________________________________________________________________
 Double_t *TVolumePosition::Local2Master(const Double_t *local, Double_t *master, Int_t nPoints) const
{
//*-*-*-*-*Convert one point from local system to master reference system*-*-*
//*-*      ==============================================================
//
//  Note that before invoking this function, the global rotation matrix
//  and translation vector for this node must have been computed.
//  This is automatically done by the Paint functions.
//  Otherwise TVolumePosition::UpdateMatrix should be called before.
  Double_t *matrix = 0;
  Double_t *trans = 0;
  if (!fMatrix ||  fMatrix == TVolume::GetIdentity() || !(matrix = ((TRotMatrix *)fMatrix)->GetMatrix()) )
  {
    trans = master;
    for (int i =0; i < nPoints; i++,local += 3, master += 3) TCL::vadd(local,fX,master,3);
  }
  else
  {
    trans = master;
    for (int i =0; i < nPoints; i++, local += 3, master += 3) {
      TCL::mxmpy2(matrix,local,master,3,3,1);
      TCL::vadd(master,fX,master,3);
    }
  }
  return trans;
}

//______________________________________________________________________________
 Float_t *TVolumePosition::Local2Master(const Float_t *local, Float_t *master, Int_t nPoints) const
{
   //*-*-*-*Convert nPoints points from local system to master reference system*-*-*
   //*-*      ==============================================================
   //
   //  Note that before invoking this function, the global rotation matrix
   //  and translation vector for this node must have been computed.
   //  This is automatically done by the Paint functions.
   //  Otherwise TVolumePosition::UpdateMatrix should be called before.
   //
   Double_t *matrix = 0;
   Float_t *trans = 0;
   if (!fMatrix ||  fMatrix == TVolume::GetIdentity() || !(matrix = ((TRotMatrix *)fMatrix)->GetMatrix()) )
   {
      trans = master;
      for (int i =0; i < nPoints; i++,local += 3, master += 3) TCL::vadd(local,fX,master,3);
   }
   else
   {
      trans = master;
      for (int i =0; i < nPoints; i++, local += 3, master += 3) {
         Double_t dlocal[3];   Double_t dmaster[3];
         TCL::ucopy(local,dlocal,3);
         TCL::mxmpy2(matrix,dlocal,dmaster,3,3,1);
         TCL::vadd(dmaster,fX,dmaster,3);
         TCL::ucopy(dmaster,master,3);
      }
   }
   return trans;
}
//______________________________________________________________________________

 Double_t *TVolumePosition::Master2Local(const Double_t *master, Double_t *local, Int_t nPoints) const
{
   //*-*-*-*-*Convert one point from master system to local reference system*-*-*

   //*-*      ==============================================================

   //

   //  Note that before invoking this function, the global rotation matrix

   //  and translation vector for this node must have been computed.

   //  This is automatically done by the Paint functions.

   //  Otherwise TVolumePosition::UpdateMatrix should be called before.

   Double_t *matrix = 0;
   Double_t *trans = 0;
   if (!fMatrix ||  fMatrix == TVolume::GetIdentity() || !(matrix = ((TRotMatrix *)fMatrix)->GetMatrix()) )
   {
      trans = local;
      for (int i =0; i < nPoints; i++,master += 3, local += 3) TCL::vsub(master,fX,local,3);
   }
   else
   {
      trans = local;
      for (int i =0; i < nPoints; i++, master += 3, local += 3) {
         Double_t dlocal[3];
         TCL::vsub(master,fX,dlocal,3);
         TCL::mxmpy(matrix,dlocal,local,3,3,1);
      }
   }
   return trans;
}

//______________________________________________________________________________

 Float_t *TVolumePosition::Master2Local(const Float_t *master, Float_t *local, Int_t nPoints) const
{
   //*-*-*-*Convert nPoints points from master system to local reference system*-*-*

   //*-*      ==============================================================

   //

   //  Note that before invoking this function, the global rotation matrix

   //  and translation vector for this node must have been computed.

   //  This is automatically done by the Paint functions.

   //  Otherwise TVolumePosition::UpdateMatrix should be called before.

   //

   Double_t *matrix = 0;
   Float_t *trans = 0;
   if (!fMatrix ||  fMatrix == TVolume::GetIdentity() || !(matrix = ((TRotMatrix *)fMatrix)->GetMatrix()) )
   {
      trans = local;
      for (int i =0; i < nPoints; i++,master += 3, local += 3) TCL::vsub(master,fX,local,3);
   }
   else
   {
      trans = local;
      for (int i =0; i < nPoints; i++, master += 3, local += 3) {
         Double_t dmaster[3];   Double_t dlocal[3];
         TCL::ucopy(master,dmaster,3);
         TCL::vsub(dmaster,fX,dmaster,3);
         TCL::mxmpy(matrix,dmaster,dlocal,3,3,1);
         TCL::ucopy(dlocal,local,3);
      }
   }
   return trans;
}
//______________________________________________________________________________
 void TVolumePosition::Paint(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*-*Paint Referenced node with current parameters*-*-*-*
//*-*                   ==============================================
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
  Error("Paint","Position can not be painted");
}

//_______________________________________________________________________
 void TVolumePosition::Print(Option_t *) const
{
  cout << " Node: " <<   GetNode()->GetName() << endl;
  cout << " Position: x=" <<
          GetX() << " : y=" <<
          GetY() << " : z=" <<
          GetZ() << endl;

  if (fMatrix){
      fMatrix->Print();
      Double_t *matrix = ((TRotMatrix *)fMatrix)->GetMatrix();
      Int_t i = 0;
      cout << setw(4) <<" " ;
      for (i=0;i<3;i++) cout << setw(3) << i+1 << setw(3) << ":" ;
      cout << endl;
      for (i=0;i<3;i++) {
        cout << i+1 << ". ";
        for (Int_t j=0;j<3;j++)
           cout << setw(6) << *matrix++ << " : " ;
        cout << endl;
      }
  }
}

//______________________________________________________________________________
 TVolumePosition *TVolumePosition::Reset(TVolume *node,Double_t x, Double_t y, Double_t z, TRotMatrix *matrix)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Reset this position *-*-*-*-*-*-*-*-*-*-*
//*-*                           ===================
//*-*    x,y,z   are the offsets of the volume with respect to his mother
//*-*    matrix  is the pointer to the rotation matrix
//*-*
//*-*    This method is to re-use the memory this object without delete/create steps
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

// This method has to be protected since it doesn't set properly kIsOwn bit.

   fNode = node;
   SetPosition(x,y,z);
   SetMatrix(matrix);
   if (!fMatrix) fMatrix = TVolume::GetIdentity();
   return this;
}

//_______________________________________________________________________
 void TVolumePosition::SavePrimitive(ofstream &, Option_t *)
{
#if 0
  out << "TVolumePosition *CreatePosition() { " << endl;
  out << "  TVolumePosition *myPosition = 0;    " << endl;
  Double_t x = GetX();
  Double_t y = GetY();
  Double_t z = GetZ();
  TRotMatrix *matrix =
   myPosition =  new TVolumePosition(TVolume *node,Double_t x, Double_t y, Double_t z, const Text_t *matrixname)
: fNode(node),fX(x),fY(y),fZ(z),fMatrix(0)
{
/
  out << "  return myPosition; "                << endl;
  out << "} "                                   << endl;
#endif

}
//______________________________________________________________________________
 void   TVolumePosition::SetLineAttributes()
{
  TVolume *thisNode = GetNode();
  if (thisNode) thisNode->SetLineAttributes();
}
//_______________________________________________________________________
 void TVolumePosition::SetMatrix(TRotMatrix *matrix)
{
   if (matrix != fMatrix) {
      DeleteOwnMatrix();
      fMatrix = matrix;
   }
}
//_______________________________________________________________________
 void TVolumePosition::UpdatePosition(Option_t *)
{
  TPadView3D *view3D=(TPadView3D *)gPad->GetView3D();
//*-*- Update translation vector and rotation matrix for new level
  if (gGeometry->GeomLevel() && fMatrix) {
     gGeometry->UpdateTempMatrix(fX[0],fX[1],fX[2]
                                ,((TRotMatrix *)fMatrix)->GetMatrix()
                                ,fMatrix->IsReflection());
     if (view3D)
        view3D->UpdatePosition(fX[0],fX[1],fX[2],((TRotMatrix *)fMatrix));
  }
}

//______________________________________________________________________________
 void TVolumePosition::SetVisibility(Int_t vis)
{
 TVolume *node = GetNode();
 if (node) node->SetVisibility(TVolume::ENodeSEEN(vis));
}
//______________________________________________________________________________
 TVolumePosition &TVolumePosition::Mult(const TVolumePosition &curPosition) {

   // This method mupltiply the position of this object to the position of the
   // curPosition object.
   // It doesn't change Id of either object involved.


   // Pick the "old" position by pieces
   TVolume *curNode = 0;
 //  UInt_t curPositionId    = 0;
      curNode       = curPosition.GetNode();
 //     curPositionId = curPosition.GetId();
   const TRotMatrix *oldMatrix = 0;
   Double_t oldTranslation[] = { 0, 0, 0 };
          oldMatrix         = GetMatrix();
          oldTranslation[0] = GetX();
          oldTranslation[1] = GetY();
          oldTranslation[2] = GetZ();
 
   // Pick the "current" position by pieces
   const TRotMatrix *curMatrix        = curPosition.GetMatrix();

   // Create a new position
   Double_t newTranslation[3];
   Double_t newMatrix[9];
   if(oldMatrix){
      TGeometry::UpdateTempMatrix(oldTranslation,((TRotMatrix *)oldMatrix)->GetMatrix()
                       ,curPosition.GetX(),curPosition.GetY(),curPosition.GetZ(),
                       ((TRotMatrix *)curMatrix)->GetMatrix()
                       ,newTranslation,newMatrix);
      Int_t num = gGeometry->GetListOfMatrices()->GetSize();
      Char_t anum[100];
      sprintf(anum,"%d",num+1);
      SetMatrixOwner();
      Reset(curNode
                           ,newTranslation[0],newTranslation[1],newTranslation[2]
                           ,new TRotMatrix(anum,"NodeView",newMatrix));

   } else {
      newTranslation[0] = oldTranslation[0] + curPosition.GetX();
      newTranslation[1] = oldTranslation[1] + curPosition.GetY();
      newTranslation[2] = oldTranslation[2] + curPosition.GetZ();
      Reset(curNode,newTranslation[0],newTranslation[1],newTranslation[2]);
   }
//    SetId(curPositionId);
   return *this;
}

//______________________________________________________________________________
 void TVolumePosition::Streamer(TBuffer &R__b)
{
   // Stream an object of class TVolumePosition.
   TRotMatrix     *save = fMatrix;
   if (R__b.IsReading()) {
      fMatrix = 0;
      TVolumePosition::Class()->ReadBuffer(R__b, this);
      if (!fMatrix) fMatrix = save;
   } else {
      if (save == TVolume::GetIdentity() ) fMatrix = 0;
      TVolumePosition::Class()->WriteBuffer(R__b, this);
      fMatrix = save;
   }
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.