Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoBranchArray.cxx
Go to the documentation of this file.
1 // @(#):$Id$
2 // Author: Andrei Gheata 01/03/11
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 /** \class TGeoBranchArray
13 \ingroup Geometry_classes
14 
15 An array of daughter indices making a geometry path. Can be used to
16 backup/restore a state. Allocated contiguously in memory.
17 
18 To setup an object of this type, one should use:
19 
20 ~~~ {.cpp}
21  TGeoBranchArray *array = new TGeoBranchArray(level);
22  array->InitFromNavigator(nav); // To initialize from current navigator state
23 ~~~
24 
25 The navigator can be updated to reflect this path array: `array->UpdateNavigator();`
26 */
27 
28 #include "TGeoBranchArray.h"
29 
30 #include "TMath.h"
31 #include "TString.h"
32 #include "TGeoNavigator.h"
33 #include "TGeoCache.h"
34 #include "TGeoManager.h"
35 
36 ClassImp(TGeoBranchArray);
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Constructor. Allocates the array with a size given by level.
40 
41 TGeoBranchArray::TGeoBranchArray(Int_t maxlevel)
42  :fLevel(-1),
43  fMaxLevel(maxlevel),
44  fMatrix(),
45  fArray(&fRealArray[0])
46 {
47  memset(fRealArray, 0, fMaxLevel*sizeof(TGeoNode*));
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Make an instance of the class which allocates the node array. To be
52 /// released using ReleaseInstance. If addr is non-zero, the user promised that
53 /// addr contains at least that many bytes: size_t needed = SizeOf(maxlevel);
54 
55 TGeoBranchArray * TGeoBranchArray::MakeInstance(size_t maxlevel)
56 {
57  TGeoBranchArray* ba = 0;
58  size_t needed = SizeOf(maxlevel);
59  char *ptr = new char[ needed ];
60  if (!ptr) return 0;
61  new (ptr) TGeoBranchArray(maxlevel);
62  ba = reinterpret_cast<TGeoBranchArray*>(ptr);
63  ba->SetBit(kBASelfAlloc, kTRUE);
64  return ba;
65 }
66 
67 ////////////////////////////////////////////////////////////////////////////////
68 /// Make an instance of the class which allocates the node array. To be
69 /// released using ReleaseInstance. If addr is non-zero, the user promised that
70 /// addr contains at least that many bytes: size_t needed = SizeOf(maxlevel);
71 
72 TGeoBranchArray * TGeoBranchArray::MakeInstanceAt(size_t maxlevel, void *addr)
73 {
74  TGeoBranchArray* ba = 0;
75  new (addr) TGeoBranchArray(maxlevel);
76  ba = reinterpret_cast<TGeoBranchArray*>(addr);
77  ba->SetBit(kBASelfAlloc, kFALSE);
78  return ba;
79 }
80 
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Make a copy of a branch array at the location (if indicated)
84 
85 TGeoBranchArray * TGeoBranchArray::MakeCopy(const TGeoBranchArray &other)
86 {
87  TGeoBranchArray *copy = 0;
88  size_t needed = SizeOf(other.fMaxLevel);
89  char *ptr = new char[ needed ];
90  if (!ptr) return 0;
91  new (ptr) TGeoBranchArray(other.fMaxLevel);
92  copy = reinterpret_cast<TGeoBranchArray*>(ptr);
93  copy->SetBit(kBASelfAlloc, kTRUE);
94  copy->fLevel = other.fLevel;
95  copy->fMatrix = other.fMatrix;
96  if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
97  return copy;
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Make a copy of a branch array at the location (if indicated)
102 
103 TGeoBranchArray * TGeoBranchArray::MakeCopyAt(const TGeoBranchArray &other, void *addr)
104 {
105  TGeoBranchArray *copy = 0;
106  new (addr) TGeoBranchArray(other.fMaxLevel);
107  copy = reinterpret_cast<TGeoBranchArray*>(addr);
108  copy->SetBit(kBASelfAlloc, kFALSE);
109  copy->fLevel = other.fLevel;
110  copy->fMatrix = other.fMatrix;
111  if (other.fLevel+1) memcpy(copy->fArray, other.fArray, (other.fLevel+1)*sizeof(TGeoNode*));
112  return copy;
113 }
114 
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 /// Raw memcpy of the branch array content to an existing destination.
118 
119 void TGeoBranchArray::CopyTo(TGeoBranchArray *dest)
120 {
121  memcpy(dest->DataStart(), DataStart(), DataSize());
122  dest->fArray = &(dest->fRealArray[0]);
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Releases the space allocated for the object
127 
128 void TGeoBranchArray::ReleaseInstance(TGeoBranchArray *obj)
129 {
130  obj->~TGeoBranchArray();
131  if (obj->TestBit(kBASelfAlloc)) delete [] (char*)obj;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Updates the internal addresses for n contiguous objects which have the same
136 /// fMaxLevel
137 /// Updates the internal addresses for n contiguous objects which have the same fMaxLevel
138 
139 void TGeoBranchArray::UpdateArray(size_t nobj)
140 {
141  size_t needed = SizeOf();
142 // char *where = &fArray;
143 // for (size_t i=0; i<nobj; ++i, where += needed) {
144 // TGeoNode ***array = reinterpret_cast<TGeoNode***>(where);
145 // *array = ((void**)where)+1;
146 // }
147  char *where = reinterpret_cast<char*>(this);
148  for (size_t i=0; i<nobj; ++i, where += needed) {
149  TGeoBranchArray *obj = reinterpret_cast<TGeoBranchArray*>(where);
150  obj->fArray = &(obj->fRealArray[0]);
151  }
152 }
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 /// Copy constructor. Not callable anymore. Use TGeoBranchArray::MakeCopy instead
156 
157 TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray& other)
158  :TObject(other),
159  fLevel(other.fLevel),
160  fMaxLevel(other.fMaxLevel),
161  fMatrix(other.fMatrix),
162  fArray(NULL)
163 {
164  if (fMaxLevel) {
165  fArray = new TGeoNode*[fMaxLevel];
166  if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Assignment. Not valid anymore. Use TGeoBranchArray::MakeCopy instead
172 
173 TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
174 {
175  if (&other == this) return *this;
176  fLevel = other.fLevel;
177  fMatrix.CopyFrom(&other.fMatrix);
178  if (fLevel+1) memcpy(fArray, other.fArray, (fLevel+1)*sizeof(TGeoNode*));
179  return *this;
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 /// Add and extra daughter to the current path array. No validity check performed !
184 
185 void TGeoBranchArray::AddLevel(Int_t dindex)
186 {
187  if (fLevel<0) {
188  Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
189  return;
190  }
191  if (fLevel>fMaxLevel) {
192  Fatal("AddLevel", "Max level = %d reached\n", fMaxLevel);
193  return;
194  }
195  fLevel++;
196 /*
197  if (fLevel+1>fMaxLevel) {
198  TGeoNode **array = new TGeoNode*[fLevel+1];
199  memcpy(array, fArray, fLevel*sizeof(TGeoNode*));
200  delete [] fArray;
201  fArray = array;
202  }
203 */
204  fArray[fLevel] = fArray[fLevel-1]->GetVolume()->GetNode(dindex);
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// Is equal operator.
209 
210 Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
211 {
212  Int_t value = Compare(&other);
213  if (value==0) return kTRUE;
214  return kFALSE;
215 }
216 
217 ////////////////////////////////////////////////////////////////////////////////
218 /// Not equal operator.
219 
220 Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
221 {
222  Int_t value = Compare(&other);
223  if (value!=0) return kTRUE;
224  return kFALSE;
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Is equal operator.
229 
230 Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
231 {
232  Int_t value = Compare(&other);
233  if (value>0) return kTRUE;
234  return kFALSE;
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Is equal operator.
239 
240 Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
241 {
242  Int_t value = Compare(&other);
243  if (value<0) return kTRUE;
244  return kFALSE;
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Is equal operator.
249 
250 Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
251 {
252  Int_t value = Compare(&other);
253  if (value>=0) return kTRUE;
254  return kFALSE;
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Is equal operator.
259 
260 Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
261 {
262  Int_t value = Compare(&other);
263  if (value<=0) return kTRUE;
264  return kFALSE;
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Binary search in an array of n pointers to branch arrays, to locate value.
269 /// Returns element index or index of nearest element smaller than value
270 
271 Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
272 {
273  Long64_t nabove, nbelow, middle;
274  const TGeoBranchArray *pind;
275  nabove = n+1;
276  nbelow = 0;
277  while(nabove-nbelow > 1) {
278  middle = (nabove+nbelow)/2;
279  pind = array[middle-1];
280  if (*value == *pind) return middle-1;
281  if (*value < *pind) nabove = middle;
282  else nbelow = middle;
283  }
284  return nbelow-1;
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Compare with other object of same type. Returns -1 if this is smaller (first
289 /// smaller array value prevails), 0 if equal (size and values) and 1 if this is
290 /// larger.
291 
292 Int_t TGeoBranchArray::Compare(const TObject *obj) const
293 {
294  Int_t i;
295  TGeoBranchArray *other = (TGeoBranchArray*)obj;
296  Int_t otherLevel = other->GetLevel();
297  Int_t maxLevel = TMath::Min(fLevel, otherLevel);
298  TGeoNode **otherArray = other->GetArray();
299  for (i=0; i<maxLevel+1; i++) {
300  if (fArray[i]==otherArray[i]) continue;
301  if ((Long64_t)fArray[i]<(Long64_t)otherArray[i]) return -1;
302  return 1;
303  }
304  if (fLevel==otherLevel) return 0;
305  if (fLevel<otherLevel) return -1;
306  return 1;
307 }
308 
309 ////////////////////////////////////////////////////////////////////////////////
310 /// Garbage collect the stored matrix.
311 
312 void TGeoBranchArray::CleanMatrix()
313 {
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Init the branch array from an array of nodes, the global matrix for the path and
318 /// the level.
319 
320 void TGeoBranchArray::Init(TGeoNode **branch, TGeoMatrix *global, Int_t level)
321 {
322  fMatrix.CopyFrom(global);
323  if (level>fMaxLevel) {
324  Fatal("Init", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
325  return;
326  }
327  fLevel = level;
328  memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Init the branch array from current navigator state.
333 
334 void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
335 {
336  TGeoNodeCache *cache = nav->GetCache();
337  const TGeoNode **branch = (const TGeoNode**)cache->GetBranch();
338  Int_t level = cache->GetLevel();
339  fMatrix.CopyFrom(cache->GetCurrentMatrix());
340  if (level>fMaxLevel) {
341  Fatal("InitFromNavigator", "Requested level %d exceeds maximum level %d", level+1, fMaxLevel);
342  return;
343  }
344  fLevel = level;
345  memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
346  if (nav->IsOutside()) fLevel = -1;
347 }
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 /// Fill path pointed by the array.
351 
352 void TGeoBranchArray::GetPath(TString &path) const
353 {
354  path = "";
355  if (!fArray || !fArray[0]) return;
356  for (Int_t i=0; i<fLevel+1; i++) {
357  path += "/";
358  path += fArray[i]->GetName();
359  }
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 /// Print branch information
364 
365 void TGeoBranchArray::Print(Option_t *) const
366 {
367  TString path;
368  GetPath(path);
369  printf("branch: %s\n", path.Data());
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Sorting of an array of branch array pointers.
374 
375 void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
376 {
377  for (Int_t i=0; i<n; i++) index[i] = i;
378  if (down)
379  std::sort(index, index + n, compareBAdesc(array));
380  else
381  std::sort(index, index + n, compareBAasc(array));
382 }
383 
384 ////////////////////////////////////////////////////////////////////////////////
385 /// Update the navigator to reflect the branch.
386 /// nav->CdTop();
387 
388 void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
389 {
390  if (fLevel<0) {nav->SetOutside(kTRUE); return;}
391  Int_t matchlev = 0;
392  Int_t navlev = nav->GetLevel();
393  Int_t i;
394  Int_t maxlev = TMath::Min(fLevel, navlev);
395  for (i=1; i<maxlev+1; ++i) {
396  if (fArray[i] != nav->GetMother(navlev-i)) break;
397  matchlev++;
398  }
399  // Go to matching level
400  for (i=0; i<navlev-matchlev; i++) nav->CdUp();
401  for (i=matchlev+1; i<fLevel+1; i++) nav->CdDown(fArray[i]);
402 }