Logo ROOT   6.12/07
Reference Guide
TGeoTube.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 24/10/01
3 // TGeoTube::Contains() and DistFromInside/In() implemented 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 TGeoTube
14 \ingroup Geometry_classes
15 
16 Cylindrical tube class. A tube has 3 parameters :
17  - Rmin - minimum radius
18  - Rmax - maximum radius
19  - dz - half length
20 Begin_Macro(source)
21 {
22  TCanvas *c = new TCanvas("c", "c",0,0,600,600);
23  new TGeoManager("tube", "poza2");
24  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
25  TGeoMedium *med = new TGeoMedium("MED",1,mat);
26  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
27  gGeoManager->SetTopVolume(top);
28  TGeoVolume *vol = gGeoManager->MakeTube("TUBE",med, 20,30,40);
29  vol->SetLineWidth(2);
30  top->AddNode(vol,1);
31  gGeoManager->CloseGeometry();
32  gGeoManager->SetNsegments(80);
33  top->Draw();
34  TView *view = gPad->GetView();
35  view->ShowAxis();
36 }
37 End_Macro
38 */
39 
40 /** \class TGeoTubeSeg
41 \ingroup Geometry_classes
42 
43 A phi segment of a tube. Has 5 parameters :
44  - the same 3 as a tube;
45  - first phi limit (in degrees)
46  - second phi limit
47 The segment will be be placed from the first angle (first phi limit)
48 to the second angle (second phi limit)
49 Begin_Macro(source)
50 {
51  TCanvas *c = new TCanvas("c", "c",0,0,600,600);
52  new TGeoManager("tubeseg", "poza3");
53  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
54  TGeoMedium *med = new TGeoMedium("MED",1,mat);
55  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
56  gGeoManager->SetTopVolume(top);
57  TGeoVolume *vol = gGeoManager->MakeTubs("TUBESEG",med, 20,30,40,-30,270);
58  vol->SetLineWidth(2);
59  top->AddNode(vol,1);
60  gGeoManager->CloseGeometry();
61  gGeoManager->SetNsegments(80);
62  top->Draw();
63  TView *view = gPad->GetView();
64  view->ShowAxis();
65 }
66 
67 End_Macro
68 */
69 
70 /** \class TGeoCtub
71 \ingroup Geometry_classes
72 
73 A tube segment cut with 2 planes. Has 11 parameters :
74  - the same 5 as a tube segment;
75  - x, y, z components of the normal to the -dZ cut plane in
76  point (0, 0, -dZ);
77  - x, y, z components of the normal to the +dZ cut plane in
78  point (0, 0, dZ);
79 
80 Begin_Macro(source)
81 {
82  TCanvas *c = new TCanvas("c", "c",0,0,600,600);
83  new TGeoManager("ctub", "poza3");
84  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
85  TGeoMedium *med = new TGeoMedium("MED",1,mat);
86  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
87  gGeoManager->SetTopVolume(top);
88  Double_t theta = 160.*TMath::Pi()/180.;
89  Double_t phi = 30.*TMath::Pi()/180.;
90  Double_t nlow[3];
91  nlow[0] = TMath::Sin(theta)*TMath::Cos(phi);
92  nlow[1] = TMath::Sin(theta)*TMath::Sin(phi);
93  nlow[2] = TMath::Cos(theta);
94  theta = 20.*TMath::Pi()/180.;
95  phi = 60.*TMath::Pi()/180.;
96  Double_t nhi[3];
97  nhi[0] = TMath::Sin(theta)*TMath::Cos(phi);
98  nhi[1] = TMath::Sin(theta)*TMath::Sin(phi);
99  nhi[2] = TMath::Cos(theta);
100  TGeoVolume *vol = gGeoManager->MakeCtub("CTUB",med, 20,30,40,-30,250, nlow[0], nlow[1], nlow[2], nhi[0],nhi[1],nhi[2]);
101  vol->SetLineWidth(2);
102  top->AddNode(vol,1);
103  gGeoManager->CloseGeometry();
104  gGeoManager->SetNsegments(80);
105  top->Draw();
106  TView *view = gPad->GetView();
107  view->ShowAxis();
108 }
109 End_Macro
110 */
111 
112 #include "Riostream.h"
113 
114 #include "TGeoManager.h"
115 #include "TGeoVolume.h"
116 #include "TVirtualGeoPainter.h"
117 #include "TGeoTube.h"
118 #include "TVirtualPad.h"
119 #include "TBuffer3D.h"
120 #include "TBuffer3DTypes.h"
121 #include "TMath.h"
122 
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 /// Default constructor
127 
129 {
131  fRmin = 0.0;
132  fRmax = 0.0;
133  fDz = 0.0;
134 }
135 
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// Default constructor specifying minimum and maximum radius
139 
141  :TGeoBBox(0, 0, 0)
142 {
144  SetTubeDimensions(rmin, rmax, dz);
145  if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
147 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
148 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
149  }
150  ComputeBBox();
151 }
152 ////////////////////////////////////////////////////////////////////////////////
153 /// Default constructor specifying minimum and maximum radius
154 
155 TGeoTube::TGeoTube(const char *name, Double_t rmin, Double_t rmax, Double_t dz)
156  :TGeoBBox(name, 0, 0, 0)
157 {
159  SetTubeDimensions(rmin, rmax, dz);
160  if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
162 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
163 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
164  }
165  ComputeBBox();
166 }
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Default constructor specifying minimum and maximum radius
170 /// - param[0] = Rmin
171 /// - param[1] = Rmax
172 /// - param[2] = dz
173 
175  :TGeoBBox(0, 0, 0)
176 {
178  SetDimensions(param);
179  if ((fDz<0) || (fRmin<0) || (fRmax<0)) SetShapeBit(kGeoRunTimeShape);
180  ComputeBBox();
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// destructor
185 
187 {
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 /// Computes capacity of the shape in [length^3]
192 
194 {
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// Computes capacity of the shape in [length^3]
200 
202 {
203  Double_t capacity = 2.*TMath::Pi()*(rmax*rmax-rmin*rmin)*dz;
204  return capacity;
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// compute bounding box of the tube
209 
211 {
212  fDX = fDY = fRmax;
213  fDZ = fDz;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Compute normal to closest surface from POINT.
218 
219 void TGeoTube::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
220 {
221  Double_t saf[3];
222  Double_t rsq = point[0]*point[0]+point[1]*point[1];
223  Double_t r = TMath::Sqrt(rsq);
224  saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
225  saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
226  saf[2] = TMath::Abs(fRmax-r);
227  Int_t i = TMath::LocMin(3,saf);
228  if (i==0) {
229  norm[0] = norm[1] = 0.;
230  norm[2] = TMath::Sign(1.,dir[2]);
231  return;
232  }
233  norm[2] = 0;
234  Double_t phi = TMath::ATan2(point[1], point[0]);
235  norm[0] = TMath::Cos(phi);
236  norm[1] = TMath::Sin(phi);
237  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
238  norm[0] = -norm[0];
239  norm[1] = -norm[1];
240  }
241 }
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 /// Compute normal to closest surface from POINT.
245 
246 void TGeoTube::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
247  Double_t /*rmin*/, Double_t /*rmax*/, Double_t /*dz*/)
248 {
249  norm[2] = 0;
250  Double_t phi = TMath::ATan2(point[1], point[0]);
251  norm[0] = TMath::Cos(phi);
252  norm[1] = TMath::Sin(phi);
253  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
254  norm[0] = -norm[0];
255  norm[1] = -norm[1];
256  }
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// test if point is inside this tube
261 
262 Bool_t TGeoTube::Contains(const Double_t *point) const
263 {
264  if (TMath::Abs(point[2]) > fDz) return kFALSE;
265  Double_t r2 = point[0]*point[0]+point[1]*point[1];
266  if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax)) return kFALSE;
267  return kTRUE;
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// compute closest distance from point px,py to each corner
272 
274 {
276  Int_t numPoints = 4*n;
277  if (!HasRmin()) numPoints = 2*(n+1);
278  return ShapeDistancetoPrimitive(numPoints, px, py);
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Compute distance from inside point to surface of the tube (static)
283 /// Boundary safe algorithm.
284 /// compute distance to surface
285 /// Do Z
286 
288 {
289  Double_t sz = TGeoShape::Big();
290  if (dir[2]) {
291  sz = (TMath::Sign(dz, dir[2])-point[2])/dir[2];
292  if (sz<=0) return 0.0;
293  }
294  // Do R
295  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
296  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return sz;
297  Double_t rsq=point[0]*point[0]+point[1]*point[1];
298  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
299  Double_t b,d;
301  // inner cylinder
302  if (rmin>0) {
303  // Protection in case point is actually outside the tube
304  if (rsq <= rmin*rmin+TGeoShape::Tolerance()) {
305  if (rdotn<0) return 0.0;
306  } else {
307  if (rdotn<0) {
308  DistToTube(rsq,nsq,rdotn,rmin,b,d);
309  if (d>0) {
310  sr=-b-d;
311  if (sr>0) return TMath::Min(sz,sr);
312  }
313  }
314  }
315  }
316  // outer cylinder
317  if (rsq >= rmax*rmax-TGeoShape::Tolerance()) {
318  if (rdotn>=0) return 0.0;
319  }
320  DistToTube(rsq,nsq,rdotn,rmax,b,d);
321  if (d>0) {
322  sr=-b+d;
323  if (sr>0) return TMath::Min(sz,sr);
324  }
325  return 0.;
326 }
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// Compute distance from inside point to surface of the tube
330 /// Boundary safe algorithm.
331 
332 Double_t TGeoTube::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
333 {
334  if (iact<3 && safe) {
335  *safe = Safety(point, kTRUE);
336  if (iact==0) return TGeoShape::Big();
337  if ((iact==1) && (*safe>step)) return TGeoShape::Big();
338  }
339  // compute distance to surface
340  return DistFromInsideS(point, dir, fRmin, fRmax, fDz);
341 }
342 
343 ////////////////////////////////////////////////////////////////////////////////
344 /// Static method to compute distance from outside point to a tube with given parameters
345 /// Boundary safe algorithm.
346 /// check Z planes
347 
349 {
350  Double_t xi,yi,zi;
351  Double_t rmaxsq = rmax*rmax;
352  Double_t rminsq = rmin*rmin;
353  zi = dz - TMath::Abs(point[2]);
355  Bool_t in = kFALSE;
356  Bool_t inz = (zi<0)?kFALSE:kTRUE;
357  if (!inz) {
358  if (point[2]*dir[2]>=0) return TGeoShape::Big();
359  s = -zi/TMath::Abs(dir[2]);
360  xi = point[0]+s*dir[0];
361  yi = point[1]+s*dir[1];
362  Double_t r2=xi*xi+yi*yi;
363  if ((rminsq<=r2) && (r2<=rmaxsq)) return s;
364  }
365 
366  Double_t rsq = point[0]*point[0]+point[1]*point[1];
367  // check outer cyl. surface
368  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
369  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
370  Double_t b,d;
371  Bool_t inrmax = kFALSE;
372  Bool_t inrmin = kFALSE;
373  if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
374  if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
375  in = inz & inrmin & inrmax;
376  // If inside, we are most likely on a boundary within machine precision.
377  if (in) {
378  Bool_t checkout = kFALSE;
379  Double_t r = TMath::Sqrt(rsq);
380  if (zi<rmax-r) {
381  if ((TGeoShape::IsSameWithinTolerance(rmin,0)) || (zi<r-rmin)) {
382  if (point[2]*dir[2]<0) return 0.0;
383  return TGeoShape::Big();
384  }
385  }
386  if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
387  if (checkout) {
388  if (rdotn>=0) return TGeoShape::Big();
389  return 0.0;
390  }
391  if (TGeoShape::IsSameWithinTolerance(rmin,0)) return 0.0;
392  if (rdotn>=0) return 0.0;
393  // Ray exiting rmin -> check (+) solution for inner tube
394  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
395  DistToTube(rsq, nsq, rdotn, rmin, b, d);
396  if (d>0) {
397  s=-b+d;
398  if (s>0) {
399  zi=point[2]+s*dir[2];
400  if (TMath::Abs(zi)<=dz) return s;
401  }
402  }
403  return TGeoShape::Big();
404  }
405  // Check outer cylinder (only r>rmax has to be considered)
406  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
407  if (!inrmax) {
408  DistToTube(rsq, nsq, rdotn, rmax, b, d);
409  if (d>0) {
410  s=-b-d;
411  if (s>0) {
412  zi=point[2]+s*dir[2];
413  if (TMath::Abs(zi)<=dz) return s;
414  }
415  }
416  }
417  // check inner cylinder
418  if (rmin>0) {
419  DistToTube(rsq, nsq, rdotn, rmin, b, d);
420  if (d>0) {
421  s=-b+d;
422  if (s>0) {
423  zi=point[2]+s*dir[2];
424  if (TMath::Abs(zi)<=dz) return s;
425  }
426  }
427  }
428  return TGeoShape::Big();
429 }
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Compute distance from outside point to surface of the tube and safe distance
433 /// Boundary safe algorithm.
434 /// fist localize point w.r.t tube
435 
436 Double_t TGeoTube::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
437 {
438  if (iact<3 && safe) {
439  *safe = Safety(point, kFALSE);
440  if (iact==0) return TGeoShape::Big();
441  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
442  }
443 // Check if the bounding box is crossed within the requested distance
444  Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
445  if (sdist>=step) return TGeoShape::Big();
446  // find distance to shape
447  return DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Static method computing the distance to a tube with given radius, starting from
452 /// POINT along DIR director cosines. The distance is computed as :
453 /// RSQ = point[0]*point[0]+point[1]*point[1]
454 /// NSQ = dir[0]*dir[0]+dir[1]*dir[1] ---> should NOT be 0 !!!
455 /// RDOTN = point[0]*dir[0]+point[1]*dir[1]
456 /// The distance can be computed as :
457 /// D = -B +/- DELTA
458 /// where DELTA.GT.0 and D.GT.0
459 
460 void TGeoTube::DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta)
461 {
462  Double_t t1 = 1./nsq;
463  Double_t t3=rsq-(radius*radius);
464  b = t1*rdotn;
465  Double_t c =t1*t3;
466  delta = b*b-c;
467  if (delta>0) {
468  delta=TMath::Sqrt(delta);
469  } else {
470  delta = -1;
471  }
472 }
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Divide this tube shape belonging to volume "voldiv" into ndiv volumes
476 /// called divname, from start position with the given step. Returns pointer
477 /// to created division cell volume in case of Z divisions. For radial division
478 /// creates all volumes with different shapes and returns pointer to volume that
479 /// was divided. In case a wrong division axis is supplied, returns pointer to
480 /// volume that was divided.
481 
482 TGeoVolume *TGeoTube::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
483  Double_t start, Double_t step)
484 {
485  TGeoShape *shape; //--- shape to be created
486  TGeoVolume *vol; //--- division volume to be created
487  TGeoVolumeMulti *vmulti; //--- generic divided volume
488  TGeoPatternFinder *finder; //--- finder to be attached
489  TString opt = ""; //--- option to be attached
490  Int_t id;
491  Double_t end = start+ndiv*step;
492  switch (iaxis) {
493  case 1: //--- R division
494  finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
495  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
496  voldiv->SetFinder(finder);
497  finder->SetDivIndex(voldiv->GetNdaughters());
498  for (id=0; id<ndiv; id++) {
499  shape = new TGeoTube(start+id*step, start+(id+1)*step, fDz);
500  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
501  vmulti->AddVolume(vol);
502  opt = "R";
503  voldiv->AddNodeOffset(vol, id, 0, opt.Data());
504  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
505  }
506  return vmulti;
507  case 2: //--- Phi division
508  finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
509  voldiv->SetFinder(finder);
510  finder->SetDivIndex(voldiv->GetNdaughters());
511  shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
512  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
513  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
514  vmulti->AddVolume(vol);
515  opt = "Phi";
516  for (id=0; id<ndiv; id++) {
517  voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
518  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
519  }
520  return vmulti;
521  case 3: //--- Z division
522  finder = new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
523  voldiv->SetFinder(finder);
524  finder->SetDivIndex(voldiv->GetNdaughters());
525  shape = new TGeoTube(fRmin, fRmax, step/2);
526  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
527  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
528  vmulti->AddVolume(vol);
529  opt = "Z";
530  for (id=0; id<ndiv; id++) {
531  voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
532  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
533  }
534  return vmulti;
535  default:
536  Error("Divide", "In shape %s wrong axis type for division", GetName());
537  return 0;
538  }
539 }
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// Returns name of axis IAXIS.
543 
544 const char *TGeoTube::GetAxisName(Int_t iaxis) const
545 {
546  switch (iaxis) {
547  case 1:
548  return "R";
549  case 2:
550  return "PHI";
551  case 3:
552  return "Z";
553  default:
554  return "UNDEFINED";
555  }
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Get range of shape for a given axis.
560 
562 {
563  xlo = 0;
564  xhi = 0;
565  Double_t dx = 0;
566  switch (iaxis) {
567  case 1:
568  xlo = fRmin;
569  xhi = fRmax;
570  dx = xhi-xlo;
571  return dx;
572  case 2:
573  xlo = 0;
574  xhi = 360;
575  dx = 360;
576  return dx;
577  case 3:
578  xlo = -fDz;
579  xhi = fDz;
580  dx = xhi-xlo;
581  return dx;
582  }
583  return dx;
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////////
587 /// Fill vector param[4] with the bounding cylinder parameters. The order
588 /// is the following : Rmin, Rmax, Phi1, Phi2, dZ
589 
591 {
592  param[0] = fRmin; // Rmin
593  param[0] *= param[0];
594  param[1] = fRmax; // Rmax
595  param[1] *= param[1];
596  param[2] = 0.; // Phi1
597  param[3] = 360.; // Phi2
598 }
599 
600 ////////////////////////////////////////////////////////////////////////////////
601 /// in case shape has some negative parameters, these has to be computed
602 /// in order to fit the mother
603 
605 {
606  if (!TestShapeBit(kGeoRunTimeShape)) return 0;
607  Double_t rmin, rmax, dz;
609  rmin = fRmin;
610  rmax = fRmax;
611  dz = fDz;
612  if (fDz<0) {
613  mother->GetAxisRange(3,xmin,xmax);
614  if (xmax<0) return 0;
615  dz=xmax;
616  }
617  mother->GetAxisRange(1,xmin,xmax);
618  if (fRmin<0) {
619  if (xmin<0) return 0;
620  rmin = xmin;
621  }
622  if (fRmax<0) {
623  if (xmax<=0) return 0;
624  rmax = xmax;
625  }
626 
627  return (new TGeoTube(GetName(), rmin, rmax, dz));
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// print shape parameters
632 
634 {
635  printf("*** Shape %s: TGeoTube ***\n", GetName());
636  printf(" Rmin = %11.5f\n", fRmin);
637  printf(" Rmax = %11.5f\n", fRmax);
638  printf(" dz = %11.5f\n", fDz);
639  printf(" Bounding box:\n");
641 }
642 
643 ////////////////////////////////////////////////////////////////////////////////
644 /// Creates a TBuffer3D describing *this* shape.
645 /// Coordinates are in local reference frame.
646 
648 {
650  Int_t nbPnts = 4*n;
651  Int_t nbSegs = 8*n;
652  Int_t nbPols = 4*n;
653  if (!HasRmin()) {
654  nbPnts = 2*(n+1);
655  nbSegs = 5*n;
656  nbPols = 3*n;
657  }
659  nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
660  if (buff)
661  {
662  SetPoints(buff->fPnts);
663  SetSegsAndPols(*buff);
664  }
665 
666  return buff;
667 }
668 
669 ////////////////////////////////////////////////////////////////////////////////
670 /// Fill TBuffer3D structure for segments and polygons.
671 
673 {
674  Int_t i, j,indx;
676  Int_t c = (((buffer.fColor) %8) -1) * 4;
677  if (c < 0) c = 0;
678 
679  if (HasRmin()) {
680  // circle segments:
681  // lower rmin circle: i=0, (0, n-1)
682  // lower rmax circle: i=1, (n, 2n-1)
683  // upper rmin circle: i=2, (2n, 3n-1)
684  // upper rmax circle: i=1, (3n, 4n-1)
685  for (i = 0; i < 4; i++) {
686  for (j = 0; j < n; j++) {
687  indx = 3*(i*n+j);
688  buffer.fSegs[indx ] = c;
689  buffer.fSegs[indx+1] = i*n+j;
690  buffer.fSegs[indx+2] = i*n+(j+1)%n;
691  }
692  }
693  // Z-parallel segments
694  // inner: i=4, (4n, 5n-1)
695  // outer: i=5, (5n, 6n-1)
696  for (i = 4; i < 6; i++) {
697  for (j = 0; j < n; j++) {
698  indx = 3*(i*n+j);
699  buffer.fSegs[indx ] = c+1;
700  buffer.fSegs[indx+1] = (i-4)*n+j;
701  buffer.fSegs[indx+2] = (i-2)*n+j;
702  }
703  }
704  // Radial segments
705  // lower: i=6, (6n, 7n-1)
706  // upper: i=7, (7n, 8n-1)
707  for (i = 6; i < 8; i++) {
708  for (j = 0; j < n; j++) {
709  indx = 3*(i*n+j);
710  buffer.fSegs[indx ] = c;
711  buffer.fSegs[indx+1] = 2*(i-6)*n+j;
712  buffer.fSegs[indx+2] = (2*(i-6)+1)*n+j;
713  }
714  }
715  // Polygons
716  i=0;
717  // Inner lateral (0, n-1)
718  for (j = 0; j < n; j++) {
719  indx = 6*(i*n+j);
720  buffer.fPols[indx ] = c;
721  buffer.fPols[indx+1] = 4;
722  buffer.fPols[indx+2] = j;
723  buffer.fPols[indx+3] = 4*n+(j+1)%n;
724  buffer.fPols[indx+4] = 2*n+j;
725  buffer.fPols[indx+5] = 4*n+j;
726  }
727  i=1;
728  // Outer lateral (n,2n-1)
729  for (j = 0; j < n; j++) {
730  indx = 6*(i*n+j);
731  buffer.fPols[indx ] = c+1;
732  buffer.fPols[indx+1] = 4;
733  buffer.fPols[indx+2] = n+j;
734  buffer.fPols[indx+3] = 5*n+j;
735  buffer.fPols[indx+4] = 3*n+j;
736  buffer.fPols[indx+5] = 5*n+(j+1)%n;
737  }
738  i=2;
739  // lower disc (2n, 3n-1)
740  for (j = 0; j < n; j++) {
741  indx = 6*(i*n+j);
742  buffer.fPols[indx ] = c;
743  buffer.fPols[indx+1] = 4;
744  buffer.fPols[indx+2] = j;
745  buffer.fPols[indx+3] = 6*n+j;
746  buffer.fPols[indx+4] = n+j;
747  buffer.fPols[indx+5] = 6*n+(j+1)%n;
748  }
749  i=3;
750  // upper disc (3n, 4n-1)
751  for (j = 0; j < n; j++) {
752  indx = 6*(i*n+j);
753  buffer.fPols[indx ] = c;
754  buffer.fPols[indx+1] = 4;
755  buffer.fPols[indx+2] = 2*n+j;
756  buffer.fPols[indx+3] = 7*n+(j+1)%n;
757  buffer.fPols[indx+4] = 3*n+j;
758  buffer.fPols[indx+5] = 7*n+j;
759  }
760  return;
761  }
762  // Rmin=0 tubes
763  // circle segments
764  // lower rmax circle: i=0, (0, n-1)
765  // upper rmax circle: i=1, (n, 2n-1)
766  for (i = 0; i < 2; i++) {
767  for (j = 0; j < n; j++) {
768  indx = 3*(i*n+j);
769  buffer.fSegs[indx ] = c;
770  buffer.fSegs[indx+1] = 2+i*n+j;
771  buffer.fSegs[indx+2] = 2+i*n+(j+1)%n;
772  }
773  }
774  // Z-parallel segments (2n,3n-1)
775  for (j = 0; j < n; j++) {
776  indx = 3*(2*n+j);
777  buffer.fSegs[indx ] = c+1;
778  buffer.fSegs[indx+1] = 2+j;
779  buffer.fSegs[indx+2] = 2+n+j;
780  }
781  // Radial segments
782  // Lower circle: i=3, (3n,4n-1)
783  // Upper circle: i=4, (4n,5n-1)
784  for (i = 3; i < 5; i++) {
785  for (j = 0; j < n; j++) {
786  indx = 3*(i*n+j);
787  buffer.fSegs[indx ] = c;
788  buffer.fSegs[indx+1] = i-3;
789  buffer.fSegs[indx+2] = 2+(i-3)*n+j;
790  }
791  }
792  // Polygons
793  // lateral (0,n-1)
794  for (j = 0; j < n; j++) {
795  indx = 6*j;
796  buffer.fPols[indx ] = c+1;
797  buffer.fPols[indx+1] = 4;
798  buffer.fPols[indx+2] = j;
799  buffer.fPols[indx+3] = 2*n+j;
800  buffer.fPols[indx+4] = n+j;
801  buffer.fPols[indx+5] = 2*n+(j+1)%n;
802  }
803  // bottom triangles (n,2n-1)
804  for (j = 0; j < n; j++) {
805  indx = 6*n + 5*j;
806  buffer.fPols[indx ] = c;
807  buffer.fPols[indx+1] = 3;
808  buffer.fPols[indx+2] = j;
809  buffer.fPols[indx+3] = 3*n+(j+1)%n;
810  buffer.fPols[indx+4] = 3*n+j;
811  }
812  // top triangles (2n,3n-1)
813  for (j = 0; j < n; j++) {
814  indx = 6*n + 5*n + 5*j;
815  buffer.fPols[indx ] = c;
816  buffer.fPols[indx+1] = 3;
817  buffer.fPols[indx+2] = n+j;
818  buffer.fPols[indx+3] = 4*n+j;
819  buffer.fPols[indx+4] = 4*n+(j+1)%n;
820  }
821 }
822 
823 ////////////////////////////////////////////////////////////////////////////////
824 /// computes the closest distance from given point to this shape, according
825 /// to option. The matching point on the shape is stored in spoint.
826 
827 Double_t TGeoTube::Safety(const Double_t *point, Bool_t in) const
828 {
829 #ifndef NEVER
830  Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
831  Double_t safe, safrmin, safrmax;
832  if (in) {
833  safe = fDz-TMath::Abs(point[2]); // positive if inside
834  if (fRmin>1E-10) {
835  safrmin = r-fRmin;
836  if (safrmin < safe) safe = safrmin;
837  }
838  safrmax = fRmax-r;
839  if (safrmax < safe) safe = safrmax;
840  } else {
841  safe = -fDz+TMath::Abs(point[2]);
842  if (fRmin>1E-10) {
843  safrmin = -r+fRmin;
844  if (safrmin > safe) safe = safrmin;
845  }
846  safrmax = -fRmax+r;
847  if (safrmax > safe) safe = safrmax;
848  }
849  return safe;
850 #else
851  Double_t saf[3];
852  Double_t rsq = point[0]*point[0]+point[1]*point[1];
853  Double_t r = TMath::Sqrt(rsq);
854  saf[0] = fDz-TMath::Abs(point[2]); // positive if inside
855  saf[1] = (fRmin>1E-10)?(r-fRmin):TGeoShape::Big();
856  saf[2] = fRmax-r;
857  if (in) return saf[TMath::LocMin(3,saf)];
858  for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
859  return saf[TMath::LocMax(3,saf)];
860 #endif
861 }
862 
863 ////////////////////////////////////////////////////////////////////////////////
864 /// computes the closest distance from given point to this shape, according
865 /// to option. The matching point on the shape is stored in spoint.
866 
867 Double_t TGeoTube::SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
868 {
869  Double_t saf[3];
870  Double_t rsq = point[0]*point[0]+point[1]*point[1];
871  Double_t r = TMath::Sqrt(rsq);
872  switch (skipz) {
873  case 1: // skip lower Z plane
874  saf[0] = dz - point[2];
875  break;
876  case 2: // skip upper Z plane
877  saf[0] = dz + point[2];
878  break;
879  case 3: // skip both
880  saf[0] = TGeoShape::Big();
881  break;
882  default:
883  saf[0] = dz-TMath::Abs(point[2]);
884  }
885  saf[1] = (rmin>1E-10)?(r-rmin):TGeoShape::Big();
886  saf[2] = rmax-r;
887 // printf("saf0=%g saf1=%g saf2=%g in=%d skipz=%d\n", saf[0],saf[1],saf[2],in,skipz);
888  if (in) return saf[TMath::LocMin(3,saf)];
889  for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
890  return saf[TMath::LocMax(3,saf)];
891 }
892 
893 ////////////////////////////////////////////////////////////////////////////////
894 /// Save a primitive as a C++ statement(s) on output stream "out".
895 
896 void TGeoTube::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
897 {
898  if (TObject::TestBit(kGeoSavePrimitive)) return;
899  out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
900  out << " rmin = " << fRmin << ";" << std::endl;
901  out << " rmax = " << fRmax << ";" << std::endl;
902  out << " dz = " << fDz << ";" << std::endl;
903  out << " TGeoShape *" << GetPointerName() << " = new TGeoTube(\"" << GetName() << "\",rmin,rmax,dz);" << std::endl;
905 }
906 
907 ////////////////////////////////////////////////////////////////////////////////
908 /// Set tube dimensions.
909 
911 {
912  fRmin = rmin;
913  fRmax = rmax;
914  fDz = dz;
915  if (fRmin>0 && fRmax>0 && fRmin>=fRmax)
916  Error("SetTubeDimensions", "In shape %s wrong rmin=%g rmax=%g", GetName(), rmin,rmax);
917 }
918 
919 ////////////////////////////////////////////////////////////////////////////////
920 /// Set tube dimensions starting from a list.
921 
923 {
924  Double_t rmin = param[0];
925  Double_t rmax = param[1];
926  Double_t dz = param[2];
927  SetTubeDimensions(rmin, rmax, dz);
928 }
929 
930 ////////////////////////////////////////////////////////////////////////////////
931 /// Fills array with n random points located on the line segments of the shape mesh.
932 /// The output array must be provided with a length of minimum 3*npoints. Returns
933 /// true if operation is implemented.
934 
936 {
937  if (npoints > (npoints/2)*2) {
938  Error("GetPointsOnSegments","Npoints must be even number");
939  return kFALSE;
940  }
941  Int_t nc = 0;
942  if (HasRmin()) nc = (Int_t)TMath::Sqrt(0.5*npoints);
943  else nc = (Int_t)TMath::Sqrt(1.*npoints);
944  Double_t dphi = TMath::TwoPi()/nc;
945  Double_t phi = 0;
946  Int_t ntop = 0;
947  if (HasRmin()) ntop = npoints/2 - nc*(nc-1);
948  else ntop = npoints - nc*(nc-1);
949  Double_t dz = 2*fDz/(nc-1);
950  Double_t z = 0;
951  Int_t icrt = 0;
952  Int_t nphi = nc;
953  // loop z sections
954  for (Int_t i=0; i<nc; i++) {
955  if (i == (nc-1)) nphi = ntop;
956  z = -fDz + i*dz;
957  // loop points on circle sections
958  for (Int_t j=0; j<nphi; j++) {
959  phi = j*dphi;
960  if (HasRmin()) {
961  array[icrt++] = fRmin * TMath::Cos(phi);
962  array[icrt++] = fRmin * TMath::Sin(phi);
963  array[icrt++] = z;
964  }
965  array[icrt++] = fRmax * TMath::Cos(phi);
966  array[icrt++] = fRmax * TMath::Sin(phi);
967  array[icrt++] = z;
968  }
969  }
970  return kTRUE;
971 }
972 
973 ////////////////////////////////////////////////////////////////////////////////
974 /// create tube mesh points
975 
977 {
978  Double_t dz;
979  Int_t j, n;
980  n = gGeoManager->GetNsegments();
981  Double_t dphi = 360./n;
982  Double_t phi = 0;
983  dz = fDz;
984  Int_t indx = 0;
985  if (points) {
986  if (HasRmin()) {
987  // 4*n points
988  // (0,n-1) lower rmin circle
989  // (2n, 3n-1) upper rmin circle
990  for (j = 0; j < n; j++) {
991  phi = j*dphi*TMath::DegToRad();
992  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
993  indx++;
994  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
995  indx++;
996  points[indx+6*n] = dz;
997  points[indx] =-dz;
998  indx++;
999  }
1000  // (n, 2n-1) lower rmax circle
1001  // (3n, 4n-1) upper rmax circle
1002  for (j = 0; j < n; j++) {
1003  phi = j*dphi*TMath::DegToRad();
1004  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
1005  indx++;
1006  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
1007  indx++;
1008  points[indx+6*n]= dz;
1009  points[indx] =-dz;
1010  indx++;
1011  }
1012  } else {
1013  // centers of lower/upper circles (0,1)
1014  points[indx++] = 0.;
1015  points[indx++] = 0.;
1016  points[indx++] = -dz;
1017  points[indx++] = 0.;
1018  points[indx++] = 0.;
1019  points[indx++] = dz;
1020  // lower rmax circle (2, 2+n-1)
1021  // upper rmax circle (2+n, 2+2n-1)
1022  for (j = 0; j < n; j++) {
1023  phi = j*dphi*TMath::DegToRad();
1024  points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1025  indx++;
1026  points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1027  indx++;
1028  points[indx+3*n]= dz;
1029  points[indx] =-dz;
1030  indx++;
1031  }
1032  }
1033  }
1034 }
1035 
1036 ////////////////////////////////////////////////////////////////////////////////
1037 /// create tube mesh points
1038 
1040 {
1041  Double_t dz;
1042  Int_t j, n;
1043  n = gGeoManager->GetNsegments();
1044  Double_t dphi = 360./n;
1045  Double_t phi = 0;
1046  dz = fDz;
1047  Int_t indx = 0;
1048  if (points) {
1049  if (HasRmin()) {
1050  // 4*n points
1051  // (0,n-1) lower rmin circle
1052  // (2n, 3n-1) upper rmin circle
1053  for (j = 0; j < n; j++) {
1054  phi = j*dphi*TMath::DegToRad();
1055  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
1056  indx++;
1057  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
1058  indx++;
1059  points[indx+6*n] = dz;
1060  points[indx] =-dz;
1061  indx++;
1062  }
1063  // (n, 2n-1) lower rmax circle
1064  // (3n, 4n-1) upper rmax circle
1065  for (j = 0; j < n; j++) {
1066  phi = j*dphi*TMath::DegToRad();
1067  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
1068  indx++;
1069  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
1070  indx++;
1071  points[indx+6*n]= dz;
1072  points[indx] =-dz;
1073  indx++;
1074  }
1075  } else {
1076  // centers of lower/upper circles (0,1)
1077  points[indx++] = 0.;
1078  points[indx++] = 0.;
1079  points[indx++] = -dz;
1080  points[indx++] = 0.;
1081  points[indx++] = 0.;
1082  points[indx++] = dz;
1083  // lower rmax circle (2, 2+n-1)
1084  // upper rmax circle (2+n, 2+2n-1)
1085  for (j = 0; j < n; j++) {
1086  phi = j*dphi*TMath::DegToRad();
1087  points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1088  indx++;
1089  points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1090  indx++;
1091  points[indx+3*n]= dz;
1092  points[indx] =-dz;
1093  indx++;
1094  }
1095  }
1096  }
1097 }
1098 
1099 ////////////////////////////////////////////////////////////////////////////////
1100 /// Return number of vertices of the mesh representation
1101 
1103 {
1105  Int_t numPoints = n*4;
1106  if (!HasRmin()) numPoints = 2*(n+1);
1107  return numPoints;
1108 }
1109 
1110 ////////////////////////////////////////////////////////////////////////////////
1111 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
1112 
1113 void TGeoTube::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
1114 {
1116  nvert = n*4;
1117  nsegs = n*8;
1118  npols = n*4;
1119  if (!HasRmin()) {
1120  nvert = 2*(n+1);
1121  nsegs = 5*n;
1122  npols = 3*n;
1123  } else {
1124  nvert = n*4;
1125  nsegs = n*8;
1126  npols = n*4;
1127  }
1128 }
1129 
1130 ////////////////////////////////////////////////////////////////////////////////
1131 /// fill size of this 3-D object
1132 
1134 {
1135 }
1136 
1137 ////////////////////////////////////////////////////////////////////////////////
1138 /// Fills a static 3D buffer and returns a reference.
1139 
1140 const TBuffer3D & TGeoTube::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
1141 {
1142  static TBuffer3DTube buffer;
1143  TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1144 
1145  if (reqSections & TBuffer3D::kShapeSpecific) {
1146  buffer.fRadiusInner = fRmin;
1147  buffer.fRadiusOuter = fRmax;
1148  buffer.fHalfLength = fDz;
1149  buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
1150  }
1151  if (reqSections & TBuffer3D::kRawSizes) {
1153  Int_t nbPnts = 4*n;
1154  Int_t nbSegs = 8*n;
1155  Int_t nbPols = 4*n;
1156  if (!HasRmin()) {
1157  nbPnts = 2*(n+1);
1158  nbSegs = 5*n;
1159  nbPols = 3*n;
1160  }
1161  if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
1162  buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1163  }
1164  }
1165  if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1166  SetPoints(buffer.fPnts);
1167  if (!buffer.fLocalFrame) {
1168  TransformPoints(buffer.fPnts, buffer.NbPnts());
1169  }
1170  SetSegsAndPols(buffer);
1171  buffer.SetSectionsValid(TBuffer3D::kRaw);
1172  }
1173 
1174  return buffer;
1175 }
1176 
1177 ////////////////////////////////////////////////////////////////////////////////
1178 /// Check the inside status for each of the points in the array.
1179 /// Input: Array of point coordinates + vector size
1180 /// Output: Array of Booleans for the inside of each point
1181 
1182 void TGeoTube::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
1183 {
1184  for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
1185 }
1186 
1187 ////////////////////////////////////////////////////////////////////////////////
1188 /// Compute the normal for an array o points so that norm.dot.dir is positive
1189 /// Input: Arrays of point coordinates and directions + vector size
1190 /// Output: Array of normal directions
1191 
1192 void TGeoTube::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
1193 {
1194  for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
1195 }
1196 
1197 ////////////////////////////////////////////////////////////////////////////////
1198 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
1199 
1200 void TGeoTube::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
1201 {
1202  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
1203 }
1204 
1205 ////////////////////////////////////////////////////////////////////////////////
1206 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
1207 
1208 void TGeoTube::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
1209 {
1210  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
1211 }
1212 
1213 ////////////////////////////////////////////////////////////////////////////////
1214 /// Compute safe distance from each of the points in the input array.
1215 /// Input: Array of point coordinates, array of statuses for these points, size of the arrays
1216 /// Output: Safety values
1217 
1218 void TGeoTube::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
1219 {
1220  for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
1221 }
1222 
1224 
1225 ////////////////////////////////////////////////////////////////////////////////
1226 /// Default constructor
1227 
1229  :TGeoTube(),
1230  fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1231 {
1233 }
1234 
1235 ////////////////////////////////////////////////////////////////////////////////
1236 /// Default constructor specifying minimum and maximum radius.
1237 /// The segment will be from phiStart to phiEnd expressed in degree.
1238 
1240  Double_t phiStart, Double_t phiEnd)
1241  :TGeoTube(rmin, rmax, dz),
1242  fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1243 {
1245  SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1246  ComputeBBox();
1247 }
1248 
1249 ////////////////////////////////////////////////////////////////////////////////
1250 /// Default constructor specifying minimum and maximum radius
1251 /// The segment will be from phiStart to phiEnd expressed in degree.
1252 
1254  Double_t phiStart, Double_t phiEnd)
1255  :TGeoTube(name, rmin, rmax, dz)
1256 {
1258  SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1259  ComputeBBox();
1260 }
1261 
1262 ////////////////////////////////////////////////////////////////////////////////
1263 /// Default constructor specifying minimum and maximum radius
1264 /// - param[0] = Rmin
1265 /// - param[1] = Rmax
1266 /// - param[2] = dz
1267 /// - param[3] = phi1
1268 /// - param[4] = phi2
1269 
1271  :TGeoTube(0, 0, 0)
1272 {
1274  SetDimensions(param);
1275  ComputeBBox();
1276 }
1277 
1278 ////////////////////////////////////////////////////////////////////////////////
1279 /// destructor
1280 
1282 {
1283 }
1284 
1285 ////////////////////////////////////////////////////////////////////////////////
1286 /// Function called after streaming an object of this class.
1287 
1289 {
1290  InitTrigonometry();
1291 }
1292 
1293 ////////////////////////////////////////////////////////////////////////////////
1294 /// Init frequently used trigonometric values
1295 
1297 {
1298  Double_t phi1 = fPhi1*TMath::DegToRad();
1299  Double_t phi2 = fPhi2*TMath::DegToRad();
1300  fC1 = TMath::Cos(phi1);
1301  fS1 = TMath::Sin(phi1);
1302  fC2 = TMath::Cos(phi2);
1303  fS2 = TMath::Sin(phi2);
1304  Double_t fio = 0.5*(phi1+phi2);
1305  fCm = TMath::Cos(fio);
1306  fSm = TMath::Sin(fio);
1307  Double_t dfi = 0.5*(phi2-phi1);
1308  fCdfi = TMath::Cos(dfi);
1309 }
1310 
1311 ////////////////////////////////////////////////////////////////////////////////
1312 /// Computes capacity of the shape in [length^3]
1313 
1315 {
1317 }
1318 
1319 ////////////////////////////////////////////////////////////////////////////////
1320 /// Computes capacity of the shape in [length^3]
1321 
1323 {
1324  Double_t capacity = TMath::Abs(phiEnd-phiStart)*TMath::DegToRad()*(rmax*rmax-rmin*rmin)*dz;
1325  return capacity;
1326 }
1327 
1328 ////////////////////////////////////////////////////////////////////////////////
1329 /// compute bounding box of the tube segment
1330 
1332 {
1333  Double_t xc[4];
1334  Double_t yc[4];
1335  xc[0] = fRmax*fC1;
1336  yc[0] = fRmax*fS1;
1337  xc[1] = fRmax*fC2;
1338  yc[1] = fRmax*fS2;
1339  xc[2] = fRmin*fC1;
1340  yc[2] = fRmin*fS1;
1341  xc[3] = fRmin*fC2;
1342  yc[3] = fRmin*fS2;
1343 
1344  Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
1345  Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
1346  Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
1347  Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
1348 
1349  Double_t dp = fPhi2-fPhi1;
1350  if (dp<0) dp+=360;
1351  Double_t ddp = -fPhi1;
1352  if (ddp<0) ddp+= 360;
1353  if (ddp>360) ddp-=360;
1354  if (ddp<=dp) xmax = fRmax;
1355  ddp = 90-fPhi1;
1356  if (ddp<0) ddp+= 360;
1357  if (ddp>360) ddp-=360;
1358  if (ddp<=dp) ymax = fRmax;
1359  ddp = 180-fPhi1;
1360  if (ddp<0) ddp+= 360;
1361  if (ddp>360) ddp-=360;
1362  if (ddp<=dp) xmin = -fRmax;
1363  ddp = 270-fPhi1;
1364  if (ddp<0) ddp+= 360;
1365  if (ddp>360) ddp-=360;
1366  if (ddp<=dp) ymin = -fRmax;
1367  fOrigin[0] = (xmax+xmin)/2;
1368  fOrigin[1] = (ymax+ymin)/2;
1369  fOrigin[2] = 0;
1370  fDX = (xmax-xmin)/2;
1371  fDY = (ymax-ymin)/2;
1372  fDZ = fDz;
1373 }
1374 
1375 ////////////////////////////////////////////////////////////////////////////////
1376 /// Compute normal to closest surface from POINT.
1377 
1378 void TGeoTubeSeg::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
1379 {
1380  Double_t saf[3];
1381  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1382  Double_t r = TMath::Sqrt(rsq);
1383  saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
1384  saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
1385  saf[2] = TMath::Abs(fRmax-r);
1386  Int_t i = TMath::LocMin(3,saf);
1387  if (((fPhi2-fPhi1)<360.) && TGeoShape::IsCloseToPhi(saf[i], point,fC1,fS1,fC2,fS2)) {
1388  TGeoShape::NormalPhi(point,dir,norm,fC1,fS1,fC2,fS2);
1389  return;
1390  }
1391  if (i==0) {
1392  norm[0] = norm[1] = 0.;
1393  norm[2] = TMath::Sign(1.,dir[2]);
1394  return;
1395  };
1396  norm[2] = 0;
1397  Double_t phi = TMath::ATan2(point[1], point[0]);
1398  norm[0] = TMath::Cos(phi);
1399  norm[1] = TMath::Sin(phi);
1400  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1401  norm[0] = -norm[0];
1402  norm[1] = -norm[1];
1403  }
1404 }
1405 
1406 ////////////////////////////////////////////////////////////////////////////////
1407 /// Compute normal to closest surface from POINT.
1408 
1409 void TGeoTubeSeg::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
1410  Double_t rmin, Double_t rmax, Double_t /*dz*/,
1412 {
1413  Double_t saf[2];
1414  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1415  Double_t r = TMath::Sqrt(rsq);
1416  saf[0] = (rmin>1E-10)?TMath::Abs(r-rmin):TGeoShape::Big();
1417  saf[1] = TMath::Abs(rmax-r);
1418  Int_t i = TMath::LocMin(2,saf);
1419  if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
1420  TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
1421  return;
1422  }
1423  norm[2] = 0;
1424  Double_t phi = TMath::ATan2(point[1], point[0]);
1425  norm[0] = TMath::Cos(phi);
1426  norm[1] = TMath::Sin(phi);
1427  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1428  norm[0] = -norm[0];
1429  norm[1] = -norm[1];
1430  }
1431 }
1432 
1433 ////////////////////////////////////////////////////////////////////////////////
1434 /// test if point is inside this tube segment
1435 /// first check if point is inside the tube
1436 
1438 {
1439  if (!TGeoTube::Contains(point)) return kFALSE;
1440  return IsInPhiRange(point, fPhi1, fPhi2);
1441 }
1442 
1443 ////////////////////////////////////////////////////////////////////////////////
1444 /// compute closest distance from point px,py to each corner
1445 
1447 {
1449  const Int_t numPoints = 4*n;
1450  return ShapeDistancetoPrimitive(numPoints, px, py);
1451 }
1452 
1453 ////////////////////////////////////////////////////////////////////////////////
1454 /// Compute distance from inside point to surface of the tube segment (static)
1455 /// Boundary safe algorithm.
1456 /// Do Z
1457 
1460 {
1461  Double_t stube = TGeoTube::DistFromInsideS(point,dir,rmin,rmax,dz);
1462  if (stube<=0) return 0.0;
1463  Double_t sfmin = TGeoShape::Big();
1464  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1465  Double_t r = TMath::Sqrt(rsq);
1466  Double_t cpsi=point[0]*cm+point[1]*sm;
1467  if (cpsi>r*cdfi+TGeoShape::Tolerance()) {
1468  sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
1469  return TMath::Min(stube,sfmin);
1470  }
1471  // Point on the phi boundary or outside
1472  // which one: phi1 or phi2
1473  Double_t ddotn, xi, yi;
1474  if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
1475  ddotn = s1*dir[0]-c1*dir[1];
1476  if (ddotn>=0) return 0.0;
1477  ddotn = -s2*dir[0]+c2*dir[1];
1478  if (ddotn<=0) return stube;
1479  sfmin = s2*point[0]-c2*point[1];
1480  if (sfmin<=0) return stube;
1481  sfmin /= ddotn;
1482  if (sfmin >= stube) return stube;
1483  xi = point[0]+sfmin*dir[0];
1484  yi = point[1]+sfmin*dir[1];
1485  if (yi*cm-xi*sm<0) return stube;
1486  return sfmin;
1487  }
1488  ddotn = -s2*dir[0]+c2*dir[1];
1489  if (ddotn>=0) return 0.0;
1490  ddotn = s1*dir[0]-c1*dir[1];
1491  if (ddotn<=0) return stube;
1492  sfmin = -s1*point[0]+c1*point[1];
1493  if (sfmin<=0) return stube;
1494  sfmin /= ddotn;
1495  if (sfmin >= stube) return stube;
1496  xi = point[0]+sfmin*dir[0];
1497  yi = point[1]+sfmin*dir[1];
1498  if (yi*cm-xi*sm>0) return stube;
1499  return sfmin;
1500 }
1501 
1502 ////////////////////////////////////////////////////////////////////////////////
1503 /// Compute distance from inside point to surface of the tube segment
1504 /// Boundary safe algorithm.
1505 
1506 Double_t TGeoTubeSeg::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
1507 {
1508  if (iact<3 && safe) {
1509  *safe = SafetyS(point, kTRUE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1510  if (iact==0) return TGeoShape::Big();
1511  if ((iact==1) && (*safe>step)) return TGeoShape::Big();
1512  }
1513  if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromInsideS(point,dir,fRmin,fRmax,fDz);
1514 
1515  // compute distance to surface
1517 }
1518 
1519 ////////////////////////////////////////////////////////////////////////////////
1520 /// Static method to compute distance to arbitrary tube segment from outside point
1521 /// Boundary safe algorithm.
1522 
1525  Double_t cm, Double_t sm, Double_t cdfi)
1526 {
1527  Double_t r2, cpsi;
1528  // check Z planes
1529  Double_t xi, yi, zi;
1530  zi = dz - TMath::Abs(point[2]);
1531  Double_t rmaxsq = rmax*rmax;
1532  Double_t rminsq = rmin*rmin;
1534  Double_t snxt=TGeoShape::Big();
1535  Bool_t in = kFALSE;
1536  Bool_t inz = (zi<0)?kFALSE:kTRUE;
1537  if (!inz) {
1538  if (point[2]*dir[2]>=0) return TGeoShape::Big();
1539  s = -zi/TMath::Abs(dir[2]);
1540  xi = point[0]+s*dir[0];
1541  yi = point[1]+s*dir[1];
1542  r2=xi*xi+yi*yi;
1543  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1544  cpsi=(xi*cm+yi*sm)/TMath::Sqrt(r2);
1545  if (cpsi>=cdfi) return s;
1546  }
1547  }
1548 
1549  // check outer cyl. surface
1550  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1551  Double_t r = TMath::Sqrt(rsq);
1552  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
1553  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
1554  Double_t b,d;
1555  Bool_t inrmax = kFALSE;
1556  Bool_t inrmin = kFALSE;
1557  Bool_t inphi = kFALSE;
1558  if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
1559  if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
1560  cpsi=point[0]*cm+point[1]*sm;
1561  if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
1562  in = inz & inrmin & inrmax & inphi;
1563  // If inside, we are most likely on a boundary within machine precision.
1564  if (in) {
1565  Bool_t checkout = kFALSE;
1566  Double_t safphi = (cpsi-r*cdfi)*TMath::Sqrt(1.-cdfi*cdfi);
1567 // Double_t sch, cch;
1568  // check if on Z boundaries
1569  if (zi<rmax-r) {
1570  if (TGeoShape::IsSameWithinTolerance(rmin,0) || (zi<r-rmin)) {
1571  if (zi<safphi) {
1572  if (point[2]*dir[2]<0) return 0.0;
1573  return TGeoShape::Big();
1574  }
1575  }
1576  }
1577  if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
1578  // check if on Rmax boundary
1579  if (checkout && (rmax-r<safphi)) {
1580  if (rdotn>=0) return TGeoShape::Big();
1581  return 0.0;
1582  }
1583  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
1584  // check if on phi boundary
1585  if (TGeoShape::IsSameWithinTolerance(rmin,0) || (safphi<r-rmin)) {
1586  // We may cross again a phi of rmin boundary
1587  // check first if we are on phi1 or phi2
1588  Double_t un;
1589  if (point[0]*c1 + point[1]*s1 > point[0]*c2 + point[1]*s2) {
1590  un = dir[0]*s1-dir[1]*c1;
1591  if (un < 0) return 0.0;
1592  if (cdfi>=0) return TGeoShape::Big();
1593  un = -dir[0]*s2+dir[1]*c2;
1594  if (un<0) {
1595  s = -point[0]*s2+point[1]*c2;
1596  if (s>0) {
1597  s /= (-un);
1598  zi = point[2]+s*dir[2];
1599  if (TMath::Abs(zi)<=dz) {
1600  xi = point[0]+s*dir[0];
1601  yi = point[1]+s*dir[1];
1602  r2=xi*xi+yi*yi;
1603  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1604  if ((yi*cm-xi*sm)>0) return s;
1605  }
1606  }
1607  }
1608  }
1609  } else {
1610  un = -dir[0]*s2+dir[1]*c2;
1611  if (un < 0) return 0.0;
1612  if (cdfi>=0) return TGeoShape::Big();
1613  un = dir[0]*s1-dir[1]*c1;
1614  if (un<0) {
1615  s = point[0]*s1-point[1]*c1;
1616  if (s>0) {
1617  s /= (-un);
1618  zi = point[2]+s*dir[2];
1619  if (TMath::Abs(zi)<=dz) {
1620  xi = point[0]+s*dir[0];
1621  yi = point[1]+s*dir[1];
1622  r2=xi*xi+yi*yi;
1623  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1624  if ((yi*cm-xi*sm)<0) return s;
1625  }
1626  }
1627  }
1628  }
1629  }
1630  // We may also cross rmin, (+) solution
1631  if (rdotn>=0) return TGeoShape::Big();
1632  if (cdfi>=0) return TGeoShape::Big();
1633  DistToTube(rsq, nsq, rdotn, rmin, b, d);
1634  if (d>0) {
1635  s=-b+d;
1636  if (s>0) {
1637  zi=point[2]+s*dir[2];
1638  if (TMath::Abs(zi)<=dz) {
1639  xi=point[0]+s*dir[0];
1640  yi=point[1]+s*dir[1];
1641  if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
1642  }
1643  }
1644  }
1645  return TGeoShape::Big();
1646  }
1647  // we are on rmin boundary: we may cross again rmin or a phi facette
1648  if (rdotn>=0) return 0.0;
1649  DistToTube(rsq, nsq, rdotn, rmin, b, d);
1650  if (d>0) {
1651  s=-b+d;
1652  if (s>0) {
1653  zi=point[2]+s*dir[2];
1654  if (TMath::Abs(zi)<=dz) {
1655  // now check phi range
1656  xi=point[0]+s*dir[0];
1657  yi=point[1]+s*dir[1];
1658  r2=xi*xi+yi*yi;
1659  if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
1660  // now we really have to check any phi crossing
1661  Double_t un=-dir[0]*s1+dir[1]*c1;
1662  if (un > 0) {
1663  s=point[0]*s1-point[1]*c1;
1664  if (s>=0) {
1665  s /= un;
1666  zi=point[2]+s*dir[2];
1667  if (TMath::Abs(zi)<=dz) {
1668  xi=point[0]+s*dir[0];
1669  yi=point[1]+s*dir[1];
1670  r2=xi*xi+yi*yi;
1671  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1672  if ((yi*cm-xi*sm)<=0) {
1673  if (s<snxt) snxt=s;
1674  }
1675  }
1676  }
1677  }
1678  }
1679  un=dir[0]*s2-dir[1]*c2;
1680  if (un > 0) {
1681  s=(point[1]*c2-point[0]*s2)/un;
1682  if (s>=0 && s<snxt) {
1683  zi=point[2]+s*dir[2];
1684  if (TMath::Abs(zi)<=dz) {
1685  xi=point[0]+s*dir[0];
1686  yi=point[1]+s*dir[1];
1687  r2=xi*xi+yi*yi;
1688  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1689  if ((yi*cm-xi*sm)>=0) {
1690  return s;
1691  }
1692  }
1693  }
1694  }
1695  }
1696  return snxt;
1697  }
1698  }
1699  }
1700  return TGeoShape::Big();
1701  }
1702  // only r>rmax has to be considered
1703  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
1704  if (rsq>=rmax*rmax) {
1705  if (rdotn>=0) return TGeoShape::Big();
1706  TGeoTube::DistToTube(rsq, nsq, rdotn, rmax, b, d);
1707  if (d>0) {
1708  s=-b-d;
1709  if (s>0) {
1710  zi=point[2]+s*dir[2];
1711  if (TMath::Abs(zi)<=dz) {
1712  xi=point[0]+s*dir[0];
1713  yi=point[1]+s*dir[1];
1714  cpsi = xi*cm+yi*sm;
1715  if (cpsi>=rmax*cdfi) return s;
1716  }
1717  }
1718  }
1719  }
1720  // check inner cylinder
1721  if (rmin>0) {
1722  TGeoTube::DistToTube(rsq, nsq, rdotn, rmin, b, d);
1723  if (d>0) {
1724  s=-b+d;
1725  if (s>0) {
1726  zi=point[2]+s*dir[2];
1727  if (TMath::Abs(zi)<=dz) {
1728  xi=point[0]+s*dir[0];
1729  yi=point[1]+s*dir[1];
1730  cpsi = xi*cm+yi*sm;
1731  if (cpsi>=rmin*cdfi) snxt=s;
1732  }
1733  }
1734  }
1735  }
1736  // check phi planes
1737  Double_t un=-dir[0]*s1+dir[1]*c1;
1738  if (un > 0) {
1739  s=point[0]*s1-point[1]*c1;
1740  if (s>=0) {
1741  s /= un;
1742  zi=point[2]+s*dir[2];
1743  if (TMath::Abs(zi)<=dz) {
1744  xi=point[0]+s*dir[0];
1745  yi=point[1]+s*dir[1];
1746  r2=xi*xi+yi*yi;
1747  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1748  if ((yi*cm-xi*sm)<=0) {
1749  if (s<snxt) snxt=s;
1750  }
1751  }
1752  }
1753  }
1754  }
1755  un=dir[0]*s2-dir[1]*c2;
1756  if (un > 0) {
1757  s=point[1]*c2-point[0]*s2;
1758  if (s>=0) {
1759  s /= un;
1760  zi=point[2]+s*dir[2];
1761  if (TMath::Abs(zi)<=dz) {
1762  xi=point[0]+s*dir[0];
1763  yi=point[1]+s*dir[1];
1764  r2=xi*xi+yi*yi;
1765  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1766  if ((yi*cm-xi*sm)>=0) {
1767  if (s<snxt) snxt=s;
1768  }
1769  }
1770  }
1771  }
1772  }
1773  return snxt;
1774 }
1775 
1776 ////////////////////////////////////////////////////////////////////////////////
1777 /// compute distance from outside point to surface of the tube segment
1778 /// fist localize point w.r.t tube
1779 
1780 Double_t TGeoTubeSeg::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
1781 {
1782  if (iact<3 && safe) {
1783  *safe = SafetyS(point, kFALSE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1784  if (iact==0) return TGeoShape::Big();
1785  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
1786  }
1787 // Check if the bounding box is crossed within the requested distance
1788  Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
1789  if (sdist>=step) return TGeoShape::Big();
1790  if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromOutsideS(point,dir,fRmin,fRmax,fDz);
1791 
1792  // find distance to shape
1793  return TGeoTubeSeg::DistFromOutsideS(point, dir, fRmin, fRmax, fDz, fC1, fS1, fC2, fS2, fCm, fSm, fCdfi);
1794 }
1795 
1796 ////////////////////////////////////////////////////////////////////////////////
1797 /// Divide this tube segment shape belonging to volume "voldiv" into ndiv volumes
1798 /// called divname, from start position with the given step. Returns pointer
1799 /// to created division cell volume in case of Z divisions. For radialdivision
1800 /// creates all volumes with different shapes and returns pointer to volume that
1801 /// was divided. In case a wrong division axis is supplied, returns pointer to
1802 /// volume that was divided.
1803 
1804 TGeoVolume *TGeoTubeSeg::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
1805  Double_t start, Double_t step)
1806 {
1807  TGeoShape *shape; //--- shape to be created
1808  TGeoVolume *vol; //--- division volume to be created
1809  TGeoVolumeMulti *vmulti; //--- generic divided volume
1810  TGeoPatternFinder *finder; //--- finder to be attached
1811  TString opt = ""; //--- option to be attached
1812  Double_t dphi;
1813  Int_t id;
1814  Double_t end = start+ndiv*step;
1815  switch (iaxis) {
1816  case 1: //--- R division
1817  finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
1818  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1819  voldiv->SetFinder(finder);
1820  finder->SetDivIndex(voldiv->GetNdaughters());
1821  for (id=0; id<ndiv; id++) {
1822  shape = new TGeoTubeSeg(start+id*step, start+(id+1)*step, fDz, fPhi1, fPhi2);
1823  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1824  vmulti->AddVolume(vol);
1825  opt = "R";
1826  voldiv->AddNodeOffset(vol, id, 0, opt.Data());
1827  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1828  }
1829  return vmulti;
1830  case 2: //--- Phi division
1831  dphi = fPhi2-fPhi1;
1832  if (dphi<0) dphi+=360.;
1833  if (step<=0) {step=dphi/ndiv; start=fPhi1; end=fPhi2;}
1834  finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
1835  voldiv->SetFinder(finder);
1836  finder->SetDivIndex(voldiv->GetNdaughters());
1837  shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
1838  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1839  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1840  vmulti->AddVolume(vol);
1841  opt = "Phi";
1842  for (id=0; id<ndiv; id++) {
1843  voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
1844  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1845  }
1846  return vmulti;
1847  case 3: //--- Z division
1848  finder = new TGeoPatternZ(voldiv, ndiv, start, end);
1849  voldiv->SetFinder(finder);
1850  finder->SetDivIndex(voldiv->GetNdaughters());
1851  shape = new TGeoTubeSeg(fRmin, fRmax, step/2, fPhi1, fPhi2);
1852  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1853  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1854  vmulti->AddVolume(vol);
1855  opt = "Z";
1856  for (id=0; id<ndiv; id++) {
1857  voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
1858  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1859  }
1860  return vmulti;
1861  default:
1862  Error("Divide", "In shape %s wrong axis type for division", GetName());
1863  return 0;
1864  }
1865 }
1866 
1867 ////////////////////////////////////////////////////////////////////////////////
1868 /// Get range of shape for a given axis.
1869 
1871 {
1872  xlo = 0;
1873  xhi = 0;
1874  Double_t dx = 0;
1875  switch (iaxis) {
1876  case 1:
1877  xlo = fRmin;
1878  xhi = fRmax;
1879  dx = xhi-xlo;
1880  return dx;
1881  case 2:
1882  xlo = fPhi1;
1883  xhi = fPhi2;
1884  dx = xhi-xlo;
1885  return dx;
1886  case 3:
1887  xlo = -fDz;
1888  xhi = fDz;
1889  dx = xhi-xlo;
1890  return dx;
1891  }
1892  return dx;
1893 }
1894 
1895 ////////////////////////////////////////////////////////////////////////////////
1896 /// Fill vector param[4] with the bounding cylinder parameters. The order
1897 /// is the following : Rmin, Rmax, Phi1, Phi2
1898 
1900 {
1901  param[0] = fRmin;
1902  param[0] *= param[0];
1903  param[1] = fRmax;
1904  param[1] *= param[1];
1905  param[2] = fPhi1;
1906  param[3] = fPhi2;
1907 }
1908 
1909 ////////////////////////////////////////////////////////////////////////////////
1910 /// in case shape has some negative parameters, these has to be computed
1911 /// in order to fit the mother
1912 
1914 {
1915  if (!TestShapeBit(kGeoRunTimeShape)) return 0;
1916  if (!mother->TestShapeBit(kGeoTube)) {
1917  Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
1918  return 0;
1919  }
1920  Double_t rmin, rmax, dz;
1921  rmin = fRmin;
1922  rmax = fRmax;
1923  dz = fDz;
1924  if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
1925  if (fRmin<0)
1926  rmin = ((TGeoTube*)mother)->GetRmin();
1927  if ((fRmax<0) || (fRmax<=fRmin))
1928  rmax = ((TGeoTube*)mother)->GetRmax();
1929 
1930  return (new TGeoTubeSeg(GetName(),rmin, rmax, dz, fPhi1, fPhi2));
1931 }
1932 
1933 ////////////////////////////////////////////////////////////////////////////////
1934 /// print shape parameters
1935 
1937 {
1938  printf("*** Shape %s: TGeoTubeSeg ***\n", GetName());
1939  printf(" Rmin = %11.5f\n", fRmin);
1940  printf(" Rmax = %11.5f\n", fRmax);
1941  printf(" dz = %11.5f\n", fDz);
1942  printf(" phi1 = %11.5f\n", fPhi1);
1943  printf(" phi2 = %11.5f\n", fPhi2);
1944  printf(" Bounding box:\n");
1946 }
1947 
1948 ////////////////////////////////////////////////////////////////////////////////
1949 /// Creates a TBuffer3D describing *this* shape.
1950 /// Coordinates are in local reference frame.
1951 
1953 {
1955  Int_t nbPnts = 4*n;
1956  Int_t nbSegs = 2*nbPnts;
1957  Int_t nbPols = nbPnts-2;
1958 
1960  nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
1961  if (buff)
1962  {
1963  SetPoints(buff->fPnts);
1964  SetSegsAndPols(*buff);
1965  }
1966 
1967  return buff;
1968 }
1969 
1970 ////////////////////////////////////////////////////////////////////////////////
1971 /// Fill TBuffer3D structure for segments and polygons.
1972 
1974 {
1975  Int_t i, j;
1977  Int_t c = GetBasicColor();
1978 
1979  memset(buff.fSegs, 0, buff.NbSegs()*3*sizeof(Int_t));
1980  for (i = 0; i < 4; i++) {
1981  for (j = 1; j < n; j++) {
1982  buff.fSegs[(i*n+j-1)*3 ] = c;
1983  buff.fSegs[(i*n+j-1)*3+1] = i*n+j-1;
1984  buff.fSegs[(i*n+j-1)*3+2] = i*n+j;
1985  }
1986  }
1987  for (i = 4; i < 6; i++) {
1988  for (j = 0; j < n; j++) {
1989  buff.fSegs[(i*n+j)*3 ] = c+1;
1990  buff.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
1991  buff.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
1992  }
1993  }
1994  for (i = 6; i < 8; i++) {
1995  for (j = 0; j < n; j++) {
1996  buff.fSegs[(i*n+j)*3 ] = c;
1997  buff.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
1998  buff.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
1999  }
2000  }
2001 
2002  Int_t indx = 0;
2003  memset(buff.fPols, 0, buff.NbPols()*6*sizeof(Int_t));
2004  i = 0;
2005  for (j = 0; j < n-1; j++) {
2006  buff.fPols[indx++] = c;
2007  buff.fPols[indx++] = 4;
2008  buff.fPols[indx++] = (4+i)*n+j+1;
2009  buff.fPols[indx++] = (2+i)*n+j;
2010  buff.fPols[indx++] = (4+i)*n+j;
2011  buff.fPols[indx++] = i*n+j;
2012  }
2013  i = 1;
2014  for (j = 0; j < n-1; j++) {
2015  buff.fPols[indx++] = c;
2016  buff.fPols[indx++] = 4;
2017  buff.fPols[indx++] = i*n+j;
2018  buff.fPols[indx++] = (4+i)*n+j;
2019  buff.fPols[indx++] = (2+i)*n+j;
2020  buff.fPols[indx++] = (4+i)*n+j+1;
2021  }
2022  i = 2;
2023  for (j = 0; j < n-1; j++) {
2024  buff.fPols[indx++] = c+i;
2025  buff.fPols[indx++] = 4;
2026  buff.fPols[indx++] = (i-2)*2*n+j;
2027  buff.fPols[indx++] = (4+i)*n+j;
2028  buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2029  buff.fPols[indx++] = (4+i)*n+j+1;
2030  }
2031  i = 3;
2032  for (j = 0; j < n-1; j++) {
2033  buff.fPols[indx++] = c+i;
2034  buff.fPols[indx++] = 4;
2035  buff.fPols[indx++] = (4+i)*n+j+1;
2036  buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2037  buff.fPols[indx++] = (4+i)*n+j;
2038  buff.fPols[indx++] = (i-2)*2*n+j;
2039  }
2040  buff.fPols[indx++] = c+2;
2041  buff.fPols[indx++] = 4;
2042  buff.fPols[indx++] = 6*n;
2043  buff.fPols[indx++] = 4*n;
2044  buff.fPols[indx++] = 7*n;
2045  buff.fPols[indx++] = 5*n;
2046  buff.fPols[indx++] = c+2;
2047  buff.fPols[indx++] = 4;
2048  buff.fPols[indx++] = 6*n-1;
2049  buff.fPols[indx++] = 8*n-1;
2050  buff.fPols[indx++] = 5*n-1;
2051  buff.fPols[indx++] = 7*n-1;
2052 }
2053 
2054 ////////////////////////////////////////////////////////////////////////////////
2055 /// computes the closest distance from given point InitTrigonometry();to this shape, according
2056 /// to option. The matching point on the shape is stored in spoint.
2057 
2059 {
2060  Double_t safe = TGeoShape::Big();
2061  Double_t saf[3];
2062  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2063  Double_t r = TMath::Sqrt(rsq);
2064  if (in) {
2065  saf[0] = fDz-TMath::Abs(point[2]);
2066  saf[1] = r-fRmin;
2067  saf[2] = fRmax-r;
2068  safe = saf[TMath::LocMin(3,saf)];
2069  if ((fPhi2-fPhi1)>=360.) return safe;
2070  Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2071  return TMath::Min(safe, safphi);
2072  }
2073  // Point expected to be outside
2074  Bool_t inphi = kFALSE;
2075  Double_t cpsi=point[0]*fCm+point[1]*fSm;
2076  saf[0] = TMath::Abs(point[2])-fDz;
2077  if (cpsi>r*fCdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2078  if (inphi) {
2079  saf[1] = fRmin-r;
2080  saf[2] = r-fRmax;
2081  safe = saf[TMath::LocMax(3,saf)];
2082  safe = TMath::Max(0., safe);
2083  return safe;
2084  }
2085  // Point outside the phi range
2086  // Compute projected radius of the (r,phi) position vector onto
2087  // phi1 and phi2 edges and take the maximum for choosing the side.
2088  Double_t rproj = TMath::Max(point[0]*fC1+point[1]*fS1, point[0]*fC2+point[1]*fS2);
2089  saf[1] = fRmin-rproj;
2090  saf[2] = rproj-fRmax;
2091  safe = TMath::Max(saf[1], saf[2]);
2092  if ((fPhi2-fPhi1)>=360.) return TMath::Max(safe,saf[0]);
2093  if (safe>0) {
2094  // rproj not within (rmin,rmax) - > no need to calculate safphi
2095  safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2096  return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2097  }
2098  Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2099  return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2100 }
2101 
2102 ////////////////////////////////////////////////////////////////////////////////
2103 /// Static method to compute the closest distance from given point to this shape.
2104 
2106  Double_t phi1d, Double_t phi2d, Int_t skipz)
2107 {
2108  Double_t safe = TGeoShape::Big();
2109  Double_t saf[3];
2110  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2111  Double_t r = TMath::Sqrt(rsq);
2112 
2113  switch (skipz) {
2114  case 1: // skip lower Z plane
2115  saf[0] = dz - point[2];
2116  break;
2117  case 2: // skip upper Z plane
2118  saf[0] = dz + point[2];
2119  break;
2120  case 3: // skip both
2121  saf[0] = TGeoShape::Big();
2122  break;
2123  default:
2124  saf[0] = dz-TMath::Abs(point[2]);
2125  }
2126 
2127  if (in) {
2128  saf[1] = r-rmin;
2129  saf[2] = rmax-r;
2130  safe = saf[TMath::LocMin(3,saf)];
2131  if ((phi2d-phi1d)>=360.) return safe;
2132  Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2133  return TMath::Min(safe, safphi);
2134  }
2135  // Point expected to be outside
2136  saf[0] = -saf[0];
2137  Bool_t inphi = kFALSE;
2138  Double_t phi1 = phi1d*TMath::DegToRad();
2139  Double_t phi2 = phi2d*TMath::DegToRad();
2140 
2141  Double_t fio = 0.5*(phi1+phi2);
2142  Double_t cm = TMath::Cos(fio);
2143  Double_t sm = TMath::Sin(fio);
2144  Double_t cpsi=point[0]*cm+point[1]*sm;
2145  Double_t dfi = 0.5*(phi2-phi1);
2146  Double_t cdfi = TMath::Cos(dfi);
2147  if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2148  if (inphi) {
2149  saf[1] = rmin-r;
2150  saf[2] = r-rmax;
2151  safe = saf[TMath::LocMax(3,saf)];
2152  safe = TMath::Max(0., safe);
2153  return safe;
2154  }
2155  // Point outside the phi range
2156  // Compute projected radius of the (r,phi) position vector onto
2157  // phi1 and phi2 edges and take the maximum for choosing the side.
2158  Double_t c1 = TMath::Cos(phi1);
2159  Double_t s1 = TMath::Sin(phi1);
2160  Double_t c2 = TMath::Cos(phi2);
2161  Double_t s2 = TMath::Sin(phi2);
2162 
2163  Double_t rproj = TMath::Max(point[0]*c1+point[1]*s1, point[0]*c2+point[1]*s2);
2164  saf[1] = rmin-rproj;
2165  saf[2] = rproj-rmax;
2166  safe = TMath::Max(saf[1], saf[2]);
2167  if ((phi2d-phi1d)>=360.) return TMath::Max(safe,saf[0]);
2168  if (safe>0) {
2169  // rproj not within (rmin,rmax) - > no need to calculate safphi
2170  safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2171  return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2172  }
2173  Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2174  return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2175 }
2176 
2177 ////////////////////////////////////////////////////////////////////////////////
2178 /// Save a primitive as a C++ statement(s) on output stream "out".
2179 
2180 void TGeoTubeSeg::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2181 {
2182  if (TObject::TestBit(kGeoSavePrimitive)) return;
2183  out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2184  out << " rmin = " << fRmin << ";" << std::endl;
2185  out << " rmax = " << fRmax << ";" << std::endl;
2186  out << " dz = " << fDz << ";" << std::endl;
2187  out << " phi1 = " << fPhi1 << ";" << std::endl;
2188  out << " phi2 = " << fPhi2 << ";" << std::endl;
2189  out << " TGeoShape *" << GetPointerName() << " = new TGeoTubeSeg(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2);" << std::endl;
2191 }
2192 
2193 ////////////////////////////////////////////////////////////////////////////////
2194 /// Set dimensions of the tube segment.
2195 /// The segment will be from phiStart to phiEnd expressed in degree.
2196 
2198  Double_t phiStart, Double_t phiEnd)
2199 {
2200  fRmin = rmin;
2201  fRmax = rmax;
2202  fDz = dz;
2203  fPhi1 = phiStart;
2204  if (fPhi1 < 0) fPhi1 += 360.;
2205  fPhi2 = phiEnd;
2206  while (fPhi2<=fPhi1) fPhi2+=360.;
2207  if (TGeoShape::IsSameWithinTolerance(fPhi1,fPhi2)) Fatal("SetTubsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
2208  InitTrigonometry();
2209 }
2210 
2211 ////////////////////////////////////////////////////////////////////////////////
2212 /// Set dimensions of the tube segment starting from a list.
2213 
2215 {
2216  Double_t rmin = param[0];
2217  Double_t rmax = param[1];
2218  Double_t dz = param[2];
2219  Double_t phi1 = param[3];
2220  Double_t phi2 = param[4];
2221  SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
2222 }
2223 
2224 ////////////////////////////////////////////////////////////////////////////////
2225 /// Fills array with n random points located on the line segments of the shape mesh.
2226 /// The output array must be provided with a length of minimum 3*npoints. Returns
2227 /// true if operation is implemented.
2228 
2230 {
2231  if (npoints > (npoints/2)*2) {
2232  Error("GetPointsOnSegments","Npoints must be even number");
2233  return kFALSE;
2234  }
2235  Int_t nc = (Int_t)TMath::Sqrt(0.5*npoints);
2236  Double_t dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nc-1);
2237  Double_t phi = 0;
2238  Double_t phi1 = fPhi1 * TMath::DegToRad();
2239  Int_t ntop = npoints/2 - nc*(nc-1);
2240  Double_t dz = 2*fDz/(nc-1);
2241  Double_t z = 0;
2242  Int_t icrt = 0;
2243  Int_t nphi = nc;
2244  // loop z sections
2245  for (Int_t i=0; i<nc; i++) {
2246  if (i == (nc-1)) {
2247  nphi = ntop;
2248  dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nphi-1);
2249  }
2250  z = -fDz + i*dz;
2251  // loop points on circle sections
2252  for (Int_t j=0; j<nphi; j++) {
2253  phi = phi1 + j*dphi;
2254  array[icrt++] = fRmin * TMath::Cos(phi);
2255  array[icrt++] = fRmin * TMath::Sin(phi);
2256  array[icrt++] = z;
2257  array[icrt++] = fRmax * TMath::Cos(phi);
2258  array[icrt++] = fRmax * TMath::Sin(phi);
2259  array[icrt++] = z;
2260  }
2261  }
2262  return kTRUE;
2263 }
2264 
2265 ////////////////////////////////////////////////////////////////////////////////
2266 /// Create tube segment mesh points.
2267 
2269 {
2270  Double_t dz;
2271  Int_t j, n;
2272  Double_t phi, phi1, phi2, dphi;
2273  phi1 = fPhi1;
2274  phi2 = fPhi2;
2275  if (phi2<phi1) phi2+=360.;
2276  n = gGeoManager->GetNsegments()+1;
2277 
2278  dphi = (phi2-phi1)/(n-1);
2279  dz = fDz;
2280 
2281  if (points) {
2282  Int_t indx = 0;
2283 
2284  for (j = 0; j < n; j++) {
2285  phi = (phi1+j*dphi)*TMath::DegToRad();
2286  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2287  indx++;
2288  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2289  indx++;
2290  points[indx+6*n] = dz;
2291  points[indx] =-dz;
2292  indx++;
2293  }
2294  for (j = 0; j < n; j++) {
2295  phi = (phi1+j*dphi)*TMath::DegToRad();
2296  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2297  indx++;
2298  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2299  indx++;
2300  points[indx+6*n]= dz;
2301  points[indx] =-dz;
2302  indx++;
2303  }
2304  }
2305 }
2306 
2307 ////////////////////////////////////////////////////////////////////////////////
2308 /// Create tube segment mesh points.
2309 
2311 {
2312  Double_t dz;
2313  Int_t j, n;
2314  Double_t phi, phi1, phi2, dphi;
2315  phi1 = fPhi1;
2316  phi2 = fPhi2;
2317  if (phi2<phi1) phi2+=360.;
2318  n = gGeoManager->GetNsegments()+1;
2319 
2320  dphi = (phi2-phi1)/(n-1);
2321  dz = fDz;
2322 
2323  if (points) {
2324  Int_t indx = 0;
2325 
2326  for (j = 0; j < n; j++) {
2327  phi = (phi1+j*dphi)*TMath::DegToRad();
2328  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2329  indx++;
2330  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2331  indx++;
2332  points[indx+6*n] = dz;
2333  points[indx] =-dz;
2334  indx++;
2335  }
2336  for (j = 0; j < n; j++) {
2337  phi = (phi1+j*dphi)*TMath::DegToRad();
2338  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2339  indx++;
2340  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2341  indx++;
2342  points[indx+6*n]= dz;
2343  points[indx] =-dz;
2344  indx++;
2345  }
2346  }
2347 }
2348 
2349 ////////////////////////////////////////////////////////////////////////////////
2350 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
2351 
2352 void TGeoTubeSeg::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
2353 {
2355  nvert = n*4;
2356  nsegs = n*8;
2357  npols = n*4 - 2;
2358 }
2359 
2360 ////////////////////////////////////////////////////////////////////////////////
2361 /// Return number of vertices of the mesh representation
2362 
2364 {
2366  Int_t numPoints = n*4;
2367  return numPoints;
2368 }
2369 
2370 ////////////////////////////////////////////////////////////////////////////////
2371 /// fill size of this 3-D object
2372 
2374 {
2375 }
2376 
2377 ////////////////////////////////////////////////////////////////////////////////
2378 /// Fills a static 3D buffer and returns a reference.
2379 
2380 const TBuffer3D & TGeoTubeSeg::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
2381 {
2382  static TBuffer3DTubeSeg buffer;
2383  TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
2384 
2385  if (reqSections & TBuffer3D::kShapeSpecific) {
2386  // These from TBuffer3DTube / TGeoTube
2387  buffer.fRadiusInner = fRmin;
2388  buffer.fRadiusOuter = fRmax;
2389  buffer.fHalfLength = fDz;
2390  buffer.fPhiMin = fPhi1;
2391  buffer.fPhiMax = fPhi2;
2392  buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
2393  }
2394  if (reqSections & TBuffer3D::kRawSizes) {
2396  Int_t nbPnts = 4*n;
2397  Int_t nbSegs = 2*nbPnts;
2398  Int_t nbPols = nbPnts-2;
2399  if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
2400  buffer.SetSectionsValid(TBuffer3D::kRawSizes);
2401  }
2402  }
2403  if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
2404  SetPoints(buffer.fPnts);
2405  if (!buffer.fLocalFrame) {
2406  TransformPoints(buffer.fPnts, buffer.NbPnts());
2407  }
2408  SetSegsAndPols(buffer);
2409  buffer.SetSectionsValid(TBuffer3D::kRaw);
2410  }
2411 
2412  return buffer;
2413 }
2414 
2415 ////////////////////////////////////////////////////////////////////////////////
2416 /// Check the inside status for each of the points in the array.
2417 /// Input: Array of point coordinates + vector size
2418 /// Output: Array of Booleans for the inside of each point
2419 
2420 void TGeoTubeSeg::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
2421 {
2422  for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
2423 }
2424 
2425 ////////////////////////////////////////////////////////////////////////////////
2426 /// Compute the normal for an array o points so that norm.dot.dir is positive
2427 /// Input: Arrays of point coordinates and directions + vector size
2428 /// Output: Array of normal directions
2429 
2430 void TGeoTubeSeg::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
2431 {
2432  for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
2433 }
2434 
2435 ////////////////////////////////////////////////////////////////////////////////
2436 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
2437 
2438 void TGeoTubeSeg::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
2439 {
2440  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////
2444 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
2445 
2446 void TGeoTubeSeg::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
2447 {
2448  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
2449 }
2450 
2451 ////////////////////////////////////////////////////////////////////////////////
2452 /// Compute safe distance from each of the points in the input array.
2453 /// Input: Array of point coordinates, array of statuses for these points, size of the arrays
2454 /// Output: Safety values
2455 
2456 void TGeoTubeSeg::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
2457 {
2458  for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
2459 }
2460 
2462 
2464 {
2465 // default ctor
2466  fNlow[0] = fNlow[1] = fNhigh[0] = fNhigh[1] = 0.;
2467  fNlow[2] = -1;
2468  fNhigh[2] = 1;
2469 }
2470 
2471 ////////////////////////////////////////////////////////////////////////////////
2472 /// constructor
2473 
2475  Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
2476  :TGeoTubeSeg(rmin, rmax, dz, phi1, phi2)
2477 {
2478  fNlow[0] = lx;
2479  fNlow[1] = ly;
2480  fNlow[2] = lz;
2481  fNhigh[0] = tx;
2482  fNhigh[1] = ty;
2483  fNhigh[2] = tz;
2485  ComputeBBox();
2486 }
2487 
2488 ////////////////////////////////////////////////////////////////////////////////
2489 /// constructor
2490 
2491 TGeoCtub::TGeoCtub(const char *name, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
2492  Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
2493  :TGeoTubeSeg(name, rmin, rmax, dz, phi1, phi2)
2494 {
2495  fNlow[0] = lx;
2496  fNlow[1] = ly;
2497  fNlow[2] = lz;
2498  fNhigh[0] = tx;
2499  fNhigh[1] = ty;
2500  fNhigh[2] = tz;
2502  ComputeBBox();
2503 }
2504 
2505 ////////////////////////////////////////////////////////////////////////////////
2506 /// ctor with parameters
2507 
2509  :TGeoTubeSeg(0,0,0,0,0)
2510 {
2511  SetCtubDimensions(params[0], params[1], params[2], params[3], params[4], params[5],
2512  params[6], params[7], params[8], params[9], params[10]);
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// destructor
2518 
2520 {
2521 }
2522 
2523 ////////////////////////////////////////////////////////////////////////////////
2524 /// Computes capacity of the shape in [length^3]
2525 
2527 {
2528  Double_t capacity = TGeoTubeSeg::Capacity();
2529  return capacity;
2530 }
2531 
2532 ////////////////////////////////////////////////////////////////////////////////
2533 /// compute minimum bounding box of the ctub
2534 
2536 {
2538  if ((fNlow[2]>-(1E-10)) || (fNhigh[2]<1E-10)) {
2539  Error("ComputeBBox", "In shape %s wrong definition of cut planes", GetName());
2540  return;
2541  }
2542  Double_t xc=0, yc=0;
2543  Double_t zmin=0, zmax=0;
2544  Double_t z1;
2545  Double_t z[8];
2546  // check if nxy is in the phi range
2547  Double_t phi_low = TMath::ATan2(fNlow[1], fNlow[0]) *TMath::RadToDeg();
2548  Double_t phi_hi = TMath::ATan2(fNhigh[1], fNhigh[0]) *TMath::RadToDeg();
2549  Bool_t in_range_low = kFALSE;
2550  Bool_t in_range_hi = kFALSE;
2551 
2552  Int_t i;
2553  for (i=0; i<2; i++) {
2554  if (phi_low<0) phi_low+=360.;
2555  Double_t dphi = fPhi2 -fPhi1;
2556  if (dphi < 0) dphi+=360.;
2557  Double_t ddp = phi_low-fPhi1;
2558  if (ddp<0) ddp += 360.;
2559  if (ddp <= dphi) {
2560  xc = fRmin*TMath::Cos(phi_low*TMath::DegToRad());
2561  yc = fRmin*TMath::Sin(phi_low*TMath::DegToRad());
2562  z1 = GetZcoord(xc, yc, -fDz);
2563  xc = fRmax*TMath::Cos(phi_low*TMath::DegToRad());
2564  yc = fRmax*TMath::Sin(phi_low*TMath::DegToRad());
2565  z1 = TMath::Min(z1, GetZcoord(xc, yc, -fDz));
2566  if (in_range_low)
2567  zmin = TMath::Min(zmin, z1);
2568  else
2569  zmin = z1;
2570  in_range_low = kTRUE;
2571  }
2572  phi_low += 180;
2573  if (phi_low>360) phi_low-=360.;
2574  }
2575 
2576  for (i=0; i<2; i++) {
2577  if (phi_hi<0) phi_hi+=360.;
2578  Double_t dphi = fPhi2 -fPhi1;
2579  if (dphi < 0) dphi+=360.;
2580  Double_t ddp = phi_hi-fPhi1;
2581  if (ddp<0) ddp += 360.;
2582  if (ddp <= dphi) {
2583  xc = fRmin*TMath::Cos(phi_hi*TMath::DegToRad());
2584  yc = fRmin*TMath::Sin(phi_hi*TMath::DegToRad());
2585  z1 = GetZcoord(xc, yc, fDz);
2586  xc = fRmax*TMath::Cos(phi_hi*TMath::DegToRad());
2587  yc = fRmax*TMath::Sin(phi_hi*TMath::DegToRad());
2588  z1 = TMath::Max(z1, GetZcoord(xc, yc, fDz));
2589  if (in_range_hi)
2590  zmax = TMath::Max(zmax, z1);
2591  else
2592  zmax = z1;
2593  in_range_hi = kTRUE;
2594  }
2595  phi_hi += 180;
2596  if (phi_hi>360) phi_hi-=360.;
2597  }
2598 
2599 
2600  xc = fRmin*fC1;
2601  yc = fRmin*fS1;
2602  z[0] = GetZcoord(xc, yc, -fDz);
2603  z[4] = GetZcoord(xc, yc, fDz);
2604 
2605  xc = fRmin*fC2;
2606  yc = fRmin*fS2;
2607  z[1] = GetZcoord(xc, yc, -fDz);
2608  z[5] = GetZcoord(xc, yc, fDz);
2609 
2610  xc = fRmax*fC1;
2611  yc = fRmax*fS1;
2612  z[2] = GetZcoord(xc, yc, -fDz);
2613  z[6] = GetZcoord(xc, yc, fDz);
2614 
2615  xc = fRmax*fC2;
2616  yc = fRmax*fS2;
2617  z[3] = GetZcoord(xc, yc, -fDz);
2618  z[7] = GetZcoord(xc, yc, fDz);
2619 
2620  z1 = z[TMath::LocMin(4, &z[0])];
2621  if (in_range_low)
2622  zmin = TMath::Min(zmin, z1);
2623  else
2624  zmin = z1;
2625 
2626  z1 = z[TMath::LocMax(4, &z[4])+4];
2627  if (in_range_hi)
2628  zmax = TMath::Max(zmax, z1);
2629  else
2630  zmax = z1;
2631 
2632  fDZ = 0.5*(zmax-zmin);
2633  fOrigin[2] = 0.5*(zmax+zmin);
2634 }
2635 
2636 ////////////////////////////////////////////////////////////////////////////////
2637 /// Compute normal to closest surface from POINT.
2638 
2639 void TGeoCtub::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
2640 {
2641  Double_t saf[4];
2642  Bool_t isseg = kTRUE;
2643  if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
2644  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2645  Double_t r = TMath::Sqrt(rsq);
2646 
2647  saf[0] = TMath::Abs(point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2]);
2648  saf[1] = TMath::Abs(point[0]*fNhigh[0] + point[1]*fNhigh[1] - (fDz-point[2])*fNhigh[2]);
2649  saf[2] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
2650  saf[3] = TMath::Abs(fRmax-r);
2651  Int_t i = TMath::LocMin(4,saf);
2652  if (isseg) {
2653  if (TGeoShape::IsCloseToPhi(saf[i], point,fC1,fS1,fC2,fS2)) {
2654  TGeoShape::NormalPhi(point,dir,norm,fC1,fS1,fC2,fS2);
2655  return;
2656  }
2657  }
2658  if (i==0) {
2659  memcpy(norm, fNlow, 3*sizeof(Double_t));
2660  if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
2661  norm[0] = -norm[0];
2662  norm[1] = -norm[1];
2663  norm[2] = -norm[2];
2664  }
2665  return;
2666  }
2667  if (i==1) {
2668  memcpy(norm, fNhigh, 3*sizeof(Double_t));
2669  if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
2670  norm[0] = -norm[0];
2671  norm[1] = -norm[1];
2672  norm[2] = -norm[2];
2673  }
2674  return;
2675  }
2676 
2677  norm[2] = 0;
2678  Double_t phi = TMath::ATan2(point[1], point[0]);
2679  norm[0] = TMath::Cos(phi);
2680  norm[1] = TMath::Sin(phi);
2681  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
2682  norm[0] = -norm[0];
2683  norm[1] = -norm[1];
2684  }
2685 }
2686 
2687 ////////////////////////////////////////////////////////////////////////////////
2688 /// check if point is contained in the cut tube
2689 /// check the lower cut plane
2690 
2692 {
2693  Double_t zin = point[0]*fNlow[0]+point[1]*fNlow[1]+(point[2]+fDz)*fNlow[2];
2694  if (zin>0) return kFALSE;
2695  // check the higher cut plane
2696  zin = point[0]*fNhigh[0]+point[1]*fNhigh[1]+(point[2]-fDz)*fNhigh[2];
2697  if (zin>0) return kFALSE;
2698  // check radius
2699  Double_t r2 = point[0]*point[0]+point[1]*point[1];
2700  if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax)) return kFALSE;
2701  // check phi
2702  Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
2703  if (phi < 0 ) phi+=360.;
2704  Double_t dphi = fPhi2 -fPhi1;
2705  Double_t ddp = phi-fPhi1;
2706  if (ddp<0) ddp += 360.;
2707 // if (ddp>360) ddp-=360;
2708  if (ddp > dphi) return kFALSE;
2709  return kTRUE;
2710 }
2711 
2712 ////////////////////////////////////////////////////////////////////////////////
2713 /// Get range of shape for a given axis.
2714 
2716 {
2717  xlo = 0;
2718  xhi = 0;
2719  Double_t dx = 0;
2720  switch (iaxis) {
2721  case 1:
2722  xlo = fRmin;
2723  xhi = fRmax;
2724  dx = xhi-xlo;
2725  return dx;
2726  case 2:
2727  xlo = fPhi1;
2728  xhi = fPhi2;
2729  dx = xhi-xlo;
2730  return dx;
2731  }
2732  return dx;
2733 }
2734 
2735 ////////////////////////////////////////////////////////////////////////////////
2736 /// compute real Z coordinate of a point belonging to either lower or
2737 /// higher caps (z should be either +fDz or -fDz)
2738 
2740 {
2741  Double_t newz = 0;
2742  if (zc<0) newz = -fDz-(xc*fNlow[0]+yc*fNlow[1])/fNlow[2];
2743  else newz = fDz-(xc*fNhigh[0]+yc*fNhigh[1])/fNhigh[2];
2744  return newz;
2745 }
2746 
2747 ////////////////////////////////////////////////////////////////////////////////
2748 /// compute distance from outside point to surface of the cut tube
2749 
2750 Double_t TGeoCtub::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
2751 {
2752  if (iact<3 && safe) {
2753  *safe = Safety(point, kFALSE);
2754  if (iact==0) return TGeoShape::Big();
2755  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
2756  }
2757 // Check if the bounding box is crossed within the requested distance
2758  Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
2759  if (sdist>=step) return TGeoShape::Big();
2760  Double_t saf[2];
2761  saf[0] = point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2];
2762  saf[1] = point[0]*fNhigh[0] + point[1]*fNhigh[1] + (point[2]-fDz)*fNhigh[2];
2763  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2764  Double_t r = TMath::Sqrt(rsq);
2765  Double_t cpsi=0;
2766  Bool_t tub = kFALSE;
2767  if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
2768 
2769  // find distance to shape
2770  Double_t r2;
2771  Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
2772  // check Z planes
2773  Double_t xi, yi, zi;
2775  if (saf[0]>0) {
2776  if (calf<0) {
2777  s = -saf[0]/calf;
2778  xi = point[0]+s*dir[0];
2779  yi = point[1]+s*dir[1];
2780  r2=xi*xi+yi*yi;
2781  if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
2782  if (tub) return s;
2783  cpsi=(xi*fCm+yi*fSm)/TMath::Sqrt(r2);
2784  if (cpsi>=fCdfi) return s;
2785  }
2786  }
2787  }
2788  calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
2789  if (saf[1]>0) {
2790  if (calf<0) {
2791  s = -saf[1]/calf;
2792  xi = point[0]+s*dir[0];
2793  yi = point[1]+s*dir[1];
2794  r2=xi*xi+yi*yi;
2795  if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
2796  if (tub) return s;
2797  cpsi=(xi*fCm+yi*fSm)/TMath::Sqrt(r2);
2798  if (cpsi>=fCdfi) return s;
2799  }
2800  }
2801  }
2802 
2803  // check outer cyl. surface
2804  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
2805  if (TMath::Abs(nsq)<1E-10) return TGeoShape::Big();
2806  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
2807  Double_t b,d;
2808  // only r>fRmax coming inwards has to be considered
2809  if (r>fRmax && rdotn<0) {
2810  TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
2811  if (d>0) {
2812  s=-b-d;
2813  if (s>0) {
2814  xi=point[0]+s*dir[0];
2815  yi=point[1]+s*dir[1];
2816  zi=point[2]+s*dir[2];
2817  if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2818  if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2819  if (tub) return s;
2820  cpsi=(xi*fCm+yi*fSm)/fRmax;
2821  if (cpsi>=fCdfi) return s;
2822  }
2823  }
2824  }
2825  }
2826  }
2827  // check inner cylinder
2828  Double_t snxt=TGeoShape::Big();
2829  if (fRmin>0) {
2830  TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
2831  if (d>0) {
2832  s=-b+d;
2833  if (s>0) {
2834  xi=point[0]+s*dir[0];
2835  yi=point[1]+s*dir[1];
2836  zi=point[2]+s*dir[2];
2837  if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2838  if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2839  if (tub) return s;
2840  cpsi=(xi*fCm+yi*fSm)/fRmin;
2841  if (cpsi>=fCdfi) snxt=s;
2842  }
2843  }
2844  }
2845  }
2846  }
2847  // check phi planes
2848  if (tub) return snxt;
2849  Double_t un=dir[0]*fS1-dir[1]*fC1;
2850  if (un<-TGeoShape::Tolerance()) {
2851  s=(point[1]*fC1-point[0]*fS1)/un;
2852  if (s>=0) {
2853  xi=point[0]+s*dir[0];
2854  yi=point[1]+s*dir[1];
2855  zi=point[2]+s*dir[2];
2856  if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2857  if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2858  r2=xi*xi+yi*yi;
2859  if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
2860  if ((yi*fCm-xi*fSm)<=0) {
2861  if (s<snxt) snxt=s;
2862  }
2863  }
2864  }
2865  }
2866  }
2867  }
2868  un=dir[0]*fS2-dir[1]*fC2;
2869  if (un>TGeoShape::Tolerance()) {
2870  s=(point[1]*fC2-point[0]*fS2)/un;
2871  if (s>=0) {
2872  xi=point[0]+s*dir[0];
2873  yi=point[1]+s*dir[1];
2874  zi=point[2]+s*dir[2];
2875  if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2876  if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2877  r2=xi*xi+yi*yi;
2878  if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
2879  if ((yi*fCm-xi*fSm)>=0) {
2880  if (s<snxt) snxt=s;
2881  }
2882  }
2883  }
2884  }
2885  }
2886  }
2887  return snxt;
2888 }
2889 
2890 ////////////////////////////////////////////////////////////////////////////////
2891 /// compute distance from inside point to surface of the cut tube
2892 
2893 Double_t TGeoCtub::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
2894 {
2895  if (iact<3 && safe) *safe = Safety(point, kTRUE);
2896  if (iact==0) return TGeoShape::Big();
2897  if ((iact==1) && (*safe>step)) return TGeoShape::Big();
2898  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2899  Bool_t tub = kFALSE;
2900  if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
2901  // compute distance to surface
2902  // Do Z
2903  Double_t sz = TGeoShape::Big();
2904  Double_t saf[2];
2905  saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
2906  saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
2907  Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
2908  if (calf>0) sz = saf[0]/calf;
2909 
2910  Double_t sz1=TGeoShape::Big();
2911  calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
2912  if (calf>0) {
2913  sz1 = saf[1]/calf;
2914  if (sz1<sz) sz = sz1;
2915  }
2916 
2917  // Do R
2918  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
2919  // track parallel to Z
2920  if (TMath::Abs(nsq)<1E-10) return sz;
2921  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
2923  Double_t b, d;
2924  Bool_t skip_outer = kFALSE;
2925  // inner cylinder
2926  if (fRmin>1E-10) {
2927  TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
2928  if (d>0) {
2929  sr=-b-d;
2930  if (sr>0) skip_outer = kTRUE;
2931  }
2932  }
2933  // outer cylinder
2934  if (!skip_outer) {
2935  TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
2936  if (d>0) {
2937  sr=-b+d;
2938  if (sr<0) sr=TGeoShape::Big();
2939  } else {
2940  return 0.; // already outside
2941  }
2942  }
2943  // phi planes
2944  Double_t sfmin = TGeoShape::Big();
2945  if (!tub) sfmin=TGeoShape::DistToPhiMin(point, dir, fS1, fC1, fS2, fC2, fSm, fCm);
2946  return TMath::Min(TMath::Min(sz,sr), sfmin);
2947 }
2948 
2949 ////////////////////////////////////////////////////////////////////////////////
2950 /// Divide the tube along one axis.
2951 
2952 TGeoVolume *TGeoCtub::Divide(TGeoVolume * /*voldiv*/, const char * /*divname*/, Int_t /*iaxis*/, Int_t /*ndiv*/,
2953  Double_t /*start*/, Double_t /*step*/)
2954 {
2955  Warning("Divide", "In shape %s division of a cut tube not implemented", GetName());
2956  return 0;
2957 }
2958 
2959 ////////////////////////////////////////////////////////////////////////////////
2960 /// in case shape has some negative parameters, these has to be computed
2961 /// in order to fit the mother
2962 
2964 {
2965  if (!TestShapeBit(kGeoRunTimeShape)) return 0;
2966  if (!mother->TestShapeBit(kGeoTube)) {
2967  Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
2968  return 0;
2969  }
2970  Double_t rmin, rmax, dz;
2971  rmin = fRmin;
2972  rmax = fRmax;
2973  dz = fDz;
2974  if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
2975  if (fRmin<0)
2976  rmin = ((TGeoTube*)mother)->GetRmin();
2977  if ((fRmax<0) || (fRmax<=fRmin))
2978  rmax = ((TGeoTube*)mother)->GetRmax();
2979 
2980  return (new TGeoCtub(rmin, rmax, dz, fPhi1, fPhi2, fNlow[0], fNlow[1], fNlow[2],
2981  fNhigh[0], fNhigh[1], fNhigh[2]));
2982 }
2983 
2984 ////////////////////////////////////////////////////////////////////////////////
2985 /// print shape parameters
2986 
2988 {
2989  printf("*** Shape %s: TGeoCtub ***\n", GetName());
2990  printf(" lx = %11.5f\n", fNlow[0]);
2991  printf(" ly = %11.5f\n", fNlow[1]);
2992  printf(" lz = %11.5f\n", fNlow[2]);
2993  printf(" tx = %11.5f\n", fNhigh[0]);
2994  printf(" ty = %11.5f\n", fNhigh[1]);
2995  printf(" tz = %11.5f\n", fNhigh[2]);
2997 }
2998 
2999 ////////////////////////////////////////////////////////////////////////////////
3000 /// computes the closest distance from given point to this shape, according
3001 /// to option. The matching point on the shape is stored in spoint.
3002 
3003 Double_t TGeoCtub::Safety(const Double_t *point, Bool_t in) const
3004 {
3005  Double_t saf[4];
3006  Double_t rsq = point[0]*point[0]+point[1]*point[1];
3007  Double_t r = TMath::Sqrt(rsq);
3008  Bool_t isseg = kTRUE;
3009  if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
3010 
3011  saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
3012  saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
3013  saf[2] = (fRmin<1E-10 && !isseg)?TGeoShape::Big():(r-fRmin);
3014  saf[3] = fRmax-r;
3015  Double_t safphi = TGeoShape::Big();
3016  Double_t safe = TGeoShape::Big();
3017  if (isseg) safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi2);
3018 
3019  if (in) {
3020  safe = saf[TMath::LocMin(4,saf)];
3021  return TMath::Min(safe, safphi);
3022  }
3023  for (Int_t i=0; i<4; i++) saf[i]=-saf[i];
3024  safe = saf[TMath::LocMax(4,saf)];
3025  if (isseg) return TMath::Max(safe, safphi);
3026  return safe;
3027 }
3028 
3029 ////////////////////////////////////////////////////////////////////////////////
3030 /// set dimensions of a cut tube
3031 
3033  Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
3034 {
3035  SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
3036  fNlow[0] = lx;
3037  fNlow[1] = ly;
3038  fNlow[2] = lz;
3039  fNhigh[0] = tx;
3040  fNhigh[1] = ty;
3041  fNhigh[2] = tz;
3042  ComputeBBox();
3043 }
3044 
3045 ////////////////////////////////////////////////////////////////////////////////
3046 /// Save a primitive as a C++ statement(s) on output stream "out".
3047 
3048 void TGeoCtub::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
3049 {
3050  if (TObject::TestBit(kGeoSavePrimitive)) return;
3051  out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
3052  out << " rmin = " << fRmin << ";" << std::endl;
3053  out << " rmax = " << fRmax << ";" << std::endl;
3054  out << " dz = " << fDz << ";" << std::endl;
3055  out << " phi1 = " << fPhi1 << ";" << std::endl;
3056  out << " phi2 = " << fPhi2 << ";" << std::endl;
3057  out << " lx = " << fNlow[0] << ";" << std::endl;
3058  out << " ly = " << fNlow[1] << ";" << std::endl;
3059  out << " lz = " << fNlow[2] << ";" << std::endl;
3060  out << " tx = " << fNhigh[0] << ";" << std::endl;
3061  out << " ty = " << fNhigh[1] << ";" << std::endl;
3062  out << " tz = " << fNhigh[2] << ";" << std::endl;
3063  out << " TGeoShape *" << GetPointerName() << " = new TGeoCtub(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2,lx,ly,lz,tx,ty,tz);" << std::endl; TObject::SetBit(TGeoShape::kGeoSavePrimitive);
3064 }
3065 
3066 ////////////////////////////////////////////////////////////////////////////////
3067 /// Set dimensions of the cut tube starting from a list.
3068 
3070 {
3071  SetCtubDimensions(param[0], param[1], param[2], param[3], param[4], param[5],
3072  param[6], param[7], param[8], param[9], param[10]);
3073  ComputeBBox();
3074 }
3075 
3076 ////////////////////////////////////////////////////////////////////////////////
3077 /// Fills array with n random points located on the line segments of the shape mesh.
3078 /// The output array must be provided with a length of minimum 3*npoints. Returns
3079 /// true if operation is implemented.
3080 
3081 Bool_t TGeoCtub::GetPointsOnSegments(Int_t /*npoints*/, Double_t * /*array*/) const
3082 {
3083  return kFALSE;
3084 }
3085 
3086 ////////////////////////////////////////////////////////////////////////////////
3087 /// Create mesh points for the cut tube.
3088 
3090 {
3091  Double_t dz;
3092  Int_t j, n;
3093  Double_t phi, phi1, phi2, dphi;
3094  phi1 = fPhi1;
3095  phi2 = fPhi2;
3096  if (phi2<phi1) phi2+=360.;
3097  n = gGeoManager->GetNsegments()+1;
3098 
3099  dphi = (phi2-phi1)/(n-1);
3100  dz = fDz;
3101 
3102  if (points) {
3103  Int_t indx = 0;
3104 
3105  for (j = 0; j < n; j++) {
3106  phi = (phi1+j*dphi)*TMath::DegToRad();
3107  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
3108  indx++;
3109  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
3110  indx++;
3111  points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
3112  points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3113  indx++;
3114  }
3115  for (j = 0; j < n; j++) {
3116  phi = (phi1+j*dphi)*TMath::DegToRad();
3117  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
3118  indx++;
3119  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
3120  indx++;
3121  points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
3122  points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3123  indx++;
3124  }
3125  }
3126 }
3127 
3128 ////////////////////////////////////////////////////////////////////////////////
3129 /// Create mesh points for the cut tube.
3130 
3132 {
3133  Double_t dz;
3134  Int_t j, n;
3135  Double_t phi, phi1, phi2, dphi;
3136  phi1 = fPhi1;
3137  phi2 = fPhi2;
3138  if (phi2<phi1) phi2+=360.;
3139  n = gGeoManager->GetNsegments()+1;
3140 
3141  dphi = (phi2-phi1)/(n-1);
3142  dz = fDz;
3143 
3144  if (points) {
3145  Int_t indx = 0;
3146 
3147  for (j = 0; j < n; j++) {
3148  phi = (phi1+j*dphi)*TMath::DegToRad();
3149  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
3150  indx++;
3151  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
3152  indx++;
3153  points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
3154  points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3155  indx++;
3156  }
3157  for (j = 0; j < n; j++) {
3158  phi = (phi1+j*dphi)*TMath::DegToRad();
3159  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
3160  indx++;
3161  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
3162  indx++;
3163  points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
3164  points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3165  indx++;
3166  }
3167  }
3168 }
3169 
3170 ////////////////////////////////////////////////////////////////////////////////
3171 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
3172 
3173 void TGeoCtub::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
3174 {
3175  TGeoTubeSeg::GetMeshNumbers(nvert,nsegs,npols);
3176 }
3177 
3178 ////////////////////////////////////////////////////////////////////////////////
3179 /// Return number of vertices of the mesh representation
3180 
3182 {
3184  Int_t numPoints = n*4;
3185  return numPoints;
3186 }
3187 
3188 ////////////////////////////////////////////////////////////////////////////////
3189 /// Fills a static 3D buffer and returns a reference.
3190 
3191 const TBuffer3D & TGeoCtub::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
3192 {
3193  static TBuffer3DCutTube buffer;
3194 
3195  TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
3196 
3197  if (reqSections & TBuffer3D::kShapeSpecific) {
3198  // These from TBuffer3DCutTube / TGeoCtub
3199  buffer.fRadiusInner = fRmin;
3200  buffer.fRadiusOuter = fRmax;
3201  buffer.fHalfLength = fDz;
3202  buffer.fPhiMin = fPhi1;
3203  buffer.fPhiMax = fPhi2;
3204 
3205  for (UInt_t i = 0; i < 3; i++ ) {
3206  buffer.fLowPlaneNorm[i] = fNlow[i];
3207  buffer.fHighPlaneNorm[i] = fNhigh[i];
3208  }
3209  buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
3210  }
3211  if (reqSections & TBuffer3D::kRawSizes) {
3213  Int_t nbPnts = 4*n;
3214  Int_t nbSegs = 2*nbPnts;
3215  Int_t nbPols = nbPnts-2;
3216  if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
3217  buffer.SetSectionsValid(TBuffer3D::kRawSizes);
3218  }
3219  }
3220  if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
3221  SetPoints(buffer.fPnts);
3222  if (!buffer.fLocalFrame) {
3223  TransformPoints(buffer.fPnts, buffer.NbPnts());
3224  }
3225  SetSegsAndPols(buffer);
3226  buffer.SetSectionsValid(TBuffer3D::kRaw);
3227  }
3228 
3229  return buffer;
3230 }
3231 
3232 ////////////////////////////////////////////////////////////////////////////////
3233 /// Check the inside status for each of the points in the array.
3234 /// Input: Array of point coordinates + vector size
3235 /// Output: Array of Booleans for the inside of each point
3236 
3237 void TGeoCtub::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
3238 {
3239  for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
3240 }
3241 
3242 ////////////////////////////////////////////////////////////////////////////////
3243 /// Compute the normal for an array o points so that norm.dot.dir is positive
3244 /// Input: Arrays of point coordinates and directions + vector size
3245 /// Output: Array of normal directions
3246 
3247 void TGeoCtub::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
3248 {
3249  for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
3250 }
3251 
3252 ////////////////////////////////////////////////////////////////////////////////
3253 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
3254 
3255 void TGeoCtub::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
3256 {
3257  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
3258 }
3259 
3260 ////////////////////////////////////////////////////////////////////////////////
3261 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
3262 
3263 void TGeoCtub::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
3264 {
3265  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
3266 }
3267 
3268 ////////////////////////////////////////////////////////////////////////////////
3269 /// Compute safe distance from each of the points in the input array.
3270 /// Input: Array of point coordinates, array of statuses for these points, size of the arrays
3271 /// Output: Safety values
3272 
3273 void TGeoCtub::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
3274 {
3275  for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
3276 }
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
Complete tube description class - see TBuffer3DTypes for producer classes.
Definition: TBuffer3D.h:155
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
computes the closest distance from given point to this shape, according to option.
Definition: TGeoTube.cxx:3003
virtual Bool_t Contains(const Double_t *point) const
test if point is inside this tube segment first check if point is inside the tube ...
Definition: TGeoTube.cxx:1437
Volume families.
Definition: TGeoVolume.h:256
Double_t fHighPlaneNorm[3]
Definition: TBuffer3D.h:224
Double_t fRadiusInner
Definition: TBuffer3D.h:174
Double_t fCm
Definition: TGeoTube.h:100
Cylindrical tube class.
Definition: TGeoTube.h:17
Double_t fPhi2
Definition: TGeoTube.h:93
float xmin
Definition: THbookFile.cxx:93
Double_t fPhi1
Definition: TGeoTube.h:92
virtual TBuffer3D * MakeBuffer3D() const
Creates a TBuffer3D describing this shape.
Definition: TGeoTube.cxx:647
Box class.
Definition: TGeoBBox.h:17
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:2363
Long64_t LocMax(Long64_t n, const T *a)
Definition: TMath.h:872
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:153
void SetFinder(TGeoPatternFinder *finder)
Definition: TGeoVolume.h:234
virtual void ComputeBBox()
compute bounding box of the tube
Definition: TGeoTube.cxx:210
virtual void GetBoundingCylinder(Double_t *param) const
Fill vector param[4] with the bounding cylinder parameters.
Definition: TGeoTube.cxx:1899
void InitTrigonometry()
Init frequently used trigonometric values.
Definition: TGeoTube.cxx:1296
float Float_t
Definition: RtypesCore.h:53
virtual void SetSegsAndPols(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons.
Definition: TGeoTube.cxx:672
Double_t fS1
Definition: TGeoTube.h:95
void AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset=0, Option_t *option="")
Add a division node to the list of nodes.
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
computes the closest distance from given point InitTrigonometry();to this shape, according to option...
Definition: TGeoTube.cxx:2058
const char Option_t
Definition: RtypesCore.h:62
Geometrical transformation package.
Definition: TGeoMatrix.h:40
Tube segment description class - see TBuffer3DTypes for producer classes.
Definition: TBuffer3D.h:183
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:1378
return c1
Definition: legend1.C:41
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:219
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:1314
constexpr Double_t TwoPi()
Definition: TMath.h:44
float ymin
Definition: THbookFile.cxx:93
virtual void DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:1200
virtual TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step)
Divide the tube along one axis.
Definition: TGeoTube.cxx:2952
virtual void ComputeBBox()
compute bounding box of the tube segment
Definition: TGeoTube.cxx:1331
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:48
Double_t fC2
Definition: TGeoTube.h:98
virtual void DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:2438
virtual void ComputeBBox()
compute minimum bounding box of the ctub
Definition: TGeoTube.cxx:2535
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:193
void SetCtubDimensions(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2, Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
set dimensions of a cut tube
Definition: TGeoTube.cxx:3032
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
static constexpr double cm
UInt_t NbPnts() const
Definition: TBuffer3D.h:80
Double_t fOrigin[3]
Definition: TGeoBBox.h:24
Basic string class.
Definition: TString.h:125
Cut tube segment description class - see TBuffer3DTypes for producer classes.
Definition: TBuffer3D.h:210
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
virtual const char * GetAxisName(Int_t iaxis) const
Returns name of axis IAXIS.
Definition: TGeoTube.cxx:544
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
Compute safe distance from each of the points in the input array.
Definition: TGeoTube.cxx:3273
static Double_t SafetyPhi(const Double_t *point, Bool_t in, Double_t phi1, Double_t phi2)
Static method to compute safety w.r.t a phi corner defined by cosines/sines of the angles phi1...
Definition: TGeoShape.cxx:464
Double_t GetZcoord(Double_t xc, Double_t yc, Double_t zc) const
compute real Z coordinate of a point belonging to either lower or higher caps (z should be either +fD...
Definition: TGeoTube.cxx:2739
virtual void SetSegsAndPols(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons.
Definition: TGeoTube.cxx:1973
virtual void InspectShape() const
Prints shape parameters.
Definition: TGeoBBox.cxx:793
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t rmin, Double_t rmax, Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:1409
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:1936
void SetTubsDimensions(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2)
Set dimensions of the tube segment.
Definition: TGeoTube.cxx:2197
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
virtual void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
Compute safe distance from each of the points in the input array.
Definition: TGeoTube.cxx:1218
static Bool_t IsSameWithinTolerance(Double_t a, Double_t b)
Check if two numbers differ with less than a tolerance.
Definition: TGeoShape.cxx:326
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
Returns numbers of vertices, segments and polygons composing the shape mesh.
Definition: TGeoTube.cxx:2352
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:3181
TObjArray * GetNodes()
Definition: TGeoVolume.h:170
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
compute closest distance from point px,py to each corner
Definition: TGeoTube.cxx:1446
static Double_t Tolerance()
Definition: TGeoShape.h:91
Int_t GetNdaughters() const
Definition: TGeoVolume.h:350
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoTube.cxx:2180
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:1102
Double_t fDZ
Definition: TGeoBBox.h:23
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
compute closest distance from point px,py to each corner
Definition: TGeoTube.cxx:273
void AddVolume(TGeoVolume *vol)
Add a volume with valid shape to the list of volumes.
virtual TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const
in case shape has some negative parameters, these has to be computed in order to fit the mother ...
Definition: TGeoTube.cxx:2963
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:1140
UInt_t NbSegs() const
Definition: TBuffer3D.h:81
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
Get range of shape for a given axis.
Definition: TGeoTube.cxx:561
Double_t * fPnts
Definition: TBuffer3D.h:112
constexpr Double_t DegToRad()
Definition: TMath.h:64
TGeoMedium * GetMedium() const
Definition: TGeoVolume.h:176
Bool_t HasRmin() const
Definition: TGeoTube.h:69
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
Get range of shape for a given axis.
Definition: TGeoTube.cxx:1870
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:580
virtual Bool_t Contains(const Double_t *point) const
check if point is contained in the cut tube check the lower cut plane
Definition: TGeoTube.cxx:2691
XFontStruct * id
Definition: TGX11.cxx:108
constexpr Double_t Pi()
Definition: TMath.h:40
Double_t fDz
Definition: TGeoTube.h:23
virtual TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const
in case shape has some negative parameters, these has to be computed in order to fit the mother ...
Definition: TGeoTube.cxx:1913
virtual void SetDimensions(Double_t *param)
Set tube dimensions starting from a list.
Definition: TGeoTube.cxx:922
void SetSectionsValid(UInt_t mask)
Definition: TBuffer3D.h:65
const char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoShape.cxx:699
Int_t * fPols
Definition: TBuffer3D.h:114
virtual void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
Returns numbers of vertices, segments and polygons composing the shape mesh.
Definition: TGeoTube.cxx:3173
Base finder class for patterns.
Bool_t fLocalFrame
Definition: TBuffer3D.h:90
point * points
Definition: X3DBuffer.c:20
Double_t fRadiusOuter
Definition: TBuffer3D.h:175
virtual const char * GetName() const
Get the shape name.
Definition: TGeoShape.cxx:248
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
Static method to compute distance to arbitrary tube segment from outside point Boundary safe algorith...
Definition: TGeoTube.cxx:1523
virtual void DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:3255
Double_t fHalfLength
Definition: TBuffer3D.h:176
virtual void SetPoints(Double_t *points) const
Create mesh points for the cut tube.
Definition: TGeoTube.cxx:3089
Double_t fC1
Definition: TGeoTube.h:96
float ymax
Definition: THbookFile.cxx:93
Int_t GetNsegments() const
Get number of segments approximating circles.
Int_t ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
Returns distance to shape primitive mesh.
Definition: TGeoShape.cxx:259
Bool_t SectionsValid(UInt_t mask) const
Definition: TBuffer3D.h:67
Base abstract class for all shapes.
Definition: TGeoShape.h:25
Double_t fNhigh[3]
Definition: TGeoTube.h:173
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
Returns numbers of vertices, segments and polygons composing the shape mesh.
Definition: TGeoTube.cxx:1113
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
Compute distance from inside point to surface of the tube (static) Boundary safe algorithm.
Definition: TGeoTube.cxx:287
virtual void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
Check the inside status for each of the points in the array.
Definition: TGeoTube.cxx:1182
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoTube.cxx:896
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:2380
static Double_t DistToPhiMin(const Double_t *point, const Double_t *dir, Double_t s1, Double_t c1, Double_t s2, Double_t c2, Double_t sm, Double_t cm, Bool_t in=kTRUE)
compute distance from point (inside phi) to both phi planes. Return minimum.
Definition: TGeoShape.cxx:405
virtual void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
Check the inside status for each of the points in the array.
Definition: TGeoTube.cxx:2420
unsigned int UInt_t
Definition: RtypesCore.h:42
static void DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta)
Static method computing the distance to a tube with given radius, starting from POINT along DIR direc...
Definition: TGeoTube.cxx:460
void TransformPoints(Double_t *points, UInt_t NbPoints) const
Tranform a set of points (LocalToMaster)
Definition: TGeoShape.cxx:552
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void SetDimensions(Double_t *param)
Set dimensions of the cut tube starting from a list.
Definition: TGeoTube.cxx:3069
virtual void SetPoints(Double_t *points) const
Create tube segment mesh points.
Definition: TGeoTube.cxx:2268
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
computes the closest distance from given point to this shape, according to option.
Definition: TGeoTube.cxx:827
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
static Bool_t IsInPhiRange(const Double_t *point, Double_t phi1, Double_t phi2)
Static method to check if a point is in the phi range (phi1, phi2) [degrees].
Definition: TGeoShape.cxx:283
Generic 3D primitive description class.
Definition: TBuffer3D.h:17
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t rmin, Double_t rmax, Double_t dz)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:246
float xmax
Definition: THbookFile.cxx:93
Double_t fCdfi
Definition: TGeoTube.h:101
UInt_t NbPols() const
Definition: TBuffer3D.h:82
virtual TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step)
Divide this tube shape belonging to volume "voldiv" into ndiv volumes called divname, from start position with the given step.
Definition: TGeoTube.cxx:482
virtual void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
Definition: TGeoTube.cxx:2430
void SetDivIndex(Int_t index)
virtual Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const
Fills array with n random points located on the line segments of the shape mesh.
Definition: TGeoTube.cxx:935
virtual void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
Definition: TGeoTube.cxx:1192
constexpr Double_t E()
Definition: TMath.h:74
Double_t Cos(Double_t)
Definition: TMath.h:550
virtual void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
Compute safe distance from each of the points in the input array.
Definition: TGeoTube.cxx:2456
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:1208
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz=0)
computes the closest distance from given point to this shape, according to option.
Definition: TGeoTube.cxx:867
A tube segment cut with 2 planes.
Definition: TGeoTube.h:168
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:2639
TGeoTube()
Default constructor.
Definition: TGeoTube.cxx:128
static Bool_t IsCloseToPhi(Double_t epsil, const Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
True if point is closer than epsil to one of the phi planes defined by c1,s1 or c2,s2.
Definition: TGeoShape.cxx:269
return c2
Definition: legend2.C:14
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
Compute distance from inside point to surface of the tube segment (static) Boundary safe algorithm...
Definition: TGeoTube.cxx:1458
auto * t1
Definition: textangle.C:20
#define ClassImp(name)
Definition: Rtypes.h:359
R__EXTERN TGeoManager * gGeoManager
Definition: TGeoManager.h:559
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:3191
double Double_t
Definition: RtypesCore.h:55
Double_t fLowPlaneNorm[3]
Definition: TBuffer3D.h:223
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
Compute distance from outside point to surface of the box.
Definition: TGeoBBox.cxx:430
Bool_t TestShapeBit(UInt_t f) const
Definition: TGeoShape.h:163
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
compute distance from outside point to surface of the tube segment fist localize point w...
Definition: TGeoTube.cxx:1780
Double_t fPhiMax
Definition: TBuffer3D.h:203
Int_t fColor
Definition: TBuffer3D.h:88
Double_t fS2
Definition: TGeoTube.h:97
Node containing an offset.
Definition: TGeoNode.h:181
static constexpr double s
virtual void AfterStreamer()
Function called after streaming an object of this class.
Definition: TGeoTube.cxx:1288
virtual TGeoShape * GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const
in case shape has some negative parameters, these has to be computed in order to fit the mother ...
Definition: TGeoTube.cxx:604
Double_t fSm
Definition: TGeoTube.h:99
virtual void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
Definition: TGeoTube.cxx:3247
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2, Int_t skipz=0)
Static method to compute the closest distance from given point to this shape.
Definition: TGeoTube.cxx:2105
virtual TBuffer3D * MakeBuffer3D() const
Creates a TBuffer3D describing this shape.
Definition: TGeoTube.cxx:1952
static Double_t Big()
Definition: TGeoShape.h:88
Double_t fDY
Definition: TGeoBBox.h:22
virtual Bool_t Contains(const Double_t *point) const
test if point is inside this tube
Definition: TGeoTube.cxx:262
void SetShapeBit(UInt_t f, Bool_t set)
Equivalent of TObject::SetBit.
Definition: TGeoShape.cxx:524
virtual TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step)
Divide this tube segment shape belonging to volume "voldiv" into ndiv volumes called divname...
Definition: TGeoTube.cxx:1804
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
virtual void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const
Fills the supplied buffer, with sections in desired frame See TBuffer3D.h for explanation of sections...
Definition: TGeoBBox.cxx:1033
constexpr Double_t RadToDeg()
Definition: TMath.h:60
virtual void GetBoundingCylinder(Double_t *param) const
Fill vector param[4] with the bounding cylinder parameters.
Definition: TGeoTube.cxx:590
Int_t * fSegs
Definition: TBuffer3D.h:113
Double_t fRmin
Definition: TGeoTube.h:21
Double_t fPhiMin
Definition: TBuffer3D.h:202
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
Compute distance from inside point to surface of the tube segment Boundary safe algorithm.
Definition: TGeoTube.cxx:1506
virtual ~TGeoCtub()
destructor
Definition: TGeoTube.cxx:2519
virtual Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const
Fills array with n random points located on the line segments of the shape mesh.
Definition: TGeoTube.cxx:3081
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
Static method to compute distance from outside point to a tube with given parameters Boundary safe al...
Definition: TGeoTube.cxx:348
Double_t Sin(Double_t)
Definition: TMath.h:547
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const =0
Double_t fDX
Definition: TGeoBBox.h:21
virtual void Sizeof3D() const
fill size of this 3-D object
Definition: TGeoTube.cxx:1133
static void NormalPhi(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Static method to compute normal to phi planes.
Definition: TGeoShape.cxx:437
virtual void Sizeof3D() const
fill size of this 3-D object
Definition: TGeoTube.cxx:2373
virtual void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
Check the inside status for each of the points in the array.
Definition: TGeoTube.cxx:3237
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:2526
virtual void SetPoints(Double_t *points) const
create tube mesh points
Definition: TGeoTube.cxx:976
Double_t fNlow[3]
Definition: TGeoTube.h:172
virtual void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:3263
Double_t Sqrt(Double_t x)
Definition: TMath.h:590
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
Compute distance from outside point to surface of the tube and safe distance Boundary safe algorithm...
Definition: TGeoTube.cxx:436
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void SetDimensions(Double_t *param)
Set dimensions of the tube segment starting from a list.
Definition: TGeoTube.cxx:2214
Long64_t LocMin(Long64_t n, const T *a)
Definition: TMath.h:843
static constexpr double sr
virtual ~TGeoTube()
destructor
Definition: TGeoTube.cxx:186
TGeoTubeSeg()
Default constructor.
Definition: TGeoTube.cxx:1228
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t GetBasicColor() const
Get the basic color (0-7).
Definition: TGeoShape.cxx:673
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:633
virtual ~TGeoTubeSeg()
destructor
Definition: TGeoTube.cxx:1281
const Int_t n
Definition: legend1.C:16
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
compute distance from outside point to surface of the cut tube
Definition: TGeoTube.cxx:2750
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoTube.cxx:3048
virtual void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Definition: TGeoTube.cxx:2446
void SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz)
Set tube dimensions.
Definition: TGeoTube.cxx:910
char name[80]
Definition: TGX11.cxx:109
Double_t fRmax
Definition: TGeoTube.h:22
virtual Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const
Fills array with n random points located on the line segments of the shape mesh.
Definition: TGeoTube.cxx:2229
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
Get range of shape for a given axis.
Definition: TGeoTube.cxx:2715
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
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
Compute distance from inside point to surface of the tube Boundary safe algorithm.
Definition: TGeoTube.cxx:332
const char * Data() const
Definition: TString.h:345
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:2987
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
compute distance from inside point to surface of the cut tube
Definition: TGeoTube.cxx:2893
A phi segment of a tube.
Definition: TGeoTube.h:88