TGeoNode.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoNode.cxx 36535 2010-11-08 14:41:54Z agheata $
00002 // Author: Andrei Gheata   24/10/01
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 ////////////////////////////////////////////////////////////////////////////////
00013 // TGeoNode
00014 //_________
00015 //   A node represent a volume positioned inside another.They store links to both
00016 // volumes and to the TGeoMatrix representing the relative positioning. Node are
00017 // never instanciated directly by users, but created as a result of volume operations.
00018 // Adding a volume named A with a given user ID inside a volume B will create a node 
00019 // node named A_ID. This will be added to the list of nodes stored by B. Also,
00020 // when applying a division operation in N slices to a volume A, a list of nodes
00021 // B_1, B_2, ..., B_N is also created. A node B_i does not represent a unique
00022 // object in the geometry because its container A might be at its turn positioned
00023 // as node inside several other volumes. Only when a complete branch of nodes
00024 // is fully defined up to the top node in the geometry, a given path like:
00025 //       /TOP_1/.../A_3/B_7 will represent an unique object. Its global transformation
00026 // matrix can be computed as the pile-up of all local transformations in its
00027 // branch. We will therefore call "logical graph" the hierarchy defined by nodes
00028 // and volumes. The expansion of the logical graph by all possible paths defines
00029 // a tree sructure where all nodes are unique "touchable" objects. We will call
00030 // this the "physical tree". Unlike the logical graph, the physical tree can
00031 // become a huge structure with several milions of nodes in case of complex
00032 // geometries, therefore it is not always a good idea to keep it transient
00033 // in memory. Since a the logical and physical structures are correlated, the
00034 // modeller rather keeps track only of the current branch, updating the current
00035 // global matrix at each change of the level in geometry. The current physical node
00036 // is not an object that can be asked for at a given moment, but rather represented
00037 // by the combination: current node + current global matrix. However, physical nodes
00038 // have unique ID's that can be retreived for a given modeler state. These can be
00039 // fed back to the modeler in order to force a physical node to become current.
00040 // The advantage of this comes from the fact that all navigation queries check
00041 // first the current node, therefore knowing the location of a point in the 
00042 // geometry can be saved as a starting state for later use.
00043 //
00044 //   Nodes can be declared as "overlapping" in case they do overlap with other
00045 // nodes inside the same container or extrude this container. Non-overlapping
00046 // nodes can be created with:
00047 //
00048 //      TGeoVolume::AddNode(TGeoVolume *daughter, Int_t copy_No, TGeoMatrix *matr);
00049 //
00050 // The creation of overapping nodes can be done with a similar prototype:
00051 //
00052 //      TGeoVolume::AddNodeOverlap(same arguments);
00053 //
00054 // When closing the geometry, overlapping nodes perform a check of possible
00055 // overlaps with their neighbours. These are stored and checked all the time
00056 // during navigation, therefore navigation is slower when embedding such nodes
00057 // into geometry.
00058 //
00059 //   Node have visualization attributes as volume have. When undefined by users,
00060 // painting a node on a pad will take the corresponding volume attributes.
00061 // 
00062 //Begin_Html
00063 /*
00064 <img src="gif/t_node.jpg">
00065 */
00066 //End_Html
00067 
00068 #include "Riostream.h"
00069 
00070 #include "TBrowser.h"
00071 #include "TObjArray.h"
00072 #include "TStyle.h"
00073 
00074 #include "TGeoManager.h"
00075 #include "TGeoMatrix.h"
00076 #include "TGeoShape.h"
00077 #include "TGeoVolume.h"
00078 #include "TVirtualGeoPainter.h"
00079 #include "TGeoVoxelFinder.h"
00080 #include "TGeoNode.h"
00081 #include "TMath.h"
00082 #include "TStopwatch.h"
00083 
00084 // statics and globals
00085 
00086 ClassImp(TGeoNode)
00087 
00088 //_____________________________________________________________________________
00089 TGeoNode::TGeoNode()
00090 {
00091 // Default constructor
00092    fVolume       = 0;
00093    fMother       = 0;
00094    fNumber       = 0;
00095    fOverlaps     = 0;
00096    fNovlp        = 0;
00097 }
00098 
00099 //_____________________________________________________________________________
00100 TGeoNode::TGeoNode(const TGeoVolume *vol)
00101 {
00102 // Constructor
00103    if (!vol) {
00104       Error("ctor", "volume not specified");
00105       return;
00106    }
00107    fVolume       = (TGeoVolume*)vol;
00108    if (fVolume->IsAdded()) fVolume->SetReplicated();
00109    fVolume->SetAdded();
00110    fMother       = 0;
00111    fNumber       = 0;
00112    fOverlaps     = 0;
00113    fNovlp        = 0;
00114 }
00115 
00116 //_____________________________________________________________________________
00117 TGeoNode::TGeoNode(const TGeoNode& gn) :
00118   TNamed(gn),
00119   TGeoAtt(gn),
00120   fVolume(gn.fVolume),
00121   fMother(gn.fMother),
00122   fNumber(gn.fNumber),
00123   fNovlp(gn.fNovlp),
00124   fOverlaps(gn.fOverlaps)
00125 { 
00126    //copy constructor
00127 }
00128 
00129 //_____________________________________________________________________________
00130 TGeoNode& TGeoNode::operator=(const TGeoNode& gn) 
00131 {
00132    //assignment operator
00133    if(this!=&gn) {
00134       TNamed::operator=(gn);
00135       TGeoAtt::operator=(gn);
00136       fVolume=gn.fVolume;
00137       fMother=gn.fMother;
00138       fNumber=gn.fNumber;
00139       fNovlp=gn.fNovlp;
00140       fOverlaps=gn.fOverlaps;
00141    } 
00142    return *this;
00143 }
00144 
00145 //_____________________________________________________________________________
00146 TGeoNode::~TGeoNode()
00147 {
00148 // Destructor
00149    if (fOverlaps) delete [] fOverlaps;
00150 }
00151 
00152 //_____________________________________________________________________________
00153 void TGeoNode::Browse(TBrowser *b)
00154 {
00155 // How-to-browse for a node.
00156    if (!b) return;
00157    if (!GetNdaughters()) return;
00158    TGeoNode *daughter;
00159    TString title;
00160    for (Int_t i=0; i<GetNdaughters(); i++) {
00161       daughter = GetDaughter(i);
00162       b->Add(daughter, daughter->GetName(), daughter->IsVisible());
00163    }      
00164 }
00165 
00166 //_____________________________________________________________________________
00167 Int_t TGeoNode::CountDaughters(Bool_t unique_volumes)
00168 {
00169 // Returns the number of daughters. Nodes pointing to same volume counted
00170 // once if unique_volumes is set.
00171    static Int_t icall = 0;   
00172    Int_t counter = 0;
00173    // Count this node
00174    if (unique_volumes) {
00175       if (!fVolume->IsSelected()) {
00176          counter++;
00177          fVolume->SelectVolume(kFALSE);
00178       }
00179    } else counter++;
00180    icall++;
00181    Int_t nd = fVolume->GetNdaughters();
00182    // Count daughters recursively
00183    for (Int_t i=0; i<nd; i++) counter += GetDaughter(i)->CountDaughters(unique_volumes);
00184    icall--;
00185    // Un-mark volumes
00186    if (icall == 0) fVolume->SelectVolume(kTRUE);
00187    return counter;
00188 }      
00189 
00190 //_____________________________________________________________________________
00191 void TGeoNode::CheckOverlaps(Double_t ovlp, Option_t *option)
00192 {
00193 // Check overlaps bigger than OVLP hierarchically, starting with this node.
00194    Int_t icheck = 0;
00195    Int_t ncheck = 0;
00196    TStopwatch *timer;
00197    Int_t i;
00198    Bool_t sampling = kFALSE;
00199    TString opt(option);
00200    opt.ToLower();
00201    if (opt.Contains("s")) sampling = kTRUE;
00202 
00203    TGeoManager *geom = fVolume->GetGeoManager();
00204    ncheck = CountDaughters(kFALSE);
00205    timer = new TStopwatch();
00206    geom->ClearOverlaps();
00207    geom->SetCheckingOverlaps(kTRUE);
00208    Info("CheckOverlaps", "Checking overlaps for %s and daughters within %g", fVolume->GetName(),ovlp);
00209    if (sampling) {
00210       Info("CheckOverlaps", "Checking overlaps by sampling <%s> for %s and daughters", option, fVolume->GetName());
00211       Info("CheckOverlaps", "=== NOTE: Extrusions NOT checked with sampling option ! ===");
00212    }   
00213    timer->Start();
00214    geom->GetGeomPainter()->OpProgress(fVolume->GetName(),icheck,ncheck,timer,kFALSE);
00215    fVolume->CheckOverlaps(ovlp,option);
00216    icheck++;
00217    TGeoIterator next(fVolume);
00218    TGeoNode *node;
00219    TString path;
00220    while ((node=next())) {
00221       next.GetPath(path);
00222       icheck++;
00223       if (!node->GetVolume()->IsSelected()) {
00224          geom->GetGeomPainter()->OpProgress(node->GetVolume()->GetName(),icheck,ncheck,timer,kFALSE);
00225          node->GetVolume()->SelectVolume(kFALSE);
00226          node->GetVolume()->CheckOverlaps(ovlp,option);
00227       }   
00228    }   
00229    fVolume->SelectVolume(kTRUE);
00230    geom->SetCheckingOverlaps(kFALSE);
00231    geom->SortOverlaps();
00232    TObjArray *overlaps = geom->GetListOfOverlaps();
00233    Int_t novlps = overlaps->GetEntriesFast();     
00234    TNamed *obj;
00235    for (i=0; i<novlps; i++) {
00236       obj = (TNamed*)overlaps->At(i);
00237       obj->SetName(TString::Format("ov%05d",i));
00238    }
00239    geom->GetGeomPainter()->OpProgress("Check overlaps:",icheck,ncheck,timer,kTRUE);
00240    Info("CheckOverlaps", "Number of illegal overlaps/extrusions : %d\n", novlps);
00241    delete timer;
00242 }      
00243 
00244 //_____________________________________________________________________________
00245 Int_t TGeoNode::DistancetoPrimitive(Int_t px, Int_t py)
00246 {
00247 // compute the closest distance of approach from point px,py to this node
00248    Int_t dist = 9999;
00249    if (!fVolume) return dist;
00250    if (gGeoManager != fVolume->GetGeoManager()) gGeoManager = fVolume->GetGeoManager();
00251    TVirtualGeoPainter *painter = gGeoManager->GetPainter();
00252    if (!painter) return dist;
00253    dist = painter->DistanceToPrimitiveVol(fVolume, px, py);
00254    return dist;
00255 }
00256       
00257 //_____________________________________________________________________________
00258 void TGeoNode::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00259 {
00260 // Execute mouse actions on this volume.
00261    if (!fVolume) return;
00262    TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
00263    if (!painter) return;
00264    painter->ExecuteVolumeEvent(fVolume, event, px, py);
00265 }
00266 
00267 //_____________________________________________________________________________
00268 char *TGeoNode::GetObjectInfo(Int_t px, Int_t py) const
00269 {
00270 // Get node info for the browser.
00271    if (!fVolume) return 0;
00272    TVirtualGeoPainter *painter = fVolume->GetGeoManager()->GetPainter();
00273    if (!painter) return 0;
00274    return (char*)painter->GetVolumeInfo(fVolume, px, py);
00275 }
00276 
00277 //_____________________________________________________________________________
00278 Bool_t TGeoNode::IsOnScreen() const
00279 {
00280 // check if this node is drawn. Assumes that this node is current
00281    
00282    if (fVolume->TestAttBit(TGeoAtt::kVisOnScreen)) return kTRUE;
00283    return kFALSE;
00284 }
00285 
00286 //_____________________________________________________________________________
00287 void TGeoNode::InspectNode() const
00288 {
00289 // Inspect this node.
00290    Info("InspectNode","Inspecting node %s", GetName());
00291    if (IsOverlapping()) Info("InspectNode","node is MANY");
00292    if (fOverlaps && fMother) {
00293       Info("InspectNode","possibly overlaping with :");
00294       for (Int_t i=0; i<fNovlp; i++)
00295          Info("InspectNode","   node %s", fMother->GetNode(fOverlaps[i])->GetName());
00296    }
00297    Info("InspectNode","Transformation matrix:\n");
00298    TGeoMatrix *matrix = GetMatrix();
00299    if (matrix) matrix->Print();
00300    if (fMother)
00301       Info("InspectNode","Mother volume %s\n", fMother->GetName());
00302    fVolume->InspectShape();
00303 }
00304 
00305 //_____________________________________________________________________________
00306 void TGeoNode::CheckShapes()
00307 {
00308 // check for wrong parameters in shapes
00309    fVolume->CheckShapes();
00310    Int_t nd = GetNdaughters();
00311    if (!nd) return;
00312    for (Int_t i=0; i<nd; i++) fVolume->GetNode(i)->CheckShapes();
00313 }
00314 
00315 //_____________________________________________________________________________
00316 void TGeoNode::DrawOnly(Option_t *option)
00317 {
00318 // draw only this node independently of its vis options
00319    fVolume->DrawOnly(option);
00320 }
00321 
00322 //_____________________________________________________________________________
00323 void TGeoNode::Draw(Option_t *option)
00324 {
00325 // draw current node according to option
00326    gGeoManager->FindNode();
00327    gGeoManager->CdUp();
00328    Double_t point[3];
00329    gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
00330    gGeoManager->SetCurrentPoint(&point[0]);
00331    gGeoManager->GetCurrentVolume()->Draw(option);
00332 }
00333 
00334 //_____________________________________________________________________________
00335 void TGeoNode::DrawOverlaps()
00336 {
00337 // Method drawing the overlap candidates with this node.
00338    if (!fNovlp) {printf("node %s is ONLY\n", GetName()); return;}
00339    if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
00340    TGeoNode *node;
00341    Int_t i;
00342    Int_t nd = fMother->GetNdaughters();
00343    for (i=0; i<nd; i++) {
00344       node = fMother->GetNode(i);
00345       node->GetVolume()->SetVisibility(kFALSE);
00346    }   
00347    fVolume->SetVisibility(kTRUE);
00348    for (i=0; i<fNovlp; i++) {
00349       node = fMother->GetNode(fOverlaps[i]);
00350       node->GetVolume()->SetVisibility(kTRUE);
00351    }
00352    gGeoManager->SetVisLevel(1);
00353    fMother->Draw();
00354 }
00355 
00356 //_____________________________________________________________________________
00357 void TGeoNode::FillIdArray(Int_t &ifree, Int_t &nodeid, Int_t *array) const
00358 {
00359 // Fill array with node id. Recursive on node branch.
00360    Int_t nd = GetNdaughters();
00361    if (!nd) return;
00362    TGeoNode *daughter;
00363    Int_t istart = ifree; // start index for daughters
00364    ifree += nd;
00365    for (Int_t id=0; id<nd; id++) {
00366       daughter = GetDaughter(id);
00367       array[istart+id] = ifree;
00368       array[ifree++] = ++nodeid;
00369       daughter->FillIdArray(ifree, nodeid, array);
00370    }
00371 }      
00372    
00373 
00374 //_____________________________________________________________________________
00375 Int_t TGeoNode::FindNode(const TGeoNode *node, Int_t level)
00376 {
00377 // Search for a node within the branch of this one.
00378    Int_t nd = GetNdaughters();
00379    if (!nd) return -1;
00380    TIter next(fVolume->GetNodes());
00381    TGeoNode *daughter;
00382    while ((daughter=(TGeoNode*)next())) {
00383       if (daughter==node) {
00384          gGeoManager->GetListOfNodes()->AddAt(daughter,level+1);
00385          return (level+1);
00386       }
00387    }
00388    next.Reset();
00389    Int_t new_level;
00390    while ((daughter=(TGeoNode*)next())) {
00391       new_level = daughter->FindNode(node, level+1);
00392       if (new_level>=0) {
00393          gGeoManager->GetListOfNodes()->AddAt(daughter, level+1);
00394          return new_level;
00395       }
00396    }
00397    return -1;
00398 }
00399 
00400 //_____________________________________________________________________________
00401 void TGeoNode::SaveAttributes(ostream &out)
00402 {
00403 // save attributes for this node
00404    if (IsVisStreamed()) return;
00405    SetVisStreamed(kTRUE);
00406    char quote='"';
00407    Bool_t voldef = kFALSE;
00408    if ((fVolume->IsVisTouched()) && (!fVolume->IsVisStreamed())) {
00409       fVolume->SetVisStreamed(kTRUE);
00410       out << "   vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<endl;
00411       voldef = kTRUE;
00412       if (!fVolume->IsVisDaughters())
00413          out << "   vol->SetVisDaughters(kFALSE);"<<endl;
00414       if (fVolume->IsVisible()) {
00415 /*
00416          if (fVolume->GetLineColor() != gStyle->GetLineColor())
00417             out<<"   vol->SetLineColor("<<fVolume->GetLineColor()<<");"<<endl;
00418          if (fVolume->GetLineStyle() != gStyle->GetLineStyle())
00419             out<<"   vol->SetLineStyle("<<fVolume->GetLineStyle()<<");"<<endl;
00420          if (fVolume->GetLineWidth() != gStyle->GetLineWidth())
00421             out<<"   vol->SetLineWidth("<<fVolume->GetLineWidth()<<");"<<endl;
00422 */
00423       } else {
00424          out <<"   vol->SetVisibility(kFALSE);"<<endl;
00425       }
00426    }
00427    if (!IsVisDaughters()) return;
00428    Int_t nd = GetNdaughters();
00429    if (!nd) return;
00430    TGeoNode *node;
00431    for (Int_t i=0; i<nd; i++) {
00432       node = GetDaughter(i);
00433       if (node->IsVisStreamed()) continue;
00434       if (node->IsVisTouched()) {
00435          if (!voldef)
00436             out << "   vol = gGeoManager->GetVolume("<<quote<<fVolume->GetName()<<quote<<");"<<endl;
00437          out<<"   node = vol->GetNode("<<i<<");"<<endl;
00438          if (!node->IsVisDaughters()) {
00439             out<<"   node->VisibleDaughters(kFALSE);"<<endl;
00440             node->SetVisStreamed(kTRUE);
00441             continue;
00442          }
00443          if (!node->IsVisible()) 
00444             out<<"   node->SetVisibility(kFALSE);"<<endl;
00445       }         
00446       node->SaveAttributes(out);
00447       node->SetVisStreamed(kTRUE);
00448    }
00449 }
00450 
00451 //_____________________________________________________________________________
00452 Bool_t TGeoNode::MayOverlap(Int_t iother) const 
00453 {
00454 // Check the overlab between the bounding box of the node overlaps with the one
00455 // the brother with index IOTHER.
00456    if (!fOverlaps) return kFALSE;
00457    for (Int_t i=0; i<fNovlp; i++) if (fOverlaps[i]==iother) return kTRUE;
00458    return kFALSE;
00459 }   
00460 
00461 //_____________________________________________________________________________
00462 void TGeoNode::MasterToLocal(const Double_t *master, Double_t *local) const
00463 {
00464 // Convert the point coordinates from mother reference to local reference system
00465    GetMatrix()->MasterToLocal(master, local);
00466 }
00467 
00468 //_____________________________________________________________________________
00469 void TGeoNode::MasterToLocalVect(const Double_t *master, Double_t *local) const
00470 {
00471 // Convert a vector from mother reference to local reference system
00472    GetMatrix()->MasterToLocalVect(master, local);
00473 }
00474 
00475 //_____________________________________________________________________________
00476 void TGeoNode::LocalToMaster(const Double_t *local, Double_t *master) const
00477 {
00478 // Convert the point coordinates from local reference system to mother reference
00479    GetMatrix()->LocalToMaster(local, master);
00480 }
00481 
00482 //_____________________________________________________________________________
00483 void TGeoNode::LocalToMasterVect(const Double_t *local, Double_t *master) const
00484 {
00485 // Convert a vector from local reference system to mother reference
00486    GetMatrix()->LocalToMasterVect(local, master);
00487 }
00488 
00489 //_____________________________________________________________________________
00490 void TGeoNode::ls(Option_t * /*option*/) const
00491 {
00492 // Print the path (A/B/C/...) to this node on stdout
00493 }
00494 
00495 //_____________________________________________________________________________
00496 void TGeoNode::Paint(Option_t *option)
00497 {
00498 // Paint this node and its content according to visualization settings.
00499    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
00500    if (!painter) return;
00501    painter->PaintNode(this, option);
00502 }
00503 
00504 //_____________________________________________________________________________
00505 void TGeoNode::PrintCandidates() const
00506 {
00507 // print daughters candidates for containing current point
00508 //   cd();
00509    Double_t point[3];
00510    gGeoManager->MasterToLocal(gGeoManager->GetCurrentPoint(), &point[0]);
00511    printf("   Local : %g, %g, %g\n", point[0], point[1], point[2]);
00512    if (!fVolume->Contains(&point[0])) {
00513       printf("current point not inside this\n");
00514       return;
00515    }
00516    TGeoPatternFinder *finder = fVolume->GetFinder();
00517    TGeoNode *node;
00518    if (finder) {
00519       printf("current node divided\n");
00520       node = finder->FindNode(&point[0]);
00521       if (!node) {
00522          printf("point not inside division element\n");
00523          return;
00524       }
00525       printf("inside division element %s\n", node->GetName());
00526       return;
00527    }
00528    TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00529    if (!voxels) {
00530       printf("volume not voxelized\n");
00531       return;
00532    }
00533    Int_t ncheck = 0;
00534    Int_t *check_list = voxels->GetCheckList(&point[0], ncheck);
00535    voxels->PrintVoxelLimits(&point[0]);
00536    if (!check_list) {
00537       printf("no candidates for current point\n");
00538       return;
00539    }
00540    TString overlap = "ONLY";
00541    for (Int_t id=0; id<ncheck; id++) {
00542       node = fVolume->GetNode(check_list[id]);
00543       if (node->IsOverlapping()) overlap = "MANY";
00544       else overlap = "ONLY";
00545       printf("%i %s %s\n", check_list[id], node->GetName(), overlap.Data());
00546    }
00547    PrintOverlaps();
00548 }
00549 
00550 //_____________________________________________________________________________
00551 void TGeoNode::PrintOverlaps() const
00552 {
00553 // print possible overlapping nodes
00554 //   if (!IsOverlapping()) {printf("node %s is ONLY\n", GetName()); return;}
00555    if (!fOverlaps) {printf("node %s no overlaps\n", GetName()); return;}
00556    printf("Overlaps for node %s :\n", GetName());
00557    TGeoNode *node;
00558    for (Int_t i=0; i<fNovlp; i++) {
00559       node = fMother->GetNode(fOverlaps[i]);
00560       printf("   %s\n", node->GetName());
00561    }
00562 }
00563 
00564 //_____________________________________________________________________________
00565 Double_t TGeoNode::Safety(Double_t *point, Bool_t in) const
00566 {
00567 // computes the closest distance from given point to this shape
00568 
00569    Double_t local[3];
00570    GetMatrix()->MasterToLocal(point,local);
00571    return fVolume->GetShape()->Safety(local,in);
00572 }
00573 
00574 //_____________________________________________________________________________
00575 void TGeoNode::SetOverlaps(Int_t *ovlp, Int_t novlp)
00576 {
00577 // set the list of overlaps for this node (ovlp must be created with operator new)
00578    if (fOverlaps) delete [] fOverlaps;
00579    fOverlaps = ovlp;
00580    fNovlp = novlp;
00581 }
00582 
00583 //_____________________________________________________________________________
00584 void TGeoNode::SetVisibility(Bool_t vis)
00585 {
00586 // Set visibility of the node (obsolete).
00587    if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
00588    TGeoAtt::SetVisibility(vis);
00589    if (vis && !fVolume->IsVisible()) fVolume->SetVisibility(vis);
00590    gGeoManager->ModifiedPad();
00591 }
00592 
00593 //_____________________________________________________________________________
00594 void TGeoNode::VisibleDaughters(Bool_t vis)
00595 {
00596 // Set visibility of the daughters (obsolete).
00597    if (gGeoManager->IsClosed()) SetVisTouched(kTRUE);
00598    SetVisDaughters(vis);
00599    gGeoManager->ModifiedPad();
00600 }
00601 
00602 ////////////////////////////////////////////////////////////////////////////////
00603 // TGeoNodeMatrix - a node containing local transformation
00604 //
00605 //
00606 //
00607 //
00608 //Begin_Html
00609 /*
00610 <img src=".gif">
00611 */
00612 //End_Html
00613 
00614 ClassImp(TGeoNodeMatrix)
00615 
00616 
00617 //_____________________________________________________________________________
00618 TGeoNodeMatrix::TGeoNodeMatrix()
00619 {
00620 // Default constructor
00621    fMatrix       = 0;
00622 }
00623 
00624 //_____________________________________________________________________________
00625 TGeoNodeMatrix::TGeoNodeMatrix(const TGeoVolume *vol, const TGeoMatrix *matrix) :
00626              TGeoNode(vol)
00627 {
00628 // Constructor. 
00629    fMatrix = (TGeoMatrix*)matrix;
00630    if (!fMatrix) fMatrix = gGeoIdentity;
00631 }
00632 
00633 //_____________________________________________________________________________
00634 TGeoNodeMatrix::TGeoNodeMatrix(const TGeoNodeMatrix& gnm)
00635                :TGeoNode(gnm), 
00636                 fMatrix(gnm.fMatrix)
00637 {
00638 // Copy ctor.
00639 }
00640 
00641 //_____________________________________________________________________________
00642 TGeoNodeMatrix& TGeoNodeMatrix::operator=(const TGeoNodeMatrix& gnm)
00643 {
00644 // Assignment.
00645    if (this!=&gnm) {
00646       TGeoNode::operator=(gnm); 
00647       fMatrix=gnm.fMatrix;
00648    }
00649    return *this;
00650 }
00651       
00652 //_____________________________________________________________________________
00653 TGeoNodeMatrix::~TGeoNodeMatrix()
00654 {
00655 // Destructor
00656 }
00657 
00658 //_____________________________________________________________________________
00659 Int_t TGeoNodeMatrix::GetByteCount() const
00660 {
00661 // return the total size in bytes of this node
00662    Int_t count = 40 + 4; // TGeoNode + fMatrix
00663 //   if (fMatrix) count += fMatrix->GetByteCount();
00664    return count;
00665 }
00666 
00667 //_____________________________________________________________________________
00668 Int_t TGeoNodeMatrix::GetOptimalVoxels() const
00669 {
00670 //--- Returns type of optimal voxelization for this node.
00671 // type = 0 -> cartesian
00672 // type = 1 -> cylindrical
00673    Bool_t type = fVolume->GetShape()->IsCylType();
00674    if (!type) return 0;
00675    if (!fMatrix->IsRotAboutZ()) return 0;
00676    const Double_t *transl = fMatrix->GetTranslation();
00677    if (TMath::Abs(transl[0])>1E-10) return 0;
00678    if (TMath::Abs(transl[1])>1E-10) return 0;
00679    return 1;
00680 }   
00681 
00682 //_____________________________________________________________________________
00683 TGeoNode *TGeoNodeMatrix::MakeCopyNode() const
00684 {
00685 // Make a copy of this node.
00686    TGeoNodeMatrix *node = new TGeoNodeMatrix(fVolume, fMatrix);
00687    node->SetName(GetName());
00688    // set the mother
00689    node->SetMotherVolume(fMother);
00690    // set the copy number
00691    node->SetNumber(fNumber);
00692    // copy overlaps
00693    if (fNovlp>0) {
00694       if (fOverlaps) {
00695          Int_t *ovlps = new Int_t[fNovlp];
00696          memcpy(ovlps, fOverlaps, fNovlp*sizeof(Int_t));
00697          node->SetOverlaps(ovlps, fNovlp);
00698       } else {
00699          node->SetOverlaps(fOverlaps, fNovlp);
00700       }
00701    }
00702    // copy VC
00703    if (IsVirtual()) node->SetVirtual();
00704    return node;
00705 }
00706 
00707 //_____________________________________________________________________________
00708 void TGeoNodeMatrix::SetMatrix(const TGeoMatrix *matrix)
00709 {
00710 // Matrix setter.
00711    fMatrix = (TGeoMatrix*)matrix;
00712    if (!fMatrix) fMatrix = gGeoIdentity;
00713 }   
00714 
00715 /*************************************************************************
00716  * TGeoNodeOffset - node containing an offset
00717  *
00718  *************************************************************************/
00719 ClassImp(TGeoNodeOffset)
00720 
00721 
00722 //_____________________________________________________________________________
00723 TGeoNodeOffset::TGeoNodeOffset()
00724 {
00725 // Default constructor
00726    TObject::SetBit(kGeoNodeOffset);
00727    fOffset = 0;
00728    fIndex = 0;
00729    fFinder = 0;
00730 }
00731 
00732 //_____________________________________________________________________________
00733 TGeoNodeOffset::TGeoNodeOffset(const TGeoVolume *vol, Int_t index, Double_t offset) :
00734            TGeoNode(vol)
00735 {
00736 // Constructor. Null pointer to matrix means identity transformation
00737    TObject::SetBit(kGeoNodeOffset);
00738    fOffset = offset;
00739    fIndex = index;
00740    fFinder = 0;
00741 }
00742 
00743 //_____________________________________________________________________________
00744 TGeoNodeOffset::TGeoNodeOffset(const TGeoNodeOffset& gno) :
00745   TGeoNode(gno),
00746   fOffset(gno.fOffset),
00747   fIndex(gno.fIndex),
00748   fFinder(gno.fFinder)
00749 { 
00750    //copy constructor
00751 }
00752 
00753 //_____________________________________________________________________________
00754 TGeoNodeOffset& TGeoNodeOffset::operator=(const TGeoNodeOffset& gno)
00755 {
00756    //assignment operator
00757    if(this!=&gno) {
00758       TGeoNode::operator=(gno);
00759       fOffset=gno.fOffset;
00760       fIndex=gno.fIndex;
00761       fFinder=gno.fFinder;
00762    } 
00763    return *this;
00764 }
00765 
00766 //_____________________________________________________________________________
00767 TGeoNodeOffset::~TGeoNodeOffset()
00768 {
00769 // Destructor
00770 }
00771 
00772 //_____________________________________________________________________________
00773 Int_t TGeoNodeOffset::GetIndex() const
00774 {
00775 // Get the index of this offset.
00776    return (fIndex+fFinder->GetDivIndex());
00777 }
00778 
00779 //_____________________________________________________________________________
00780 TGeoNode *TGeoNodeOffset::MakeCopyNode() const
00781 {
00782 // make a copy of this node
00783    TGeoNodeOffset *node = new TGeoNodeOffset(fVolume, GetIndex(), fOffset);
00784    node->SetName(GetName());
00785    // set the mother
00786    node->SetMotherVolume(fMother);
00787    // set the copy number
00788    node->SetNumber(fNumber);
00789    if (IsVirtual()) node->SetVirtual();
00790    // set the finder
00791    node->SetFinder(GetFinder());
00792    return node;
00793 }
00794 
00795 /*************************************************************************
00796  * TGeoIterator - a geometry iterator
00797  *
00798  *************************************************************************/
00799 
00800 ////////////////////////////////////////////////////////////////////////////////
00801 // TGeoIterator
00802 //==============
00803 // A geometry iterator that sequentially follows all nodes of the geometrical
00804 // hierarchy of a volume. The iterator has to be initiated with a top volume 
00805 // pointer:
00806 //
00807 //    TGeoIterator next(myVolume);
00808 //
00809 // One can use the iterator as any other in ROOT:
00810 //
00811 //    TGeoNode *node;
00812 //    while ((node=next())) {
00813 //       ...
00814 //    }
00815 // 
00816 // The iterator can perform 2 types of iterations that can be selected via:
00817 //
00818 //    next.SetType(Int_t type);
00819 //
00820 // Here TYPE can be:
00821 //    0 (default) - 'first daughter next' behavior
00822 //    1           - iteration at the current level only
00823 //
00824 // Supposing the tree structure looks like:
00825 //
00826 // TOP ___ A_1 ___ A1_1 ___ A11_1
00827 //    |       |        |___ A12_1
00828 //    |      |_____A2_1 ___ A21_1
00829 //    |                |___ A21_2
00830 //    |___ B_1 ...
00831 //
00832 // The order of iteration for TYPE=0 is: A_1, A1_1, A11_1, A12_1, A2_1, A21_1,
00833 // A21_2, B_1, ...
00834 // The order of iteration for TYPE=1 is: A_1, B_1, ...
00835 // At any moment during iteration, TYPE can be changed. If the last iterated node
00836 // is for instance A1_1 and the iteration type was 0, one can do:
00837 //
00838 //    next.SetType(1);
00839 // The next iterated nodes will be the rest of A daughters: A2,A3,... The iterator
00840 // will return 0 after finishing all daughters of A.
00841 //
00842 // During iteration, the following can be retreived:
00843 // - Top volume where iteration started:    TGeoIterator::GetTopVolume()
00844 // - Node at level I in the current branch: TGeoIterator::GetNode(Int_t i)
00845 // - Iteration type:                        TGeoIterator::GetType()
00846 // - Global matrix of the current node with respect to the top volume:
00847 //                                          TGeoIterator::GetCurrentMatrix()
00848 //
00849 // The iterator can be reset by changing (or not) the top volume:
00850 //
00851 //    TGeoIterator::Reset(TGeoVolume *top);
00852 //
00853 // Example:
00854 //==========
00855 // We want to find out a volume named "MyVol" in the hierarchy of TOP volume.
00856 // 
00857 //    TIter next(TOP);
00858 //    TGeoNode *node;
00859 //    TString name("MyVol");
00860 //    while ((node=next())) 
00861 //       if (name == node->GetVolume()->GetName()) return node->GetVolume();
00862 //
00863 ////////////////////////////////////////////////////////////////////////////////
00864 
00865 ClassImp(TGeoIteratorPlugin)
00866 ClassImp(TGeoIterator)
00867 //_____________________________________________________________________________
00868 TGeoIterator::TGeoIterator(TGeoVolume *top)
00869 {
00870 // Geometry iterator for a branch starting with a TOP node.
00871    fTop = top;
00872    fLevel = 0;
00873    fMustResume = kFALSE;
00874    fMustStop = kFALSE;
00875    fType = 0;
00876    fArray = new Int_t[30];
00877    fMatrix = new TGeoHMatrix();
00878    fTopName = fTop->GetName();
00879    fPlugin = 0;
00880    fPluginAutoexec = kFALSE;
00881 }   
00882 
00883 //_____________________________________________________________________________
00884 TGeoIterator::TGeoIterator(const TGeoIterator &iter)
00885 {
00886 // Copy ctor.
00887    fTop = iter.GetTopVolume();
00888    fLevel = iter.GetLevel();
00889    fMustResume = kFALSE;
00890    fMustStop = kFALSE;
00891    fType = iter.GetType();
00892    fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
00893    for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
00894    fMatrix = new TGeoHMatrix(*iter.GetCurrentMatrix());
00895    fTopName = fTop->GetName();
00896    fPlugin = iter.fPlugin;
00897    fPluginAutoexec = iter.fPluginAutoexec;;
00898 }
00899 
00900 //_____________________________________________________________________________
00901 TGeoIterator::~TGeoIterator()
00902 {
00903 // Destructor.
00904    if (fArray) delete [] fArray;
00905    delete fMatrix;
00906 }   
00907 
00908 //_____________________________________________________________________________
00909 TGeoIterator &TGeoIterator::operator=(const TGeoIterator &iter)
00910 {
00911 // Assignment.
00912    if (&iter == this) return *this;
00913    fTop = iter.GetTopVolume();
00914    fLevel = iter.GetLevel();
00915    fMustResume = kFALSE;
00916    fMustStop = kFALSE;
00917    fType = iter.GetType();
00918    if (fArray) delete [] fArray;
00919    fArray = new Int_t[30+ 30*Int_t(fLevel/30)];
00920    for (Int_t i=0; i<fLevel+1; i++) fArray[i] = iter.GetIndex(i);
00921    if (!fMatrix) fMatrix = new TGeoHMatrix();
00922    *fMatrix = *iter.GetCurrentMatrix();
00923    fTopName = fTop->GetName();
00924    fPlugin = iter.fPlugin;
00925    fPluginAutoexec = iter.fPluginAutoexec;;
00926    return *this;   
00927 }   
00928 
00929 //_____________________________________________________________________________
00930 TGeoNode *TGeoIterator::Next()
00931 {
00932 // Returns next node.
00933    if (fMustStop) return 0;
00934    TGeoNode *mother = 0;
00935    TGeoNode *next = 0;
00936    Int_t i;
00937    Int_t nd = fTop->GetNdaughters();
00938    if (!nd) {
00939       fMustStop = kTRUE;
00940       return 0;
00941    }   
00942    if (!fLevel) {
00943       fArray[++fLevel] = 0;
00944       next = fTop->GetNode(0);
00945       if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00946       return next;
00947    }   
00948    next = fTop->GetNode(fArray[1]);
00949    // Move to current node
00950    for (i=2; i<fLevel+1; i++) {
00951       mother = next;
00952       next = mother->GetDaughter(fArray[i]);
00953    }   
00954    if (fMustResume) {
00955       fMustResume = kFALSE;
00956       if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00957       return next;
00958    }   
00959    
00960    switch (fType) {
00961       case 0:  // default next daughter behavior
00962          nd = next->GetNdaughters();
00963          if (nd) {
00964             // First daughter next
00965             fLevel++;
00966             if ((fLevel%30)==0) IncreaseArray();
00967             fArray[fLevel] = 0;
00968             if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00969             return next->GetDaughter(0);
00970          }
00971          // cd up and pick next
00972          while (next) {
00973             next = GetNode(fLevel-1);
00974             if (!next) {
00975                nd = fTop->GetNdaughters();
00976                if (fArray[fLevel]<nd-1) {
00977                   fArray[fLevel]++;
00978                   if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00979                   return fTop->GetNode(fArray[fLevel]);
00980                }   
00981                fMustStop = kTRUE;
00982                return 0;
00983             } else {
00984                nd = next->GetNdaughters();
00985                if (fArray[fLevel]<nd-1) {
00986                   fArray[fLevel]++;
00987                   if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00988                   return next->GetDaughter(fArray[fLevel]);
00989                }   
00990             }   
00991             fLevel--;
00992          }   
00993          break;
00994       case 1:  // one level search
00995          if (mother) nd = mother->GetNdaughters();
00996          if (fArray[fLevel]<nd-1) {
00997             fArray[fLevel]++;
00998             if (fPlugin && fPluginAutoexec) fPlugin->ProcessNode();
00999             if (!mother) return fTop->GetNode(fArray[fLevel]);
01000             else return mother->GetDaughter(fArray[fLevel]);
01001          }
01002    }
01003    fMustStop = kTRUE;
01004    return 0;
01005 }
01006    
01007 //_____________________________________________________________________________
01008 TGeoNode *TGeoIterator::operator()()
01009 {
01010 // Returns next node.
01011    return Next();
01012 }   
01013 
01014 //_____________________________________________________________________________
01015 const TGeoMatrix *TGeoIterator::GetCurrentMatrix() const
01016 {
01017 // Returns global matrix for current node.
01018    fMatrix->Clear();
01019    if (!fLevel) return fMatrix;
01020    TGeoNode *node = fTop->GetNode(fArray[1]);
01021    fMatrix->Multiply(node->GetMatrix());
01022    for (Int_t i=2; i<fLevel+1; i++) {
01023       node = node->GetDaughter(fArray[i]);
01024       fMatrix->Multiply(node->GetMatrix());
01025    }
01026    return fMatrix;   
01027 }   
01028 
01029 //_____________________________________________________________________________
01030 TGeoNode *TGeoIterator::GetNode(Int_t level) const
01031 {
01032 // Returns current node at a given level.
01033    if (!level || level>fLevel) return 0;
01034    TGeoNode *node = fTop->GetNode(fArray[1]);
01035    for (Int_t i=2; i<level+1; i++) node = node->GetDaughter(fArray[i]);
01036    return node;
01037 }
01038 
01039 //_____________________________________________________________________________
01040 void TGeoIterator::GetPath(TString &path) const
01041 {
01042 // Returns the path for the current node.
01043    path = fTopName;
01044    if (!fLevel) return;
01045    TGeoNode *node = fTop->GetNode(fArray[1]);
01046    path += "/";
01047    path += node->GetName();
01048    for (Int_t i=2; i<fLevel+1; i++) {
01049       node = node->GetDaughter(fArray[i]);
01050       path += "/";
01051       path += node->GetName();
01052    }   
01053 }      
01054 
01055 //_____________________________________________________________________________
01056 void TGeoIterator::IncreaseArray() 
01057 {
01058 // Increase by 30 the size of the array.
01059    Int_t *array = new Int_t[fLevel+30];
01060    memcpy(array, fArray, fLevel*sizeof(Int_t));
01061    delete [] fArray;
01062    fArray = array;
01063 }   
01064  
01065 //_____________________________________________________________________________
01066 void TGeoIterator::Reset(TGeoVolume *top)
01067 {
01068 // Resets the iterator for volume TOP.
01069    if (top) fTop = top;
01070    fLevel = 0;
01071    fMustResume = kFALSE;
01072    fMustStop = kFALSE;
01073 }      
01074 
01075 //_____________________________________________________________________________
01076 void TGeoIterator::SetTopName(const char *name)
01077 {
01078 // Set the top name for path
01079    fTopName = name;
01080 }   
01081 
01082 //_____________________________________________________________________________
01083 void TGeoIterator::Skip()
01084 {
01085 // Stop iterating the current branch. The iteration of the next node will
01086 // behave as if the branch starting from the current node (included) is not existing.
01087    fMustResume = kTRUE;
01088    TGeoNode *next = GetNode(fLevel);
01089    if (!next) return;
01090    Int_t nd;
01091    switch (fType) {
01092       case 0:  // default next daughter behavior
01093          // cd up and pick next
01094          while (next) {
01095             next = GetNode(fLevel-1);
01096             nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
01097             if (fArray[fLevel]<nd-1) {
01098                ++fArray[fLevel];
01099                return;
01100             }
01101             fLevel--;
01102             if (!fLevel) {
01103                fMustStop = kTRUE;
01104                return;
01105             }   
01106          }     
01107          break;
01108       case 1:  // one level search
01109          next = GetNode(fLevel-1);
01110          nd = (next==0)?fTop->GetNdaughters():next->GetNdaughters();
01111          if (fArray[fLevel]<nd-1) {
01112             ++fArray[fLevel];
01113             return;
01114          }
01115          fMustStop = kTRUE;   
01116          break;
01117    }
01118 }         
01119 
01120 //_____________________________________________________________________________
01121 void TGeoIterator::SetUserPlugin(TGeoIteratorPlugin *plugin)
01122 {
01123 // Set a plugin.
01124    fPlugin = plugin;
01125    if (plugin) plugin->SetIterator(this);
01126 }   

Generated on Tue Jul 5 14:12:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1