Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoCache.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 18/03/02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TGeoCache.h"
13 
14 #include "Rtypes.h"
15 #include "TGeoManager.h"
16 #include "TGeoMatrix.h"
17 #include "TGeoVolume.h"
18 #include "TObject.h"
19 
20 //const Int_t kN3 = 3*sizeof(Double_t);
21 
22 ClassImp(TGeoNodeCache);
23 
24 /** \class TGeoNodeCache
25 \ingroup Geometry_classes
26 
27 Special pool of reusable nodes
28 
29 */
30 
31 ////////////////////////////////////////////////////////////////////////////////
32 /// Dummy constructor
33 
34 TGeoNodeCache::TGeoNodeCache()
35 {
36  fGeoCacheMaxLevels = 100;
37  fGeoCacheStackSize = 10;
38  fGeoInfoStackSize = 100;
39  fLevel = 0;
40  fStackLevel = 0;
41  fInfoLevel = 0;
42  fCurrentID = 0;
43  fIndex = 0;
44  fPath = "";
45  fTop = 0;
46  fNode = 0;
47  fMatrix = 0;
48  fStack = 0;
49  fMatrixBranch = 0;
50  fMPB = 0;
51  fNodeBranch = 0;
52  fInfoBranch = 0;
53  fPWInfo = 0;
54  fNodeIdArray = 0;
55  for (Int_t i=0; i<100; i++) fIdBranch[i] = 0;
56 }
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Default constructor
60 
61 TGeoNodeCache::TGeoNodeCache(TGeoNode *top, Bool_t nodeid, Int_t capacity)
62 {
63  fGeoCacheMaxLevels = capacity;
64  fGeoCacheStackSize = 10;
65  fGeoInfoStackSize = 100;
66  fLevel = 0;
67  fStackLevel = 0;
68  fInfoLevel = 0;
69  fCurrentID = 0;
70  fIndex = 0;
71  fPath = "";
72  fTop = top;
73  fNode = top;
74  fStack = new TObjArray(fGeoCacheStackSize);
75  for (Int_t ist=0; ist<fGeoCacheStackSize; ist++)
76  fStack->Add(new TGeoCacheState(fGeoCacheMaxLevels)); // !obsolete 100
77  fMatrixBranch = new TGeoHMatrix *[fGeoCacheMaxLevels];
78  fMPB = new TGeoHMatrix *[fGeoCacheMaxLevels];
79  fNodeBranch = new TGeoNode*[fGeoCacheMaxLevels];
80  fInfoBranch = new TGeoStateInfo*[fGeoInfoStackSize];
81  for (Int_t i=0; i<fGeoCacheMaxLevels; i++) {
82  fMPB[i] = new TGeoHMatrix(TString::Format("global_%d",i));
83  fMatrixBranch[i] = 0;
84  fNodeBranch[i] = 0;
85  }
86  for (Int_t i=0; i<fGeoInfoStackSize; i++) {
87  fInfoBranch[i] = 0;
88  }
89  fPWInfo = 0;
90  fMatrix = fMatrixBranch[0] = fMPB[0];
91  fNodeBranch[0] = top;
92  fNodeIdArray = 0;
93  for (Int_t i=0; i<100; i++) fIdBranch[i] = 0;
94  if (nodeid) BuildIdArray();
95  CdTop();
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// Destructor
100 
101 TGeoNodeCache::~TGeoNodeCache()
102 {
103  if (fStack) {
104  fStack->Delete();
105  delete fStack;
106  }
107  if (fMatrixBranch) delete [] fMatrixBranch;
108  if (fMPB) {
109  for (Int_t i=0; i<fGeoCacheMaxLevels; i++) delete fMPB[i];
110  delete [] fMPB;
111  }
112  delete [] fNodeBranch;
113  if (fInfoBranch) {
114  for (Int_t i=0; i<fGeoInfoStackSize; i++) delete fInfoBranch[i];
115  }
116  delete [] fInfoBranch;
117  if (fNodeIdArray) delete [] fNodeIdArray;
118  delete fPWInfo;
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Builds node id array.
123 
124 void TGeoNodeCache::BuildIdArray()
125 {
126  Int_t nnodes = gGeoManager->GetNNodes();
127  //if (nnodes>3E7) return;
128  if (fNodeIdArray) delete [] fNodeIdArray;
129  Info("BuildIDArray","--- node ID tracking enabled, size=%lu Bytes\n", ULong_t((2*nnodes+1)*sizeof(Int_t)));
130  fNodeIdArray = new Int_t[2*nnodes+1];
131  fNodeIdArray[0] = 0;
132  Int_t ifree = 1;
133  Int_t nodeid = 0;
134  gGeoManager->GetTopNode()->FillIdArray(ifree, nodeid, fNodeIdArray);
135  gGeoManager->CdTop();
136  fIdBranch[0] = 0;
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Builds info branch. Navigation is possible only after this step.
141 
142 void TGeoNodeCache::BuildInfoBranch()
143 {
144  if (!fInfoBranch) fInfoBranch = new TGeoStateInfo*[fGeoInfoStackSize];
145  else if (fInfoBranch[0]) return;
146  for (Int_t i=0; i<fGeoInfoStackSize; i++) {
147  fInfoBranch[i] = new TGeoStateInfo();
148  }
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// Get the PW info, if none create one
153 
154 TGeoStateInfo *TGeoNodeCache::GetMakePWInfo(Int_t nd)
155 {
156  if (fPWInfo) return fPWInfo;
157  fPWInfo = new TGeoStateInfo(nd);
158  return fPWInfo;
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// Change current path to point to the node having this id.
163 /// Node id has to be in range : 0 to fNNodes-1 (no check for performance reasons)
164 
165 void TGeoNodeCache::CdNode(Int_t nodeid) {
166  if (!fNodeIdArray) {
167  Error("CdNode", "Navigation based on physical node unique id disabled.\n To enable, use: gGeoManager->GetCache()->BuildIdArray()");
168  return;
169  }
170  Int_t *arr = fNodeIdArray;
171  if (nodeid == arr[fIndex]) return;
172  while (fLevel>0) {
173  gGeoManager->CdUp();
174  if (nodeid == arr[fIndex]) return;
175  }
176  gGeoManager->CdTop();
177  Int_t currentID = 0;
178  Int_t nd = GetNode()->GetNdaughters();
179  Int_t nabove, nbelow, middle;
180  while (nodeid!=currentID && nd) {
181  nabove = nd+1;
182  nbelow = 0;
183  while (nabove-nbelow > 1) {
184  middle = (nabove+nbelow)>>1;
185  currentID = arr[arr[fIndex+middle]];
186  if (nodeid == currentID) {
187  gGeoManager->CdDown(middle-1);
188  return;
189  }
190  if (nodeid < currentID) nabove = middle;
191  else nbelow = middle;
192  }
193  gGeoManager->CdDown(nbelow-1);
194  currentID = arr[fIndex];
195  nd = GetNode()->GetNdaughters();
196  }
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Make daughter INDEX of current node the active state. Compute global matrix.
201 
202 Bool_t TGeoNodeCache::CdDown(Int_t index)
203 {
204  TGeoNode *newnode = fNode->GetDaughter(index);
205  if (!newnode) return kFALSE;
206  fLevel++;
207  if (fNodeIdArray) {
208  fIndex = fNodeIdArray[fIndex+index+1];
209  fIdBranch[fLevel] = fIndex;
210  }
211  fNode = newnode;
212  fNodeBranch[fLevel] = fNode;
213  TGeoMatrix *local = newnode->GetMatrix();
214  TGeoHMatrix *newmat = fMPB[fLevel];
215  if (!local->IsIdentity()) {
216  newmat->CopyFrom(fMatrix);
217  newmat->Multiply(local);
218  fMatrix = newmat;
219  }
220  fMatrixBranch[fLevel] = fMatrix;
221  return kTRUE;
222 }
223 
224 ////////////////////////////////////////////////////////////////////////////////
225 /// Make daughter INDEX of current node the active state. Compute global matrix.
226 
227 Bool_t TGeoNodeCache::CdDown(TGeoNode *newnode)
228 {
229  if (!newnode) return kFALSE;
230  fLevel++;
231  if (fNodeIdArray) {
232  Int_t index = fNode->GetVolume()->GetIndex(newnode);
233  fIndex = fNodeIdArray[fIndex+index+1];
234  fIdBranch[fLevel] = fIndex;
235  }
236  fNode = newnode;
237  fNodeBranch[fLevel] = fNode;
238  TGeoMatrix *local = newnode->GetMatrix();
239  TGeoHMatrix *newmat = fMPB[fLevel];
240  if (!local->IsIdentity()) {
241  newmat->CopyFrom(fMatrix);
242  newmat->Multiply(local);
243  fMatrix = newmat;
244  }
245  fMatrixBranch[fLevel] = fMatrix;
246  return kTRUE;
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Make mother of current node the active state.
251 
252 void TGeoNodeCache::CdUp()
253 {
254  if (!fLevel) return;
255  fLevel--;
256  if (fNodeIdArray) fIndex = fIdBranch[fLevel];
257  fNode = fNodeBranch[fLevel];
258  fMatrix = fMatrixBranch[fLevel];
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Returns a fixed ID for current physical node
263 
264 Int_t TGeoNodeCache::GetCurrentNodeId() const
265 {
266  if (fNodeIdArray) return fNodeIdArray[fIndex];
267  return GetNodeId();
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Get unique node id.
272 
273 Int_t TGeoNodeCache::GetNodeId() const
274 {
275  Long_t id=0;
276  for (Int_t level=0;level<fLevel+1; level++)
277  id += (Long_t)fNodeBranch[level];
278  return (Int_t)id;
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Fill names with current branch volume names (4 char - used by GEANT3 interface).
283 
284 void TGeoNodeCache::GetBranchNames(Int_t *names) const
285 {
286  const char *name;
287  for (Int_t i=0; i<fLevel+1; i++) {
288  name = fNodeBranch[i]->GetVolume()->GetName();
289  memcpy(&names[i], name, sizeof(Int_t));
290  }
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 /// Fill copy numbers of current branch nodes.
295 
296 void TGeoNodeCache::GetBranchNumbers(Int_t *copyNumbers, Int_t *volumeNumbers) const
297 {
298  for (Int_t i=0; i<fLevel+1; i++) {
299  copyNumbers[i] = fNodeBranch[i]->GetNumber();
300  volumeNumbers[i] = fNodeBranch[i]->GetVolume()->GetNumber();
301  }
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Fill copy numbers of current branch nodes.
306 
307 void TGeoNodeCache::GetBranchOnlys(Int_t *isonly) const
308 {
309  Bool_t ismany = kFALSE;
310  for (Int_t i=0; i<fLevel+1; i++) {
311  if (!fNodeBranch[i]->IsOffset()) ismany=fNodeBranch[i]->IsOverlapping();
312  isonly[i] = (ismany)?0:1;
313  }
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Get next state info pointer.
318 
319 TGeoStateInfo *TGeoNodeCache::GetInfo()
320 {
321  if (fInfoLevel==fGeoInfoStackSize-1) {
322  TGeoStateInfo **infoBranch = new TGeoStateInfo*[2*fGeoInfoStackSize];
323  memcpy(infoBranch, fInfoBranch, fGeoInfoStackSize*sizeof(TGeoStateInfo*));
324  for (Int_t i=fGeoInfoStackSize; i<2*fGeoInfoStackSize; i++)
325  infoBranch[i] = new TGeoStateInfo();
326  delete [] fInfoBranch;
327  fInfoBranch = infoBranch;
328  fGeoInfoStackSize *= 2;
329  }
330  return fInfoBranch[fInfoLevel++];
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 /// Release last used state info pointer.
335 
336 void TGeoNodeCache::ReleaseInfo()
337 {
338  fInfoLevel--;
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Returns the current geometry path.
343 
344 const char *TGeoNodeCache::GetPath()
345 {
346  fPath = "";
347  for (Int_t level=0;level<fLevel+1; level++) {
348  fPath += "/";
349  fPath += fNodeBranch[level]->GetName();
350  }
351  return fPath.Data();
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Push current state into heap.
356 
357 Int_t TGeoNodeCache::PushState(Bool_t ovlp, Int_t startlevel, Int_t nmany, Double_t *point)
358 {
359  if (fStackLevel>=fGeoCacheStackSize) {
360  for (Int_t ist=0; ist<fGeoCacheStackSize; ist++)
361  fStack->Add(new TGeoCacheState(fGeoCacheMaxLevels));
362  }
363  ((TGeoCacheState*)fStack->At(fStackLevel))->SetState(fLevel,startlevel,nmany,ovlp,point);
364  return ++fStackLevel;
365 }
366 
367 ////////////////////////////////////////////////////////////////////////////////
368 /// Pop next state/point from heap.
369 
370 Bool_t TGeoNodeCache::PopState(Int_t &nmany, Double_t *point)
371 {
372  if (!fStackLevel) return 0;
373  Bool_t ovlp = ((TGeoCacheState*)fStack->At(--fStackLevel))->GetState(fLevel,nmany,point);
374  Refresh();
375 // return (fStackLevel+1);
376  return ovlp;
377 }
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// Pop next state/point from heap and restore matrices starting from LEVEL.
381 
382 Bool_t TGeoNodeCache::PopState(Int_t &nmany, Int_t level, Double_t *point)
383 {
384  if (level<=0) return 0;
385  Bool_t ovlp = ((TGeoCacheState*)fStack->At(level-1))->GetState(fLevel,nmany,point);
386  Refresh();
387  return ovlp;
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 /// Pop next state/point from a backed-up state.
392 
393 Bool_t TGeoNodeCache::RestoreState(Int_t &nmany, TGeoCacheState *state, Double_t *point)
394 {
395  Bool_t ovlp = state->GetState(fLevel,nmany,point);
396  Refresh();
397  return ovlp;
398 }
399 
400 ////////////////////////////////////////////////////////////////////////////////
401 /// Local point converted to master frame defined by current matrix.
402 
403 void TGeoNodeCache::LocalToMaster(const Double_t *local, Double_t *master) const
404 {
405  fMatrix->LocalToMaster(local, master);
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// Point in master frame defined by current matrix converted to local one.
410 
411 void TGeoNodeCache::MasterToLocal(const Double_t *master, Double_t *local) const
412 {
413  fMatrix->MasterToLocal(master, local);
414 }
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// Local vector converted to master frame defined by current matrix.
418 
419 void TGeoNodeCache::LocalToMasterVect(const Double_t *local, Double_t *master) const
420 {
421  fMatrix->LocalToMasterVect(local, master);
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Vector in master frame defined by current matrix converted to local one.
426 
427 void TGeoNodeCache::MasterToLocalVect(const Double_t *master, Double_t *local) const
428 {
429  fMatrix->MasterToLocalVect(master,local);
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// Local point converted to master frame defined by current matrix and rescaled with bomb factor.
434 
435 void TGeoNodeCache::LocalToMasterBomb(const Double_t *local, Double_t *master) const
436 {
437  fMatrix->LocalToMasterBomb(local, master);
438 }
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Point in master frame defined by current matrix converted to local one and rescaled with bomb factor.
442 
443 void TGeoNodeCache::MasterToLocalBomb(const Double_t *master, Double_t *local) const
444 {
445  fMatrix->MasterToLocalBomb(master, local);
446 }
447 
448 ClassImp(TGeoCacheState);
449 
450 /** \class TGeoCacheState
451 \ingroup Geometry_classes
452 
453 Class storing the state of the cache at a given moment
454 
455 */
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Default ctor.
459 
460 TGeoCacheState::TGeoCacheState()
461 {
462  fCapacity = 0;
463  fLevel = 0;
464  fNmany = 0;
465  fStart = 0;
466  memset(fIdBranch, 0, 30*sizeof(Int_t));
467  memset(fPoint, 0, 3*sizeof(Int_t));
468  fOverlapping = kFALSE;
469  fNodeBranch = 0;
470  fMatrixBranch = 0;
471  fMatPtr = 0;
472 }
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Ctor.
476 
477 TGeoCacheState::TGeoCacheState(Int_t capacity)
478 {
479  fCapacity = capacity;
480  fLevel = 0;
481  fNmany = 0;
482  fStart = 0;
483  memset(fIdBranch, 0, 30*sizeof(Int_t));
484  memset(fPoint, 0, 3*sizeof(Int_t));
485  fOverlapping = kFALSE;
486  fNodeBranch = new TGeoNode *[capacity];
487  fMatrixBranch = new TGeoHMatrix *[capacity];
488  fMatPtr = new TGeoHMatrix *[capacity];
489  for (Int_t i=0; i<capacity; i++) {
490  fMatrixBranch[i] = new TGeoHMatrix("global");
491  fNodeBranch[i] = 0;
492  }
493 }
494 
495 ////////////////////////////////////////////////////////////////////////////////
496 ///copy constructor
497 
498 TGeoCacheState::TGeoCacheState(const TGeoCacheState& gcs) :
499  TObject(gcs),
500  fCapacity(gcs.fCapacity),
501  fLevel(gcs.fLevel),
502  fNmany(gcs.fNmany),
503  fStart(gcs.fStart),
504  fOverlapping(gcs.fOverlapping)
505 {
506  Int_t i;
507  for (i=0; i<3; i++) fPoint[i]=gcs.fPoint[i];
508  for(i=0; i<30; i++) fIdBranch[i]=gcs.fIdBranch[i];
509  fNodeBranch = new TGeoNode *[fCapacity];
510  fMatrixBranch = new TGeoHMatrix *[fCapacity];
511  fMatPtr = new TGeoHMatrix *[fCapacity];
512  for (i=0; i<fCapacity; i++) {
513  fNodeBranch[i] = gcs.fNodeBranch[i];
514  fMatrixBranch[i] = new TGeoHMatrix(*gcs.fMatrixBranch[i]);
515  fMatPtr[i] = gcs.fMatPtr[i];
516  }
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 ///assignment operator
521 
522 TGeoCacheState& TGeoCacheState::operator=(const TGeoCacheState& gcs)
523 {
524  Int_t i;
525  if(this!=&gcs) {
526  TObject::operator=(gcs);
527  fCapacity=gcs.fCapacity;
528  fLevel=gcs.fLevel;
529  fNmany=gcs.fNmany;
530  fStart=gcs.fStart;
531  for(i=0; i<30; i++) fIdBranch[i]=gcs.fIdBranch[i];
532  for(i=0; i<3; i++) fPoint[i]=gcs.fPoint[i];
533  fOverlapping=gcs.fOverlapping;
534  fNodeBranch = new TGeoNode *[fCapacity];
535  fMatrixBranch = new TGeoHMatrix *[fCapacity];
536  fMatPtr = new TGeoHMatrix *[fCapacity];
537  for (i=0; i<fCapacity; i++) {
538  fNodeBranch[i] = gcs.fNodeBranch[i];
539  fMatrixBranch[i] = new TGeoHMatrix(*gcs.fMatrixBranch[i]);
540  fMatPtr[i] = gcs.fMatPtr[i];
541  }
542  }
543  return *this;
544 }
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 /// Dtor.
548 
549 TGeoCacheState::~TGeoCacheState()
550 {
551  if (fNodeBranch) {
552  for (Int_t i=0; i<fCapacity; i++) {
553  delete fMatrixBranch[i];
554  }
555  delete [] fNodeBranch;
556  delete [] fMatrixBranch;
557  delete [] fMatPtr;
558  }
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Fill current modeller state.
563 
564 void TGeoCacheState::SetState(Int_t level, Int_t startlevel, Int_t nmany, Bool_t ovlp, Double_t *point)
565 {
566  fLevel = level;
567  fStart = startlevel;
568  fNmany = nmany;
569  TGeoNodeCache *cache = gGeoManager->GetCache();
570  if (cache->HasIdArray()) memcpy(fIdBranch, cache->GetIdBranch()+fStart, (level+1-fStart)*sizeof(Int_t));
571  TGeoNode **node_branch = (TGeoNode **) cache->GetBranch();
572  TGeoHMatrix **mat_branch = (TGeoHMatrix **) cache->GetMatrices();
573  Int_t nelem = level+1-fStart;
574  memcpy(fNodeBranch, node_branch+fStart, nelem*sizeof(TGeoNode *));
575  memcpy(fMatPtr, mat_branch+fStart, nelem*sizeof(TGeoHMatrix *));
576  TGeoHMatrix *last = 0;
577  TGeoHMatrix *current;
578  for (Int_t i=0; i<nelem; i++) {
579  current = mat_branch[i+fStart];
580  if (current == last) continue;
581  *fMatrixBranch[i] = current;
582  last = current;
583  }
584  fOverlapping = ovlp;
585  if (point) memcpy(fPoint, point, 3*sizeof(Double_t));
586 }
587 
588 ////////////////////////////////////////////////////////////////////////////////
589 /// Restore a modeler state.
590 
591 Bool_t TGeoCacheState::GetState(Int_t &level, Int_t &nmany, Double_t *point) const
592 {
593  level = fLevel;
594  nmany = fNmany;
595  TGeoNodeCache *cache = gGeoManager->GetCache();
596  if (cache->HasIdArray()) cache->FillIdBranch(fIdBranch, fStart);
597  TGeoNode **node_branch = (TGeoNode **) cache->GetBranch();
598  TGeoHMatrix **mat_branch = (TGeoHMatrix **) cache->GetMatrices();
599  Int_t nelem = level+1-fStart;
600  memcpy(node_branch+fStart, fNodeBranch, nelem*sizeof(TGeoNode *));
601  memcpy(mat_branch+fStart, fMatPtr, (level+1-fStart)*sizeof(TGeoHMatrix *));
602  TGeoHMatrix *last = 0;
603  TGeoHMatrix *current;
604  for (Int_t i=0; i<nelem; i++) {
605  current = mat_branch[i+fStart];
606  if (current == last) continue;
607  *current = fMatrixBranch[i];
608  last = current;
609  }
610  if (point) memcpy(point, fPoint, 3*sizeof(Double_t));
611  return fOverlapping;
612 }