Logo ROOT   6.12/07
Reference Guide
TGeoChecker.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 01/11/01
3 // CheckGeometry(), CheckOverlaps() by Mihaela Gheata
4 
5 /*************************************************************************
6  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
7  * All rights reserved. *
8  * *
9  * For the licensing terms see $ROOTSYS/LICENSE. *
10  * For the list of contributors see $ROOTSYS/README/CREDITS. *
11  *************************************************************************/
12 
13 /** \class TGeoChecker
14 \ingroup Geometry_classes
15 
16 Geometry checking package.
17 
18 TGeoChecker class provides several geometry checking methods. There are two
19 types of tests that can be performed. One is based on random sampling or
20 ray-tracing and provides a visual check on how navigation methods work for
21 a given geometry. The second actually checks the validity of the geometry
22 definition in terms of overlapping/extruding objects. Both types of checks
23 can be done for a given branch (starting with a given volume) as well as for
24 the geometry as a whole.
25 
26 #### TGeoChecker::CheckPoint(Double_t x, Double_t y, Double_t z)
27 
28 This method can be called directly from the TGeoManager class and print a
29 report on how a given point is classified by the modeller: which is the
30 full path to the deepest node containing it, and the (under)estimation
31 of the distance to the closest boundary (safety).
32 
33 #### TGeoChecker::RandomPoints(Int_t npoints)
34 
35 Can be called from TGeoVolume class. It first draws the volume and its
36 content with the current visualization settings. Then randomly samples points
37 in its bounding box, plotting in the geometry display only the points
38 classified as belonging to visible volumes.
39 
40 #### TGeoChecker::RandomRays(Int_t nrays, Double_t startx, starty, startz)
41 
42 Can be called and acts in the same way as the previous, but instead of points,
43 rays having random isotropic directions are generated from the given point.
44 A raytracing algorithm propagates all rays until they exit geometry, plotting
45 all segments crossing visible nodes in the same color as these.
46 
47 #### TGeoChecker::Test(Int_t npoints)
48 
49 Implementation of TGeoManager::Test(). Computes the time for the modeller
50 to find out "Where am I?" for a given number of random points.
51 
52 #### TGeoChecker::LegoPlot(ntheta, themin, themax, nphi, phimin, phimax,...)
53 
54 Implementation of TGeoVolume::LegoPlot(). Draws a spherical radiation length
55 lego plot for a given volume, in a given theta/phi range.
56 
57 #### TGeoChecker::Weight(Double_t precision)
58 
59 Implementation of TGeoVolume::Weight(). Estimates the total weight of a given
60 volume by material sampling. Accepts as input the desired precision.
61 */
62 
63 #include "TVirtualPad.h"
64 #include "TCanvas.h"
65 #include "TStyle.h"
66 #include "TFile.h"
67 #include "TNtuple.h"
68 #include "TH2.h"
69 #include "TRandom3.h"
70 #include "TPolyMarker3D.h"
71 #include "TPolyLine3D.h"
72 #include "TStopwatch.h"
73 
74 #include "TGeoVoxelFinder.h"
75 #include "TGeoBBox.h"
76 #include "TGeoPcon.h"
77 #include "TGeoManager.h"
78 #include "TGeoOverlap.h"
79 #include "TGeoPainter.h"
80 #include "TGeoChecker.h"
81 
82 #include "TBuffer3D.h"
83 #include "TBuffer3DTypes.h"
84 #include "TMath.h"
85 
86 #include <stdlib.h>
87 
88 // statics and globals
89 
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 /// Default constructor
94 
96  :TObject(),
97  fGeoManager(NULL),
98  fVsafe(NULL),
99  fBuff1(NULL),
100  fBuff2(NULL),
101  fFullCheck(kFALSE),
102  fVal1(NULL),
103  fVal2(NULL),
104  fFlags(NULL),
105  fTimer(NULL),
106  fSelectedNode(NULL),
107  fNchecks(0),
108  fNmeshPoints(1000)
109 {
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Constructor for a given geometry
114 
116  :TObject(),
117  fGeoManager(geom),
118  fVsafe(NULL),
119  fBuff1(NULL),
120  fBuff2(NULL),
122  fVal1(NULL),
123  fVal2(NULL),
124  fFlags(NULL),
125  fTimer(NULL),
126  fSelectedNode(NULL),
127  fNchecks(0),
128  fNmeshPoints(1000)
129 {
130  fBuff1 = new TBuffer3D(TBuffer3DTypes::kGeneric,500,3*500,0,0,0,0);
131  fBuff2 = new TBuffer3D(TBuffer3DTypes::kGeneric,500,3*500,0,0,0,0);
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Destructor
136 
138 {
139  if (fBuff1) delete fBuff1;
140  if (fBuff2) delete fBuff2;
141  if (fTimer) delete fTimer;
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 /// Print current operation progress.
146 
147 void TGeoChecker::OpProgress(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch, Bool_t last, Bool_t refresh, const char *msg)
148 {
149  static Long64_t icount = 0;
150  static TString oname;
151  static TString nname;
152  static Long64_t ocurrent = 0;
153  static Long64_t osize = 0;
154  static Int_t oseconds = 0;
155  static TStopwatch *owatch = 0;
156  static Bool_t oneoftwo = kFALSE;
157  static Int_t nrefresh = 0;
158  const char symbol[4] = {'=','\\','|','/'};
159  char progress[11] = " ";
160  Int_t ichar = icount%4;
161  TString message(msg);
162  message += " ";
163 
164  if (!refresh) {
165  nrefresh = 0;
166  if (!size) return;
167  owatch = watch;
168  oname = opname;
169  ocurrent = TMath::Abs(current);
170  osize = TMath::Abs(size);
171  if (ocurrent > osize) ocurrent=osize;
172  } else {
173  nrefresh++;
174  if (!osize) return;
175  }
176  icount++;
177  Double_t time = 0.;
178  Int_t hours = 0;
179  Int_t minutes = 0;
180  Int_t seconds = 0;
181  if (owatch && !last) {
182  owatch->Stop();
183  time = owatch->RealTime();
184  hours = (Int_t)(time/3600.);
185  time -= 3600*hours;
186  minutes = (Int_t)(time/60.);
187  time -= 60*minutes;
188  seconds = (Int_t)time;
189  if (refresh) {
190  if (oseconds==seconds) {
191  owatch->Continue();
192  return;
193  }
194  oneoftwo = !oneoftwo;
195  }
196  oseconds = seconds;
197  }
198  if (refresh && oneoftwo) {
199  nname = oname;
200  if (fNchecks <= nrefresh) fNchecks = nrefresh+1;
201  Int_t pctdone = (Int_t)(100.*nrefresh/fNchecks);
202  oname = TString::Format(" == %3d%% ==", pctdone);
203  }
204  Double_t percent = 100.0*ocurrent/osize;
205  Int_t nchar = Int_t(percent/10);
206  if (nchar>10) nchar=10;
207  Int_t i;
208  for (i=0; i<nchar; i++) progress[i] = '=';
209  progress[nchar] = symbol[ichar];
210  for (i=nchar+1; i<10; i++) progress[i] = ' ';
211  progress[10] = '\0';
212  oname += " ";
213  oname.Remove(20);
214  if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
215  else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
216  else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
217  if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d %s\r", percent, hours, minutes, seconds, message.Data());
218  else fprintf(stderr, "[%6.2f %%] %s\r", percent, message.Data());
219  if (refresh && oneoftwo) oname = nname;
220  if (owatch) owatch->Continue();
221  if (last) {
222  icount = 0;
223  owatch = 0;
224  ocurrent = 0;
225  osize = 0;
226  oseconds = 0;
227  oneoftwo = kFALSE;
228  nrefresh = 0;
229  fprintf(stderr, "\n");
230  }
231 }
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// Check pushes and pulls needed to cross the next boundary with respect to the
235 /// position given by FindNextBoundary. If radius is not mentioned the full bounding
236 /// box will be sampled.
237 
239 {
241  Info("CheckBoundaryErrors", "Top volume is %s",tvol->GetName());
242  const TGeoShape *shape = tvol->GetShape();
243  TGeoBBox *box = (TGeoBBox *)shape;
244  Double_t dl[3];
245  Double_t ori[3];
246  Double_t xyz[3];
247  Double_t nxyz[3];
248  Double_t dir[3];
249  Double_t relp;
250  Char_t path[1024];
251  Char_t cdir[10];
252 
253  // Tree part
254  TFile *f=new TFile("geobugs.root","recreate");
255  TTree *bug=new TTree("bug","Geometrical problems");
256  bug->Branch("pos",xyz,"xyz[3]/D");
257  bug->Branch("dir",dir,"dir[3]/D");
258  bug->Branch("push",&relp,"push/D");
259  bug->Branch("path",&path,"path/C");
260  bug->Branch("cdir",&cdir,"cdir/C");
261 
262  dl[0] = box->GetDX();
263  dl[1] = box->GetDY();
264  dl[2] = box->GetDZ();
265  ori[0] = (box->GetOrigin())[0];
266  ori[1] = (box->GetOrigin())[1];
267  ori[2] = (box->GetOrigin())[2];
268  if (radius>0)
269  dl[0] = dl[1] = dl[2] = radius;
270 
272  TH1F *hnew = new TH1F("hnew","Precision pushing",30,-20.,10.);
273  TH1F *hold = new TH1F("hold","Precision pulling", 30,-20.,10.);
274  TH2F *hplotS = new TH2F("hplotS","Problematic points",100,-dl[0],dl[0],100,-dl[1],dl[1]);
275  gStyle->SetOptStat(111111);
276 
277  TGeoNode *node = 0;
278  Long_t igen=0;
279  Long_t itry=0;
280  Long_t n100 = ntracks/100;
281  Double_t rad = TMath::Sqrt(dl[0]*dl[0]+dl[1]*dl[1]);
282  printf("Random box : %f, %f, %f, %f, %f, %f\n", ori[0], ori[1], ori[2], dl[0], dl[1], dl[2]);
283  printf("Start... %i points\n", ntracks);
284  if (!fTimer) fTimer = new TStopwatch();
285  fTimer->Reset();
286  fTimer->Start();
287  while (igen<ntracks) {
288  Double_t phi1 = TMath::TwoPi()*gRandom->Rndm();
289  Double_t r = rad*gRandom->Rndm();
290  xyz[0] = ori[0] + r*TMath::Cos(phi1);
291  xyz[1] = ori[1] + r*TMath::Sin(phi1);
292  Double_t z = (1.-2.*gRandom->Rndm());
293  xyz[2] = ori[2]+dl[2]*z*TMath::Abs(z);
294  ++itry;
296  node = fGeoManager->FindNode();
297  if (!node || node==fGeoManager->GetTopNode()) continue;
298  ++igen;
299  if (n100 && !(igen%n100))
300  OpProgress("Sampling progress:",igen, ntracks, fTimer);
301  Double_t cost = 1.-2.*gRandom->Rndm();
302  Double_t sint = TMath::Sqrt((1.+cost)*(1.-cost));
303  Double_t phi = TMath::TwoPi()*gRandom->Rndm();
304  dir[0] = sint * TMath::Cos(phi);
305  dir[1] = sint * TMath::Sin(phi);
306  dir[2] = cost;
309  Double_t step = fGeoManager->GetStep();
310 
311  relp = 1.e-21;
312  for(Int_t i=0; i<30; ++i) {
313  relp *=10.;
314  for(Int_t j=0; j<3; ++j) nxyz[j]=xyz[j]+step*(1.+relp)*dir[j];
315  if(!fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2])) {
316  hnew->Fill(i-20.);
317  if(i>15) {
318  const Double_t* norm = fGeoManager->FindNormal();
319  strncpy(path,fGeoManager->GetPath(),1024);
320  path[1023] = '\0';
321  Double_t dotp = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
322  printf("Forward error i=%d p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
323  i,xyz[0],xyz[1],xyz[2],step,dotp,path);
324  hplotS->Fill(xyz[0],xyz[1],(Double_t)i);
325  strncpy(cdir,"Forward",10);
326  bug->Fill();
327  }
328  break;
329  }
330  }
331 
332  relp = -1.e-21;
333  for(Int_t i=0; i<30; ++i) {
334  relp *=10.;
335  for(Int_t j=0; j<3; ++j) nxyz[j]=xyz[j]+step*(1.+relp)*dir[j];
336  if(fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2])) {
337  hold->Fill(i-20.);
338  if(i>15) {
339  const Double_t* norm = fGeoManager->FindNormal();
340  strncpy(path,fGeoManager->GetPath(),1024);
341  path[1023] = '\0';
342  Double_t dotp = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
343  printf("Backward error i=%d p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
344  i,xyz[0],xyz[1],xyz[2],step,dotp,path);
345  strncpy(cdir,"Backward",10);
346  bug->Fill();
347  }
348  break;
349  }
350  }
351  }
352  fTimer->Stop();
353 
354  if (itry) printf("CPU time/point = %5.2emus: Real time/point = %5.2emus\n",
355  1000000.*fTimer->CpuTime()/itry,1000000.*fTimer->RealTime()/itry);
356  bug->Write();
357  delete bug;
358  bug=0;
359  delete f;
360 
362 
363  if (itry) printf("Effic = %3.1f%%\n",(100.*igen)/itry);
364  TCanvas *c1 = new TCanvas("c1","Results",600,800);
365  c1->Divide(1,2);
366  c1->cd(1);
367  gPad->SetLogy();
368  hold->Draw();
369  c1->cd(2);
370  gPad->SetLogy();
371  hnew->Draw();
372  /*TCanvas *c3 = */new TCanvas("c3","Plot",600,600);
373  hplotS->Draw("cont0");
374 }
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 /// Check the boundary errors reference file created by CheckBoundaryErrors method.
378 /// The shape for which the crossing failed is drawn with the starting point in red
379 /// and the extrapolated point to boundary (+/- failing push/pull) in yellow.
380 
382 {
383  Double_t xyz[3];
384  Double_t nxyz[3];
385  Double_t dir[3];
386  Double_t lnext[3];
387  Double_t push;
388  Char_t path[1024];
389  Char_t cdir[10];
390  // Tree part
391  TFile *f=new TFile("geobugs.root","read");
392  TTree *bug=(TTree*)f->Get("bug");
393  bug->SetBranchAddress("pos",xyz);
394  bug->SetBranchAddress("dir",dir);
395  bug->SetBranchAddress("push",&push);
396  bug->SetBranchAddress("path",&path);
397  bug->SetBranchAddress("cdir",&cdir);
398 
399  Int_t nentries = (Int_t)bug->GetEntries();
400  printf("nentries %d\n",nentries);
401  if (icheck<0) {
402  for (Int_t i=0;i<nentries;i++) {
403  bug->GetEntry(i);
404  printf("%-9s error push=%g p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
405  cdir,push,xyz[0],xyz[1],xyz[2],1.,1.,path);
406  }
407  } else {
408  if (icheck>=nentries) return;
411  bug->GetEntry(icheck);
412  printf("%-9s error push=%g p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
413  cdir,push,xyz[0],xyz[1],xyz[2],1.,1.,path);
418  Double_t step = fGeoManager->GetStep();
419  for (Int_t j=0; j<3; j++) nxyz[j]=xyz[j]+step*(1.+0.1*push)*dir[j];
420  Bool_t change = !fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2]);
421  printf("step=%g in: %s\n", step, fGeoManager->GetPath());
422  printf(" -> next = %s push=%g change=%d\n", next->GetName(),push, (UInt_t)change);
423  next->GetVolume()->InspectShape();
424  next->GetVolume()->DrawOnly();
425  if (next != fGeoManager->GetCurrentNode()) {
426  Int_t index1 = fGeoManager->GetCurrentVolume()->GetIndex(next);
427  if (index1>=0) fGeoManager->CdDown(index1);
428  }
429  TPolyMarker3D *pm = new TPolyMarker3D();
430  fGeoManager->MasterToLocal(xyz, lnext);
431  pm->SetNextPoint(lnext[0], lnext[1], lnext[2]);
432  pm->SetMarkerStyle(2);
433  pm->SetMarkerSize(0.2);
434  pm->SetMarkerColor(kRed);
435  pm->Draw("SAME");
436  TPolyMarker3D *pm1 = new TPolyMarker3D();
437  for (Int_t j=0; j<3; j++) nxyz[j]=xyz[j]+step*dir[j];
438  fGeoManager->MasterToLocal(nxyz, lnext);
439  pm1->SetNextPoint(lnext[0], lnext[1], lnext[2]);
440  pm1->SetMarkerStyle(2);
441  pm1->SetMarkerSize(0.2);
442  pm1->SetMarkerColor(kYellow);
443  pm1->Draw("SAME");
445  }
446  delete bug;
447  delete f;
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Geometry checking. Optional overlap checkings (by sampling and by mesh). Optional
452 /// boundary crossing check + timing per volume.
453 ///
454 /// STAGE 1: extensive overlap checking by sampling per volume. Stdout need to be
455 /// checked by user to get report, then TGeoVolume::CheckOverlaps(0.01, "s") can
456 /// be called for the suspicious volumes.
457 ///
458 /// STAGE 2: normal overlap checking using the shapes mesh - fills the list of
459 /// overlaps.
460 ///
461 /// STAGE 3: shooting NRAYS rays from VERTEX and counting the total number of
462 /// crossings per volume (rays propagated from boundary to boundary until
463 /// geometry exit). Timing computed and results stored in a histo.
464 ///
465 /// STAGE 4: shooting 1 mil. random rays inside EACH volume and calling
466 /// FindNextBoundary() + Safety() for each call. The timing is normalized by the
467 /// number of crossings computed at stage 2 and presented as percentage.
468 /// One can get a picture on which are the most "burned" volumes during
469 /// transportation from geometry point of view. Another plot of the timing per
470 /// volume vs. number of daughters is produced.
471 ///
472 /// All histos are saved in the file statistics.root
473 
474 void TGeoChecker::CheckGeometryFull(Bool_t checkoverlaps, Bool_t checkcrossings, Int_t ntracks, const Double_t *vertex)
475 {
477  if (!fTimer) fTimer = new TStopwatch();
478  Int_t i;
479  Double_t value;
480  fFlags = new Bool_t[nuid];
481  memset(fFlags, 0, nuid*sizeof(Bool_t));
482  TGeoVolume *vol;
483  TCanvas *c = new TCanvas("overlaps", "Overlaps by sampling", 800,800);
484 
485 // STAGE 1: Overlap checking by sampling per volume
486  if (checkoverlaps) {
487  printf("====================================================================\n");
488  printf("STAGE 1: Overlap checking by sampling within 10 microns\n");
489  printf("====================================================================\n");
490  fGeoManager->CheckOverlaps(0.001, "s");
491 
492  // STAGE 2: Global overlap/extrusion checking
493  printf("====================================================================\n");
494  printf("STAGE 2: Global overlap/extrusion checking within 10 microns\n");
495  printf("====================================================================\n");
496  fGeoManager->CheckOverlaps(0.001);
497  }
498 
499  if (!checkcrossings) {
500  delete [] fFlags;
501  fFlags = 0;
502  delete c;
503  return;
504  }
505 
506  fVal1 = new Double_t[nuid];
507  fVal2 = new Double_t[nuid];
508  memset(fVal1, 0, nuid*sizeof(Double_t));
509  memset(fVal2, 0, nuid*sizeof(Double_t));
510  // STAGE 3: How many crossings per volume in a realistic case ?
511  // Ignore volumes with no daughters
512 
513  // Generate rays from vertex in phi=[0,2*pi] theta=[0,pi]
514 // Int_t ntracks = 1000000;
515  printf("====================================================================\n");
516  printf("STAGE 3: Propagating %i tracks starting from vertex\n and counting number of boundary crossings...\n", ntracks);
517  printf("====================================================================\n");
518  Int_t nbound = 0;
519  Double_t theta, phi;
520  Double_t point[3], dir[3];
521  memset(point, 0, 3*sizeof(Double_t));
522  if (vertex) memcpy(point, vertex, 3*sizeof(Double_t));
523 
524  fTimer->Reset();
525  fTimer->Start();
526  for (i=0; i<ntracks; i++) {
527  phi = 2.*TMath::Pi()*gRandom->Rndm();
528  theta= TMath::ACos(1.-2.*gRandom->Rndm());
529  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
530  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
531  dir[2]=TMath::Cos(theta);
532  if ((i%100)==0) OpProgress("Transporting tracks",i, ntracks, fTimer);
533 // if ((i%1000)==0) printf("... remaining tracks %i\n", ntracks-i);
534  nbound += PropagateInGeom(point,dir);
535  }
536  if (!nbound) {
537  printf("No boundary crossed\n");
538  return;
539  }
540  fTimer->Stop();
541  Double_t time1 = fTimer->CpuTime() *1.E6;
542  Double_t time2 = time1/ntracks;
543  Double_t time3 = time1/nbound;
544  OpProgress("Transporting tracks",ntracks, ntracks, fTimer, kTRUE);
545  printf("Time for crossing %i boundaries: %g [ms]\n", nbound, time1);
546  printf("Time per track for full geometry traversal: %g [ms], per crossing: %g [ms]\n", time2, time3);
547 
548 // STAGE 4: How much time per volume:
549 
550  printf("====================================================================\n");
551  printf("STAGE 4: How much navigation time per volume per next+safety call\n");
552  printf("====================================================================\n");
554  TGeoNode*current;
555  TString path;
556  vol = fGeoManager->GetTopVolume();
557  memset(fFlags, 0, nuid*sizeof(Bool_t));
558  TStopwatch timer;
559  timer.Start();
560  i = 0;
561  char volname[30];
562  strncpy(volname, vol->GetName(),15);
563  volname[15] = '\0';
564  OpProgress(volname,i++, nuid, &timer);
565  Score(vol, 1, TimingPerVolume(vol));
566  while ((current=next())) {
567  vol = current->GetVolume();
568  Int_t uid = vol->GetNumber();
569  if (fFlags[uid]) continue;
570  fFlags[uid] = kTRUE;
571  next.GetPath(path);
572  fGeoManager->cd(path.Data());
573  strncpy(volname, vol->GetName(),15);
574  volname[15] = '\0';
575  OpProgress(volname,i++, nuid, &timer);
576  Score(vol,1,TimingPerVolume(vol));
577  }
578  OpProgress("STAGE 4 completed",i, nuid, &timer, kTRUE);
579  // Draw some histos
580  Double_t time_tot_pertrack = 0.;
581  TCanvas *c1 = new TCanvas("c2","ncrossings",10,10,900,500);
582  c1->SetGrid();
583  c1->SetTopMargin(0.15);
584  TFile *f = new TFile("statistics.root", "RECREATE");
585  TH1F *h = new TH1F("h","number of boundary crossings per volume",3,0,3);
586  h->SetStats(0);
587  h->SetFillColor(38);
589 
590  memset(fFlags, 0, nuid*sizeof(Bool_t));
591  for (i=0; i<nuid; i++) {
592  vol = fGeoManager->GetVolume(i);
593  if (!vol->GetNdaughters()) continue;
594  time_tot_pertrack += fVal1[i]*fVal2[i];
595  h->Fill(vol->GetName(), (Int_t)fVal1[i]);
596  }
597  time_tot_pertrack /= ntracks;
598  h->LabelsDeflate();
599  h->LabelsOption(">","X");
600  h->Draw();
601 
602 
603  TCanvas *c2 = new TCanvas("c3","time spent per volume in navigation",10,10,900,500);
604  c2->SetGrid();
605  c2->SetTopMargin(0.15);
606  TH2F *h2 = new TH2F("h2", "time per FNB call vs. ndaughters", 100, 0,100,100,0,15);
607  h2->SetStats(0);
608  h2->SetMarkerStyle(2);
609  TH1F *h1 = new TH1F("h1","percent of time spent per volume",3,0,3);
610  h1->SetStats(0);
611  h1->SetFillColor(38);
613  for (i=0; i<nuid; i++) {
614  vol = fGeoManager->GetVolume(i);
615  if (!vol || !vol->GetNdaughters()) continue;
616  value = fVal1[i]*fVal2[i]/ntracks/time_tot_pertrack;
617  h1->Fill(vol->GetName(), value);
618  h2->Fill(vol->GetNdaughters(), fVal2[i]);
619  }
620  h1->LabelsDeflate();
621  h1->LabelsOption(">","X");
622  h1->Draw();
623  TCanvas *c3 = new TCanvas("c4","timing vs. ndaughters",10,10,900,500);
624  c3->SetGrid();
625  c3->SetTopMargin(0.15);
626  h2->Draw();
627  f->Write();
628  delete [] fFlags;
629  fFlags = 0;
630  delete [] fVal1;
631  fVal1 = 0;
632  delete [] fVal2;
633  fVal2 = 0;
634  delete fTimer;
635  fTimer = 0;
636  delete c;
637 }
638 
639 ////////////////////////////////////////////////////////////////////////////////
640 /// Propagate from START along DIR from boundary to boundary until exiting
641 /// geometry. Fill array of hits.
642 
644 {
645  fGeoManager->InitTrack(start, dir);
646  TGeoNode *current = 0;
647  Int_t nzero = 0;
648  Int_t nhits = 0;
649  while (!fGeoManager->IsOutside()) {
650  if (nzero>3) {
651  // Problems in trying to cross a boundary
652  printf("Error in trying to cross boundary of %s\n", current->GetName());
653  return nhits;
654  }
656  if (!current || fGeoManager->IsOutside()) return nhits;
657  Double_t step = fGeoManager->GetStep();
658  if (step<2.*TGeoShape::Tolerance()) {
659  nzero++;
660  continue;
661  }
662  else nzero = 0;
663  // Generate the hit
664  nhits++;
665  TGeoVolume *vol = current->GetVolume();
666  Score(vol,0,1.);
667  Int_t iup = 1;
668  TGeoNode *mother = fGeoManager->GetMother(iup++);
669  while (mother && mother->GetVolume()->IsAssembly()) {
670  Score(mother->GetVolume(), 0, 1.);
671  mother = fGeoManager->GetMother(iup++);
672  }
673  }
674  return nhits;
675 }
676 
677 ////////////////////////////////////////////////////////////////////////////////
678 /// Score a hit for VOL
679 
680 void TGeoChecker::Score(TGeoVolume *vol, Int_t ifield, Double_t value)
681 {
682  Int_t uid = vol->GetNumber();
683  switch (ifield) {
684  case 0:
685  fVal1[uid] += value;
686  break;
687  case 1:
688  fVal2[uid] += value;
689  }
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 /// Set number of points to be generated on the shape outline when checking for overlaps.
694 
696  fNmeshPoints = npoints;
697  if (npoints<1000) {
698  Error("SetNmeshPoints", "Cannot allow less than 1000 points for checking - set to 1000");
699  fNmeshPoints = 1000;
700  }
701 }
702 
703 ////////////////////////////////////////////////////////////////////////////////
704 /// Compute timing per "FindNextBoundary" + "Safety" call. Volume must be
705 /// in the current path.
706 
708 {
709  fTimer->Reset();
710  const TGeoShape *shape = vol->GetShape();
711  TGeoBBox *box = (TGeoBBox *)shape;
712  Double_t dx = box->GetDX();
713  Double_t dy = box->GetDY();
714  Double_t dz = box->GetDZ();
715  Double_t ox = (box->GetOrigin())[0];
716  Double_t oy = (box->GetOrigin())[1];
717  Double_t oz = (box->GetOrigin())[2];
718  Double_t point[3], dir[3], lpt[3], ldir[3];
719  Double_t pstep = 0.;
720  pstep = TMath::Max(pstep,dz);
721  Double_t theta, phi;
722  Int_t idaughter;
723  fTimer->Start();
724  Bool_t inside;
725  for (Int_t i=0; i<1000000; i++) {
726  lpt[0] = ox-dx+2*dx*gRandom->Rndm();
727  lpt[1] = oy-dy+2*dy*gRandom->Rndm();
728  lpt[2] = oz-dz+2*dz*gRandom->Rndm();
730  fGeoManager->SetCurrentPoint(point[0],point[1],point[2]);
731  phi = 2*TMath::Pi()*gRandom->Rndm();
732  theta= TMath::ACos(1.-2.*gRandom->Rndm());
733  ldir[0]=TMath::Sin(theta)*TMath::Cos(phi);
734  ldir[1]=TMath::Sin(theta)*TMath::Sin(phi);
735  ldir[2]=TMath::Cos(theta);
738  fGeoManager->SetStep(pstep);
740  inside = kTRUE;
741  // dist = TGeoShape::Big();
742  if (!vol->IsAssembly()) {
743  inside = vol->Contains(lpt);
744  if (!inside) {
745  // dist = vol->GetShape()->DistFromOutside(lpt,ldir,3,pstep);
746  // if (dist>=pstep) continue;
747  } else {
748  vol->GetShape()->DistFromInside(lpt,ldir,3,pstep);
749  }
750 
751  if (!vol->GetNdaughters()) vol->GetShape()->Safety(lpt, inside);
752  }
753  if (vol->GetNdaughters()) {
754  fGeoManager->Safety();
755  fGeoManager->FindNextDaughterBoundary(point,dir,idaughter,kFALSE);
756  }
757  }
758  fTimer->Stop();
759  Double_t time_per_track = fTimer->CpuTime();
760  Int_t uid = vol->GetNumber();
761  Int_t ncrossings = (Int_t)fVal1[uid];
762  if (!vol->GetNdaughters())
763  printf("Time for volume %s (shape=%s): %g [ms] ndaughters=%d ncross=%d\n", vol->GetName(), vol->GetShape()->GetName(), time_per_track, vol->GetNdaughters(), ncrossings);
764  else
765  printf("Time for volume %s (assemb=%d): %g [ms] ndaughters=%d ncross=%d\n", vol->GetName(), vol->IsAssembly(), time_per_track, vol->GetNdaughters(), ncrossings);
766  return time_per_track;
767 }
768 
769 ////////////////////////////////////////////////////////////////////////////////
770 /// Shoot nrays with random directions from starting point (startx, starty, startz)
771 /// in the reference frame of this volume. Track each ray until exiting geometry, then
772 /// shoot backwards from exiting point and compare boundary crossing points.
773 
774 void TGeoChecker::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
775 {
776  Int_t i, j;
777  Double_t start[3], end[3];
778  Double_t dir[3];
779  Double_t dummy[3];
780  Double_t eps = 0.;
781  Double_t *array1 = new Double_t[3*1000];
782  Double_t *array2 = new Double_t[3*1000];
783  TObjArray *pma = new TObjArray();
784  TPolyMarker3D *pm;
785  pm = new TPolyMarker3D();
786  pm->SetMarkerColor(2); // error > eps
787  pm->SetMarkerStyle(8);
788  pm->SetMarkerSize(0.4);
789  pma->AddAt(pm, 0);
790  pm = new TPolyMarker3D();
791  pm->SetMarkerColor(4); // point not found
792  pm->SetMarkerStyle(8);
793  pm->SetMarkerSize(0.4);
794  pma->AddAt(pm, 1);
795  pm = new TPolyMarker3D();
796  pm->SetMarkerColor(6); // extra point back
797  pm->SetMarkerStyle(8);
798  pm->SetMarkerSize(0.4);
799  pma->AddAt(pm, 2);
800  Int_t nelem1, nelem2;
801  Int_t dim1=1000, dim2=1000;
802  if ((startx==0) && (starty==0) && (startz==0)) eps=1E-3;
803  start[0] = startx+eps;
804  start[1] = starty+eps;
805  start[2] = startz+eps;
806  Int_t n10=nrays/10;
807  Double_t theta,phi;
808  Double_t dw, dwmin, dx, dy, dz;
809  Int_t ist1, ist2, ifound;
810  for (i=0; i<nrays; i++) {
811  if (n10) {
812  if ((i%n10) == 0) printf("%i percent\n", Int_t(100*i/nrays));
813  }
814  phi = 2*TMath::Pi()*gRandom->Rndm();
815  theta= TMath::ACos(1.-2.*gRandom->Rndm());
816  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
817  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
818  dir[2]=TMath::Cos(theta);
819  // shoot direct ray
820  nelem1=nelem2=0;
821 // printf("DIRECT %i\n", i);
822  array1 = ShootRay(&start[0], dir[0], dir[1], dir[2], array1, nelem1, dim1);
823  if (!nelem1) continue;
824 // for (j=0; j<nelem1; j++) printf("%i : %f %f %f\n", j, array1[3*j], array1[3*j+1], array1[3*j+2]);
825  memcpy(&end[0], &array1[3*(nelem1-1)], 3*sizeof(Double_t));
826  // shoot ray backwards
827 // printf("BACK %i\n", i);
828  array2 = ShootRay(&end[0], -dir[0], -dir[1], -dir[2], array2, nelem2, dim2, &start[0]);
829  if (!nelem2) {
830  printf("#### NOTHING BACK ###########################\n");
831  for (j=0; j<nelem1; j++) {
832  pm = (TPolyMarker3D*)pma->At(0);
833  pm->SetNextPoint(array1[3*j], array1[3*j+1], array1[3*j+2]);
834  }
835  continue;
836  }
837 // printf("BACKWARDS\n");
838  Int_t k=nelem2>>1;
839  for (j=0; j<k; j++) {
840  memcpy(&dummy[0], &array2[3*j], 3*sizeof(Double_t));
841  memcpy(&array2[3*j], &array2[3*(nelem2-1-j)], 3*sizeof(Double_t));
842  memcpy(&array2[3*(nelem2-1-j)], &dummy[0], 3*sizeof(Double_t));
843  }
844 // for (j=0; j<nelem2; j++) printf("%i : %f ,%f ,%f \n", j, array2[3*j], array2[3*j+1], array2[3*j+2]);
845  if (nelem1!=nelem2) printf("### DIFFERENT SIZES : nelem1=%i nelem2=%i ##########\n", nelem1, nelem2);
846  ist1 = ist2 = 0;
847  // check first match
848 
849  dx = array1[3*ist1]-array2[3*ist2];
850  dy = array1[3*ist1+1]-array2[3*ist2+1];
851  dz = array1[3*ist1+2]-array2[3*ist2+2];
852  dw = dx*dir[0]+dy*dir[1]+dz*dir[2];
853  fGeoManager->SetCurrentPoint(&array1[3*ist1]);
855 // printf("%i : %s (%g, %g, %g)\n", ist1, fGeoManager->GetPath(),
856 // array1[3*ist1], array1[3*ist1+1], array1[3*ist1+2]);
857  if (TMath::Abs(dw)<1E-4) {
858 // printf(" matching %i (%g, %g, %g)\n", ist2, array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2]);
859  ist2++;
860  } else {
861  printf("### NOT MATCHING %i f:(%f, %f, %f) b:(%f %f %f) DCLOSE=%f\n", ist2, array1[3*ist1], array1[3*ist1+1], array1[3*ist1+2], array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2],dw);
862  pm = (TPolyMarker3D*)pma->At(0);
863  pm->SetNextPoint(array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2]);
864  if (dw<0) {
865  // first boundary missed on way back
866  } else {
867  // first boundary different on way back
868  ist2++;
869  }
870  }
871 
872  while ((ist1<nelem1-1) && (ist2<nelem2)) {
873  fGeoManager->SetCurrentPoint(&array1[3*ist1+3]);
875 // printf("%i : %s (%g, %g, %g)\n", ist1+1, fGeoManager->GetPath(),
876 // array1[3*ist1+3], array1[3*ist1+4], array1[3*ist1+5]);
877 
878  dx = array1[3*ist1+3]-array1[3*ist1];
879  dy = array1[3*ist1+4]-array1[3*ist1+1];
880  dz = array1[3*ist1+5]-array1[3*ist1+2];
881  // distance to next point
882  dwmin = dx+dir[0]+dy*dir[1]+dz*dir[2];
883  while (ist2<nelem2) {
884  ifound = 0;
885  dx = array2[3*ist2]-array1[3*ist1];
886  dy = array2[3*ist2+1]-array1[3*ist1+1];
887  dz = array2[3*ist2+2]-array1[3*ist1+2];
888  dw = dx+dir[0]+dy*dir[1]+dz*dir[2];
889  if (TMath::Abs(dw-dwmin)<1E-4) {
890  ist1++;
891  ist2++;
892  break;
893  }
894  if (dw<dwmin) {
895  // point found on way back. Check if close enough to ist1+1
896  ifound++;
897  dw = dwmin-dw;
898  if (dw<1E-4) {
899  // point is matching ist1+1
900 // printf(" matching %i (%g, %g, %g) DCLOSE=%g\n", ist2, array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2], dw);
901  ist2++;
902  ist1++;
903  break;
904  } else {
905  // extra boundary found on way back
906  fGeoManager->SetCurrentPoint(&array2[3*ist2]);
908  pm = (TPolyMarker3D*)pma->At(2);
909  pm->SetNextPoint(array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2]);
910  printf("### EXTRA BOUNDARY %i : %s found at DCLOSE=%f\n", ist2, fGeoManager->GetPath(), dw);
911  ist2++;
912  continue;
913  }
914  } else {
915  if (!ifound) {
916  // point ist1+1 not found on way back
917  fGeoManager->SetCurrentPoint(&array1[3*ist1+3]);
919  pm = (TPolyMarker3D*)pma->At(1);
920  pm->SetNextPoint(array2[3*ist1+3], array2[3*ist1+4], array2[3*ist1+5]);
921  printf("### BOUNDARY MISSED BACK #########################\n");
922  ist1++;
923  break;
924  } else {
925  ist1++;
926  break;
927  }
928  }
929  }
930  }
931  }
932  pm = (TPolyMarker3D*)pma->At(0);
933  pm->Draw("SAME");
934  pm = (TPolyMarker3D*)pma->At(1);
935  pm->Draw("SAME");
936  pm = (TPolyMarker3D*)pma->At(2);
937  pm->Draw("SAME");
938  if (gPad) {
939  gPad->Modified();
940  gPad->Update();
941  }
942  delete [] array1;
943  delete [] array2;
944 }
945 
946 ////////////////////////////////////////////////////////////////////////////////
947 /// Clean-up the mesh of pcon/pgon from useless points
948 
950 {
951  Int_t ipoint = 0;
952  Int_t j, k=0;
953  Double_t rsq;
954  for (Int_t i=0; i<numPoints; i++) {
955  j = 3*i;
956  rsq = points[j]*points[j]+points[j+1]*points[j+1];
957  if (rsq < 1.e-10) continue;
958  points[k] = points[j];
959  points[k+1] = points[j+1];
960  points[k+2] = points[j+2];
961  ipoint++;
962  k = 3*ipoint;
963  }
964  numPoints = ipoint;
965 }
966 
967 ////////////////////////////////////////////////////////////////////////////////
968 /// Check if the 2 non-assembly volume candidates overlap/extrude. Returns overlap object.
969 
971 {
972  TGeoOverlap *nodeovlp = 0;
973  Int_t numPoints1 = fBuff1->NbPnts();
974  Int_t numSegs1 = fBuff1->NbSegs();
975  Int_t numPols1 = fBuff1->NbPols();
976  Int_t numPoints2 = fBuff2->NbPnts();
977  Int_t numSegs2 = fBuff2->NbSegs();
978  Int_t numPols2 = fBuff2->NbPols();
979  Int_t ip;
980  Bool_t extrude, isextrusion, isoverlapping;
981  Double_t *points1 = fBuff1->fPnts;
982  Double_t *points2 = fBuff2->fPnts;
983  Double_t local[3], local1[3];
984  Double_t point[3];
985  Double_t safety = TGeoShape::Big();
986  Double_t tolerance = TGeoShape::Tolerance();
987  if (vol1->IsAssembly() || vol2->IsAssembly()) return nodeovlp;
988  TGeoShape *shape1 = vol1->GetShape();
989  TGeoShape *shape2 = vol2->GetShape();
990  OpProgress("refresh", 0,0,NULL,kFALSE,kTRUE);
991  shape1->GetMeshNumbers(numPoints1, numSegs1, numPols1);
992  if (fBuff1->fID != (TObject*)shape1) {
993  // Fill first buffer.
994  fBuff1->SetRawSizes(TMath::Max(numPoints1,fNmeshPoints), 3*TMath::Max(numPoints1,fNmeshPoints), 0, 0, 0, 0);
995  points1 = fBuff1->fPnts;
996  if (shape1->GetPointsOnSegments(fNmeshPoints, points1)) {
997  numPoints1 = fNmeshPoints;
998  } else {
999  shape1->SetPoints(points1);
1000  }
1001 // if (shape1->InheritsFrom(TGeoPcon::Class())) {
1002 // CleanPoints(points1, numPoints1);
1003 // fBuff1->SetRawSizes(numPoints1, 3*numPoints1,0, 0, 0, 0);
1004 // }
1005  fBuff1->fID = shape1;
1006  }
1007  shape2->GetMeshNumbers(numPoints2, numSegs2, numPols2);
1008  if (fBuff2->fID != (TObject*)shape2) {
1009  // Fill second buffer.
1010  fBuff2->SetRawSizes(TMath::Max(numPoints2,fNmeshPoints), 3*TMath::Max(numPoints2,fNmeshPoints), 0, 0, 0,0);
1011  points2 = fBuff2->fPnts;
1012  if (shape2->GetPointsOnSegments(fNmeshPoints, points2)) {
1013  numPoints2 = fNmeshPoints;
1014  } else {
1015  shape2->SetPoints(points2);
1016  }
1017 // if (shape2->InheritsFrom(TGeoPcon::Class())) {
1018 // CleanPoints(points2, numPoints2);
1019 // fBuff1->SetRawSizes(numPoints2, 3*numPoints2,0,0,0,0);
1020 // }
1021  fBuff2->fID = shape2;
1022  }
1023 
1024  if (!isovlp) {
1025  // Extrusion case. Test vol2 extrude vol1.
1026  isextrusion=kFALSE;
1027  // loop all points of the daughter
1028  for (ip=0; ip<numPoints2; ip++) {
1029  memcpy(local, &points2[3*ip], 3*sizeof(Double_t));
1030  if (TMath::Abs(local[0])<tolerance && TMath::Abs(local[1])<tolerance) continue;
1031  mat2->LocalToMaster(local, point);
1032  mat1->MasterToLocal(point, local);
1033  extrude = !shape1->Contains(local);
1034  if (extrude) {
1035  safety = shape1->Safety(local, kFALSE);
1036  if (safety<ovlp) extrude=kFALSE;
1037  }
1038  if (extrude) {
1039  if (!isextrusion) {
1040  isextrusion = kTRUE;
1041  nodeovlp = new TGeoOverlap(name, vol1, vol2, mat1,mat2,kFALSE,safety);
1042  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1043  fGeoManager->AddOverlap(nodeovlp);
1044  } else {
1045  if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
1046  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1047  }
1048  }
1049  }
1050  // loop all points of the mother
1051  for (ip=0; ip<numPoints1; ip++) {
1052  memcpy(local, &points1[3*ip], 3*sizeof(Double_t));
1053  if (local[0]<1e-10 && local[1]<1e-10) continue;
1054  mat1->LocalToMaster(local, point);
1055  mat2->MasterToLocal(point, local1);
1056  extrude = shape2->Contains(local1);
1057  if (extrude) {
1058  // skip points on mother mesh that have no neighborhood outside mother
1059  safety = shape1->Safety(local,kTRUE);
1060  if (safety>1E-6) {
1061  extrude = kFALSE;
1062  } else {
1063  safety = shape2->Safety(local1,kTRUE);
1064  if (safety<ovlp) extrude=kFALSE;
1065  }
1066  }
1067  if (extrude) {
1068  if (!isextrusion) {
1069  isextrusion = kTRUE;
1070  nodeovlp = new TGeoOverlap(name, vol1,vol2,mat1,mat2,kFALSE,safety);
1071  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1072  fGeoManager->AddOverlap(nodeovlp);
1073  } else {
1074  if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
1075  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1076  }
1077  }
1078  }
1079  return nodeovlp;
1080  }
1081  // Check overlap
1082  Bool_t overlap;
1083  overlap = kFALSE;
1084  isoverlapping = kFALSE;
1085  // loop all points of first candidate
1086  for (ip=0; ip<numPoints1; ip++) {
1087  memcpy(local, &points1[3*ip], 3*sizeof(Double_t));
1088  if (local[0]<1e-10 && local[1]<1e-10) continue;
1089  mat1->LocalToMaster(local, point);
1090  mat2->MasterToLocal(point, local); // now point in local reference of second
1091  overlap = shape2->Contains(local);
1092  if (overlap) {
1093  safety = shape2->Safety(local, kTRUE);
1094  if (safety<ovlp) overlap=kFALSE;
1095  }
1096  if (overlap) {
1097  if (!isoverlapping) {
1098  isoverlapping = kTRUE;
1099  nodeovlp = new TGeoOverlap(name,vol1,vol2,mat1,mat2,kTRUE,safety);
1100  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1101  fGeoManager->AddOverlap(nodeovlp);
1102  } else {
1103  if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
1104  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1105  }
1106  }
1107  }
1108  // loop all points of second candidate
1109  for (ip=0; ip<numPoints2; ip++) {
1110  memcpy(local, &points2[3*ip], 3*sizeof(Double_t));
1111  if (local[0]<1e-10 && local[1]<1e-10) continue;
1112  mat2->LocalToMaster(local, point);
1113  mat1->MasterToLocal(point, local); // now point in local reference of first
1114  overlap = shape1->Contains(local);
1115  if (overlap) {
1116  safety = shape1->Safety(local, kTRUE);
1117  if (safety<ovlp) overlap=kFALSE;
1118  }
1119  if (overlap) {
1120  if (!isoverlapping) {
1121  isoverlapping = kTRUE;
1122  nodeovlp = new TGeoOverlap(name,vol1,vol2,mat1,mat2,kTRUE,safety);
1123  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1124  fGeoManager->AddOverlap(nodeovlp);
1125  } else {
1126  if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
1127  nodeovlp->SetNextPoint(point[0],point[1],point[2]);
1128  }
1129  }
1130  }
1131  return nodeovlp;
1132 }
1133 
1134 ////////////////////////////////////////////////////////////////////////////////
1135 /// Check illegal overlaps for volume VOL within a limit OVLP by sampling npoints
1136 /// inside the volume shape.
1137 
1138 void TGeoChecker::CheckOverlapsBySampling(TGeoVolume *vol, Double_t /* ovlp */, Int_t npoints) const
1139 {
1140  Int_t nd = vol->GetNdaughters();
1141  if (nd<2) return;
1142  TGeoVoxelFinder *voxels = vol->GetVoxels();
1143  if (!voxels) return;
1144  if (voxels->NeedRebuild()) {
1145  voxels->Voxelize();
1146  vol->FindOverlaps();
1147  }
1148  TGeoBBox *box = (TGeoBBox*)vol->GetShape();
1149  TGeoShape *shape;
1150  TGeoNode *node;
1151  Double_t dx = box->GetDX();
1152  Double_t dy = box->GetDY();
1153  Double_t dz = box->GetDZ();
1154  Double_t pt[3];
1155  Double_t local[3];
1156  Int_t *check_list = 0;
1157  Int_t ncheck = 0;
1158  const Double_t *orig = box->GetOrigin();
1159  Int_t ipoint = 0;
1160  Int_t itry = 0;
1161  Int_t iovlp = 0;
1162  Int_t id=0, id0=0, id1=0;
1163  Bool_t in, incrt;
1164  Double_t safe;
1165  TString name1 = "";
1166  TString name2 = "";
1167  TGeoOverlap **flags = 0;
1168  TGeoNode *node1, *node2;
1169  Int_t novlps = 0;
1170  TGeoHMatrix mat1, mat2;
1171 // Int_t tid = TGeoManager::ThreadId();
1173  TGeoStateInfo &td = *nav->GetCache()->GetInfo();
1174  while (ipoint < npoints) {
1175  // Shoot randomly in the bounding box.
1176  pt[0] = orig[0] - dx + 2.*dx*gRandom->Rndm();
1177  pt[1] = orig[1] - dy + 2.*dy*gRandom->Rndm();
1178  pt[2] = orig[2] - dz + 2.*dz*gRandom->Rndm();
1179  if (!vol->Contains(pt)) {
1180  itry++;
1181  if (itry>10000 && !ipoint) {
1182  Error("CheckOverlapsBySampling", "No point inside volume!!! - aborting");
1183  break;
1184  }
1185  continue;
1186  }
1187  // Check if the point is inside one or more daughters
1188  in = kFALSE;
1189  ipoint++;
1190  check_list = voxels->GetCheckList(pt, ncheck, td);
1191  if (!check_list || ncheck<2) continue;
1192  for (id=0; id<ncheck; id++) {
1193  id0 = check_list[id];
1194  node = vol->GetNode(id0);
1195  // Ignore MANY's
1196  if (node->IsOverlapping()) continue;
1197  node->GetMatrix()->MasterToLocal(pt,local);
1198  shape = node->GetVolume()->GetShape();
1199  incrt = shape->Contains(local);
1200  if (!incrt) continue;
1201  if (!in) {
1202  in = kTRUE;
1203  id1 = id0;
1204  continue;
1205  }
1206  // The point is inside 2 or more daughters, check safety
1207  safe = shape->Safety(local, kTRUE);
1208 // if (safe < ovlp) continue;
1209  // We really have found an overlap -> store the point in a container
1210  iovlp++;
1211  if (!novlps) {
1212  flags = new TGeoOverlap*[nd*nd];
1213  memset(flags, 0, nd*nd*sizeof(TGeoOverlap*));
1214  }
1215  TGeoOverlap *nodeovlp = flags[nd*id1+id0];
1216  if (!nodeovlp) {
1217  novlps++;
1218  node1 = vol->GetNode(id1);
1219  name1 = node1->GetName();
1220  mat1 = node1->GetMatrix();
1221  Int_t cindex = node1->GetVolume()->GetCurrentNodeIndex();
1222  while (cindex >= 0) {
1223  node1 = node1->GetVolume()->GetNode(cindex);
1224  name1 += TString::Format("/%s", node1->GetName());
1225  mat1.Multiply(node1->GetMatrix());
1226  cindex = node1->GetVolume()->GetCurrentNodeIndex();
1227  }
1228  node2 = vol->GetNode(id0);
1229  name2 = node2->GetName();
1230  mat2 = node2->GetMatrix();
1231  cindex = node2->GetVolume()->GetCurrentNodeIndex();
1232  while (cindex >= 0) {
1233  node2 = node2->GetVolume()->GetNode(cindex);
1234  name2 += TString::Format("/%s", node2->GetName());
1235  mat2.Multiply(node2->GetMatrix());
1236  cindex = node2->GetVolume()->GetCurrentNodeIndex();
1237  }
1238  nodeovlp = new TGeoOverlap(TString::Format("Volume %s: node %s overlapping %s",
1239  vol->GetName(), name1.Data(), name2.Data()), node1->GetVolume(),node2->GetVolume(),
1240  &mat1,&mat2, kTRUE, safe);
1241  flags[nd*id1+id0] = nodeovlp;
1242  fGeoManager->AddOverlap(nodeovlp);
1243  }
1244  // Max 100 points per marker
1245  if (nodeovlp->GetPolyMarker()->GetN()<100) nodeovlp->SetNextPoint(pt[0],pt[1],pt[2]);
1246  if (nodeovlp->GetOverlap()<safe) nodeovlp->SetOverlap(safe);
1247  }
1248  }
1249  nav->GetCache()->ReleaseInfo();
1250  if (flags) delete [] flags;
1251  if (!novlps) return;
1252  Double_t capacity = vol->GetShape()->Capacity();
1253  capacity *= Double_t(iovlp)/Double_t(npoints);
1254  Double_t err = 1./TMath::Sqrt(Double_t(iovlp));
1255  Info("CheckOverlapsBySampling", "#Found %d overlaps adding-up to %g +/- %g [cm3] for daughters of %s",
1256  novlps, capacity, err*capacity, vol->GetName());
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// Compute number of overlaps combinations to check per volume
1261 
1263 {
1264  if (vol->GetFinder()) return 0;
1265  UInt_t nd = vol->GetNdaughters();
1266  if (!nd) return 0;
1267  Bool_t is_assembly = vol->IsAssembly();
1268  TGeoIterator next1(vol);
1269  TGeoIterator next2(vol);
1270  Int_t nchecks = 0;
1271  TGeoNode *node;
1272  UInt_t id;
1273  if (!is_assembly) {
1274  while ((node=next1())) {
1275  if (node->IsOverlapping()) {
1276  next1.Skip();
1277  continue;
1278  }
1279  if (!node->GetVolume()->IsAssembly()) {
1280  nchecks++;
1281  next1.Skip();
1282  }
1283  }
1284  }
1285  // now check if the daughters overlap with each other
1286  if (nd<2) return nchecks;
1287  TGeoVoxelFinder *vox = vol->GetVoxels();
1288  if (!vox) return nchecks;
1289 
1290 
1291  TGeoNode *node1, *node01, *node02;
1292  Int_t novlp;
1293  Int_t *ovlps;
1294  Int_t ko;
1295  UInt_t io;
1296  for (id=0; id<nd; id++) {
1297  node01 = vol->GetNode(id);
1298  if (node01->IsOverlapping()) continue;
1299  vox->FindOverlaps(id);
1300  ovlps = node01->GetOverlaps(novlp);
1301  if (!ovlps) continue;
1302  for (ko=0; ko<novlp; ko++) { // loop all possible overlapping candidates
1303  io = ovlps[ko]; // (node1, shaped, matrix1, points, fBuff1)
1304  if (io<=id) continue;
1305  node02 = vol->GetNode(io);
1306  if (node02->IsOverlapping()) continue;
1307 
1308  // We have to check node against node1, but they may be assemblies
1309  if (node01->GetVolume()->IsAssembly()) {
1310  next1.Reset(node01->GetVolume());
1311  while ((node=next1())) {
1312  if (!node->GetVolume()->IsAssembly()) {
1313  if (node02->GetVolume()->IsAssembly()) {
1314  next2.Reset(node02->GetVolume());
1315  while ((node1=next2())) {
1316  if (!node1->GetVolume()->IsAssembly()) {
1317  nchecks++;
1318  next2.Skip();
1319  }
1320  }
1321  } else {
1322  nchecks++;
1323  }
1324  next1.Skip();
1325  }
1326  }
1327  } else {
1328  // node not assembly
1329  if (node02->GetVolume()->IsAssembly()) {
1330  next2.Reset(node02->GetVolume());
1331  while ((node1=next2())) {
1332  if (!node1->GetVolume()->IsAssembly()) {
1333  nchecks++;
1334  next2.Skip();
1335  }
1336  }
1337  } else {
1338  // node1 also not assembly
1339  nchecks++;
1340  }
1341  }
1342  }
1343  node01->SetOverlaps(0,0);
1344  }
1345  return nchecks;
1346 }
1347 
1348 ////////////////////////////////////////////////////////////////////////////////
1349 /// Check illegal overlaps for volume VOL within a limit OVLP.
1350 
1352 {
1353  if (vol->GetFinder()) return;
1354  UInt_t nd = vol->GetNdaughters();
1355  if (!nd) return;
1358  Bool_t sampling = kFALSE;
1359  TString opt(option);
1360  opt.ToLower();
1361  if (opt.Contains("s")) sampling = kTRUE;
1362  if (opt.Contains("f")) fFullCheck = kTRUE;
1363  else fFullCheck = kFALSE;
1364  if (sampling) {
1365  opt = opt.Strip(TString::kLeading, 's');
1366  Int_t npoints = atoi(opt.Data());
1367  if (!npoints) npoints = 1000000;
1368  CheckOverlapsBySampling((TGeoVolume*)vol, ovlp, npoints);
1369  return;
1370  }
1371  Bool_t is_assembly = vol->IsAssembly();
1372  TGeoIterator next1((TGeoVolume*)vol);
1373  TGeoIterator next2((TGeoVolume*)vol);
1374  TString path;
1375  // first, test if daughters extrude their container
1376  TGeoNode * node, *nodecheck;
1377  TGeoChecker *checker = (TGeoChecker*)this;
1378 
1379 // TGeoOverlap *nodeovlp = 0;
1380  UInt_t id;
1381  Int_t level;
1382 // Check extrusion only for daughters of a non-assembly volume
1383  if (!is_assembly) {
1384  while ((node=next1())) {
1385  if (node->IsOverlapping()) {
1386  next1.Skip();
1387  continue;
1388  }
1389  if (!node->GetVolume()->IsAssembly()) {
1390  if (fSelectedNode) {
1391  // We have to check only overlaps of the selected node (or real daughters if an assembly)
1392  if ((fSelectedNode != node) && (!fSelectedNode->GetVolume()->IsAssembly())) {
1393  next1.Skip();
1394  continue;
1395  }
1396  if (node != fSelectedNode) {
1397  level = next1.GetLevel();
1398  while ((nodecheck=next1.GetNode(level--))) {
1399  if (nodecheck == fSelectedNode) break;
1400  }
1401  if (!nodecheck) {
1402  next1.Skip();
1403  continue;
1404  }
1405  }
1406  }
1407  next1.GetPath(path);
1408  checker->MakeCheckOverlap(TString::Format("%s extruded by: %s", vol->GetName(),path.Data()),
1409  (TGeoVolume*)vol,node->GetVolume(),gGeoIdentity,(TGeoMatrix*)next1.GetCurrentMatrix(),kFALSE,ovlp);
1410  next1.Skip();
1411  }
1412  }
1413  }
1414 
1415  // now check if the daughters overlap with each other
1416  if (nd<2) return;
1417  TGeoVoxelFinder *vox = vol->GetVoxels();
1418  if (!vox) {
1419  Warning("CheckOverlaps", "Volume %s with %i daughters but not voxelized", vol->GetName(),nd);
1420  return;
1421  }
1422  if (vox->NeedRebuild()) {
1423  vox->Voxelize();
1424  vol->FindOverlaps();
1425  }
1426  TGeoNode *node1, *node01, *node02;
1427  TGeoHMatrix hmat1, hmat2;
1428  TString path1;
1429  Int_t novlp;
1430  Int_t *ovlps;
1431  Int_t ko;
1432  UInt_t io;
1433  for (id=0; id<nd; id++) {
1434  node01 = vol->GetNode(id);
1435  if (node01->IsOverlapping()) continue;
1436  vox->FindOverlaps(id);
1437  ovlps = node01->GetOverlaps(novlp);
1438  if (!ovlps) continue;
1439  next1.SetTopName(node01->GetName());
1440  path = node01->GetName();
1441  for (ko=0; ko<novlp; ko++) { // loop all possible overlapping candidates
1442  io = ovlps[ko]; // (node1, shaped, matrix1, points, fBuff1)
1443  if (io<=id) continue;
1444  node02 = vol->GetNode(io);
1445  if (node02->IsOverlapping()) continue;
1446  // Try to fasten-up things...
1447 // if (!TGeoBBox::AreOverlapping((TGeoBBox*)node01->GetVolume()->GetShape(), node01->GetMatrix(),
1448 // (TGeoBBox*)node02->GetVolume()->GetShape(), node02->GetMatrix())) continue;
1449  next2.SetTopName(node02->GetName());
1450  path1 = node02->GetName();
1451 
1452  // We have to check node against node1, but they may be assemblies
1453  if (node01->GetVolume()->IsAssembly()) {
1454  next1.Reset(node01->GetVolume());
1455  while ((node=next1())) {
1456  if (!node->GetVolume()->IsAssembly()) {
1457  next1.GetPath(path);
1458  hmat1 = node01->GetMatrix();
1459  hmat1 *= *next1.GetCurrentMatrix();
1460  if (node02->GetVolume()->IsAssembly()) {
1461  next2.Reset(node02->GetVolume());
1462  while ((node1=next2())) {
1463  if (!node1->GetVolume()->IsAssembly()) {
1464  if (fSelectedNode) {
1465  // We have to check only overlaps of the selected node (or real daughters if an assembly)
1466  if ((fSelectedNode != node) && (fSelectedNode != node1) && (!fSelectedNode->GetVolume()->IsAssembly())) {
1467  next2.Skip();
1468  continue;
1469  }
1470  if ((fSelectedNode != node1) && (fSelectedNode != node)) {
1471  level = next2.GetLevel();
1472  while ((nodecheck=next2.GetNode(level--))) {
1473  if (nodecheck == fSelectedNode) break;
1474  }
1475  if (node02 == fSelectedNode) nodecheck = node02;
1476  if (!nodecheck) {
1477  level = next1.GetLevel();
1478  while ((nodecheck=next1.GetNode(level--))) {
1479  if (nodecheck == fSelectedNode) break;
1480  }
1481  }
1482  if (node01 == fSelectedNode) nodecheck = node01;
1483  if (!nodecheck) {
1484  next2.Skip();
1485  continue;
1486  }
1487  }
1488  }
1489  next2.GetPath(path1);
1490  hmat2 = node02->GetMatrix();
1491  hmat2 *= *next2.GetCurrentMatrix();
1492  checker->MakeCheckOverlap(TString::Format("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
1493  node->GetVolume(),node1->GetVolume(),&hmat1,&hmat2,kTRUE,ovlp);
1494  next2.Skip();
1495  }
1496  }
1497  } else {
1498  if (fSelectedNode) {
1499  // We have to check only overlaps of the selected node (or real daughters if an assembly)
1500  if ((fSelectedNode != node) && (fSelectedNode != node02) && (!fSelectedNode->GetVolume()->IsAssembly())) {
1501  next1.Skip();
1502  continue;
1503  }
1504  if ((fSelectedNode != node) && (fSelectedNode != node02)) {
1505  level = next1.GetLevel();
1506  while ((nodecheck=next1.GetNode(level--))) {
1507  if (nodecheck == fSelectedNode) break;
1508  }
1509  if (node01 == fSelectedNode) nodecheck = node01;
1510  if (!nodecheck) {
1511  next1.Skip();
1512  continue;
1513  }
1514  }
1515  }
1516  checker->MakeCheckOverlap(TString::Format("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
1517  node->GetVolume(),node02->GetVolume(),&hmat1,node02->GetMatrix(),kTRUE,ovlp);
1518  }
1519  next1.Skip();
1520  }
1521  }
1522  } else {
1523  // node not assembly
1524  if (node02->GetVolume()->IsAssembly()) {
1525  next2.Reset(node02->GetVolume());
1526  while ((node1=next2())) {
1527  if (!node1->GetVolume()->IsAssembly()) {
1528  if (fSelectedNode) {
1529  // We have to check only overlaps of the selected node (or real daughters if an assembly)
1530  if ((fSelectedNode != node1) && (fSelectedNode != node01) && (!fSelectedNode->GetVolume()->IsAssembly())) {
1531  next2.Skip();
1532  continue;
1533  }
1534  if ((fSelectedNode != node1) && (fSelectedNode != node01)) {
1535  level = next2.GetLevel();
1536  while ((nodecheck=next2.GetNode(level--))) {
1537  if (nodecheck == fSelectedNode) break;
1538  }
1539  if (node02 == fSelectedNode) nodecheck = node02;
1540  if (!nodecheck) {
1541  next2.Skip();
1542  continue;
1543  }
1544  }
1545  }
1546  next2.GetPath(path1);
1547  hmat2 = node02->GetMatrix();
1548  hmat2 *= *next2.GetCurrentMatrix();
1549  checker->MakeCheckOverlap(TString::Format("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
1550  node01->GetVolume(),node1->GetVolume(),node01->GetMatrix(),&hmat2,kTRUE,ovlp);
1551  next2.Skip();
1552  }
1553  }
1554  } else {
1555  // node1 also not assembly
1556  if (fSelectedNode && (fSelectedNode != node01) && (fSelectedNode != node02)) continue;
1557  checker->MakeCheckOverlap(TString::Format("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
1558  node01->GetVolume(),node02->GetVolume(),node01->GetMatrix(),node02->GetMatrix(),kTRUE,ovlp);
1559  }
1560  }
1561  }
1562  node01->SetOverlaps(0,0);
1563  }
1564 }
1565 
1566 ////////////////////////////////////////////////////////////////////////////////
1567 /// Print the current list of overlaps held by the manager class.
1568 
1570 {
1572  TGeoOverlap *ov;
1573  printf("=== Overlaps for %s ===\n", fGeoManager->GetName());
1574  while ((ov=(TGeoOverlap*)next())) ov->PrintInfo();
1575 }
1576 
1577 ////////////////////////////////////////////////////////////////////////////////
1578 /// Draw point (x,y,z) over the picture of the daughters of the volume containing this point.
1579 /// Generates a report regarding the path to the node containing this point and the distance to
1580 /// the closest boundary.
1581 
1583 {
1584  Double_t point[3];
1585  Double_t local[3];
1586  point[0] = x;
1587  point[1] = y;
1588  point[2] = z;
1590  if (fVsafe) {
1591  TGeoNode *old = fVsafe->GetNode("SAFETY_1");
1592  if (old) fVsafe->GetNodes()->RemoveAt(vol->GetNdaughters()-1);
1593  }
1594 // if (vol != fGeoManager->GetMasterVolume()) fGeoManager->RestoreMasterVolume();
1595  TGeoNode *node = fGeoManager->FindNode(point[0], point[1], point[2]);
1596  fGeoManager->MasterToLocal(point, local);
1597  // get current node
1598  printf("=== Check current point : (%g, %g, %g) ===\n", point[0], point[1], point[2]);
1599  printf(" - path : %s\n", fGeoManager->GetPath());
1600  // get corresponding volume
1601  if (node) vol = node->GetVolume();
1602  // compute safety distance (distance to boundary ignored)
1604  printf("Safety radius : %f\n", close);
1605  if (close>1E-4) {
1606  TGeoVolume *sph = fGeoManager->MakeSphere("SAFETY", vol->GetMedium(), 0, close, 0,180,0,360);
1607  sph->SetLineColor(2);
1608  sph->SetLineStyle(3);
1609  vol->AddNode(sph,1,new TGeoTranslation(local[0], local[1], local[2]));
1610  fVsafe = vol;
1611  }
1612  TPolyMarker3D *pm = new TPolyMarker3D();
1613  pm->SetMarkerColor(2);
1614  pm->SetMarkerStyle(8);
1615  pm->SetMarkerSize(0.5);
1616  pm->SetNextPoint(local[0], local[1], local[2]);
1617  if (vol->GetNdaughters()<2) fGeoManager->SetTopVisible();
1620  if (!vol->IsVisible()) vol->SetVisibility(kTRUE);
1621  vol->Draw();
1622  pm->Draw("SAME");
1623  gPad->Modified();
1624  gPad->Update();
1625 }
1626 
1627 ////////////////////////////////////////////////////////////////////////////////
1628 /// Test for shape navigation methods. Summary for test numbers:
1629 /// - 1: DistFromInside/Outside. Sample points inside the shape. Generate
1630 /// directions randomly in cos(theta). Compute DistFromInside and move the
1631 /// point with bigger distance. Compute DistFromOutside back from new point.
1632 /// Plot d-(d1+d2)
1633 /// - 2: Safety test. Sample points inside the bounding and compute safety. Generate
1634 /// directions randomly in cos(theta) and compute distance to boundary. Check if
1635 /// distance to boundary is bigger than safety
1636 
1637 void TGeoChecker::CheckShape(TGeoShape *shape, Int_t testNo, Int_t nsamples, Option_t *option)
1638 {
1639  switch (testNo) {
1640  case 1:
1641  ShapeDistances(shape, nsamples, option);
1642  break;
1643  case 2:
1644  ShapeSafety(shape, nsamples, option);
1645  break;
1646  case 3:
1647  ShapeNormal(shape, nsamples, option);
1648  break;
1649  default:
1650  Error("CheckShape", "Test number %d not existent", testNo);
1651  }
1652 }
1653 
1654 ////////////////////////////////////////////////////////////////////////////////
1655 /// Test TGeoShape::DistFromInside/Outside. Sample points inside the shape. Generate
1656 /// directions randomly in cos(theta). Compute d1 = DistFromInside and move the
1657 /// point on the boundary. Compute DistFromOutside and propagate with d2 making sure that
1658 /// the shape is not re-entered. Swap direction and call DistFromOutside that
1659 /// should fall back on the same point on the boundary (at d2). Propagate back on boundary
1660 /// then compute DistFromInside that should be bigger than d1.
1661 /// Plot d-(d1+d2)
1662 
1664 {
1665  Double_t dx = ((TGeoBBox*)shape)->GetDX();
1666  Double_t dy = ((TGeoBBox*)shape)->GetDY();
1667  Double_t dz = ((TGeoBBox*)shape)->GetDZ();
1668  Double_t dmax = 2.*TMath::Sqrt(dx*dx+dy*dy+dz*dz);
1669  Double_t d1, d2, dmove, dnext;
1670  Int_t itot = 0;
1671  // Number of tracks shot for every point inside the shape
1672  const Int_t kNtracks = 1000;
1673  Int_t n10 = nsamples/10;
1674  Int_t i,j;
1675  Double_t point[3], pnew[3];
1676  Double_t dir[3], dnew[3];
1677  Double_t theta, phi, delta;
1678  TPolyMarker3D *pmfrominside = 0;
1679  TPolyMarker3D *pmfromoutside = 0;
1680  TH1D *hist = new TH1D("hTest1", "Residual distance from inside/outside",200,-20, 0);
1681  hist->GetXaxis()->SetTitle("delta[cm] - first bin=overflow");
1682  hist->GetYaxis()->SetTitle("count");
1683  hist->SetMarkerStyle(kFullCircle);
1684 
1685  if (!fTimer) fTimer = new TStopwatch();
1686  fTimer->Reset();
1687  fTimer->Start();
1688  while (itot<nsamples) {
1689  Bool_t inside = kFALSE;
1690  while (!inside) {
1691  point[0] = gRandom->Uniform(-dx,dx);
1692  point[1] = gRandom->Uniform(-dy,dy);
1693  point[2] = gRandom->Uniform(-dz,dz);
1694  inside = shape->Contains(point);
1695  }
1696  itot++;
1697  if (n10) {
1698  if ((itot%n10) == 0) printf("%i percent\n", Int_t(100*itot/nsamples));
1699  }
1700  for (i=0; i<kNtracks; i++) {
1701  phi = 2*TMath::Pi()*gRandom->Rndm();
1702  theta= TMath::ACos(1.-2.*gRandom->Rndm());
1703  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
1704  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
1705  dir[2]=TMath::Cos(theta);
1706  dmove = dmax;
1707  // We have track direction, compute distance from inside
1708  d1 = shape->DistFromInside(point,dir,3);
1709  if (d1>dmove || d1<TGeoShape::Tolerance()) {
1710  // Bad distance or bbox size, to debug
1711  new TCanvas("shape01", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1712  shape->Draw();
1713  printf("DistFromInside: (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) %f/%f(max)\n",
1714  point[0],point[1],point[2],dir[0],dir[1],dir[2], d1,dmove);
1715  pmfrominside = new TPolyMarker3D(2);
1716  pmfrominside->SetMarkerColor(kRed);
1717  pmfrominside->SetMarkerStyle(24);
1718  pmfrominside->SetMarkerSize(0.4);
1719  pmfrominside->SetNextPoint(point[0],point[1],point[2]);
1720  for (j=0; j<3; j++) pnew[j] = point[j] + d1*dir[j];
1721  pmfrominside->SetNextPoint(pnew[0],pnew[1],pnew[2]);
1722  pmfrominside->Draw();
1723  return;
1724  }
1725  // Propagate BEFORE the boundary and make sure that DistFromOutside
1726  // does not return 0 (!!!)
1727  // Check if there is a second crossing
1728  for (j=0; j<3; j++) pnew[j] = point[j] + (d1-TGeoShape::Tolerance())*dir[j];
1729  dnext = shape->DistFromOutside(pnew,dir,3);
1730  if (d1+dnext<dmax) dmove = d1+0.5*dnext;
1731  // Move point and swap direction
1732  for (j=0; j<3; j++) {
1733  pnew[j] = point[j] + dmove*dir[j];
1734  dnew[j] = -dir[j];
1735  }
1736  // Compute now distance from outside
1737  d2 = shape->DistFromOutside(pnew,dnew,3);
1738  delta = dmove-d1-d2;
1739  if (TMath::Abs(delta)>1E-6 || dnext<2.*TGeoShape::Tolerance()) {
1740  // Error->debug this
1741  new TCanvas("shape01", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1742  shape->Draw();
1743  printf("Error: (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) d1=%f d2=%f dmove=%f\n",
1744  point[0],point[1],point[2],dir[0],dir[1],dir[2], d1,d2,dmove);
1745  if (dnext<2.*TGeoShape::Tolerance()) {
1746  printf(" (*)DistFromOutside(%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) dnext = %f\n",
1747  point[0]+(d1-TGeoShape::Tolerance())*dir[0],
1748  point[1]+(d1-TGeoShape::Tolerance())*dir[1],
1749  point[2]+(d1-TGeoShape::Tolerance())*dir[2], dir[0],dir[1],dir[2],dnext);
1750  } else {
1751  printf(" DistFromOutside(%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) dnext = %f\n",
1752  point[0]+d1*dir[0],point[1]+d1*dir[1], point[2]+d1*dir[2], dir[0],dir[1],dir[2],dnext);
1753  }
1754  printf(" DistFromOutside(%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) = %f\n",
1755  pnew[0],pnew[1],pnew[2],dnew[0],dnew[1],dnew[2], d2);
1756  pmfrominside = new TPolyMarker3D(2);
1757  pmfrominside->SetMarkerStyle(24);
1758  pmfrominside->SetMarkerSize(0.4);
1759  pmfrominside->SetMarkerColor(kRed);
1760  pmfrominside->SetNextPoint(point[0],point[1],point[2]);
1761  for (j=0; j<3; j++) point[j] += d1*dir[j];
1762  pmfrominside->SetNextPoint(point[0],point[1],point[2]);
1763  pmfrominside->Draw();
1764  pmfromoutside = new TPolyMarker3D(2);
1765  pmfromoutside->SetMarkerStyle(20);
1766  pmfromoutside->SetMarkerStyle(7);
1767  pmfromoutside->SetMarkerSize(0.3);
1768  pmfromoutside->SetMarkerColor(kBlue);
1769  pmfromoutside->SetNextPoint(pnew[0],pnew[1],pnew[2]);
1770  for (j=0; j<3; j++) pnew[j] += d2*dnew[j];
1771  if (d2<1E10) pmfromoutside->SetNextPoint(pnew[0],pnew[1],pnew[2]);
1772  pmfromoutside->Draw();
1773  return;
1774  }
1775  // Compute distance from inside which should be bigger than d1
1776  for (j=0; j<3; j++) pnew[j] += (d2-TGeoShape::Tolerance())*dnew[j];
1777  dnext = shape->DistFromInside(pnew,dnew,3);
1778  if (dnext<d1-TGeoShape::Tolerance() || dnext>dmax) {
1779  new TCanvas("shape01", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1780  shape->Draw();
1781  printf("Error DistFromInside(%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) d1=%f d1p=%f\n",
1782  pnew[0],pnew[1],pnew[2],dnew[0],dnew[1],dnew[2],d1,dnext);
1783  pmfrominside = new TPolyMarker3D(2);
1784  pmfrominside->SetMarkerStyle(24);
1785  pmfrominside->SetMarkerSize(0.4);
1786  pmfrominside->SetMarkerColor(kRed);
1787  pmfrominside->SetNextPoint(point[0],point[1],point[2]);
1788  for (j=0; j<3; j++) point[j] += d1*dir[j];
1789  pmfrominside->SetNextPoint(point[0],point[1],point[2]);
1790  pmfrominside->Draw();
1791  pmfromoutside = new TPolyMarker3D(2);
1792  pmfromoutside->SetMarkerStyle(20);
1793  pmfromoutside->SetMarkerStyle(7);
1794  pmfromoutside->SetMarkerSize(0.3);
1795  pmfromoutside->SetMarkerColor(kBlue);
1796  pmfromoutside->SetNextPoint(pnew[0],pnew[1],pnew[2]);
1797  for (j=0; j<3; j++) pnew[j] += dnext*dnew[j];
1798  if (d2<1E10) pmfromoutside->SetNextPoint(pnew[0],pnew[1],pnew[2]);
1799  pmfromoutside->Draw();
1800  return;
1801  }
1802  if (TMath::Abs(delta) < 1E-20) delta = 1E-30;
1803  hist->Fill(TMath::Max(TMath::Log(TMath::Abs(delta)),-20.));
1804  }
1805  }
1806  fTimer->Stop();
1807  fTimer->Print();
1808  new TCanvas("Test01", "Residuals DistFromInside/Outside", 800, 600);
1809  hist->Draw();
1810 }
1811 
1812 ////////////////////////////////////////////////////////////////////////////////
1813 /// Check of validity of safe distance for a given shape.
1814 /// Sample points inside the 2x bounding box and compute safety. Generate
1815 /// directions randomly in cos(theta) and compute distance to boundary. Check if
1816 /// distance to boundary is bigger than safety.
1817 
1819 {
1820  Double_t dx = ((TGeoBBox*)shape)->GetDX();
1821  Double_t dy = ((TGeoBBox*)shape)->GetDY();
1822  Double_t dz = ((TGeoBBox*)shape)->GetDZ();
1823  // Number of tracks shot for every point inside the shape
1824  const Int_t kNtracks = 1000;
1825  Int_t n10 = nsamples/10;
1826  Int_t i;
1827  Double_t dist;
1828  Double_t point[3];
1829  Double_t dir[3];
1830  Double_t theta, phi;
1831  TPolyMarker3D *pm1 = 0;
1832  TPolyMarker3D *pm2 = 0;
1833  if (!fTimer) fTimer = new TStopwatch();
1834  fTimer->Reset();
1835  fTimer->Start();
1836  Int_t itot = 0;
1837  while (itot<nsamples) {
1838  Bool_t inside = kFALSE;
1839  point[0] = gRandom->Uniform(-2*dx,2*dx);
1840  point[1] = gRandom->Uniform(-2*dy,2*dy);
1841  point[2] = gRandom->Uniform(-2*dz,2*dz);
1842  inside = shape->Contains(point);
1843  Double_t safe = shape->Safety(point, inside);
1844  itot++;
1845  if (n10) {
1846  if ((itot%n10) == 0) printf("%i percent\n", Int_t(100*itot/nsamples));
1847  }
1848  for (i=0; i<kNtracks; i++) {
1849  phi = 2*TMath::Pi()*gRandom->Rndm();
1850  theta= TMath::ACos(1.-2.*gRandom->Rndm());
1851  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
1852  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
1853  dir[2]=TMath::Cos(theta);
1854  if (inside) dist = shape->DistFromInside(point,dir,3);
1855  else dist = shape->DistFromOutside(point,dir,3);
1856  if (dist<safe) {
1857  printf("Error safety (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) safe=%f dist=%f\n",
1858  point[0],point[1],point[2], dir[0], dir[1], dir[2], safe, dist);
1859  new TCanvas("shape02", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1860  shape->Draw();
1861  pm1 = new TPolyMarker3D(2);
1862  pm1->SetMarkerStyle(24);
1863  pm1->SetMarkerSize(0.4);
1864  pm1->SetMarkerColor(kRed);
1865  pm1->SetNextPoint(point[0],point[1],point[2]);
1866  pm1->SetNextPoint(point[0]+safe*dir[0],point[1]+safe*dir[1],point[2]+safe*dir[2]);
1867  pm1->Draw();
1868  pm2 = new TPolyMarker3D(1);
1869  pm2->SetMarkerStyle(7);
1870  pm2->SetMarkerSize(0.3);
1871  pm2->SetMarkerColor(kBlue);
1872  pm2->SetNextPoint(point[0]+dist*dir[0],point[1]+dist*dir[1],point[2]+dist*dir[2]);
1873  pm2->Draw();
1874  return;
1875  }
1876  }
1877  }
1878  fTimer->Stop();
1879  fTimer->Print();
1880 }
1881 
1882 ////////////////////////////////////////////////////////////////////////////////
1883 /// Check of validity of the normal for a given shape.
1884 /// Sample points inside the shape. Generate directions randomly in cos(theta)
1885 /// and propagate to boundary. Compute normal and safety at crossing point, plot
1886 /// the point and generate a random direction so that (dir) dot (norm) <0.
1887 
1889 {
1890  Double_t dx = ((TGeoBBox*)shape)->GetDX();
1891  Double_t dy = ((TGeoBBox*)shape)->GetDY();
1892  Double_t dz = ((TGeoBBox*)shape)->GetDZ();
1893  Double_t dmax = 2.*TMath::Sqrt(dx*dx+dy*dy+dz*dz);
1894  // Number of tracks shot for every point inside the shape
1895  const Int_t kNtracks = 1000;
1896  Int_t n10 = nsamples/10;
1897  Int_t itot = 0, errcnt = 0, errsame=0;
1898  Int_t i;
1899  Double_t dist, olddist, safe, dot;
1900  Double_t theta, phi, ndotd;
1901  Double_t *spoint = new Double_t[3*nsamples];
1902  Double_t *sdir = new Double_t[3*nsamples];
1903  while (itot<nsamples) {
1904  Bool_t inside = kFALSE;
1905  while (!inside) {
1906  spoint[3*itot] = gRandom->Uniform(-dx,dx);
1907  spoint[3*itot+1] = gRandom->Uniform(-dy,dy);
1908  spoint[3*itot+2] = gRandom->Uniform(-dz,dz);
1909  inside = shape->Contains(&spoint[3*itot]);
1910  }
1911  phi = 2*TMath::Pi()*gRandom->Rndm();
1912  theta= TMath::ACos(1.-2.*gRandom->Rndm());
1913  sdir[3*itot] = TMath::Sin(theta)*TMath::Cos(phi);
1914  sdir[3*itot+1] = TMath::Sin(theta)*TMath::Sin(phi);
1915  sdir[3*itot+2] = TMath::Cos(theta);
1916  itot++;
1917  }
1918  Double_t point[3],newpoint[3], oldpoint[3];
1919  Double_t dir[3], olddir[3];
1920  Double_t norm[3], newnorm[3], oldnorm[3];
1921  TCanvas *errcanvas = 0;
1922  TPolyMarker3D *pm1 = 0;
1923  TPolyMarker3D *pm2 = 0;
1924  pm2 = new TPolyMarker3D();
1925 // pm2->SetMarkerStyle(24);
1926  pm2->SetMarkerSize(0.2);
1927  pm2->SetMarkerColor(kBlue);
1928  if (!fTimer) fTimer = new TStopwatch();
1929  fTimer->Reset();
1930  fTimer->Start();
1931  for (itot = 0; itot<nsamples; itot++) {
1932  if (n10) {
1933  if ((itot%n10) == 0) printf("%i percent\n", Int_t(100*itot/nsamples));
1934  }
1935  oldnorm[0] = oldnorm[1] = oldnorm[2] = 0.;
1936  olddist = 0.;
1937  for (Int_t j=0; j<3; j++) {
1938  oldpoint[j] = point[j] = spoint[3*itot+j];
1939  olddir[j] = dir[j] = sdir[3*itot+j];
1940  }
1941  for (i=0; i<kNtracks; i++) {
1942  if (errcnt>0) break;
1943  dist = shape->DistFromInside(point,dir,3);
1944  for (Int_t j=0; j<3; j++) {
1945  newpoint[j] = point[j] + dist*dir[j];
1946  }
1947  shape->ComputeNormal(newpoint,dir,newnorm);
1948 
1949  dot = olddir[0]*oldnorm[0]+olddir[1]*oldnorm[1]+ olddir[2]*oldnorm[2];
1950  if (!shape->Contains(point) && shape->Safety(point,kFALSE)>1.E-3) {
1951  errcnt++;
1952  printf("Error point outside (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) =%g olddist=%g\n",
1953  point[0],point[1],point[2], dir[0], dir[1], dir[2], dist, olddist);
1954  printf(" old point: (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f)\n",
1955  oldpoint[0],oldpoint[1],oldpoint[2], olddir[0], olddir[1], olddir[2]);
1956  if (!errcanvas) errcanvas = new TCanvas("shape_err03", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1957  if (!pm1) {
1958  pm1 = new TPolyMarker3D();
1959  pm1->SetMarkerStyle(24);
1960  pm1->SetMarkerSize(0.4);
1961  pm1->SetMarkerColor(kRed);
1962  }
1963  pm1->SetNextPoint(point[0],point[1],point[2]);
1964  pm1->SetNextPoint(oldpoint[0],oldpoint[1],oldpoint[2]);
1965  break;
1966  }
1967  if ((dist<TGeoShape::Tolerance() && olddist*dot>1.E-3) || dist>dmax) {
1968  errsame++;
1969  if (errsame>1) {
1970  errcnt++;
1971  printf("Error DistFromInside(%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f) =%g olddist=%g\n",
1972  point[0],point[1],point[2], dir[0], dir[1], dir[2], dist, olddist);
1973  printf(" new norm: (%g, %g, %g)\n", newnorm[0], newnorm[1], newnorm[2]);
1974  printf(" old point: (%19.15f, %19.15f, %19.15f, %19.15f, %19.15f, %19.15f)\n",
1975  oldpoint[0],oldpoint[1],oldpoint[2], olddir[0], olddir[1], olddir[2]);
1976  printf(" old norm: (%g, %g, %g)\n", oldnorm[0], oldnorm[1], oldnorm[2]);
1977  if (!errcanvas) errcanvas = new TCanvas("shape_err03", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
1978  if (!pm1) {
1979  pm1 = new TPolyMarker3D();
1980  pm1->SetMarkerStyle(24);
1981  pm1->SetMarkerSize(0.4);
1982  pm1->SetMarkerColor(kRed);
1983  }
1984  pm1->SetNextPoint(point[0],point[1],point[2]);
1985  pm1->SetNextPoint(oldpoint[0],oldpoint[1],oldpoint[2]);
1986  break;
1987  }
1988  } else errsame = 0;
1989 
1990  olddist = dist;
1991  for (Int_t j=0; j<3; j++) {
1992  oldpoint[j] = point[j];
1993  point[j] += dist*dir[j];
1994  }
1995  safe = shape->Safety(point, kTRUE);
1996  if (safe>1.E-3) {
1997  errcnt++;
1998  printf("Error safety (%19.15f, %19.15f, %19.15f) safe=%g\n",
1999  point[0],point[1],point[2], safe);
2000  if (!errcanvas) errcanvas = new TCanvas("shape_err03", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
2001  if (!pm1) {
2002  pm1 = new TPolyMarker3D();
2003  pm1->SetMarkerStyle(24);
2004  pm1->SetMarkerSize(0.4);
2005  pm1->SetMarkerColor(kRed);
2006  }
2007  pm1->SetNextPoint(point[0],point[1],point[2]);
2008  break;
2009  }
2010  // Compute normal
2011  shape->ComputeNormal(point,dir,norm);
2012  memcpy(oldnorm, norm, 3*sizeof(Double_t));
2013  memcpy(olddir, dir, 3*sizeof(Double_t));
2014  while (1) {
2015  phi = 2*TMath::Pi()*gRandom->Rndm();
2016  theta= TMath::ACos(1.-2.*gRandom->Rndm());
2017  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
2018  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
2019  dir[2]=TMath::Cos(theta);
2020  ndotd = dir[0]*norm[0]+dir[1]*norm[1]+dir[2]*norm[2];
2021  if (ndotd<0) break; // backwards, still inside shape
2022  }
2023  if ((itot%10) == 0) pm2->SetNextPoint(point[0],point[1],point[2]);
2024  }
2025  }
2026  fTimer->Stop();
2027  fTimer->Print();
2028  if (errcanvas) {
2029  shape->Draw();
2030  pm1->Draw();
2031  }
2032 
2033  new TCanvas("shape03", Form("Shape %s (%s)",shape->GetName(),shape->ClassName()), 1000, 800);
2034  pm2->Draw();
2035  delete [] spoint;
2036  delete [] sdir;
2037 }
2038 
2039 ////////////////////////////////////////////////////////////////////////////////
2040 /// Generate a lego plot fot the top volume, according to option.
2041 
2043  Int_t nphi, Double_t phimin, Double_t phimax,
2044  Double_t /*rmin*/, Double_t /*rmax*/, Option_t *option)
2045 {
2046  TH2F *hist = new TH2F("lego", option, nphi, phimin, phimax, ntheta, themin, themax);
2047 
2048  Double_t degrad = TMath::Pi()/180.;
2049  Double_t theta, phi, step, matprop, x;
2050  Double_t start[3];
2051  Double_t dir[3];
2052  TGeoNode *startnode, *endnode;
2053  Int_t i; // loop index for phi
2054  Int_t j; // loop index for theta
2055  Int_t ntot = ntheta * nphi;
2056  Int_t n10 = ntot/10;
2057  Int_t igen = 0, iloop=0;
2058  printf("=== Lego plot sph. => nrays=%i\n", ntot);
2059  for (i=1; i<=nphi; i++) {
2060  for (j=1; j<=ntheta; j++) {
2061  igen++;
2062  if (n10) {
2063  if ((igen%n10) == 0) printf("%i percent\n", Int_t(100*igen/ntot));
2064  }
2065  x = 0;
2066  theta = hist->GetYaxis()->GetBinCenter(j);
2067  phi = hist->GetXaxis()->GetBinCenter(i)+1E-3;
2068  start[0] = start[1] = start[2] = 1E-3;
2069  dir[0]=TMath::Sin(theta*degrad)*TMath::Cos(phi*degrad);
2070  dir[1]=TMath::Sin(theta*degrad)*TMath::Sin(phi*degrad);
2071  dir[2]=TMath::Cos(theta*degrad);
2072  fGeoManager->InitTrack(&start[0], &dir[0]);
2073  startnode = fGeoManager->GetCurrentNode();
2074  if (fGeoManager->IsOutside()) startnode=0;
2075  if (startnode) {
2076  matprop = startnode->GetVolume()->GetMaterial()->GetRadLen();
2077  } else {
2078  matprop = 0.;
2079  }
2081 // fGeoManager->IsStepEntering();
2082  // find where we end-up
2083  endnode = fGeoManager->Step();
2084  step = fGeoManager->GetStep();
2085  while (step<1E10) {
2086  // now see if we can make an other step
2087  iloop=0;
2088  while (!fGeoManager->IsEntering()) {
2089  iloop++;
2090  fGeoManager->SetStep(1E-3);
2091  step += 1E-3;
2092  endnode = fGeoManager->Step();
2093  }
2094  if (iloop>1000) printf("%i steps\n", iloop);
2095  if (matprop>0) {
2096  x += step/matprop;
2097  }
2098  if (endnode==0 && step>1E10) break;
2099  // generate an extra step to cross boundary
2100  startnode = endnode;
2101  if (startnode) {
2102  matprop = startnode->GetVolume()->GetMaterial()->GetRadLen();
2103  } else {
2104  matprop = 0.;
2105  }
2106 
2108  endnode = fGeoManager->Step();
2109  step = fGeoManager->GetStep();
2110  }
2111  hist->Fill(phi, theta, x);
2112  }
2113  }
2114  return hist;
2115 }
2116 
2117 ////////////////////////////////////////////////////////////////////////////////
2118 /// Draw random points in the bounding box of a volume.
2119 
2121 {
2122  if (!vol) return;
2123  vol->VisibleDaughters(kTRUE);
2124  vol->Draw();
2125  TString opt = option;
2126  opt.ToLower();
2127  TObjArray *pm = new TObjArray(128);
2128  TPolyMarker3D *marker = 0;
2129  const TGeoShape *shape = vol->GetShape();
2130  TGeoBBox *box = (TGeoBBox *)shape;
2131  Double_t dx = box->GetDX();
2132  Double_t dy = box->GetDY();
2133  Double_t dz = box->GetDZ();
2134  Double_t ox = (box->GetOrigin())[0];
2135  Double_t oy = (box->GetOrigin())[1];
2136  Double_t oz = (box->GetOrigin())[2];
2137  Double_t *xyz = new Double_t[3];
2138  printf("Random box : %f, %f, %f\n", dx, dy, dz);
2139  TGeoNode *node = 0;
2140  printf("Start... %i points\n", npoints);
2141  Int_t i=0;
2142  Int_t igen=0;
2143  Int_t ic = 0;
2144  Int_t n10 = npoints/10;
2145  Double_t ratio=0;
2146  while (igen<npoints) {
2147  xyz[0] = ox-dx+2*dx*gRandom->Rndm();
2148  xyz[1] = oy-dy+2*dy*gRandom->Rndm();
2149  xyz[2] = oz-dz+2*dz*gRandom->Rndm();
2151  igen++;
2152  if (n10) {
2153  if ((igen%n10) == 0) printf("%i percent\n", Int_t(100*igen/npoints));
2154  }
2155  node = fGeoManager->FindNode();
2156  if (!node) continue;
2157  if (!node->IsOnScreen()) continue;
2158  // draw only points in overlapping/non-overlapping volumes
2159  if (opt.Contains("many") && !node->IsOverlapping()) continue;
2160  if (opt.Contains("only") && node->IsOverlapping()) continue;
2161  ic = node->GetColour();
2162  if ((ic<0) || (ic>=128)) ic = 1;
2163  marker = (TPolyMarker3D*)pm->At(ic);
2164  if (!marker) {
2165  marker = new TPolyMarker3D();
2166  marker->SetMarkerColor(ic);
2167 // marker->SetMarkerStyle(8);
2168 // marker->SetMarkerSize(0.4);
2169  pm->AddAt(marker, ic);
2170  }
2171  marker->SetNextPoint(xyz[0], xyz[1], xyz[2]);
2172  i++;
2173  }
2174  printf("Number of visible points : %i\n", i);
2175  if (igen) ratio = (Double_t)i/(Double_t)igen;
2176  printf("efficiency : %g\n", ratio);
2177  for (Int_t m=0; m<128; m++) {
2178  marker = (TPolyMarker3D*)pm->At(m);
2179  if (marker) marker->Draw("SAME");
2180  }
2182  printf("---Daughters of %s made invisible.\n", fGeoManager->GetTopVolume()->GetName());
2183  printf("---Make them visible with : gGeoManager->GetTopVolume()->VisibleDaughters();\n");
2184  delete pm;
2185  delete [] xyz;
2186 }
2187 
2188 ////////////////////////////////////////////////////////////////////////////////
2189 /// Randomly shoot nrays from point (startx,starty,startz) and plot intersections
2190 /// with surfaces for current top node.
2191 
2192 void TGeoChecker::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz, const char *target_vol, Bool_t check_norm)
2193 {
2194  TObjArray *pm = new TObjArray(128);
2195  TString starget = target_vol;
2196  TPolyLine3D *line = 0;
2197  TPolyLine3D *normline = 0;
2199 // vol->VisibleDaughters(kTRUE);
2200 
2201  Bool_t random = kFALSE;
2202  if (nrays<=0) {
2203  nrays = 100000;
2204  random = kTRUE;
2205  }
2206  Double_t start[3];
2207  Double_t dir[3];
2208  const Double_t *point = fGeoManager->GetCurrentPoint();
2209  vol->Draw();
2210  printf("Start... %i rays\n", nrays);
2211  TGeoNode *startnode, *endnode;
2212  Bool_t vis1,vis2;
2213  Int_t i=0;
2214  Int_t ipoint, inull;
2215  Int_t itot=0;
2216  Int_t n10=nrays/10;
2217  Double_t theta,phi, step, normlen;
2218  Double_t ox = ((TGeoBBox*)vol->GetShape())->GetOrigin()[0];
2219  Double_t oy = ((TGeoBBox*)vol->GetShape())->GetOrigin()[1];
2220  Double_t oz = ((TGeoBBox*)vol->GetShape())->GetOrigin()[2];
2221  Double_t dx = ((TGeoBBox*)vol->GetShape())->GetDX();
2222  Double_t dy = ((TGeoBBox*)vol->GetShape())->GetDY();
2223  Double_t dz = ((TGeoBBox*)vol->GetShape())->GetDZ();
2224  normlen = TMath::Max(dx,dy);
2225  normlen = TMath::Max(normlen,dz);
2226  normlen *= 0.05;
2227  while (itot<nrays) {
2228  itot++;
2229  inull = 0;
2230  ipoint = 0;
2231  if (n10) {
2232  if ((itot%n10) == 0) printf("%i percent\n", Int_t(100*itot/nrays));
2233  }
2234  if (random) {
2235  start[0] = ox-dx+2*dx*gRandom->Rndm();
2236  start[1] = oy-dy+2*dy*gRandom->Rndm();
2237  start[2] = oz-dz+2*dz*gRandom->Rndm();
2238  } else {
2239  start[0] = startx;
2240  start[1] = starty;
2241  start[2] = startz;
2242  }
2243  phi = 2*TMath::Pi()*gRandom->Rndm();
2244  theta= TMath::ACos(1.-2.*gRandom->Rndm());
2245  dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
2246  dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
2247  dir[2]=TMath::Cos(theta);
2248  startnode = fGeoManager->InitTrack(start[0],start[1],start[2], dir[0],dir[1],dir[2]);
2249  line = 0;
2250  if (fGeoManager->IsOutside()) startnode=0;
2251  vis1 = kFALSE;
2252  if (target_vol) {
2253  if (startnode && starget==startnode->GetVolume()->GetName()) vis1 = kTRUE;
2254  } else {
2255  if (startnode && startnode->IsOnScreen()) vis1 = kTRUE;
2256  }
2257  if (vis1) {
2258  line = new TPolyLine3D(2);
2259  line->SetLineColor(startnode->GetVolume()->GetLineColor());
2260  line->SetPoint(ipoint++, start[0], start[1], start[2]);
2261  i++;
2262  pm->Add(line);
2263  }
2264  while ((endnode=fGeoManager->FindNextBoundaryAndStep())) {
2265  step = fGeoManager->GetStep();
2266  if (step<TGeoShape::Tolerance()) inull++;
2267  else inull = 0;
2268  if (inull>5) break;
2269  const Double_t *normal = 0;
2270  if (check_norm) {
2271  normal = fGeoManager->FindNormalFast();
2272  if (!normal) break;
2273  }
2274  vis2 = kFALSE;
2275  if (target_vol) {
2276  if (starget==endnode->GetVolume()->GetName()) vis2 = kTRUE;
2277  } else if (endnode->IsOnScreen()) vis2 = kTRUE;
2278  if (ipoint>0) {
2279  // old visible node had an entry point -> finish segment
2280  line->SetPoint(ipoint, point[0], point[1], point[2]);
2281  if (!vis2 && check_norm) {
2282  normline = new TPolyLine3D(2);
2283  normline->SetLineColor(kBlue);
2284  normline->SetLineWidth(1);
2285  normline->SetPoint(0, point[0], point[1], point[2]);
2286  normline->SetPoint(1, point[0]+normal[0]*normlen,
2287  point[1]+normal[1]*normlen,
2288  point[2]+normal[2]*normlen);
2289  pm->Add(normline);
2290  }
2291  ipoint = 0;
2292  line = 0;
2293  }
2294  if (vis2) {
2295  // create new segment
2296  line = new TPolyLine3D(2);
2297  line->SetLineColor(endnode->GetVolume()->GetLineColor());
2298  line->SetPoint(ipoint++, point[0], point[1], point[2]);
2299  i++;
2300  if (check_norm) {
2301  normline = new TPolyLine3D(2);
2302  normline->SetLineColor(kBlue);
2303  normline->SetLineWidth(2);
2304  normline->SetPoint(0, point[0], point[1], point[2]);
2305  normline->SetPoint(1, point[0]+normal[0]*normlen,
2306  point[1]+normal[1]*normlen,
2307  point[2]+normal[2]*normlen);
2308  }
2309  pm->Add(line);
2310  if (!random) pm->Add(normline);
2311  }
2312  }
2313  }
2314  // draw all segments
2315  for (Int_t m=0; m<pm->GetEntriesFast(); m++) {
2316  line = (TPolyLine3D*)pm->At(m);
2317  if (line) line->Draw("SAME");
2318  }
2319  printf("number of segments : %i\n", i);
2320 // fGeoManager->GetTopVolume()->VisibleDaughters(kFALSE);
2321 // printf("---Daughters of %s made invisible.\n", fGeoManager->GetTopVolume()->GetName());
2322 // printf("---Make them visible with : gGeoManager->GetTopVolume()->VisibleDaughters();\n");
2323  delete pm;
2324 }
2325 
2326 ////////////////////////////////////////////////////////////////////////////////
2327 /// shoot npoints randomly in a box of 1E-5 around current point.
2328 /// return minimum distance to points outside
2329 /// make sure that path to current node is updated
2330 /// get the response of tgeo
2331 
2333  const char* g3path)
2334 {
2335  TGeoNode *node = fGeoManager->FindNode();
2336  TGeoNode *nodegeo = 0;
2337  TGeoNode *nodeg3 = 0;
2338  TGeoNode *solg3 = 0;
2339  if (!node) {dist=-1; return 0;}
2340  Bool_t hasg3 = kFALSE;
2341  if (strlen(g3path)) hasg3 = kTRUE;
2342  TString geopath = fGeoManager->GetPath();
2343  dist = 1E10;
2344  TString common = "";
2345  // cd to common path
2346  Double_t point[3];
2347  Double_t closest[3];
2348  TGeoNode *node1 = 0;
2349  TGeoNode *node_close = 0;
2350  dist = 1E10;
2351  Double_t dist1 = 0;
2352  // initialize size of random box to epsil
2353  Double_t eps[3];
2354  eps[0] = epsil; eps[1]=epsil; eps[2]=epsil;
2355  const Double_t *pointg = fGeoManager->GetCurrentPoint();
2356  if (hasg3) {
2357  TString spath = geopath;
2358  TString name = "";
2359  Int_t index=0;
2360  while (index>=0) {
2361  index = spath.Index("/", index+1);
2362  if (index>0) {
2363  name = spath(0, index);
2364  if (strstr(g3path, name.Data())) {
2365  common = name;
2366  continue;
2367  } else break;
2368  }
2369  }
2370  // if g3 response was given, cd to common path
2371  if (strlen(common.Data())) {
2372  while (strcmp(fGeoManager->GetPath(), common.Data()) && fGeoManager->GetLevel()) {
2373  nodegeo = fGeoManager->GetCurrentNode();
2374  fGeoManager->CdUp();
2375  }
2376  fGeoManager->cd(g3path);
2377  solg3 = fGeoManager->GetCurrentNode();
2378  while (strcmp(fGeoManager->GetPath(), common.Data()) && fGeoManager->GetLevel()) {
2379  nodeg3 = fGeoManager->GetCurrentNode();
2380  fGeoManager->CdUp();
2381  }
2382  if (!nodegeo) return 0;
2383  if (!nodeg3) return 0;
2384  fGeoManager->cd(common.Data());
2386  Double_t xyz[3], local[3];
2387  for (Int_t i=0; i<npoints; i++) {
2388  xyz[0] = point[0] - eps[0] + 2*eps[0]*gRandom->Rndm();
2389  xyz[1] = point[1] - eps[1] + 2*eps[1]*gRandom->Rndm();
2390  xyz[2] = point[2] - eps[2] + 2*eps[2]*gRandom->Rndm();
2391  nodeg3->MasterToLocal(&xyz[0], &local[0]);
2392  if (!nodeg3->GetVolume()->Contains(&local[0])) continue;
2393  dist1 = TMath::Sqrt((xyz[0]-point[0])*(xyz[0]-point[0])+
2394  (xyz[1]-point[1])*(xyz[1]-point[1])+(xyz[2]-point[2])*(xyz[2]-point[2]));
2395  if (dist1<dist) {
2396  // save node and closest point
2397  dist = dist1;
2398  node_close = solg3;
2399  // make the random box smaller
2400  eps[0] = TMath::Abs(point[0]-pointg[0]);
2401  eps[1] = TMath::Abs(point[1]-pointg[1]);
2402  eps[2] = TMath::Abs(point[2]-pointg[2]);
2403  }
2404  }
2405  }
2406  if (!node_close) dist = -1;
2407  return node_close;
2408  }
2409 
2410  // save current point
2411  memcpy(&point[0], pointg, 3*sizeof(Double_t));
2412  for (Int_t i=0; i<npoints; i++) {
2413  // generate a random point in MARS
2414  fGeoManager->SetCurrentPoint(point[0] - eps[0] + 2*eps[0]*gRandom->Rndm(),
2415  point[1] - eps[1] + 2*eps[1]*gRandom->Rndm(),
2416  point[2] - eps[2] + 2*eps[2]*gRandom->Rndm());
2417  // check if new node is different from the old one
2418  if (node1!=node) {
2419  dist1 = TMath::Sqrt((point[0]-pointg[0])*(point[0]-pointg[0])+
2420  (point[1]-pointg[1])*(point[1]-pointg[1])+(point[2]-pointg[2])*(point[2]-pointg[2]));
2421  if (dist1<dist) {
2422  dist = dist1;
2423  node_close = node1;
2424  memcpy(&closest[0], pointg, 3*sizeof(Double_t));
2425  // make the random box smaller
2426  eps[0] = TMath::Abs(point[0]-pointg[0]);
2427  eps[1] = TMath::Abs(point[1]-pointg[1]);
2428  eps[2] = TMath::Abs(point[2]-pointg[2]);
2429  }
2430  }
2431  }
2432  // restore the original point and path
2433  fGeoManager->FindNode(point[0], point[1], point[2]); // really needed ?
2434  if (!node_close) dist=-1;
2435  return node_close;
2436 }
2437 
2438 ////////////////////////////////////////////////////////////////////////////////
2439 /// Shoot one ray from start point with direction (dirx,diry,dirz). Fills input array
2440 /// with points just after boundary crossings.
2441 
2442 Double_t *TGeoChecker::ShootRay(Double_t *start, Double_t dirx, Double_t diry, Double_t dirz, Double_t *array, Int_t &nelem, Int_t &dim, Double_t *endpoint) const
2443 {
2444 // Int_t array_dimension = 3*dim;
2445  nelem = 0;
2446  Int_t istep = 0;
2447  if (!dim) {
2448  printf("empty input array\n");
2449  return array;
2450  }
2451 // fGeoManager->CdTop();
2452  const Double_t *point = fGeoManager->GetCurrentPoint();
2453  TGeoNode *endnode;
2454  Bool_t is_entering;
2455  Double_t step, forward;
2456  Double_t dir[3];
2457  dir[0] = dirx;
2458  dir[1] = diry;
2459  dir[2] = dirz;
2460  fGeoManager->InitTrack(start, &dir[0]);
2462 // printf("Start : (%f,%f,%f)\n", point[0], point[1], point[2]);
2464  step = fGeoManager->GetStep();
2465 // printf("---next : at step=%f\n", step);
2466  if (step>1E10) return array;
2467  endnode = fGeoManager->Step();
2468  is_entering = fGeoManager->IsEntering();
2469  while (step<1E10) {
2470  if (endpoint) {
2471  forward = dirx*(endpoint[0]-point[0])+diry*(endpoint[1]-point[1])+dirz*(endpoint[2]-point[2]);
2472  if (forward<1E-3) {
2473 // printf("exit : Passed start point. nelem=%i\n", nelem);
2474  return array;
2475  }
2476  }
2477  if (is_entering) {
2478  if (nelem>=dim) {
2479  Double_t *temparray = new Double_t[3*(dim+20)];
2480  memcpy(temparray, array, 3*dim*sizeof(Double_t));
2481  delete [] array;
2482  array = temparray;
2483  dim += 20;
2484  }
2485  memcpy(&array[3*nelem], point, 3*sizeof(Double_t));
2486 // printf("%i (%f, %f, %f) step=%f\n", nelem, point[0], point[1], point[2], step);
2487  nelem++;
2488  } else {
2489  if (endnode==0 && step>1E10) {
2490 // printf("exit : NULL endnode. nelem=%i\n", nelem);
2491  return array;
2492  }
2493  if (!fGeoManager->IsEntering()) {
2494 // if (startnode) printf("stepping %f from (%f, %f, %f) inside %s...\n", step,point[0], point[1], point[2], startnode->GetName());
2495 // else printf("stepping %f from (%f, %f, %f) OUTSIDE...\n", step,point[0], point[1], point[2]);
2496  istep = 0;
2497  }
2498  while (!fGeoManager->IsEntering()) {
2499  istep++;
2500  if (istep>1E3) {
2501 // Error("ShootRay", "more than 1000 steps. Step was %f", step);
2502  nelem = 0;
2503  return array;
2504  }
2505  fGeoManager->SetStep(1E-5);
2506  endnode = fGeoManager->Step();
2507  }
2508  if (istep>0) printf("%i steps\n", istep);
2509  if (nelem>=dim) {
2510  Double_t *temparray = new Double_t[3*(dim+20)];
2511  memcpy(temparray, array, 3*dim*sizeof(Double_t));
2512  delete [] array;
2513  array = temparray;
2514  dim += 20;
2515  }
2516  memcpy(&array[3*nelem], point, 3*sizeof(Double_t));
2517 // if (endnode) printf("%i (%f, %f, %f) step=%f\n", nelem, point[0], point[1], point[2], step);
2518  nelem++;
2519  }
2521  step = fGeoManager->GetStep();
2522 // printf("---next at step=%f\n", step);
2523  endnode = fGeoManager->Step();
2524  is_entering = fGeoManager->IsEntering();
2525  }
2526  return array;
2527 // printf("exit : INFINITE step. nelem=%i\n", nelem);
2528 }
2529 
2530 ////////////////////////////////////////////////////////////////////////////////
2531 /// Check time of finding "Where am I" for n points.
2532 
2533 void TGeoChecker::Test(Int_t npoints, Option_t *option)
2534 {
2535  Bool_t recheck = !strcmp(option, "RECHECK");
2536  if (recheck) printf("RECHECK\n");
2537  const TGeoShape *shape = fGeoManager->GetTopVolume()->GetShape();
2538  Double_t dx = ((TGeoBBox*)shape)->GetDX();
2539  Double_t dy = ((TGeoBBox*)shape)->GetDY();
2540  Double_t dz = ((TGeoBBox*)shape)->GetDZ();
2541  Double_t ox = (((TGeoBBox*)shape)->GetOrigin())[0];
2542  Double_t oy = (((TGeoBBox*)shape)->GetOrigin())[1];
2543  Double_t oz = (((TGeoBBox*)shape)->GetOrigin())[2];
2544  Double_t *xyz = new Double_t[3*npoints];
2545  TStopwatch *timer = new TStopwatch();
2546  printf("Random box : %f, %f, %f\n", dx, dy, dz);
2547  timer->Start(kFALSE);
2548  Int_t i;
2549  for (i=0; i<npoints; i++) {
2550  xyz[3*i] = ox-dx+2*dx*gRandom->Rndm();
2551  xyz[3*i+1] = oy-dy+2*dy*gRandom->Rndm();
2552  xyz[3*i+2] = oz-dz+2*dz*gRandom->Rndm();
2553  }
2554  timer->Stop();
2555  printf("Generation time :\n");
2556  timer->Print();
2557  timer->Reset();
2558  TGeoNode *node, *node1;
2559  printf("Start... %i points\n", npoints);
2560  timer->Start(kFALSE);
2561  for (i=0; i<npoints; i++) {
2562  fGeoManager->SetCurrentPoint(xyz+3*i);
2563  if (recheck) fGeoManager->CdTop();
2564  node = fGeoManager->FindNode();
2565  if (recheck) {
2566  node1 = fGeoManager->FindNode();
2567  if (node1 != node) {
2568  printf("Difference for x=%g y=%g z=%g\n", xyz[3*i], xyz[3*i+1], xyz[3*i+2]);
2569  printf(" from top : %s\n", node->GetName());
2570  printf(" redo : %s\n", fGeoManager->GetPath());
2571  }
2572  }
2573  }
2574  timer->Stop();
2575  timer->Print();
2576  delete [] xyz;
2577  delete timer;
2578 }
2579 
2580 ////////////////////////////////////////////////////////////////////////////////
2581 /// Geometry overlap checker based on sampling.
2582 
2583 void TGeoChecker::TestOverlaps(const char* path)
2584 {
2586  printf("Checking overlaps for path :\n");
2587  if (!fGeoManager->cd(path)) return;
2588  TGeoNode *checked = fGeoManager->GetCurrentNode();
2589  checked->InspectNode();
2590  // shoot 1E4 points in the shape of the current volume
2591  Int_t npoints = 1000000;
2592  Double_t big = 1E6;
2593  Double_t xmin = big;
2594  Double_t xmax = -big;
2595  Double_t ymin = big;
2596  Double_t ymax = -big;
2597  Double_t zmin = big;
2598  Double_t zmax = -big;
2599  TObjArray *pm = new TObjArray(128);
2600  TPolyMarker3D *marker = 0;
2601  TPolyMarker3D *markthis = new TPolyMarker3D();
2602  markthis->SetMarkerColor(5);
2603  TNtuple *ntpl = new TNtuple("ntpl","random points","x:y:z");
2605  Double_t *point = new Double_t[3];
2606  Double_t dx = ((TGeoBBox*)shape)->GetDX();
2607  Double_t dy = ((TGeoBBox*)shape)->GetDY();
2608  Double_t dz = ((TGeoBBox*)shape)->GetDZ();
2609  Double_t ox = (((TGeoBBox*)shape)->GetOrigin())[0];
2610  Double_t oy = (((TGeoBBox*)shape)->GetOrigin())[1];
2611  Double_t oz = (((TGeoBBox*)shape)->GetOrigin())[2];
2612  Double_t *xyz = new Double_t[3*npoints];
2613  Int_t i=0;
2614  printf("Generating %i points inside %s\n", npoints, fGeoManager->GetPath());
2615  while (i<npoints) {
2616  point[0] = ox-dx+2*dx*gRandom->Rndm();
2617  point[1] = oy-dy+2*dy*gRandom->Rndm();
2618  point[2] = oz-dz+2*dz*gRandom->Rndm();
2619  if (!shape->Contains(point)) continue;
2620  // convert each point to MARS
2621 // printf("local %9.3f %9.3f %9.3f\n", point[0], point[1], point[2]);
2622  fGeoManager->LocalToMaster(point, &xyz[3*i]);
2623 // printf("master %9.3f %9.3f %9.3f\n", xyz[3*i], xyz[3*i+1], xyz[3*i+2]);
2624  xmin = TMath::Min(xmin, xyz[3*i]);
2625  xmax = TMath::Max(xmax, xyz[3*i]);
2626  ymin = TMath::Min(ymin, xyz[3*i+1]);
2627  ymax = TMath::Max(ymax, xyz[3*i+1]);
2628  zmin = TMath::Min(zmin, xyz[3*i+2]);
2629  zmax = TMath::Max(zmax, xyz[3*i+2]);
2630  i++;
2631  }
2632  delete [] point;
2633  ntpl->Fill(xmin,ymin,zmin);
2634  ntpl->Fill(xmax,ymin,zmin);
2635  ntpl->Fill(xmin,ymax,zmin);
2636  ntpl->Fill(xmax,ymax,zmin);
2637  ntpl->Fill(xmin,ymin,zmax);
2638  ntpl->Fill(xmax,ymin,zmax);
2639  ntpl->Fill(xmin,ymax,zmax);
2640  ntpl->Fill(xmax,ymax,zmax);
2641  ntpl->Draw("z:y:x");
2642 
2643  // shoot the poins in the geometry
2644  TGeoNode *node;
2645  TString cpath;
2646  Int_t ic=0;
2647  TObjArray *overlaps = new TObjArray();
2648  printf("using FindNode...\n");
2649  for (Int_t j=0; j<npoints; j++) {
2650  // always start from top level (testing only)
2651  fGeoManager->CdTop();
2652  fGeoManager->SetCurrentPoint(&xyz[3*j]);
2653  node = fGeoManager->FindNode();
2654  cpath = fGeoManager->GetPath();
2655  if (cpath.Contains(path)) {
2656  markthis->SetNextPoint(xyz[3*j], xyz[3*j+1], xyz[3*j+2]);
2657  continue;
2658  }
2659  // current point is found in an overlapping node
2660  if (!node) ic=128;
2661  else ic = node->GetVolume()->GetLineColor();
2662  if (ic >= 128) ic = 0;
2663  marker = (TPolyMarker3D*)pm->At(ic);
2664  if (!marker) {
2665  marker = new TPolyMarker3D();
2666  marker->SetMarkerColor(ic);
2667  pm->AddAt(marker, ic);
2668  }
2669  // draw the overlapping point
2670  marker->SetNextPoint(xyz[3*j], xyz[3*j+1], xyz[3*j+2]);
2671  if (node) {
2672  if (overlaps->IndexOf(node) < 0) overlaps->Add(node);
2673  }
2674  }
2675  // draw all overlapping points
2676 // for (Int_t m=0; m<128; m++) {
2677 // marker = (TPolyMarker3D*)pm->At(m);
2678 // if (marker) marker->Draw("SAME");
2679 // }
2680  markthis->Draw("SAME");
2681  if (gPad) gPad->Update();
2682  // display overlaps
2683  if (overlaps->GetEntriesFast()) {
2684  printf("list of overlapping nodes :\n");
2685  for (i=0; i<overlaps->GetEntriesFast(); i++) {
2686  node = (TGeoNode*)overlaps->At(i);
2687  if (node->IsOverlapping()) printf("%s MANY\n", node->GetName());
2688  else printf("%s ONLY\n", node->GetName());
2689  }
2690  } else printf("No overlaps\n");
2691  delete ntpl;
2692  delete pm;
2693  delete [] xyz;
2694  delete overlaps;
2695 }
2696 
2697 ////////////////////////////////////////////////////////////////////////////////
2698 /// Estimate weight of top level volume with a precision SIGMA(W)/W
2699 /// better than PRECISION. Option can be "v" - verbose (default).
2700 
2702 {
2703  TList *matlist = fGeoManager->GetListOfMaterials();
2704  Int_t nmat = matlist->GetSize();
2705  if (!nmat) return 0;
2706  Int_t *nin = new Int_t[nmat];
2707  memset(nin, 0, nmat*sizeof(Int_t));
2708  TString opt = option;
2709  opt.ToLower();
2710  Bool_t isverbose = opt.Contains("v");
2712  Double_t dx = box->GetDX();
2713  Double_t dy = box->GetDY();
2714  Double_t dz = box->GetDZ();
2715  Double_t ox = (box->GetOrigin())[0];
2716  Double_t oy = (box->GetOrigin())[1];
2717  Double_t oz = (box->GetOrigin())[2];
2718  Double_t x,y,z;
2719  TGeoNode *node;
2720  TGeoMaterial *mat;
2721  Double_t vbox = 0.000008*dx*dy*dz; // m3
2722  Bool_t end = kFALSE;
2723  Double_t weight=0, sigma, eps, dens;
2724  Double_t eps0=1.;
2725  Int_t indmat;
2726  Int_t igen=0;
2727  Int_t iin = 0;
2728  while (!end) {
2729  x = ox-dx+2*dx*gRandom->Rndm();
2730  y = oy-dy+2*dy*gRandom->Rndm();
2731  z = oz-dz+2*dz*gRandom->Rndm();
2732  node = fGeoManager->FindNode(x,y,z);
2733  igen++;
2734  if (!node) continue;
2735  mat = node->GetVolume()->GetMedium()->GetMaterial();
2736  indmat = mat->GetIndex();
2737  if (indmat<0) continue;
2738  nin[indmat]++;
2739  iin++;
2740  if ((iin%100000)==0 || igen>1E8) {
2741  weight = 0;
2742  sigma = 0;
2743  for (indmat=0; indmat<nmat; indmat++) {
2744  mat = (TGeoMaterial*)matlist->At(indmat);
2745  dens = mat->GetDensity(); // [g/cm3]
2746  if (dens<1E-2) dens=0;
2747  dens *= 1000.; // [kg/m3]
2748  weight += dens*Double_t(nin[indmat]);
2749  sigma += dens*dens*nin[indmat];
2750  }
2751  sigma = TMath::Sqrt(sigma);
2752  eps = sigma/weight;
2753  weight *= vbox/Double_t(igen);
2754  sigma *= vbox/Double_t(igen);
2755  if (eps<precision || igen>1E8) {
2756  if (isverbose) {
2757  printf("=== Weight of %s : %g +/- %g [kg]\n",
2758  fGeoManager->GetTopVolume()->GetName(), weight, sigma);
2759  }
2760  end = kTRUE;
2761  } else {
2762  if (isverbose && eps<0.5*eps0) {
2763  printf("%8dK: %14.7g kg %g %%\n",
2764  igen/1000, weight, eps*100);
2765  eps0 = eps;
2766  }
2767  }
2768  }
2769  }
2770  delete [] nin;
2771  return weight;
2772 }
2773 ////////////////////////////////////////////////////////////////////////////////
2774 /// count voxel timing
2775 
2777 {
2778  TStopwatch timer;
2779  Double_t time;
2780  TGeoShape *shape = vol->GetShape();
2781  TGeoNode *node;
2782  TGeoMatrix *matrix;
2783  Double_t *point;
2784  Double_t local[3];
2785  Int_t *checklist;
2786  Int_t ncheck;
2788  TGeoStateInfo &td = *nav->GetCache()->GetInfo();
2789  timer.Start();
2790  for (Int_t i=0; i<npoints; i++) {
2791  point = xyz + 3*i;
2792  if (!shape->Contains(point)) continue;
2793  checklist = voxels->GetCheckList(point, ncheck, td);
2794  if (!checklist) continue;
2795  if (!ncheck) continue;
2796  for (Int_t id=0; id<ncheck; id++) {
2797  node = vol->GetNode(checklist[id]);
2798  matrix = node->GetMatrix();
2799  matrix->MasterToLocal(point, &local[0]);
2800  if (node->GetVolume()->GetShape()->Contains(&local[0])) break;
2801  }
2802  }
2803  nav->GetCache()->ReleaseInfo();
2804  time = timer.CpuTime();
2805  return time;
2806 }
2807 
2808 ////////////////////////////////////////////////////////////////////////////////
2809 /// Returns optimal voxelization type for volume vol.
2810 /// - kFALSE - cartesian
2811 /// - kTRUE - cylindrical
2812 
2814 {
2815  return kFALSE;
2816 }
void SetTopVisible(Bool_t vis=kTRUE)
make top volume visible on screen
Statefull info for the current geometry level.
Definition: TGeoStateInfo.h:21
Bool_t IsEntering() const
Definition: TGeoManager.h:401
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
virtual ~TGeoChecker()
Destructor.
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3244
void TestOverlaps(const char *path)
Geometry overlap checker based on sampling.
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
An array of TObjects.
Definition: TObjArray.h:37
float xmin
Definition: THbookFile.cxx:93
TGeoNode * InitTrack(const Double_t *point, const Double_t *dir)
Initialize current point and current direction vector (normalized) in MARS.
void GetPath(TString &path) const
Returns the path for the current node.
Definition: TGeoNode.cxx:1183
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Double_t RealTime()
Stop the stopwatch (if it is running) and return the realtime (in seconds) passed between the start a...
Definition: TStopwatch.cxx:110
The manager class for any TGeo geometry.
Definition: TGeoManager.h:38
Double_t * ShootRay(Double_t *start, Double_t dirx, Double_t diry, Double_t dirz, Double_t *array, Int_t &nelem, Int_t &dim, Double_t *enpoint=0) const
Shoot one ray from start point with direction (dirx,diry,dirz).
Box class.
Definition: TGeoBBox.h:17
long long Long64_t
Definition: RtypesCore.h:69
Bool_t IsSameLocation(Double_t x, Double_t y, Double_t z, Bool_t change=kFALSE)
Checks if point (x,y,z) is still in the current node.
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
Definition: TStopwatch.cxx:58
auto * m
Definition: textangle.C:8
void SetCurrentDirection(Double_t *dir)
Definition: TGeoManager.h:506
virtual void LabelsOption(Option_t *option="h", Option_t *axis="X")
Set option(s) to draw axis with labels.
Definition: TH1.cxx:5059
virtual void Voxelize(Option_t *option="")
Voxelize attached volume according to option If the volume is an assembly, make sure the bbox is comp...
Double_t Log(Double_t x)
Definition: TMath.h:648
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)=0
void Print(Option_t *option="") const
Print the real and cpu time passed between the start and stop events.
Definition: TStopwatch.cxx:219
TLine * line
virtual Double_t GetDX() const
Definition: TGeoBBox.h:70
Double_t * fVal2
Array of number of crossings per volume.
Definition: TGeoChecker.h:47
TGeoOverlap * MakeCheckOverlap(const char *name, TGeoVolume *vol1, TGeoVolume *vol2, TGeoMatrix *mat1, TGeoMatrix *mat2, Bool_t isovlp, Double_t ovlp)
Check if the 2 non-assembly volume candidates overlap/extrude. Returns overlap object.
TGeoNode * fSelectedNode
Timer.
Definition: TGeoChecker.h:50
virtual Double_t GetDensity() const
Definition: TGeoMaterial.h:87
Bool_t IsOverlapping() const
Definition: TGeoNode.h:102
const char Option_t
Definition: RtypesCore.h:62
Geometrical transformation package.
Definition: TGeoMatrix.h:40
TBuffer3D * fBuff1
Definition: TGeoChecker.h:43
Double_t Safety(Bool_t inside=kFALSE)
Compute safe distance from the current point.
return c1
Definition: legend1.C:41
Definition: Rtypes.h:59
constexpr Double_t TwoPi()
Definition: TMath.h:44
float ymin
Definition: THbookFile.cxx:93
virtual Int_t * GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td)
get the list of daughter indices for which point is inside their bbox
TGeoStateInfo * GetInfo()
Get next state info pointer.
Definition: TGeoCache.cxx:318
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
void CdUp()
Go one level up in geometry.
void CheckOverlaps(Double_t ovlp=0.1, Option_t *option="")
Check all geometry for illegal overlaps within a limit OVLP.
R__EXTERN TStyle * gStyle
Definition: TStyle.h:402
void ShapeNormal(TGeoShape *shape, Int_t nsamples, Option_t *option)
Check of validity of the normal for a given shape.
void CleanPoints(Double_t *points, Int_t &numPoints) const
Number of points on mesh to be checked.
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4364
TGeoMaterial * GetMaterial() const
Definition: TGeoMedium.h:52
THist< 1, float, THistStatContent, THistStatUncertainty > TH1F
Definition: THist.hxx:285
TH1 * h
Definition: legend2.C:5
virtual void CheckBoundaryErrors(Int_t ntracks=1000000, Double_t radius=-1.)
Check pushes and pulls needed to cross the next boundary with respect to the position given by FindNe...
#define lnext(otri1, otri2)
Definition: triangle.c:942
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:48
TGeoVolume * fVsafe
Definition: TGeoChecker.h:42
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
TVirtualPad * cd(Int_t subpadnumber=0)
Set current canvas & pad.
Definition: TCanvas.cxx:688
TH2F * LegoPlot(Int_t ntheta=60, Double_t themin=0., Double_t themax=180., Int_t nphi=90, Double_t phimin=0., Double_t phimax=360., Double_t rmin=0., Double_t rmax=9999999, Option_t *option="")
Generate a lego plot fot the top volume, according to option.
void Skip()
Stop iterating the current branch.
Definition: TGeoNode.cxx:1231
virtual void Draw(Option_t *option="")
draw top volume according to option
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
TGeoVolume * GetVolume(const char *name) const
Search for a named volume. All trailing blanks stripped.
Class describing translations.
Definition: TGeoMatrix.h:121
static Int_t GetVerboseLevel()
Set verbosity level (static function).
static void SetVerboseLevel(Int_t vl)
Return current verbosity level (static function).
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
void InspectShape() const
Definition: TGeoVolume.h:196
UInt_t NbPnts() const
Definition: TBuffer3D.h:80
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5330
Basic string class.
Definition: TString.h:125
Matrix class used for computing global transformations Should NOT be used for node definition...
Definition: TGeoMatrix.h:420
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:567
Base class describing materials.
Definition: TGeoMaterial.h:29
void Multiply(const TGeoMatrix *right)
multiply to the right with an other transformation if right is identity matrix, just return ...
void MasterToLocal(const Double_t *master, Double_t *local) const
Definition: TGeoManager.h:514
Double_t CpuTime()
Stop the stopwatch (if it is running) and return the cputime (in seconds) passed between the start an...
Definition: TStopwatch.cxx:125
virtual void DrawOnly(Option_t *option="")
draw only this volume
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
int Int_t
Definition: RtypesCore.h:41
void VisibleDaughters(Bool_t vis=kTRUE)
set visibility for daughters
A 3-dimensional polyline.
Definition: TPolyLine3D.h:31
bool Bool_t
Definition: RtypesCore.h:59
TGeoVolume * GetMasterVolume() const
Definition: TGeoManager.h:499
TGeoNodeCache * GetCache() const
TGeoNode * GetNode(Int_t level) const
Returns current node at a given level.
Definition: TGeoNode.cxx:1172
Definition: Rtypes.h:59
Double_t GetStep() const
Definition: TGeoManager.h:385
void Score(TGeoVolume *, Int_t, Double_t)
Score a hit for VOL.
void Reset(TGeoVolume *top=0)
Resets the iterator for volume TOP.
Definition: TGeoNode.cxx:1211
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Int_t GetLevel() const
Definition: TGeoManager.h:495
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
static constexpr double rad
Int_t PropagateInGeom(Double_t *, Double_t *)
Propagate from START along DIR from boundary to boundary until exiting geometry.
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
virtual void SetTopMargin(Float_t topmargin)
Set Pad top margin in fraction of the pad height.
Definition: TAttPad.cxx:130
Bool_t NeedRebuild() const
TList * GetListOfMaterials() const
Definition: TGeoManager.h:463
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1225
virtual void PrintInfo() const
Print some info.
TObjArray * GetNodes()
Definition: TGeoVolume.h:170
static Double_t Tolerance()
Definition: TGeoShape.h:91
void ResetState()
Reset current state flags.
Int_t GetNdaughters() const
Definition: TGeoVolume.h:350
Int_t fNmeshPoints
Number of checks for current volume.
Definition: TGeoChecker.h:52
TGeoVolume * MakeSphere(const char *name, TGeoMedium *medium, Double_t rmin, Double_t rmax, Double_t themin=0, Double_t themax=180, Double_t phimin=0, Double_t phimax=360)
Make in one step a volume pointing to a sphere shape with given medium.
virtual Bool_t Contains(const Double_t *point) const =0
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Double_t TimingPerVolume(TGeoVolume *)
Compute timing per "FindNextBoundary" + "Safety" call.
TGeoPatternFinder * GetFinder() const
Definition: TGeoVolume.h:178
void Stop()
Stop the stopwatch.
Definition: TStopwatch.cxx:77
Double_t x[n]
Definition: legend1.C:17
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2365
Int_t GetLevel() const
Definition: TGeoNode.h:274
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7898
void CheckOverlaps(const TGeoVolume *vol, Double_t ovlp=0.1, Option_t *option="")
Check illegal overlaps for volume VOL within a limit OVLP.
void SetCurrentPoint(Double_t *point)
Definition: TGeoManager.h:503
A geometry iterator.
Definition: TGeoNode.h:243
void CdDown(Int_t index)
Make a daughter of current node current.
virtual void SetGrid(Int_t valuex=1, Int_t valuey=1)
Definition: TPad.h:327
void InspectNode() const
Inspect this node.
Definition: TGeoNode.cxx:317
const char * GetPath() const
Get path to the current node in the form /node0/node1/...
UInt_t NbSegs() const
Definition: TBuffer3D.h:81
Bool_t IsOnScreen() const
check if this node is drawn. Assumes that this node is current
Definition: TGeoNode.cxx:308
Double_t * fPnts
Definition: TBuffer3D.h:112
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
TGeoMedium * GetMedium() const
Definition: TGeoVolume.h:176
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
const TGeoMatrix * GetCurrentMatrix() const
Returns global matrix for current node.
Definition: TGeoNode.cxx:1156
void CheckOverlapsBySampling(TGeoVolume *vol, Double_t ovlp=0.1, Int_t npoints=1000000) const
Check illegal overlaps for volume VOL within a limit OVLP by sampling npoints inside the volume shape...
void SetTopName(const char *name)
Set the top name for path.
Definition: TGeoNode.cxx:1222
void Test(Int_t npoints, Option_t *option)
Check time of finding "Where am I" for n points.
virtual Bool_t IsVisible() const
Definition: TGeoVolume.h:156
void LocalToMaster(const Double_t *local, Double_t *master) const
Definition: TGeoManager.h:511
virtual TGeoMatrix * GetMatrix() const =0
const Double_t sigma
TGeoMaterial * GetMaterial() const
Definition: TGeoVolume.h:175
void RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz, const char *target_vol=0, Bool_t check_norm=kFALSE)
Randomly shoot nrays from point (startx,starty,startz) and plot intersections with surfaces for curre...
void SetNmeshPoints(Int_t npoints=1000)
Set number of points to be generated on the shape outline when checking for overlaps.
void Continue()
Resume a stopped stopwatch.
Definition: TStopwatch.cxx:93
XFontStruct * id
Definition: TGX11.cxx:108
virtual void LocalToMasterVect(const Double_t *local, Double_t *master) const
convert a vector by multiplying its column vector (x, y, z, 1) to matrix inverse
Definition: TGeoMatrix.cxx:363
void RestoreMasterVolume()
Restore the master volume of the geometry.
TH1F * h1
Definition: legend1.C:5
constexpr Double_t Pi()
Definition: TMath.h:40
Int_t GetColour() const
Definition: TGeoNode.h:85
static void SetTransform(TGeoMatrix *matrix)
Set current transformation matrix that applies to shape.
Definition: TGeoShape.cxx:544
void SetOverlap(Double_t ovlp)
Definition: TGeoOverlap.h:94
TGeoNode * GetCurrentNode() const
Definition: TGeoManager.h:487
void ReleaseInfo()
Release last used state info pointer.
Definition: TGeoCache.cxx:335
REAL * vertex
Definition: triangle.c:512
virtual void AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=0, Option_t *option="")
Add a TGeoNode to the list of nodes.
Definition: TGeoVolume.cxx:984
A doubly linked list.
Definition: TList.h:44
virtual Double_t Rndm()
Machine independent random number generator.
Definition: TRandom.cxx:533
Int_t fNchecks
Selected node for overlap checking.
Definition: TGeoChecker.h:51
Int_t GetIndex()
Retrieve material index in the list of materials.
point * points
Definition: X3DBuffer.c:20
Double_t * fVal1
Definition: TGeoChecker.h:46
virtual const char * GetName() const
Get the shape name.
Definition: TGeoShape.cxx:248
Int_t AddOverlap(const TNamed *ovlp)
Add an illegal overlap/extrusion to the list.
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
Double_t CheckVoxels(TGeoVolume *vol, TGeoVoxelFinder *voxels, Double_t *xyz, Int_t npoints)
count voxel timing
float ymax
Definition: THbookFile.cxx:93
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TTree.cxx:9212
Bool_t TestVoxels(TGeoVolume *vol, Int_t npoints=1000000)
Returns optimal voxelization type for volume vol.
Base abstract class for all shapes.
Definition: TGeoShape.h:25
TPaveText * pt
ROOT::R::TRInterface & r
Definition: Object.C:4
A simple TTree restricted to a list of float variables only.
Definition: TNtuple.h:28
void ShapeSafety(TGeoShape *shape, Int_t nsamples, Option_t *option)
Check of validity of safe distance for a given shape.
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2969
TGeoNode * Step(Bool_t is_geom=kTRUE, Bool_t cross=kTRUE)
Make a rectilinear step of length fStep from current point (fPoint) on current direction (fDirection)...
void SetNextPoint(Double_t x, Double_t y, Double_t z)
Set next overlapping point.
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
Bool_t * fFlags
Array of timing per volume.
Definition: TGeoChecker.h:48
virtual Int_t Write(const char *name=0, Int_t opt=0, Int_t bufsiz=0)
Write memory objects to this file.
Definition: TFile.cxx:2313
TGeoNode * FindNextBoundaryAndStep(Double_t stepmax=TGeoShape::Big(), Bool_t compsafe=kFALSE)
Compute distance to next boundary within STEPMAX.
virtual void FindOverlaps(Int_t inode) const
create the list of nodes for which the bboxes overlap with inode&#39;s bbox
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
Int_t GetIndex(const TGeoNode *node) const
get index number for a given daughter
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:249
void SetStep(Double_t step)
Definition: TGeoManager.h:399
Double_t * FindNormalFast()
Computes fast normal to next crossed boundary, assuming that the current point is close enough to the...
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const =0
void RandomPoints(TGeoVolume *vol, Int_t npoints, Option_t *option)
Draw random points in the bounding box of a volume.
static int push(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout)
Definition: civetweb.c:3754
virtual void CheckBoundaryReference(Int_t icheck=-1)
Check the boundary errors reference file created by CheckBoundaryErrors method.
TGeoVolume * GetCurrentVolume() const
Definition: TGeoManager.h:491
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label...
Definition: TH1.cxx:4928
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
TGeoManager * fGeoManager
Definition: TGeoChecker.h:41
TGeoHMatrix * GetCurrentMatrix() const
Definition: TGeoManager.h:484
virtual const Double_t * GetOrigin() const
Definition: TGeoBBox.h:73
Bool_t SetRawSizes(UInt_t reqPnts, UInt_t reqPntsCapacity, UInt_t reqSegs, UInt_t reqSegsCapacity, UInt_t reqPols, UInt_t reqPolsCapacity)
Set kRaw tessellation section of buffer with supplied sizes.
Definition: TBuffer3D.cxx:359
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
Generic 3D primitive description class.
Definition: TBuffer3D.h:17
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
TGeoNode * GetTopNode() const
Definition: TGeoManager.h:501
TAxis * GetYaxis()
Definition: TH1.h:316
Double_t ACos(Double_t)
Definition: TMath.h:571
float xmax
Definition: THbookFile.cxx:93
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
TBuffer3D * fBuff2
Definition: TGeoChecker.h:44
UInt_t NbPols() const
Definition: TBuffer3D.h:82
TObject * fID
Definition: TBuffer3D.h:87
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:610
virtual Double_t GetDY() const
Definition: TGeoBBox.h:71
virtual void Draw(Option_t *option="")
Draws 3-D polymarker with its current attributes.
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:253
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=0) const =0
constexpr Double_t E()
Definition: TMath.h:74
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Definition: TGeoMatrix.cxx:339
Double_t Cos(Double_t)
Definition: TMath.h:550
TGeoNode * FindNode(Bool_t safe_start=kTRUE)
Returns deepest node containing current point.
Bool_t Contains(const Double_t *point) const
Definition: TGeoVolume.h:112
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
Convert the point coordinates from mother reference to local reference system.
Definition: TGeoNode.cxx:553
const Bool_t kFALSE
Definition: RtypesCore.h:88
Geometry checking package.
Definition: TGeoChecker.h:37
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=0) const =0
virtual void Draw(Option_t *option="")
Draw this 3-D polyline with its current attributes.
virtual Int_t GetCurrentNodeIndex() const
Definition: TGeoVolume.h:168
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
virtual Bool_t cd(const char *path="")
Browse the tree of nodes starting from fTopNode according to pathname.
virtual Int_t SetNextPoint(Double_t x, Double_t y, Double_t z)
Set point following LastPoint to x, y, z.
The Canvas class.
Definition: TCanvas.h:31
void OpProgress(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch=0, Bool_t last=kFALSE, Bool_t refresh=kFALSE, const char *msg="")
Print current operation progress.
virtual void SetPoint(Int_t point, Double_t x, Double_t y, Double_t z)
Set point n to x, y, z.
return c2
Definition: legend2.C:14
Bool_t IsOutside() const
Definition: TGeoManager.h:405
#define ClassImp(name)
Definition: Rtypes.h:359
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix
Definition: TGeoMatrix.cxx:406
double Double_t
Definition: RtypesCore.h:55
Int_t GetNumber() const
Definition: TGeoVolume.h:185
virtual void SetVisibility(Bool_t vis=kTRUE)
set visibility of this volume
virtual void GetMeshNumbers(Int_t &, Int_t &, Int_t &) const
Definition: TGeoShape.h:125
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
void CheckShape(TGeoShape *shape, Int_t testNo, Int_t nsamples, Option_t *option)
Test for shape navigation methods.
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:589
void CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
Shoot nrays with random directions from starting point (startx, starty, startz) in the reference fram...
void CdTop()
Make top level node the current node.
void CheckPoint(Double_t x=0, Double_t y=0, Double_t z=0, Option_t *option="")
Draw point (x,y,z) over the picture of the daughters of the volume containing this point...
static RooMathCoreReg dummy
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:355
int nentries
Definition: THbookFile.cxx:89
Double_t y[n]
Definition: legend1.C:17
virtual Int_t Fill()
Fill a Ntuple with current values in fArgs.
Definition: TNtuple.cxx:170
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
void forward(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData)
apply the weights (and functions) in forward direction of the DNN
Definition: NeuralNet.icc:545
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition: TRandom.cxx:627
Finder class handling voxels.
TObjArray * GetListOfUVolumes() const
Definition: TGeoManager.h:469
static Double_t Big()
Definition: TGeoShape.h:88
virtual Long64_t GetEntries() const
Definition: TTree.h:382
virtual Double_t Capacity() const =0
virtual void SetLineColor(Color_t lcolor)
Set the line color.
virtual UInt_t SetCanExtend(UInt_t extendBitMask)
Make the histogram axes extendable / not extendable according to the bit mask returns the previous bi...
Definition: TH1.cxx:6100
void PrintOverlaps() const
Print the current list of overlaps held by the manager class.
Mother of all ROOT objects.
Definition: TObject.h:37
Double_t Weight(Double_t precision=0.01, Option_t *option="v")
Estimate weight of top level volume with a precision SIGMA(W)/W better than PRECISION.
Base class describing geometry overlaps.
Definition: TGeoOverlap.h:37
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
TGeoNode * FindNextBoundary(Double_t stepmax=TGeoShape::Big(), const char *path="", Bool_t frombdr=kFALSE)
Find distance to next boundary and store it in fStep.
Class providing navigation API for TGeo geometries.
Definition: TGeoNavigator.h:33
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1701
TGeoNode * SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil, const char *g3path)
shoot npoints randomly in a box of 1E-5 around current point.
void CheckGeometryFull(Bool_t checkoverlaps=kTRUE, Bool_t checkcrossings=kTRUE, Int_t nrays=10000, const Double_t *vertex=NULL)
Geometry checking.
char Char_t
Definition: RtypesCore.h:29
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition: TGeoNode.h:39
void ShapeDistances(TGeoShape *shape, Int_t nsamples, Option_t *option)
Test TGeoShape::DistFromInside/Outside.
R__EXTERN TGeoIdentity * gGeoIdentity
Definition: TGeoMatrix.h:478
void SetVisLevel(Int_t level=3)
set default level down to which visualization is performed
TGeoNavigator * GetCurrentNavigator() const
Returns current navigator for the calling thread.
A 3D polymarker.
Definition: TPolyMarker3D.h:32
virtual void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0)
Automatic pad generation by division.
Definition: TPad.cxx:1153
#define dnext(otri1, otri2)
Definition: triangle.c:986
virtual Int_t GetN() const
Definition: TPolyMarker3D.h:58
Double_t * FindNormal(Bool_t forward=kTRUE)
Computes normal vector to the next surface that will be or was already crossed when propagating on a ...
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
const Double_t * GetCurrentPoint() const
Definition: TGeoManager.h:489
Int_t * GetOverlaps(Int_t &novlp) const
Definition: TGeoNode.h:93
Double_t Sin(Double_t)
Definition: TMath.h:547
void SetOptStat(Int_t stat=1)
The type of information printed in the histogram statistics box can be selected via the parameter mod...
Definition: TStyle.cxx:1266
THist< 1, double, THistStatContent, THistStatUncertainty > TH1D
Definition: THist.hxx:284
TGeoNode * GetMother(Int_t up=1) const
Definition: TGeoManager.h:481
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
#define gPad
Definition: TVirtualPad.h:285
void Reset()
Definition: TStopwatch.h:52
void Add(TObject *obj)
Definition: TObjArray.h:73
TPolyMarker3D * GetPolyMarker() const
Definition: TGeoOverlap.h:72
A TTree object has a header with a name and a title.
Definition: TTree.h:70
TStopwatch * fTimer
Array of flags per volume.
Definition: TGeoChecker.h:49
Definition: Rtypes.h:59
TObjArray * GetListOfOverlaps()
Definition: TGeoManager.h:461
def normal(shape, name=None)
Double_t Sqrt(Double_t x)
Definition: TMath.h:590
TGeoVolume * GetTopVolume() const
Definition: TGeoManager.h:500
virtual Double_t GetRadLen() const
Definition: TGeoMaterial.h:93
void FindOverlaps() const
loop all nodes marked as overlaps and find overlapping brothers
TGeoShape * GetShape() const
Definition: TGeoVolume.h:191
TGeoNode * FindNextDaughterBoundary(Double_t *point, Double_t *dir, Int_t &idaughter, Bool_t compmatrix=kFALSE)
Computes as fStep the distance to next daughter of the current volume.
virtual Int_t GetSize() const
Definition: TCollection.h:180
virtual void Draw(Option_t *option="")
Draw this shape.
Definition: TGeoShape.cxx:721
Int_t Fill(Double_t)
Invalid Fill method.
Definition: TH2.cxx:292
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
THist< 2, float, THistStatContent, THistStatUncertainty > TH2F
Definition: THist.hxx:291
TGeoChecker()
Default constructor.
Definition: TGeoChecker.cxx:95
const Bool_t kTRUE
Definition: RtypesCore.h:87
return c3
Definition: legend3.C:15
TGeoVolume * GetVolume() const
Definition: TGeoNode.h:94
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition: TH1.cxx:8247
char name[80]
Definition: TGX11.cxx:109
void SetOverlaps(Int_t *ovlp, Int_t novlp)
set the list of overlaps for this node (ovlp must be created with operator new)
Definition: TGeoNode.cxx:675
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:315
Int_t NChecksPerVolume(TGeoVolume *vol)
Compute number of overlaps combinations to check per volume.
Double_t GetOverlap() const
Definition: TGeoOverlap.h:77
virtual Double_t GetDZ() const
Definition: TGeoBBox.h:72
Bool_t fFullCheck
Definition: TGeoChecker.h:45
const char * Data() const
Definition: TString.h:345
Stopwatch class.
Definition: TStopwatch.h:28
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.