Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoPatternFinder.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 30/10/01
3 
4 /** \class TGeoPatternFinder
5 \ingroup Geometry_classes
6 
7 Base finder class for patterns.
8 
9  A pattern is specifying a division type which applies only to a given
10 shape type. The implemented patterns are for the moment equidistant slices
11 on different axis. Implemented patterns are:
12 
13  - TGeoPatternX - a X axis divison pattern
14  - TGeoPatternY - a Y axis divison pattern
15  - TGeoPatternZ - a Z axis divison pattern
16  - TGeoPatternParaX - a X axis divison pattern for PARA shape
17  - TGeoPatternParaY - a Y axis divison pattern for PARA shape
18  - TGeoPatternParaZ - a Z axis divison pattern for PARA shape
19  - TGeoPatternTrapZ - a Z axis divison pattern for TRAP or GTRA shapes
20  - TGeoPatternCylR - a cylindrical R divison pattern
21  - TGeoPatternCylPhi - a cylindrical phi divison pattern
22  - TGeoPatternSphR - a spherical R divison pattern
23  - TGeoPatternSphTheta - a spherical theta divison pattern
24  - TGeoPatternSphPhi - a spherical phi divison pattern
25  - TGeoPatternHoneycomb - a divison pattern specialized for honeycombs
26 */
27 
28 #include "TGeoPatternFinder.h"
29 
30 #include "Riostream.h"
31 #include "TBuffer.h"
32 #include "TObject.h"
33 #include "TGeoMatrix.h"
34 #include "TGeoPara.h"
35 #include "TGeoArb8.h"
36 #include "TGeoNode.h"
37 #include "TGeoManager.h"
38 #include "TMath.h"
39 
40 ClassImp(TGeoPatternFinder);
41 ClassImp(TGeoPatternX);
42 ClassImp(TGeoPatternY);
43 ClassImp(TGeoPatternZ);
44 ClassImp(TGeoPatternParaX);
45 ClassImp(TGeoPatternParaY);
46 ClassImp(TGeoPatternParaZ);
47 ClassImp(TGeoPatternTrapZ);
48 ClassImp(TGeoPatternCylR);
49 ClassImp(TGeoPatternCylPhi);
50 ClassImp(TGeoPatternSphR);
51 ClassImp(TGeoPatternSphTheta);
52 ClassImp(TGeoPatternSphPhi);
53 ClassImp(TGeoPatternHoneycomb);
54 
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 /// Constructor.
58 
59 TGeoPatternFinder::ThreadData_t::ThreadData_t() :
60  fMatrix(0), fCurrent(-1), fNextIndex(-1)
61 {
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Destructor.
66 
67 TGeoPatternFinder::ThreadData_t::~ThreadData_t()
68 {
69 // if (fMatrix != gGeoIdentity) delete fMatrix;
70 }
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 
74 TGeoPatternFinder::ThreadData_t& TGeoPatternFinder::GetThreadData() const
75 {
76  Int_t tid = TGeoManager::ThreadId();
77  return *fThreadData[tid];
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 
82 void TGeoPatternFinder::ClearThreadData() const
83 {
84  std::lock_guard<std::mutex> guard(fMutex);
85  std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
86  while (i != fThreadData.end())
87  {
88  delete *i;
89  ++i;
90  }
91  fThreadData.clear();
92  fThreadSize = 0;
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Create thread data for n threads max.
97 
98 void TGeoPatternFinder::CreateThreadData(Int_t nthreads)
99 {
100  std::lock_guard<std::mutex> guard(fMutex);
101  fThreadData.resize(nthreads);
102  fThreadSize = nthreads;
103  for (Int_t tid=0; tid<nthreads; tid++) {
104  if (fThreadData[tid] == 0) {
105  fThreadData[tid] = new ThreadData_t;
106  fThreadData[tid]->fMatrix = CreateMatrix();
107  }
108  }
109 }
110 
111 ////////////////////////////////////////////////////////////////////////////////
112 /// Default constructor
113 
114 TGeoPatternFinder::TGeoPatternFinder()
115 {
116  fNdivisions = 0;
117  fDivIndex = 0;
118  fStep = 0;
119  fStart = 0;
120  fEnd = 0;
121  fVolume = 0;
122  fThreadSize = 0;
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Default constructor
127 
128 TGeoPatternFinder::TGeoPatternFinder(TGeoVolume *vol, Int_t ndiv)
129 {
130  fVolume = vol;
131  fNdivisions = ndiv;
132  fDivIndex = 0;
133  fStep = 0;
134  fStart = 0;
135  fEnd = 0;
136  fThreadSize = 0;
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 ///copy constructor
141 
142 TGeoPatternFinder::TGeoPatternFinder(const TGeoPatternFinder& pf) :
143  TObject(pf),
144  fStep(pf.fStep),
145  fStart(pf.fStart),
146  fEnd(pf.fEnd),
147  fNdivisions(pf.fNdivisions),
148  fDivIndex(pf.fDivIndex),
149  fVolume(pf.fVolume)
150 {
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 ///assignment operator
155 
156 TGeoPatternFinder& TGeoPatternFinder::operator=(const TGeoPatternFinder& pf)
157 {
158  if(this!=&pf) {
159  TObject::operator=(pf);
160  fStep=pf.fStep;
161  fStart=pf.fStart;
162  fEnd=pf.fEnd;
163  fNdivisions=pf.fNdivisions;
164  fDivIndex=pf.fDivIndex;
165  fVolume=pf.fVolume;
166  }
167  return *this;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Destructor
172 
173 TGeoPatternFinder::~TGeoPatternFinder()
174 {
175  ClearThreadData();
176 }
177 
178 ////////////////////////////////////////////////////////////////////////////////
179 /// Return current index.
180 
181 Int_t TGeoPatternFinder::GetCurrent()
182 {
183  return GetThreadData().fCurrent;
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Return current matrix.
188 
189 TGeoMatrix* TGeoPatternFinder::GetMatrix()
190 {
191  return GetThreadData().fMatrix;
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Get index of next division.
196 
197 Int_t TGeoPatternFinder::GetNext() const
198 {
199  return GetThreadData().fNextIndex;
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Set index of next division.
204 
205 void TGeoPatternFinder::SetNext(Int_t index)
206 {
207  GetThreadData().fNextIndex = index;
208 }
209 
210 ////////////////////////////////////////////////////////////////////////////////
211 /// Make next node (if any) current.
212 
213 TGeoNode *TGeoPatternFinder::CdNext()
214 {
215  ThreadData_t& td = GetThreadData();
216  if (td.fNextIndex < 0) return NULL;
217  cd(td.fNextIndex);
218  return GetNodeOffset(td.fCurrent);
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Set division range. Use this method only when dividing an assembly.
223 
224 void TGeoPatternFinder::SetRange(Double_t start, Double_t step, Int_t ndivisions)
225 {
226  fStart = start;
227  fEnd = fStart + ndivisions*step;
228  fStep = step;
229  fNdivisions = ndivisions;
230 }
231 
232 //______________________________________________________________________________
233 // TGeoPatternX - a X axis divison pattern
234 //______________________________________________________________________________
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 /// Default constructor
238 
239 TGeoPatternX::TGeoPatternX()
240 {
241  CreateThreadData(1);
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// constructor
246 
247 TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions)
248  :TGeoPatternFinder(vol, ndivisions)
249 {
250  Double_t dx = ((TGeoBBox*)vol->GetShape())->GetDX();
251  fStart = -dx;
252  fEnd = dx;
253  fStep = 2*dx/ndivisions;
254  CreateThreadData(1);
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// constructor
259 
260 TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions, Double_t step)
261  :TGeoPatternFinder(vol, ndivisions)
262 {
263  Double_t dx = ((TGeoBBox*)vol->GetShape())->GetDX();
264  fStart = -dx;
265  fEnd = fStart + ndivisions*step;
266  fStep = step;
267  CreateThreadData(1);
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// constructor
272 
273 TGeoPatternX::TGeoPatternX(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
274  :TGeoPatternFinder(vol, ndivisions)
275 {
276  fStart = start;
277  fEnd = end;
278  fStep = (end - start)/ndivisions;
279  CreateThreadData(1);
280 }
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 ///copy constructor
284 
285 TGeoPatternX::TGeoPatternX(const TGeoPatternX& pf) :
286  TGeoPatternFinder(pf)
287 {
288  CreateThreadData(1);
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 ///assignment operator
293 
294 TGeoPatternX& TGeoPatternX::operator=(const TGeoPatternX& pf)
295 {
296  if(this!=&pf) {
297  TGeoPatternFinder::operator=(pf);
298  CreateThreadData(1);
299  }
300  return *this;
301 }
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 /// Destructor
305 
306 TGeoPatternX::~TGeoPatternX()
307 {
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Update current division index and global matrix to point to a given slice.
312 
313 void TGeoPatternX::cd(Int_t idiv)
314 {
315  ThreadData_t& td = GetThreadData();
316  td.fCurrent=idiv;
317  td.fMatrix->SetDx(fStart+idiv*fStep+0.5*fStep);
318 }
319 
320 ////////////////////////////////////////////////////////////////////////////////
321 /// Return new matrix of type used by this finder.
322 
323 TGeoMatrix* TGeoPatternX::CreateMatrix() const
324 {
325  if (!IsReflected()) {
326  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
327  matrix->RegisterYourself();
328  return matrix;
329  }
330  TGeoCombiTrans *combi = new TGeoCombiTrans();
331  combi->RegisterYourself();
332  combi->ReflectZ(kTRUE);
333  combi->ReflectZ(kFALSE);
334  return combi;
335 }
336 
337 ////////////////////////////////////////////////////////////////////////////////
338 /// Fills external matrix with the local one corresponding to the given division
339 /// index.
340 
341 void TGeoPatternX::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
342 {
343  matrix.Clear();
344  matrix.SetDx(fStart+idiv*fStep+0.5*fStep);
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /// Checks if the current point is on division boundary
349 
350 Bool_t TGeoPatternX::IsOnBoundary(const Double_t *point) const
351 {
352  Double_t seg = (point[0]-fStart)/fStep;
353  Double_t diff = seg - Int_t(seg);
354  if (diff>0.5) diff = 1.-diff;
355  if (diff<1e-8) return kTRUE;
356  return kFALSE;
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 /// Find the cell corresponding to point and next cell along dir (if asked)
361 
362 TGeoNode *TGeoPatternX::FindNode(Double_t *point, const Double_t *dir)
363 {
364  ThreadData_t& td = GetThreadData();
365  TGeoNode *node = 0;
366  Int_t ind = (Int_t)(1.+(point[0]-fStart)/fStep) - 1;
367  if (dir) {
368  td.fNextIndex = ind;
369  if (dir[0]>0) td.fNextIndex++;
370  else td.fNextIndex--;
371  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
372  }
373  if ((ind<0) || (ind>=fNdivisions)) return node;
374  node = GetNodeOffset(ind);
375  cd(ind);
376  return node;
377 }
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// Compute distance to next division layer returning the index of next section.
381 /// Point is in the frame of the divided volume.
382 
383 Double_t TGeoPatternX::FindNextBoundary(Double_t *point, Double_t *dir, Int_t &indnext)
384 {
385  ThreadData_t& td = GetThreadData();
386  indnext = -1;
387  Double_t dist = TGeoShape::Big();
388  if (TMath::Abs(dir[0])<TGeoShape::Tolerance()) return dist;
389  if (td.fCurrent<0) {
390  Error("FindNextBoundary", "Must call FindNode first");
391  return dist;
392  }
393  Int_t inc = (dir[0]>0)?1:0;
394  dist = (fStep*(td.fCurrent+inc)-point[0])/dir[0];
395  if (dist<0.) Error("FindNextBoundary", "Negative distance d=%g",dist);
396  if (!inc) inc = -1;
397  indnext = td.fCurrent+inc;
398  return dist;
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Make a copy of this finder. Reflect by Z if required.
403 
404 TGeoPatternFinder *TGeoPatternX::MakeCopy(Bool_t reflect)
405 {
406  TGeoPatternX *finder = new TGeoPatternX(*this);
407  if (!reflect) return finder;
408  finder->Reflect();
409  return finder;
410 }
411 
412 ////////////////////////////////////////////////////////////////////////////////
413 /// Save a primitive as a C++ statement(s) on output stream "out".
414 
415 void TGeoPatternX::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
416 {
417  Int_t iaxis = 1;
418  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
419 }
420 
421 //______________________________________________________________________________
422 // TGeoPatternY - a Y axis divison pattern
423 //______________________________________________________________________________
424 
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// Default constructor
428 
429 TGeoPatternY::TGeoPatternY()
430 {
431  CreateThreadData(1);
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// constructor
436 
437 TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions)
438  :TGeoPatternFinder(vol, ndivisions)
439 {
440  Double_t dy = ((TGeoBBox*)vol->GetShape())->GetDY();
441  fStart = -dy;
442  fEnd = dy;
443  fStep = 2*dy/ndivisions;
444  CreateThreadData(1);
445 }
446 
447 ////////////////////////////////////////////////////////////////////////////////
448 /// constructor
449 
450 TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions, Double_t step)
451  :TGeoPatternFinder(vol, ndivisions)
452 {
453  Double_t dy = ((TGeoBBox*)vol->GetShape())->GetDY();
454  fStart = -dy;
455  fEnd = fStart + ndivisions*step;
456  fStep = step;
457  CreateThreadData(1);
458 }
459 
460 ////////////////////////////////////////////////////////////////////////////////
461 /// constructor
462 
463 TGeoPatternY::TGeoPatternY(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
464  :TGeoPatternFinder(vol, ndivisions)
465 {
466  fStart = start;
467  fEnd = end;
468  fStep = (end - start)/ndivisions;
469  CreateThreadData(1);
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 ///copy constructor
474 
475 TGeoPatternY::TGeoPatternY(const TGeoPatternY& pf) :
476  TGeoPatternFinder(pf)
477 {
478  CreateThreadData(1);
479 }
480 
481 ////////////////////////////////////////////////////////////////////////////////
482 ///assignment operator
483 
484 TGeoPatternY& TGeoPatternY::operator=(const TGeoPatternY& pf)
485 {
486  if(this!=&pf) {
487  TGeoPatternFinder::operator=(pf);
488  CreateThreadData(1);
489  }
490  return *this;
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Destructor
495 
496 TGeoPatternY::~TGeoPatternY()
497 {
498 }
499 
500 ////////////////////////////////////////////////////////////////////////////////
501 /// Update current division index and global matrix to point to a given slice.
502 
503 void TGeoPatternY::cd(Int_t idiv)
504 {
505  ThreadData_t& td = GetThreadData();
506  td.fCurrent=idiv;
507  td.fMatrix->SetDy(fStart+idiv*fStep+0.5*fStep);
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////
511 /// Return new matrix of type used by this finder.
512 
513 TGeoMatrix* TGeoPatternY::CreateMatrix() const
514 {
515  if (!IsReflected()) {
516  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
517  matrix->RegisterYourself();
518  return matrix;
519  }
520  TGeoCombiTrans *combi = new TGeoCombiTrans();
521  combi->RegisterYourself();
522  combi->ReflectZ(kTRUE);
523  combi->ReflectZ(kFALSE);
524  return combi;
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// Fills external matrix with the local one corresponding to the given division
529 /// index.
530 
531 void TGeoPatternY::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
532 {
533  matrix.Clear();
534  matrix.SetDy(fStart+idiv*fStep+0.5*fStep);
535 }
536 
537 ////////////////////////////////////////////////////////////////////////////////
538 /// Checks if the current point is on division boundary
539 
540 Bool_t TGeoPatternY::IsOnBoundary(const Double_t *point) const
541 {
542  Double_t seg = (point[1]-fStart)/fStep;
543  Double_t diff = seg - Int_t(seg);
544  if (diff>0.5) diff = 1.-diff;
545  if (diff<1e-8) return kTRUE;
546  return kFALSE;
547 }
548 
549 ////////////////////////////////////////////////////////////////////////////////
550 /// Find the cell corresponding to point and next cell along dir (if asked)
551 
552 TGeoNode *TGeoPatternY::FindNode(Double_t *point, const Double_t *dir)
553 {
554  ThreadData_t& td = GetThreadData();
555  TGeoNode *node = 0;
556  Int_t ind = (Int_t)(1.+(point[1]-fStart)/fStep) - 1;
557  if (dir) {
558  td.fNextIndex = ind;
559  if (dir[1]>0) td.fNextIndex++;
560  else td.fNextIndex--;
561  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
562  }
563  if ((ind<0) || (ind>=fNdivisions)) return node;
564  node = GetNodeOffset(ind);
565  cd(ind);
566  return node;
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 /// Compute distance to next division layer returning the index of next section.
571 /// Point is in the frame of the divided volume.
572 
573 Double_t TGeoPatternY::FindNextBoundary(Double_t *point, Double_t *dir, Int_t &indnext)
574 {
575  ThreadData_t& td = GetThreadData();
576  indnext = -1;
577  Double_t dist = TGeoShape::Big();
578  if (TMath::Abs(dir[1])<TGeoShape::Tolerance()) return dist;
579  if (td.fCurrent<0) {
580  Error("FindNextBoundary", "Must call FindNode first");
581  return dist;
582  }
583  Int_t inc = (dir[1]>0)?1:0;
584  dist = (fStep*(td.fCurrent+inc)-point[1])/dir[1];
585  if (dist<0.) Error("FindNextBoundary", "Negative distance d=%g",dist);
586  if (!inc) inc = -1;
587  indnext = td.fCurrent+inc;
588  return dist;
589 }
590 
591 ////////////////////////////////////////////////////////////////////////////////
592 /// Make a copy of this finder. Reflect by Z if required.
593 
594 TGeoPatternFinder *TGeoPatternY::MakeCopy(Bool_t reflect)
595 {
596  TGeoPatternY *finder = new TGeoPatternY(*this);
597  if (!reflect) return finder;
598  finder->Reflect();
599  return finder;
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// Save a primitive as a C++ statement(s) on output stream "out".
604 
605 void TGeoPatternY::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
606 {
607  Int_t iaxis = 2;
608  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
609 }
610 
611 //______________________________________________________________________________
612 // TGeoPatternZ - a Z axis divison pattern
613 //______________________________________________________________________________
614 
615 
616 ////////////////////////////////////////////////////////////////////////////////
617 /// Default constructor
618 
619 TGeoPatternZ::TGeoPatternZ()
620 {
621  CreateThreadData(1);
622 }
623 ////////////////////////////////////////////////////////////////////////////////
624 /// constructor
625 
626 TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions)
627  :TGeoPatternFinder(vol, ndivisions)
628 {
629  Double_t dz = ((TGeoBBox*)vol->GetShape())->GetDZ();
630  fStart = -dz;
631  fEnd = dz;
632  fStep = 2*dz/ndivisions;
633  CreateThreadData(1);
634 }
635 ////////////////////////////////////////////////////////////////////////////////
636 /// constructor
637 
638 TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
639  :TGeoPatternFinder(vol, ndivisions)
640 {
641  Double_t dz = ((TGeoBBox*)vol->GetShape())->GetDZ();
642  fStart = -dz;
643  fEnd = fStart + ndivisions*step;
644  fStep = step;
645  CreateThreadData(1);
646 }
647 ////////////////////////////////////////////////////////////////////////////////
648 /// constructor
649 
650 TGeoPatternZ::TGeoPatternZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
651  :TGeoPatternFinder(vol, ndivisions)
652 {
653  fStart = start;
654  fEnd = end;
655  fStep = (end - start)/ndivisions;
656  CreateThreadData(1);
657 }
658 
659 ////////////////////////////////////////////////////////////////////////////////
660 ///copy constructor
661 
662 TGeoPatternZ::TGeoPatternZ(const TGeoPatternZ& pf) :
663  TGeoPatternFinder(pf)
664 {
665  CreateThreadData(1);
666 }
667 
668 ////////////////////////////////////////////////////////////////////////////////
669 ///assignment operator
670 
671 TGeoPatternZ& TGeoPatternZ::operator=(const TGeoPatternZ& pf)
672 {
673  if(this!=&pf) {
674  TGeoPatternFinder::operator=(pf);
675  CreateThreadData(1);
676  }
677  return *this;
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 /// Destructor
682 
683 TGeoPatternZ::~TGeoPatternZ()
684 {
685 }
686 ////////////////////////////////////////////////////////////////////////////////
687 /// Update current division index and global matrix to point to a given slice.
688 
689 void TGeoPatternZ::cd(Int_t idiv)
690 {
691  ThreadData_t& td = GetThreadData();
692  td.fCurrent=idiv;
693  td.fMatrix->SetDz(((IsReflected())?-1.:1.)*(fStart+idiv*fStep+0.5*fStep));
694 }
695 
696 ////////////////////////////////////////////////////////////////////////////////
697 /// Return new matrix of type used by this finder.
698 
699 TGeoMatrix* TGeoPatternZ::CreateMatrix() const
700 {
701  if (!IsReflected()) {
702  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
703  matrix->RegisterYourself();
704  return matrix;
705  }
706  TGeoCombiTrans *combi = new TGeoCombiTrans();
707  combi->RegisterYourself();
708  combi->ReflectZ(kTRUE);
709  combi->ReflectZ(kFALSE);
710  return combi;
711 }
712 
713 ////////////////////////////////////////////////////////////////////////////////
714 /// Fills external matrix with the local one corresponding to the given division
715 /// index.
716 
717 void TGeoPatternZ::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
718 {
719  matrix.Clear();
720  matrix.SetDz(((IsReflected())?-1.:1.)*(fStart+idiv*fStep+0.5*fStep));
721 }
722 
723 ////////////////////////////////////////////////////////////////////////////////
724 /// Checks if the current point is on division boundary
725 
726 Bool_t TGeoPatternZ::IsOnBoundary(const Double_t *point) const
727 {
728  Double_t seg = (point[2]-fStart)/fStep;
729  Double_t diff = seg - Int_t(seg);
730  if (diff>0.5) diff = 1.-diff;
731  if (diff<1e-8) return kTRUE;
732  return kFALSE;
733 }
734 
735 ////////////////////////////////////////////////////////////////////////////////
736 /// Find the cell corresponding to point and next cell along dir (if asked)
737 
738 TGeoNode *TGeoPatternZ::FindNode(Double_t *point, const Double_t *dir)
739 {
740  ThreadData_t& td = GetThreadData();
741  TGeoNode *node = 0;
742  Int_t ind = (Int_t)(1.+(point[2]-fStart)/fStep) - 1;
743  if (dir) {
744  td.fNextIndex = ind;
745  if (dir[2]>0) td.fNextIndex++;
746  else td.fNextIndex--;
747  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
748  }
749  if ((ind<0) || (ind>=fNdivisions)) return node;
750  node = GetNodeOffset(ind);
751  cd(ind);
752  return node;
753 }
754 
755 ////////////////////////////////////////////////////////////////////////////////
756 /// Compute distance to next division layer returning the index of next section.
757 /// Point is in the frame of the divided volume.
758 
759 Double_t TGeoPatternZ::FindNextBoundary(Double_t *point, Double_t *dir, Int_t &indnext)
760 {
761  indnext = -1;
762  ThreadData_t& td = GetThreadData();
763  Double_t dist = TGeoShape::Big();
764  if (TMath::Abs(dir[2])<TGeoShape::Tolerance()) return dist;
765  if (td.fCurrent<0) {
766  Error("FindNextBoundary", "Must call FindNode first");
767  return dist;
768  }
769  Int_t inc = (dir[2]>0)?1:0;
770  dist = (fStep*(td.fCurrent+inc)-point[2])/dir[2];
771  if (dist<0.) Error("FindNextBoundary", "Negative distance d=%g",dist);
772  if (!inc) inc = -1;
773  indnext = td.fCurrent+inc;
774  return dist;
775 }
776 
777 ////////////////////////////////////////////////////////////////////////////////
778 /// Make a copy of this finder. Reflect by Z if required.
779 
780 TGeoPatternFinder *TGeoPatternZ::MakeCopy(Bool_t reflect)
781 {
782  TGeoPatternZ *finder = new TGeoPatternZ(*this);
783  if (!reflect) return finder;
784  finder->Reflect();
785  return finder;
786 }
787 
788 ////////////////////////////////////////////////////////////////////////////////
789 /// Save a primitive as a C++ statement(s) on output stream "out".
790 
791 void TGeoPatternZ::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
792 {
793  Int_t iaxis = 3;
794  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
795 }
796 
797 //______________________________________________________________________________
798 // TGeoPatternParaX - a X axis divison pattern for PARA shape
799 //______________________________________________________________________________
800 
801 ////////////////////////////////////////////////////////////////////////////////
802 /// Default constructor
803 
804 TGeoPatternParaX::TGeoPatternParaX()
805 {
806  CreateThreadData(1);
807 }
808 ////////////////////////////////////////////////////////////////////////////////
809 /// constructor
810 
811 TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions)
812  :TGeoPatternFinder(vol, ndivisions)
813 {
814  Double_t dx = ((TGeoPara*)vol->GetShape())->GetX();
815  fStart = -dx;
816  fEnd = dx;
817  fStep = 2*dx/ndivisions;
818  CreateThreadData(1);
819 }
820 ////////////////////////////////////////////////////////////////////////////////
821 /// constructor
822 
823 TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions, Double_t step)
824  :TGeoPatternFinder(vol, ndivisions)
825 {
826  Double_t dx = ((TGeoPara*)vol->GetShape())->GetX();
827  fStart = -dx;
828  fEnd = fStart + ndivisions*step;
829  fStep = step;
830  CreateThreadData(1);
831 }
832 ////////////////////////////////////////////////////////////////////////////////
833 /// constructor
834 
835 TGeoPatternParaX::TGeoPatternParaX(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
836  :TGeoPatternFinder(vol, ndivisions)
837 {
838  fStart = start;
839  fEnd = end;
840  fStep = (end - start)/ndivisions;
841  CreateThreadData(1);
842 }
843 
844 ////////////////////////////////////////////////////////////////////////////////
845 ///copy constructor
846 
847 TGeoPatternParaX::TGeoPatternParaX(const TGeoPatternParaX& pf) :
848  TGeoPatternFinder(pf)
849 {
850  CreateThreadData(1);
851 }
852 
853 ////////////////////////////////////////////////////////////////////////////////
854 ///assignment operator
855 
856 TGeoPatternParaX& TGeoPatternParaX::operator=(const TGeoPatternParaX& pf)
857 {
858  if(this!=&pf) {
859  TGeoPatternFinder::operator=(pf);
860  CreateThreadData(1);
861  }
862  return *this;
863 }
864 
865 ////////////////////////////////////////////////////////////////////////////////
866 /// Destructor
867 
868 TGeoPatternParaX::~TGeoPatternParaX()
869 {
870 }
871 ////////////////////////////////////////////////////////////////////////////////
872 /// Update current division index and global matrix to point to a given slice.
873 
874 void TGeoPatternParaX::cd(Int_t idiv)
875 {
876  ThreadData_t& td = GetThreadData();
877  td.fCurrent=idiv;
878  td.fMatrix->SetDx(fStart+idiv*fStep+0.5*fStep);
879 }
880 
881 ////////////////////////////////////////////////////////////////////////////////
882 /// Checks if the current point is on division boundary
883 
884 Bool_t TGeoPatternParaX::IsOnBoundary(const Double_t *point) const
885 {
886  Double_t txy = ((TGeoPara*)fVolume->GetShape())->GetTxy();
887  Double_t txz = ((TGeoPara*)fVolume->GetShape())->GetTxz();
888  Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
889  Double_t xt = point[0]-txz*point[2]-txy*(point[1]-tyz*point[2]);
890  Double_t seg = (xt-fStart)/fStep;
891  Double_t diff = seg - Int_t(seg);
892  if (diff>0.5) diff = 1.-diff;
893  if (diff<1e-8) return kTRUE;
894  return kFALSE;
895 }
896 
897 ////////////////////////////////////////////////////////////////////////////////
898 /// get the node division containing the query point
899 
900 TGeoNode *TGeoPatternParaX::FindNode(Double_t *point, const Double_t *dir)
901 {
902  ThreadData_t& td = GetThreadData();
903  TGeoNode *node = 0;
904  Double_t txy = ((TGeoPara*)fVolume->GetShape())->GetTxy();
905  Double_t txz = ((TGeoPara*)fVolume->GetShape())->GetTxz();
906  Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
907  Double_t xt = point[0]-txz*point[2]-txy*(point[1]-tyz*point[2]);
908  Int_t ind = (Int_t)(1.+(xt-fStart)/fStep)-1;
909  if (dir) {
910  Double_t ttsq = txy*txy + (txz-txy*tyz)*(txz-txy*tyz);
911  Double_t divdirx = 1./TMath::Sqrt(1.+ttsq);
912  Double_t divdiry = -txy*divdirx;
913  Double_t divdirz = -(txz-txy*tyz)*divdirx;
914  Double_t dot = dir[0]*divdirx + dir[1]*divdiry + dir[2]*divdirz;
915  td.fNextIndex = ind;
916  if (dot>0) td.fNextIndex++;
917  else td.fNextIndex--;
918  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
919  }
920  if ((ind<0) || (ind>=fNdivisions)) return node;
921  node = GetNodeOffset(ind);
922  cd(ind);
923  return node;
924 }
925 
926 ////////////////////////////////////////////////////////////////////////////////
927 /// Make a copy of this finder. Reflect by Z if required.
928 
929 TGeoPatternFinder *TGeoPatternParaX::MakeCopy(Bool_t reflect)
930 {
931  TGeoPatternParaX *finder = new TGeoPatternParaX(*this);
932  if (!reflect) return finder;
933  finder->Reflect();
934  return finder;
935 }
936 
937 ////////////////////////////////////////////////////////////////////////////////
938 /// Save a primitive as a C++ statement(s) on output stream "out".
939 
940 void TGeoPatternParaX::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
941 {
942  Int_t iaxis = 1;
943  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
944 }
945 
946 ////////////////////////////////////////////////////////////////////////////////
947 /// Return new matrix of type used by this finder.
948 
949 TGeoMatrix* TGeoPatternParaX::CreateMatrix() const
950 {
951  if (!IsReflected()) {
952  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
953  matrix->RegisterYourself();
954  return matrix;
955  }
956  TGeoCombiTrans *combi = new TGeoCombiTrans();
957  combi->RegisterYourself();
958  combi->ReflectZ(kTRUE);
959  combi->ReflectZ(kFALSE);
960  return combi;
961 }
962 
963 ////////////////////////////////////////////////////////////////////////////////
964 /// Fills external matrix with the local one corresponding to the given division
965 /// index.
966 
967 void TGeoPatternParaX::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
968 {
969  matrix.Clear();
970  matrix.SetDx(fStart+idiv*fStep+0.5*fStep);
971 }
972 
973 //______________________________________________________________________________
974 // TGeoPatternParaY - a Y axis divison pattern for PARA shape
975 //______________________________________________________________________________
976 
977 ////////////////////////////////////////////////////////////////////////////////
978 /// Default constructor
979 
980 TGeoPatternParaY::TGeoPatternParaY()
981 {
982  fTxy = 0;
983  CreateThreadData(1);
984 }
985 ////////////////////////////////////////////////////////////////////////////////
986 /// constructor
987 
988 TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions)
989  :TGeoPatternFinder(vol, ndivisions)
990 {
991  fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
992  Double_t dy = ((TGeoPara*)vol->GetShape())->GetY();
993  fStart = -dy;
994  fEnd = dy;
995  fStep = 2*dy/ndivisions;
996  CreateThreadData(1);
997 }
998 ////////////////////////////////////////////////////////////////////////////////
999 /// constructor
1000 
1001 TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1002  :TGeoPatternFinder(vol, ndivisions)
1003 {
1004  fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
1005  Double_t dy = ((TGeoPara*)vol->GetShape())->GetY();
1006  fStart = -dy;
1007  fEnd = fStart + ndivisions*step;
1008  fStep = step;
1009  CreateThreadData(1);
1010 }
1011 ////////////////////////////////////////////////////////////////////////////////
1012 /// constructor
1013 
1014 TGeoPatternParaY::TGeoPatternParaY(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1015  :TGeoPatternFinder(vol, ndivisions)
1016 {
1017  fTxy = ((TGeoPara*)vol->GetShape())->GetTxy();
1018  fStart = start;
1019  fEnd = end;
1020  fStep = (end - start)/ndivisions;
1021  CreateThreadData(1);
1022 }
1023 ////////////////////////////////////////////////////////////////////////////////
1024 ///copy constructor
1025 
1026 TGeoPatternParaY::TGeoPatternParaY(const TGeoPatternParaY& pf) :
1027  TGeoPatternFinder(pf)
1028 {
1029  CreateThreadData(1);
1030 }
1031 
1032 ////////////////////////////////////////////////////////////////////////////////
1033 ///assignment operator
1034 
1035 TGeoPatternParaY& TGeoPatternParaY::operator=(const TGeoPatternParaY& pf)
1036 {
1037  if(this!=&pf) {
1038  TGeoPatternFinder::operator=(pf);
1039  CreateThreadData(1);
1040  }
1041  return *this;
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Destructor
1046 
1047 TGeoPatternParaY::~TGeoPatternParaY()
1048 {
1049 }
1050 ////////////////////////////////////////////////////////////////////////////////
1051 /// Update current division index and global matrix to point to a given slice.
1052 
1053 void TGeoPatternParaY::cd(Int_t idiv)
1054 {
1055  ThreadData_t& td = GetThreadData();
1056  td.fCurrent = idiv;
1057  Double_t dy = fStart+idiv*fStep+0.5*fStep;
1058  td.fMatrix->SetDx(fTxy*dy);
1059  td.fMatrix->SetDy(dy);
1060 }
1061 
1062 ////////////////////////////////////////////////////////////////////////////////
1063 /// Checks if the current point is on division boundary
1064 
1065 Bool_t TGeoPatternParaY::IsOnBoundary(const Double_t *point) const
1066 {
1067  Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
1068  Double_t yt = point[1]-tyz*point[2];
1069  Double_t seg = (yt-fStart)/fStep;
1070  Double_t diff = seg - Int_t(seg);
1071  if (diff>0.5) diff = 1.-diff;
1072  if (diff<1e-8) return kTRUE;
1073  return kFALSE;
1074 }
1075 
1076 ////////////////////////////////////////////////////////////////////////////////
1077 /// get the node division containing the query point
1078 
1079 TGeoNode *TGeoPatternParaY::FindNode(Double_t *point, const Double_t *dir)
1080 {
1081  ThreadData_t& td = GetThreadData();
1082  TGeoNode *node = 0;
1083  Double_t tyz = ((TGeoPara*)fVolume->GetShape())->GetTyz();
1084  Double_t yt = point[1]-tyz*point[2];
1085  Int_t ind = (Int_t)(1.+(yt-fStart)/fStep) - 1;
1086  if (dir) {
1087  Double_t divdiry = 1./TMath::Sqrt(1.+tyz*tyz);
1088  Double_t divdirz = -tyz*divdiry;
1089  Double_t dot = dir[1]*divdiry + dir[2]*divdirz;
1090  td.fNextIndex = ind;
1091  if (dot>0) td.fNextIndex++;
1092  else td.fNextIndex--;
1093  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
1094  }
1095  if ((ind<0) || (ind>=fNdivisions)) return node;
1096  node = GetNodeOffset(ind);
1097  cd(ind);
1098  return node;
1099 }
1100 
1101 ////////////////////////////////////////////////////////////////////////////////
1102 /// Make a copy of this finder. Reflect by Z if required.
1103 
1104 TGeoPatternFinder *TGeoPatternParaY::MakeCopy(Bool_t reflect)
1105 {
1106  TGeoPatternParaY *finder = new TGeoPatternParaY(*this);
1107  if (!reflect) return finder;
1108  finder->Reflect();
1109  return finder;
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// Save a primitive as a C++ statement(s) on output stream "out".
1114 
1115 void TGeoPatternParaY::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1116 {
1117  Int_t iaxis = 2;
1118  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1119 }
1120 
1121 ////////////////////////////////////////////////////////////////////////////////
1122 /// Return new matrix of type used by this finder.
1123 
1124 TGeoMatrix* TGeoPatternParaY::CreateMatrix() const
1125 {
1126  if (!IsReflected()) {
1127  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
1128  matrix->RegisterYourself();
1129  return matrix;
1130  }
1131  TGeoCombiTrans *combi = new TGeoCombiTrans();
1132  combi->RegisterYourself();
1133  combi->ReflectZ(kTRUE);
1134  combi->ReflectZ(kFALSE);
1135  return combi;
1136 }
1137 
1138 ////////////////////////////////////////////////////////////////////////////////
1139 /// Fills external matrix with the local one corresponding to the given division
1140 /// index.
1141 
1142 void TGeoPatternParaY::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
1143 {
1144  matrix.Clear();
1145  Double_t dy = fStart+idiv*fStep+0.5*fStep;
1146  matrix.SetDx(fTxy*dy);
1147  matrix.SetDy(dy);
1148 }
1149 
1150 //______________________________________________________________________________
1151 // TGeoPatternParaZ - a Z axis divison pattern for PARA shape
1152 //______________________________________________________________________________
1153 
1154 ////////////////////////////////////////////////////////////////////////////////
1155 /// Default constructor
1156 
1157 TGeoPatternParaZ::TGeoPatternParaZ()
1158 {
1159  fTxz = 0;
1160  fTyz = 0;
1161  CreateThreadData(1);
1162 }
1163 ////////////////////////////////////////////////////////////////////////////////
1164 /// constructor
1165 
1166 TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions)
1167  :TGeoPatternFinder(vol, ndivisions)
1168 {
1169  fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
1170  fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
1171  Double_t dz = ((TGeoPara*)vol->GetShape())->GetZ();
1172  fStart = -dz;
1173  fEnd = dz;
1174  fStep = 2*dz/ndivisions;
1175  CreateThreadData(1);
1176 }
1177 ////////////////////////////////////////////////////////////////////////////////
1178 /// constructor
1179 
1180 TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1181  :TGeoPatternFinder(vol, ndivisions)
1182 {
1183  fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
1184  fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
1185  Double_t dz = ((TGeoPara*)vol->GetShape())->GetZ();
1186  fStart = -dz;
1187  fEnd = fStart + ndivisions*step;
1188  fStep = step;
1189  CreateThreadData(1);
1190 }
1191 
1192 ////////////////////////////////////////////////////////////////////////////////
1193 /// constructor
1194 
1195 TGeoPatternParaZ::TGeoPatternParaZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1196  :TGeoPatternFinder(vol, ndivisions)
1197 {
1198  fTxz = ((TGeoPara*)vol->GetShape())->GetTxz();
1199  fTyz = ((TGeoPara*)vol->GetShape())->GetTyz();
1200  fStart = start;
1201  fEnd = end;
1202  fStep = (end - start)/ndivisions;
1203  CreateThreadData(1);
1204 }
1205 
1206 ////////////////////////////////////////////////////////////////////////////////
1207 ///copy constructor
1208 
1209 TGeoPatternParaZ::TGeoPatternParaZ(const TGeoPatternParaZ& pf) :
1210  TGeoPatternFinder(pf)
1211 {
1212  CreateThreadData(1);
1213 }
1214 
1215 ////////////////////////////////////////////////////////////////////////////////
1216 ///assignment operator
1217 
1218 TGeoPatternParaZ& TGeoPatternParaZ::operator=(const TGeoPatternParaZ& pf)
1219 {
1220  if(this!=&pf) {
1221  TGeoPatternFinder::operator=(pf);
1222  CreateThreadData(1);
1223  }
1224  return *this;
1225 }
1226 
1227 ////////////////////////////////////////////////////////////////////////////////
1228 /// Destructor
1229 
1230 TGeoPatternParaZ::~TGeoPatternParaZ()
1231 {
1232 }
1233 
1234 ////////////////////////////////////////////////////////////////////////////////
1235 /// Update current division index and global matrix to point to a given slice.
1236 
1237 void TGeoPatternParaZ::cd(Int_t idiv)
1238 {
1239  ThreadData_t& td = GetThreadData();
1240  td.fCurrent = idiv;
1241  Double_t dz = fStart+idiv*fStep+0.5*fStep;
1242  td.fMatrix->SetDx(fTxz*dz);
1243  td.fMatrix->SetDy(fTyz*dz);
1244  td.fMatrix->SetDz((IsReflected())?-dz:dz);
1245 }
1246 
1247 ////////////////////////////////////////////////////////////////////////////////
1248 /// Checks if the current point is on division boundary
1249 
1250 Bool_t TGeoPatternParaZ::IsOnBoundary(const Double_t *point) const
1251 {
1252  Double_t seg = (point[2]-fStart)/fStep;
1253  Double_t diff = seg - Int_t(seg);
1254  if (diff>0.5) diff = 1.-diff;
1255  if (diff<1e-8) return kTRUE;
1256  return kFALSE;
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////////
1260 /// get the node division containing the query point
1261 
1262 TGeoNode *TGeoPatternParaZ::FindNode(Double_t *point, const Double_t *dir)
1263 {
1264  ThreadData_t& td = GetThreadData();
1265  TGeoNode *node = 0;
1266  Double_t zt = point[2];
1267  Int_t ind = (Int_t)(1.+(zt-fStart)/fStep) - 1;
1268  if (dir) {
1269  td.fNextIndex = ind;
1270  if (dir[2]>0) td.fNextIndex++;
1271  else td.fNextIndex--;
1272  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
1273  }
1274  if ((ind<0) || (ind>=fNdivisions)) return node;
1275  node = GetNodeOffset(ind);
1276  cd(ind);
1277  return node;
1278 }
1279 
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// Make a copy of this finder. Reflect by Z if required.
1282 
1283 TGeoPatternFinder *TGeoPatternParaZ::MakeCopy(Bool_t reflect)
1284 {
1285  TGeoPatternParaZ *finder = new TGeoPatternParaZ(*this);
1286  if (!reflect) return finder;
1287  finder->Reflect();
1288  return finder;
1289 }
1290 
1291 ////////////////////////////////////////////////////////////////////////////////
1292 /// Save a primitive as a C++ statement(s) on output stream "out".
1293 
1294 void TGeoPatternParaZ::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1295 {
1296  Int_t iaxis = 3;
1297  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1298 }
1299 
1300 ////////////////////////////////////////////////////////////////////////////////
1301 /// Return new matrix of type used by this finder.
1302 
1303 TGeoMatrix* TGeoPatternParaZ::CreateMatrix() const
1304 {
1305  if (!IsReflected()) {
1306  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
1307  matrix->RegisterYourself();
1308  return matrix;
1309  }
1310  TGeoCombiTrans *combi = new TGeoCombiTrans();
1311  combi->RegisterYourself();
1312  combi->ReflectZ(kTRUE);
1313  combi->ReflectZ(kFALSE);
1314  return combi;
1315 }
1316 
1317 ////////////////////////////////////////////////////////////////////////////////
1318 /// Fills external matrix with the local one corresponding to the given division
1319 /// index.
1320 
1321 void TGeoPatternParaZ::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
1322 {
1323  matrix.Clear();
1324  Double_t dz = fStart+idiv*fStep+0.5*fStep;
1325  matrix.SetDx(fTxz*dz);
1326  matrix.SetDy(fTyz*dz);
1327  matrix.SetDz((IsReflected())?-dz:dz);
1328 }
1329 
1330 //______________________________________________________________________________
1331 // TGeoPatternTrapZ - a Z axis divison pattern for TRAP or GTRA shapes
1332 //______________________________________________________________________________
1333 
1334 ////////////////////////////////////////////////////////////////////////////////
1335 /// Default constructor
1336 
1337 TGeoPatternTrapZ::TGeoPatternTrapZ()
1338 {
1339  fTxz = 0;
1340  fTyz = 0;
1341  CreateThreadData(1);
1342 }
1343 ////////////////////////////////////////////////////////////////////////////////
1344 /// constructor
1345 
1346 TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions)
1347  :TGeoPatternFinder(vol, ndivisions)
1348 {
1349  Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
1350  Double_t phi = ((TGeoTrap*)vol->GetShape())->GetPhi();
1351  fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
1352  fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
1353  Double_t dz = ((TGeoArb8*)vol->GetShape())->GetDz();
1354  fStart = -dz;
1355  fEnd = dz;
1356  fStep = 2*dz/ndivisions;
1357  CreateThreadData(1);
1358 }
1359 ////////////////////////////////////////////////////////////////////////////////
1360 /// constructor
1361 
1362 TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1363  :TGeoPatternFinder(vol, ndivisions)
1364 {
1365  Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
1366  Double_t phi = ((TGeoTrap*)vol->GetShape())->GetPhi();
1367  fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
1368  fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
1369  Double_t dz = ((TGeoArb8*)vol->GetShape())->GetDz();
1370  fStart = -dz;
1371  fEnd = fStart + ndivisions*step;
1372  fStep = step;
1373  CreateThreadData(1);
1374 }
1375 ////////////////////////////////////////////////////////////////////////////////
1376 /// constructor
1377 
1378 TGeoPatternTrapZ::TGeoPatternTrapZ(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1379  :TGeoPatternFinder(vol, ndivisions)
1380 {
1381  Double_t theta = ((TGeoTrap*)vol->GetShape())->GetTheta();
1382  Double_t phi = ((TGeoTrap*)vol->GetShape())->GetPhi();
1383  fTxz = TMath::Tan(theta*TMath::DegToRad())*TMath::Cos(phi*TMath::DegToRad());
1384  fTyz = TMath::Tan(theta*TMath::DegToRad())*TMath::Sin(phi*TMath::DegToRad());
1385  fStart = start;
1386  fEnd = end;
1387  fStep = (end - start)/ndivisions;
1388  CreateThreadData(1);
1389 }
1390 
1391 ////////////////////////////////////////////////////////////////////////////////
1392 ///copy constructor
1393 
1394 TGeoPatternTrapZ::TGeoPatternTrapZ(const TGeoPatternTrapZ& pf) :
1395  TGeoPatternFinder(pf),
1396  fTxz(pf.fTxz),
1397  fTyz(pf.fTyz)
1398 {
1399  CreateThreadData(1);
1400 }
1401 
1402 ////////////////////////////////////////////////////////////////////////////////
1403 ///assignment operator
1404 
1405 TGeoPatternTrapZ& TGeoPatternTrapZ::operator=(const TGeoPatternTrapZ& pf)
1406 {
1407  if(this!=&pf) {
1408  TGeoPatternFinder::operator=(pf);
1409  fTxz = pf.fTxz;
1410  fTyz = pf.fTyz;
1411  CreateThreadData(1);
1412  }
1413  return *this;
1414 }
1415 
1416 ////////////////////////////////////////////////////////////////////////////////
1417 /// Destructor
1418 
1419 TGeoPatternTrapZ::~TGeoPatternTrapZ()
1420 {
1421 }
1422 ////////////////////////////////////////////////////////////////////////////////
1423 /// Update current division index and global matrix to point to a given slice.
1424 
1425 void TGeoPatternTrapZ::cd(Int_t idiv)
1426 {
1427  ThreadData_t& td = GetThreadData();
1428  td.fCurrent = idiv;
1429  Double_t dz = fStart+idiv*fStep+0.5*fStep;
1430  td.fMatrix->SetDx(fTxz*dz);
1431  td.fMatrix->SetDy(fTyz*dz);
1432  td.fMatrix->SetDz((IsReflected())?-dz:dz);
1433 }
1434 
1435 ////////////////////////////////////////////////////////////////////////////////
1436 /// Checks if the current point is on division boundary
1437 
1438 Bool_t TGeoPatternTrapZ::IsOnBoundary(const Double_t *point) const
1439 {
1440  Double_t seg = (point[2]-fStart)/fStep;
1441  Double_t diff = seg - Int_t(seg);
1442  if (diff>0.5) diff = 1.-diff;
1443  if (diff<1e-8) return kTRUE;
1444  return kFALSE;
1445 }
1446 
1447 ////////////////////////////////////////////////////////////////////////////////
1448 /// get the node division containing the query point
1449 
1450 TGeoNode *TGeoPatternTrapZ::FindNode(Double_t *point, const Double_t *dir)
1451 {
1452  ThreadData_t& td = GetThreadData();
1453  TGeoNode *node = 0;
1454  Double_t zt = point[2];
1455  Int_t ind = (Int_t)(1. + (zt-fStart)/fStep) - 1;
1456  if (dir) {
1457  td.fNextIndex = ind;
1458  if (dir[2]>0) td.fNextIndex++;
1459  else td.fNextIndex--;
1460  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
1461  }
1462  if ((ind<0) || (ind>=fNdivisions)) return node;
1463  node = GetNodeOffset(ind);
1464  cd(ind);
1465  return node;
1466 }
1467 
1468 ////////////////////////////////////////////////////////////////////////////////
1469 /// Make a copy of this finder. Reflect by Z if required.
1470 
1471 TGeoPatternFinder *TGeoPatternTrapZ::MakeCopy(Bool_t reflect)
1472 {
1473  TGeoPatternTrapZ *finder = new TGeoPatternTrapZ(*this);
1474  if (!reflect) return finder;
1475  finder->Reflect();
1476  return finder;
1477 }
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// Save a primitive as a C++ statement(s) on output stream "out".
1481 
1482 void TGeoPatternTrapZ::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1483 {
1484  Int_t iaxis = 3;
1485  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1486 }
1487 
1488 ////////////////////////////////////////////////////////////////////////////////
1489 /// Return new matrix of type used by this finder.
1490 
1491 TGeoMatrix* TGeoPatternTrapZ::CreateMatrix() const
1492 {
1493  if (!IsReflected()) {
1494  TGeoMatrix *matrix = new TGeoTranslation(0.,0.,0.);
1495  matrix->RegisterYourself();
1496  return matrix;
1497  }
1498  TGeoCombiTrans *combi = new TGeoCombiTrans();
1499  combi->RegisterYourself();
1500  combi->ReflectZ(kTRUE);
1501  combi->ReflectZ(kFALSE);
1502  return combi;
1503 }
1504 
1505 ////////////////////////////////////////////////////////////////////////////////
1506 /// Fills external matrix with the local one corresponding to the given division
1507 /// index.
1508 
1509 void TGeoPatternTrapZ::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
1510 {
1511  matrix.Clear();
1512  Double_t dz = fStart+idiv*fStep+0.5*fStep;
1513  matrix.SetDx(fTxz*dz);
1514  matrix.SetDy(fTyz*dz);
1515  matrix.SetDz((IsReflected())?-dz:dz);
1516 }
1517 
1518 //______________________________________________________________________________
1519 // TGeoPatternCylR - a cylindrical R divison pattern
1520 //______________________________________________________________________________
1521 
1522 ////////////////////////////////////////////////////////////////////////////////
1523 /// Default constructor
1524 
1525 TGeoPatternCylR::TGeoPatternCylR()
1526 {
1527  CreateThreadData(1);
1528 }
1529 ////////////////////////////////////////////////////////////////////////////////
1530 /// constructor
1531 
1532 TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions)
1533  :TGeoPatternFinder(vol, ndivisions)
1534 {
1535  CreateThreadData(1);
1536 }
1537 ////////////////////////////////////////////////////////////////////////////////
1538 /// constructor
1539 
1540 TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1541  :TGeoPatternFinder(vol, ndivisions)
1542 {
1543  fStep = step;
1544  CreateThreadData(1);
1545 // compute start, end
1546 }
1547 ////////////////////////////////////////////////////////////////////////////////
1548 /// constructor
1549 
1550 TGeoPatternCylR::TGeoPatternCylR(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1551  :TGeoPatternFinder(vol, ndivisions)
1552 {
1553  fStart = start;
1554  fEnd = end;
1555  fStep = (end - start)/ndivisions;
1556  CreateThreadData(1);
1557 }
1558 ////////////////////////////////////////////////////////////////////////////////
1559 ///copy constructor
1560 
1561 TGeoPatternCylR::TGeoPatternCylR(const TGeoPatternCylR& pf) :
1562  TGeoPatternFinder(pf)
1563 {
1564  CreateThreadData(1);
1565 }
1566 
1567 ////////////////////////////////////////////////////////////////////////////////
1568 ///assignment operator
1569 
1570 TGeoPatternCylR& TGeoPatternCylR::operator=(const TGeoPatternCylR& pf)
1571 {
1572  if(this!=&pf) {
1573  TGeoPatternFinder::operator=(pf);
1574  CreateThreadData(1);
1575  }
1576  return *this;
1577 }
1578 
1579 ////////////////////////////////////////////////////////////////////////////////
1580 /// Destructor
1581 
1582 TGeoPatternCylR::~TGeoPatternCylR()
1583 {
1584 }
1585 
1586 ////////////////////////////////////////////////////////////////////////////////
1587 /// Checks if the current point is on division boundary
1588 
1589 Bool_t TGeoPatternCylR::IsOnBoundary(const Double_t *point) const
1590 {
1591  Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
1592  Double_t seg = (r-fStart)/fStep;
1593  Double_t diff = seg - Int_t(seg);
1594  if (diff>0.5) diff = 1.-diff;
1595  if (diff<1e-8) return kTRUE;
1596  return kFALSE;
1597 }
1598 
1599 ////////////////////////////////////////////////////////////////////////////////
1600 /// Update current division index and global matrix to point to a given slice.
1601 
1602 void TGeoPatternCylR::cd(Int_t idiv)
1603 {
1604  ThreadData_t& td = GetThreadData();
1605  td.fCurrent=idiv;
1606 }
1607 
1608 ////////////////////////////////////////////////////////////////////////////////
1609 /// find the node containing the query point
1610 
1611 TGeoNode *TGeoPatternCylR::FindNode(Double_t *point, const Double_t *dir)
1612 {
1613  ThreadData_t& td = GetThreadData();
1614  if (!td.fMatrix) td.fMatrix = gGeoIdentity;
1615  TGeoNode *node = 0;
1616  Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
1617  Int_t ind = (Int_t)(1. + (r-fStart)/fStep) - 1;
1618  if (dir) {
1619  td.fNextIndex = ind;
1620  Double_t dot = point[0]*dir[0] + point[1]*dir[1];
1621  if (dot>0) td.fNextIndex++;
1622  else td.fNextIndex--;
1623  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
1624  }
1625  if ((ind<0) || (ind>=fNdivisions)) return node;
1626  node = GetNodeOffset(ind);
1627  cd(ind);
1628  return node;
1629 }
1630 
1631 ////////////////////////////////////////////////////////////////////////////////
1632 /// Make a copy of this finder. Reflect by Z if required.
1633 
1634 TGeoPatternFinder *TGeoPatternCylR::MakeCopy(Bool_t reflect)
1635 {
1636  TGeoPatternCylR *finder = new TGeoPatternCylR(*this);
1637  if (!reflect) return finder;
1638  finder->Reflect();
1639  return finder;
1640 }
1641 
1642 ////////////////////////////////////////////////////////////////////////////////
1643 /// Save a primitive as a C++ statement(s) on output stream "out".
1644 
1645 void TGeoPatternCylR::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1646 {
1647  Int_t iaxis = 1;
1648  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1649 }
1650 
1651 ////////////////////////////////////////////////////////////////////////////////
1652 /// Return new matrix of type used by this finder.
1653 
1654 TGeoMatrix* TGeoPatternCylR::CreateMatrix() const
1655 {
1656  return gGeoIdentity;
1657 }
1658 
1659 ////////////////////////////////////////////////////////////////////////////////
1660 /// Fills external matrix with the local one corresponding to the given division
1661 /// index.
1662 
1663 void TGeoPatternCylR::UpdateMatrix(Int_t, TGeoHMatrix &matrix) const
1664 {
1665  matrix.Clear();
1666 }
1667 
1668 //______________________________________________________________________________
1669 // TGeoPatternCylPhi - a cylindrical phi divison pattern
1670 //______________________________________________________________________________
1671 
1672 ////////////////////////////////////////////////////////////////////////////////
1673 /// Default constructor
1674 
1675 TGeoPatternCylPhi::TGeoPatternCylPhi()
1676 {
1677  fSinCos = 0;
1678  CreateThreadData(1);
1679 }
1680 ////////////////////////////////////////////////////////////////////////////////
1681 /// constructor
1682 /// compute step, start, end
1683 
1684 TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions)
1685  :TGeoPatternFinder(vol, ndivisions)
1686 {
1687  fStart = 0;
1688  fEnd = 0;
1689  fStep = 0;
1690  fSinCos = new Double_t[2*fNdivisions];
1691  for (Int_t i = 0; i<fNdivisions; i++) {
1692  fSinCos[2*i] = TMath::Sin(TMath::DegToRad()*(fStart+0.5*fStep+i*fStep));
1693  fSinCos[2*i+1] = TMath::Cos(TMath::DegToRad()*(fStart+0.5*fStep+i*fStep));
1694  }
1695  CreateThreadData(1);
1696 }
1697 ////////////////////////////////////////////////////////////////////////////////
1698 /// constructor
1699 
1700 TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1701  :TGeoPatternFinder(vol, ndivisions)
1702 {
1703  fStep = step;
1704  fSinCos = new Double_t[2*ndivisions];
1705  for (Int_t i = 0; i<fNdivisions; i++) {
1706  fSinCos[2*i] = TMath::Sin(TMath::DegToRad()*(fStart+0.5*fStep+i*fStep));
1707  fSinCos[2*i+1] = TMath::Cos(TMath::DegToRad()*(fStart+0.5*fStep+i*fStep));
1708  }
1709  CreateThreadData(1);
1710 // compute start, end
1711 }
1712 ////////////////////////////////////////////////////////////////////////////////
1713 /// constructor
1714 
1715 TGeoPatternCylPhi::TGeoPatternCylPhi(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1716  :TGeoPatternFinder(vol, ndivisions)
1717 {
1718  fStart = start;
1719  if (fStart<0) fStart+=360;
1720  fEnd = end;
1721  if (fEnd<0) fEnd+=360;
1722  if ((end-start)<0)
1723  fStep = (end-start+360)/ndivisions;
1724  else
1725  fStep = (end-start)/ndivisions;
1726  fSinCos = new Double_t[2*ndivisions];
1727  for (Int_t idiv = 0; idiv<ndivisions; idiv++) {
1728  fSinCos[2*idiv] = TMath::Sin(TMath::DegToRad()*(start+0.5*fStep+idiv*fStep));
1729  fSinCos[2*idiv+1] = TMath::Cos(TMath::DegToRad()*(start+0.5*fStep+idiv*fStep));
1730  }
1731  CreateThreadData(1);
1732 }
1733 ////////////////////////////////////////////////////////////////////////////////
1734 /// Destructor
1735 
1736 TGeoPatternCylPhi::~TGeoPatternCylPhi()
1737 {
1738  if (fSinCos) delete [] fSinCos;
1739 }
1740 ////////////////////////////////////////////////////////////////////////////////
1741 /// Update current division index and global matrix to point to a given slice.
1742 
1743 void TGeoPatternCylPhi::cd(Int_t idiv)
1744 {
1745  ThreadData_t& td = GetThreadData();
1746  td.fCurrent = idiv;
1747  ((TGeoRotation*)td.fMatrix)->FastRotZ(&fSinCos[2*idiv]);
1748 }
1749 
1750 ////////////////////////////////////////////////////////////////////////////////
1751 /// Checks if the current point is on division boundary
1752 
1753 Bool_t TGeoPatternCylPhi::IsOnBoundary(const Double_t *point) const
1754 {
1755  Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
1756  if (phi<0) phi += 360;
1757  Double_t ddp = phi - fStart;
1758  if (ddp<0) ddp+=360;
1759  Double_t seg = ddp/fStep;
1760  Double_t diff = seg - Int_t(seg);
1761  if (diff>0.5) diff = 1.-diff;
1762  if (diff<1e-8) return kTRUE;
1763  return kFALSE;
1764 }
1765 
1766 ////////////////////////////////////////////////////////////////////////////////
1767 /// find the node containing the query point
1768 
1769 TGeoNode *TGeoPatternCylPhi::FindNode(Double_t *point, const Double_t *dir)
1770 {
1771  ThreadData_t& td = GetThreadData();
1772  TGeoNode *node = 0;
1773  Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
1774  if (phi<0) phi += 360;
1775 // Double_t dphi = fStep*fNdivisions;
1776  Double_t ddp = phi - fStart;
1777  if (ddp<0) ddp+=360;
1778 // if (ddp>360) ddp-=360;
1779  Int_t ind = (Int_t)(1. + ddp/fStep) - 1;
1780  if (dir) {
1781  td.fNextIndex = ind;
1782  Double_t dot = point[0]*dir[1]-point[1]*dir[0];
1783  if (dot>0) td.fNextIndex++;
1784  else td.fNextIndex--;
1785  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
1786  }
1787  if ((ind<0) || (ind>=fNdivisions)) return node;
1788  node = GetNodeOffset(ind);
1789  cd(ind);
1790  return node;
1791 }
1792 
1793 ////////////////////////////////////////////////////////////////////////////////
1794 /// Make a copy of this finder. Reflect by Z if required.
1795 
1796 TGeoPatternFinder *TGeoPatternCylPhi::MakeCopy(Bool_t reflect)
1797 {
1798  TGeoPatternCylPhi *finder = new TGeoPatternCylPhi(*this);
1799  if (!reflect) return finder;
1800  finder->Reflect();
1801  return finder;
1802 }
1803 
1804 ////////////////////////////////////////////////////////////////////////////////
1805 /// Save a primitive as a C++ statement(s) on output stream "out".
1806 
1807 void TGeoPatternCylPhi::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1808 {
1809  Int_t iaxis = 2;
1810  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1811 }
1812 
1813 ////////////////////////////////////////////////////////////////////////////////
1814 /// Stream an object of class TGeoVolume.
1815 
1816 void TGeoPatternCylPhi::Streamer(TBuffer &R__b)
1817 {
1818  if (R__b.IsReading()) {
1819  R__b.ReadClassBuffer(TGeoPatternCylPhi::Class(), this);
1820  if (fNdivisions) {
1821  fSinCos = new Double_t[2*fNdivisions];
1822  for (Int_t idiv = 0; idiv<fNdivisions; idiv++) {
1823  fSinCos[2*idiv] = TMath::Sin(TMath::DegToRad()*(fStart+0.5*fStep+idiv*fStep));
1824  fSinCos[2*idiv+1] = TMath::Cos(TMath::DegToRad()*(fStart+0.5*fStep+idiv*fStep));
1825  }
1826  }
1827  } else {
1828  R__b.WriteClassBuffer(TGeoPatternCylPhi::Class(), this);
1829  }
1830 }
1831 
1832 ////////////////////////////////////////////////////////////////////////////////
1833 /// Return new matrix of type used by this finder.
1834 
1835 TGeoMatrix* TGeoPatternCylPhi::CreateMatrix() const
1836 {
1837  if (!IsReflected()) {
1838  TGeoRotation *matrix = new TGeoRotation();
1839  matrix->RegisterYourself();
1840  return matrix;
1841  }
1842  TGeoRotation *rot = new TGeoRotation();
1843  rot->RegisterYourself();
1844  rot->ReflectZ(kTRUE);
1845  rot->ReflectZ(kFALSE);
1846  return rot;
1847 }
1848 
1849 ////////////////////////////////////////////////////////////////////////////////
1850 /// Fills external matrix with the local one corresponding to the given division
1851 /// index.
1852 
1853 void TGeoPatternCylPhi::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
1854 {
1855  matrix.Clear();
1856  matrix.FastRotZ(&fSinCos[2*idiv]);
1857 }
1858 
1859 //______________________________________________________________________________
1860 // TGeoPatternSphR - a spherical R divison pattern
1861 //______________________________________________________________________________
1862 
1863 ////////////////////////////////////////////////////////////////////////////////
1864 /// Default constructor
1865 
1866 TGeoPatternSphR::TGeoPatternSphR()
1867 {
1868  CreateThreadData(1);
1869 }
1870 ////////////////////////////////////////////////////////////////////////////////
1871 /// constructor
1872 /// compute step, start, end
1873 
1874 TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions)
1875  :TGeoPatternFinder(vol, ndivisions)
1876 {
1877  CreateThreadData(1);
1878 }
1879 ////////////////////////////////////////////////////////////////////////////////
1880 /// constructor
1881 
1882 TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions, Double_t step)
1883  :TGeoPatternFinder(vol, ndivisions)
1884 {
1885  fStep = step;
1886  CreateThreadData(1);
1887 // compute start, end
1888 }
1889 ////////////////////////////////////////////////////////////////////////////////
1890 /// constructor
1891 
1892 TGeoPatternSphR::TGeoPatternSphR(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
1893  :TGeoPatternFinder(vol, ndivisions)
1894 {
1895  fStart = start;
1896  fEnd = end;
1897  fStep = (end - start)/ndivisions;
1898  CreateThreadData(1);
1899 }
1900 ////////////////////////////////////////////////////////////////////////////////
1901 ///copy constructor
1902 
1903 TGeoPatternSphR::TGeoPatternSphR(const TGeoPatternSphR& pf) :
1904  TGeoPatternFinder(pf)
1905 {
1906  CreateThreadData(1);
1907 }
1908 
1909 ////////////////////////////////////////////////////////////////////////////////
1910 ///assignment operator
1911 
1912 TGeoPatternSphR& TGeoPatternSphR::operator=(const TGeoPatternSphR& pf)
1913 {
1914  if(this!=&pf) {
1915  TGeoPatternFinder::operator=(pf);
1916  CreateThreadData(1);
1917  }
1918  return *this;
1919 }
1920 
1921 ////////////////////////////////////////////////////////////////////////////////
1922 /// Destructor
1923 
1924 TGeoPatternSphR::~TGeoPatternSphR()
1925 {
1926 }
1927 ////////////////////////////////////////////////////////////////////////////////
1928 /// Update current division index and global matrix to point to a given slice.
1929 
1930 void TGeoPatternSphR::cd(Int_t idiv)
1931 {
1932  ThreadData_t& td = GetThreadData();
1933  td.fCurrent = idiv;
1934 }
1935 ////////////////////////////////////////////////////////////////////////////////
1936 /// find the node containing the query point
1937 
1938 TGeoNode *TGeoPatternSphR::FindNode(Double_t * /*point*/, const Double_t * /*dir*/)
1939 {
1940  return 0;
1941 }
1942 
1943 ////////////////////////////////////////////////////////////////////////////////
1944 /// Make a copy of this finder. Reflect by Z if required.
1945 
1946 TGeoPatternFinder *TGeoPatternSphR::MakeCopy(Bool_t)
1947 {
1948  TGeoPatternSphR *finder = new TGeoPatternSphR(*this);
1949  return finder;
1950 }
1951 
1952 ////////////////////////////////////////////////////////////////////////////////
1953 /// Save a primitive as a C++ statement(s) on output stream "out".
1954 
1955 void TGeoPatternSphR::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1956 {
1957  Int_t iaxis = 1;
1958  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
1959 }
1960 
1961 ////////////////////////////////////////////////////////////////////////////////
1962 /// Return new matrix of type used by this finder.
1963 
1964 TGeoMatrix* TGeoPatternSphR::CreateMatrix() const
1965 {
1966  return gGeoIdentity;
1967 }
1968 
1969 ////////////////////////////////////////////////////////////////////////////////
1970 /// Fills external matrix with the local one corresponding to the given division
1971 /// index.
1972 
1973 void TGeoPatternSphR::UpdateMatrix(Int_t, TGeoHMatrix &matrix) const
1974 {
1975  matrix.Clear();
1976 }
1977 
1978 //______________________________________________________________________________
1979 // TGeoPatternSphTheta - a spherical theta divison pattern
1980 //______________________________________________________________________________
1981 
1982 ////////////////////////////////////////////////////////////////////////////////
1983 /// Default constructor
1984 
1985 TGeoPatternSphTheta::TGeoPatternSphTheta()
1986 {
1987  CreateThreadData(1);
1988 }
1989 ////////////////////////////////////////////////////////////////////////////////
1990 /// constructor
1991 /// compute step, start, end
1992 
1993 TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions)
1994  :TGeoPatternFinder(vol, ndivisions)
1995 {
1996  CreateThreadData(1);
1997 }
1998 ////////////////////////////////////////////////////////////////////////////////
1999 /// constructor
2000 
2001 TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions, Double_t step)
2002  :TGeoPatternFinder(vol, ndivisions)
2003 {
2004  fStep = step;
2005  CreateThreadData(1);
2006 // compute start, end
2007 }
2008 ////////////////////////////////////////////////////////////////////////////////
2009 /// constructor
2010 
2011 TGeoPatternSphTheta::TGeoPatternSphTheta(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
2012  :TGeoPatternFinder(vol, ndivisions)
2013 {
2014  fStart = start;
2015  fEnd = end;
2016  fStep = (end - start)/ndivisions;
2017  CreateThreadData(1);
2018 }
2019 ////////////////////////////////////////////////////////////////////////////////
2020 ///copy constructor
2021 
2022 TGeoPatternSphTheta::TGeoPatternSphTheta(const TGeoPatternSphTheta& pf) :
2023  TGeoPatternFinder(pf)
2024 {
2025  CreateThreadData(1);
2026 }
2027 ////////////////////////////////////////////////////////////////////////////////
2028 ///assignment operator
2029 
2030 TGeoPatternSphTheta& TGeoPatternSphTheta::operator=(const TGeoPatternSphTheta& pf)
2031 {
2032  if(this!=&pf) {
2033  TGeoPatternFinder::operator=(pf);
2034  CreateThreadData(1);
2035  }
2036  return *this;
2037 }
2038 ////////////////////////////////////////////////////////////////////////////////
2039 /// Destructor
2040 
2041 TGeoPatternSphTheta::~TGeoPatternSphTheta()
2042 {
2043 }
2044 ////////////////////////////////////////////////////////////////////////////////
2045 /// Update current division index and global matrix to point to a given slice.
2046 
2047 void TGeoPatternSphTheta::cd(Int_t idiv)
2048 {
2049  ThreadData_t& td = GetThreadData();
2050  td.fCurrent=idiv;
2051 }
2052 ////////////////////////////////////////////////////////////////////////////////
2053 /// find the node containing the query point
2054 
2055 TGeoNode *TGeoPatternSphTheta::FindNode(Double_t * /*point*/, const Double_t * /*dir*/)
2056 {
2057  return 0;
2058 }
2059 
2060 ////////////////////////////////////////////////////////////////////////////////
2061 /// Make a copy of this finder. Reflect by Z if required.
2062 
2063 TGeoPatternFinder *TGeoPatternSphTheta::MakeCopy(Bool_t)
2064 {
2065  TGeoPatternSphTheta *finder = new TGeoPatternSphTheta(*this);
2066  return finder;
2067 }
2068 
2069 ////////////////////////////////////////////////////////////////////////////////
2070 /// Save a primitive as a C++ statement(s) on output stream "out".
2071 
2072 void TGeoPatternSphTheta::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2073 {
2074  Int_t iaxis = 2;
2075  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
2076 }
2077 
2078 ////////////////////////////////////////////////////////////////////////////////
2079 /// Return new matrix of type used by this finder.
2080 
2081 TGeoMatrix* TGeoPatternSphTheta::CreateMatrix() const
2082 {
2083  return gGeoIdentity;
2084 }
2085 
2086 ////////////////////////////////////////////////////////////////////////////////
2087 /// Fills external matrix with the local one corresponding to the given division
2088 /// index.
2089 
2090 void TGeoPatternSphTheta::UpdateMatrix(Int_t, TGeoHMatrix &matrix) const
2091 {
2092  matrix.Clear();
2093 }
2094 
2095 //______________________________________________________________________________
2096 // TGeoPatternSphPhi - a spherical phi divison pattern
2097 //______________________________________________________________________________
2098 
2099 ////////////////////////////////////////////////////////////////////////////////
2100 /// Default constructor
2101 
2102 TGeoPatternSphPhi::TGeoPatternSphPhi()
2103 {
2104  fSinCos = 0;
2105  CreateThreadData(1);
2106 }
2107 ////////////////////////////////////////////////////////////////////////////////
2108 /// constructor
2109 /// compute step, start, end
2110 
2111 TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions)
2112  :TGeoPatternFinder(vol, ndivisions)
2113 {
2114  fStart = 0;
2115  fEnd = 360.;
2116  fStep = 360./ndivisions;
2117  CreateSinCos();
2118  CreateThreadData(1);
2119 }
2120 ////////////////////////////////////////////////////////////////////////////////
2121 /// constructor
2122 /// compute start, end
2123 
2124 TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions, Double_t step)
2125  :TGeoPatternFinder(vol, ndivisions)
2126 {
2127  fStep = step;
2128  CreateSinCos();
2129  CreateThreadData(1);
2130 }
2131 ////////////////////////////////////////////////////////////////////////////////
2132 /// constructor
2133 /// compute step
2134 
2135 TGeoPatternSphPhi::TGeoPatternSphPhi(TGeoVolume *vol, Int_t ndivisions, Double_t start, Double_t end)
2136  :TGeoPatternFinder(vol, ndivisions)
2137 {
2138  fStart = start;
2139  if (fStart<0) fStart+=360;
2140  fEnd = end;
2141  if (fEnd<0) fEnd+=360;
2142  if ((end-start)<0)
2143  fStep = (end-start+360)/ndivisions;
2144  else
2145  fStep = (end-start)/ndivisions;
2146  CreateSinCos();
2147  CreateThreadData(1);
2148 }
2149 
2150 ////////////////////////////////////////////////////////////////////////////////
2151 /// Destructor
2152 
2153 TGeoPatternSphPhi::~TGeoPatternSphPhi()
2154 {
2155  delete [] fSinCos;
2156 }
2157 
2158 ////////////////////////////////////////////////////////////////////////////////
2159 /// Create the sincos table if it does not exist
2160 
2161 Double_t *TGeoPatternSphPhi::CreateSinCos()
2162 {
2163  fSinCos = new Double_t[2*fNdivisions];
2164  for (Int_t idiv = 0; idiv<fNdivisions; idiv++) {
2165  fSinCos[2*idiv] = TMath::Sin(TMath::DegToRad()*(fStart+0.5*fStep+idiv*fStep));
2166  fSinCos[2*idiv+1] = TMath::Cos(TMath::DegToRad()*(fStart+0.5*fStep+idiv*fStep));
2167  }
2168  return fSinCos;
2169 }
2170 
2171 ////////////////////////////////////////////////////////////////////////////////
2172 /// Update current division index and global matrix to point to a given slice.
2173 
2174 void TGeoPatternSphPhi::cd(Int_t idiv)
2175 {
2176  ThreadData_t& td = GetThreadData();
2177  td.fCurrent = idiv;
2178  if (!fSinCos) CreateSinCos();
2179  ((TGeoRotation*)td.fMatrix)->FastRotZ(&fSinCos[2*idiv]);
2180 }
2181 
2182 ////////////////////////////////////////////////////////////////////////////////
2183 /// Checks if the current point is on division boundary
2184 
2185 Bool_t TGeoPatternSphPhi::IsOnBoundary(const Double_t *point) const
2186 {
2187  Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
2188  if (phi<0) phi += 360;
2189  Double_t ddp = phi - fStart;
2190  if (ddp<0) ddp+=360;
2191  Double_t seg = ddp/fStep;
2192  Double_t diff = seg - Int_t(seg);
2193  if (diff>0.5) diff = 1.-diff;
2194  if (diff<1e-8) return kTRUE;
2195  return kFALSE;
2196 }
2197 ////////////////////////////////////////////////////////////////////////////////
2198 /// find the node containing the query point
2199 
2200 TGeoNode *TGeoPatternSphPhi::FindNode(Double_t * point, const Double_t * dir)
2201 {
2202  ThreadData_t& td = GetThreadData();
2203  TGeoNode *node = 0;
2204  Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
2205  if (phi<0) phi += 360;
2206 // Double_t dphi = fStep*fNdivisions;
2207  Double_t ddp = phi - fStart;
2208  if (ddp<0) ddp+=360;
2209 // if (ddp>360) ddp-=360;
2210  Int_t ind = (Int_t)(1. + ddp/fStep) - 1;
2211  if (dir) {
2212  td.fNextIndex = ind;
2213  Double_t dot = point[0]*dir[1]-point[1]*dir[0];
2214  if (dot>0) td.fNextIndex++;
2215  else td.fNextIndex--;
2216  if ((td.fNextIndex<0) || (td.fNextIndex>=fNdivisions)) td.fNextIndex = -1;
2217  }
2218  if ((ind<0) || (ind>=fNdivisions)) return node;
2219  node = GetNodeOffset(ind);
2220  cd(ind);
2221  return node;
2222 }
2223 ////////////////////////////////////////////////////////////////////////////////
2224 /// Make a copy of this finder. Reflect by Z if required.
2225 
2226 TGeoPatternFinder *TGeoPatternSphPhi::MakeCopy(Bool_t reflect)
2227 {
2228  TGeoPatternSphPhi *finder = new TGeoPatternSphPhi(fVolume, fNdivisions, fStart, fEnd);
2229  if (!reflect) return finder;
2230  finder->Reflect();
2231  return finder;
2232 }
2233 
2234 ////////////////////////////////////////////////////////////////////////////////
2235 /// Save a primitive as a C++ statement(s) on output stream "out".
2236 
2237 void TGeoPatternSphPhi::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2238 {
2239  Int_t iaxis = 2;
2240  out << iaxis << ", " << fNdivisions << ", " << fStart << ", " << fStep;
2241 }
2242 ////////////////////////////////////////////////////////////////////////////////
2243 /// Return new matrix of type used by this finder.
2244 
2245 TGeoMatrix* TGeoPatternSphPhi::CreateMatrix() const
2246 {
2247  if (!IsReflected()) {
2248  TGeoRotation *matrix = new TGeoRotation();
2249  matrix->RegisterYourself();
2250  return matrix;
2251  }
2252  TGeoRotation *rot = new TGeoRotation();
2253  rot->RegisterYourself();
2254  rot->ReflectZ(kTRUE);
2255  rot->ReflectZ(kFALSE);
2256  return rot;
2257 }
2258 ////////////////////////////////////////////////////////////////////////////////
2259 /// Fills external matrix with the local one corresponding to the given division
2260 /// index.
2261 
2262 void TGeoPatternSphPhi::UpdateMatrix(Int_t idiv, TGeoHMatrix &matrix) const
2263 {
2264  if (!fSinCos) ((TGeoPatternSphPhi*)this)->CreateSinCos();
2265  matrix.Clear();
2266  matrix.FastRotZ(&fSinCos[2*idiv]);
2267 }
2268 
2269 //______________________________________________________________________________
2270 // TGeoPatternHoneycomb - a divison pattern specialized for honeycombs
2271 //______________________________________________________________________________
2272 
2273 ////////////////////////////////////////////////////////////////////////////////
2274 /// Default constructor
2275 
2276 TGeoPatternHoneycomb::TGeoPatternHoneycomb()
2277 {
2278  fNrows = 0;
2279  fAxisOnRows = 0;
2280  fNdivisions = 0;
2281  fStart = 0;
2282  CreateThreadData(1);
2283 }
2284 ////////////////////////////////////////////////////////////////////////////////
2285 /// Default constructor
2286 
2287 TGeoPatternHoneycomb::TGeoPatternHoneycomb(TGeoVolume *vol, Int_t nrows)
2288  :TGeoPatternFinder(vol, nrows)
2289 {
2290  fNrows = nrows;
2291  fAxisOnRows = 0;
2292  fNdivisions = 0;
2293  fStart = 0;
2294  CreateThreadData(1);
2295 // compute everything else
2296 }
2297 ////////////////////////////////////////////////////////////////////////////////
2298 ///copy constructor
2299 
2300 TGeoPatternHoneycomb::TGeoPatternHoneycomb(const TGeoPatternHoneycomb& pfh) :
2301  TGeoPatternFinder(pfh),
2302  fNrows(pfh.fNrows),
2303  fAxisOnRows(pfh.fAxisOnRows),
2304  fNdivisions(pfh.fNdivisions),
2305  fStart(pfh.fStart)
2306 {
2307  CreateThreadData(1);
2308 }
2309 
2310 ////////////////////////////////////////////////////////////////////////////////
2311 ///assignment operator
2312 
2313 TGeoPatternHoneycomb& TGeoPatternHoneycomb::operator=(const TGeoPatternHoneycomb& pfh)
2314 {
2315  if(this!=&pfh) {
2316  TGeoPatternFinder::operator=(pfh);
2317  fNrows=pfh.fNrows;
2318  fAxisOnRows=pfh.fAxisOnRows;
2319  fNdivisions=pfh.fNdivisions;
2320  fStart=pfh.fStart;
2321  CreateThreadData(1);
2322  }
2323  return *this;
2324 }
2325 ////////////////////////////////////////////////////////////////////////////////
2326 /// destructor
2327 
2328 TGeoPatternHoneycomb::~TGeoPatternHoneycomb()
2329 {
2330 }
2331 ////////////////////////////////////////////////////////////////////////////////
2332 /// Update current division index and global matrix to point to a given slice.
2333 
2334 void TGeoPatternHoneycomb::cd(Int_t idiv)
2335 {
2336  ThreadData_t& td = GetThreadData();
2337  td.fCurrent=idiv;
2338 }
2339 ////////////////////////////////////////////////////////////////////////////////
2340 /// find the node containing the query point
2341 
2342 TGeoNode *TGeoPatternHoneycomb::FindNode(Double_t * /*point*/, const Double_t * /*dir*/)
2343 {
2344  return 0;
2345 }
2346 
2347 ////////////////////////////////////////////////////////////////////////////////
2348 /// Return new matrix of type used by this finder.
2349 
2350 TGeoMatrix* TGeoPatternHoneycomb::CreateMatrix() const
2351 {
2352  return gGeoIdentity;
2353 }
2354 
2355 ////////////////////////////////////////////////////////////////////////////////
2356 /// Fills external matrix with the local one corresponding to the given division
2357 /// index.
2358 
2359 void TGeoPatternHoneycomb::UpdateMatrix(Int_t, TGeoHMatrix &matrix) const
2360 {
2361  matrix.Clear();
2362 }