ROOT  6.06/09
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 //_____________________________________________________________________________
14 // TGeoTube - cylindrical tube class. It takes 3 parameters :
15 // inner radius, outer radius and half-length dz.
16 //
17 //_____________________________________________________________________________
18 //Begin_Html
19 /*
20 <img src="gif/t_tube.gif">
21 */
22 //End_Html
23 //Begin_Html
24 /*
25 <img src="gif/t_tubedivR.gif">
26 */
27 //End_Html
28 //Begin_Html
29 /*
30 <img src="gif/t_tubedivstepR.gif">
31 */
32 //End_Html
33 //Begin_Html
34 /*
35 <img src="gif/t_tubedivPHI.gif">
36 */
37 //End_Html
38 //Begin_Html
39 /*
40 <img src="gif/t_tubedivstepPHI.gif">
41 */
42 //End_Html
43 //Begin_Html
44 /*
45 <img src="gif/t_tubedivZ.gif">
46 */
47 //End_Html
48 //Begin_Html
49 /*
50 <img src="gif/t_tubedivstepZ.gif">
51 */
52 //End_Html
53 //_____________________________________________________________________________
54 // TGeoTubeSeg - a phi segment of a tube. Has 5 parameters :
55 // - the same 3 as a tube;
56 // - first phi limit (in degrees)
57 // - second phi limit
58 // The segment will be be placed from the first angle (first phi limit)
59 // to the second angle (second phi limit)
60 //_____________________________________________________________________________
61 //Begin_Html
62 /*
63 <img src="gif/t_tubseg.gif">
64 */
65 //End_Html
66 //Begin_Html
67 /*
68 <img src="gif/t_tubsegdivstepR.gif">
69 */
70 //End_Html
71 //Begin_Html
72 /*
73 <img src="gif/t_tubsegdivPHI.gif">
74 */
75 //End_Html
76 //Begin_Html
77 /*
78 <img src="gif/t_tubsegdivZ.gif">
79 */
80 //End_Html
81 //_____________________________________________________________________________
82 // TGeoCtub - a tube segment cut with 2 planes. Has 11 parameters :
83 // - the same 5 as a tube segment;
84 // - x, y, z components of the normal to the -dZ cut plane in
85 // point (0, 0, -dZ);
86 // - x, y, z components of the normal to the +dZ cut plane in
87 // point (0, 0, dZ);
88 //
89 //_____________________________________________________________________________
90 //Begin_Html
91 /*
92 <img src="gif/t_ctub.gif">
93 */
94 //End_Html
95 
96 #include "Riostream.h"
97 
98 #include "TGeoManager.h"
99 #include "TGeoVolume.h"
100 #include "TVirtualGeoPainter.h"
101 #include "TGeoTube.h"
102 #include "TVirtualPad.h"
103 #include "TBuffer3D.h"
104 #include "TBuffer3DTypes.h"
105 #include "TMath.h"
106 
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Default constructor
111 
113 {
114  SetShapeBit(TGeoShape::kGeoTube);
115  fRmin = 0.0;
116  fRmax = 0.0;
117  fDz = 0.0;
118 }
119 
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Default constructor specifying minimum and maximum radius
123 
125  :TGeoBBox(0, 0, 0)
126 {
128  SetTubeDimensions(rmin, rmax, dz);
129  if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
131 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
132 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
133  }
134  ComputeBBox();
135 }
136 ////////////////////////////////////////////////////////////////////////////////
137 /// Default constructor specifying minimum and maximum radius
138 
139 TGeoTube::TGeoTube(const char *name, Double_t rmin, Double_t rmax, Double_t dz)
140  :TGeoBBox(name, 0, 0, 0)
141 {
143  SetTubeDimensions(rmin, rmax, dz);
144  if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
146 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
147 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
148  }
149  ComputeBBox();
150 }
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 /// Default constructor specifying minimum and maximum radius
154 /// param[0] = Rmin
155 /// param[1] = Rmax
156 /// param[2] = dz
157 
159  :TGeoBBox(0, 0, 0)
160 {
162  SetDimensions(param);
163  if ((fDz<0) || (fRmin<0) || (fRmax<0)) SetShapeBit(kGeoRunTimeShape);
164  ComputeBBox();
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 /// destructor
169 
171 {
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Computes capacity of the shape in [length^3]
176 
178 {
180 }
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 /// Computes capacity of the shape in [length^3]
184 
186 {
187  Double_t capacity = 2.*TMath::Pi()*(rmax*rmax-rmin*rmin)*dz;
188  return capacity;
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 /// compute bounding box of the tube
193 
195 {
196  fDX = fDY = fRmax;
197  fDZ = fDz;
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
201 /// Compute normal to closest surface from POINT.
202 
203 void TGeoTube::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
204 {
205  Double_t saf[3];
206  Double_t rsq = point[0]*point[0]+point[1]*point[1];
207  Double_t r = TMath::Sqrt(rsq);
208  saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
209  saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
210  saf[2] = TMath::Abs(fRmax-r);
211  Int_t i = TMath::LocMin(3,saf);
212  if (i==0) {
213  norm[0] = norm[1] = 0.;
214  norm[2] = TMath::Sign(1.,dir[2]);
215  return;
216  }
217  norm[2] = 0;
218  Double_t phi = TMath::ATan2(point[1], point[0]);
219  norm[0] = TMath::Cos(phi);
220  norm[1] = TMath::Sin(phi);
221  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
222  norm[0] = -norm[0];
223  norm[1] = -norm[1];
224  }
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Compute normal to closest surface from POINT.
229 
230 void TGeoTube::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
231  Double_t /*rmin*/, Double_t /*rmax*/, Double_t /*dz*/)
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 /// test if point is inside this tube
245 
246 Bool_t TGeoTube::Contains(const Double_t *point) const
247 {
248  if (TMath::Abs(point[2]) > fDz) return kFALSE;
249  Double_t r2 = point[0]*point[0]+point[1]*point[1];
250  if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax)) return kFALSE;
251  return kTRUE;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// compute closest distance from point px,py to each corner
256 
258 {
260  Int_t numPoints = 4*n;
261  if (!HasRmin()) numPoints = 2*(n+1);
262  return ShapeDistancetoPrimitive(numPoints, px, py);
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// Compute distance from inside point to surface of the tube (static)
267 /// Boundary safe algorithm.
268 /// compute distance to surface
269 /// Do Z
270 
272 {
273  Double_t sz = TGeoShape::Big();
274  if (dir[2]) {
275  sz = (TMath::Sign(dz, dir[2])-point[2])/dir[2];
276  if (sz<=0) return 0.0;
277  }
278  // Do R
279  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
280  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return sz;
281  Double_t rsq=point[0]*point[0]+point[1]*point[1];
282  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
283  Double_t b,d;
284  Double_t sr = TGeoShape::Big();
285  // inner cylinder
286  if (rmin>0) {
287  // Protection in case point is actually outside the tube
288  if (rsq <= rmin*rmin+TGeoShape::Tolerance()) {
289  if (rdotn<0) return 0.0;
290  } else {
291  if (rdotn<0) {
292  DistToTube(rsq,nsq,rdotn,rmin,b,d);
293  if (d>0) {
294  sr=-b-d;
295  if (sr>0) return TMath::Min(sz,sr);
296  }
297  }
298  }
299  }
300  // outer cylinder
301  if (rsq >= rmax*rmax-TGeoShape::Tolerance()) {
302  if (rdotn>=0) return 0.0;
303  }
304  DistToTube(rsq,nsq,rdotn,rmax,b,d);
305  if (d>0) {
306  sr=-b+d;
307  if (sr>0) return TMath::Min(sz,sr);
308  }
309  return 0.;
310 }
311 
312 ////////////////////////////////////////////////////////////////////////////////
313 /// Compute distance from inside point to surface of the tube
314 /// Boundary safe algorithm.
315 
316 Double_t TGeoTube::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
317 {
318  if (iact<3 && safe) {
319  *safe = Safety(point, kTRUE);
320  if (iact==0) return TGeoShape::Big();
321  if ((iact==1) && (*safe>step)) return TGeoShape::Big();
322  }
323  // compute distance to surface
324  return DistFromInsideS(point, dir, fRmin, fRmax, fDz);
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// Static method to compute distance from outside point to a tube with given parameters
329 /// Boundary safe algorithm.
330 /// check Z planes
331 
333 {
334  Double_t xi,yi,zi;
335  Double_t rmaxsq = rmax*rmax;
336  Double_t rminsq = rmin*rmin;
337  zi = dz - TMath::Abs(point[2]);
338  Double_t s = TGeoShape::Big();
339  Bool_t in = kFALSE;
340  Bool_t inz = (zi<0)?kFALSE:kTRUE;
341  if (!inz) {
342  if (point[2]*dir[2]>=0) return TGeoShape::Big();
343  s = -zi/TMath::Abs(dir[2]);
344  xi = point[0]+s*dir[0];
345  yi = point[1]+s*dir[1];
346  Double_t r2=xi*xi+yi*yi;
347  if ((rminsq<=r2) && (r2<=rmaxsq)) return s;
348  }
349 
350  Double_t rsq = point[0]*point[0]+point[1]*point[1];
351  // check outer cyl. surface
352  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
353  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
354  Double_t b,d;
355  Bool_t inrmax = kFALSE;
356  Bool_t inrmin = kFALSE;
357  if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
358  if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
359  in = inz & inrmin & inrmax;
360  // If inside, we are most likely on a boundary within machine precision.
361  if (in) {
362  Bool_t checkout = kFALSE;
363  Double_t r = TMath::Sqrt(rsq);
364  if (zi<rmax-r) {
365  if ((TGeoShape::IsSameWithinTolerance(rmin,0)) || (zi<r-rmin)) {
366  if (point[2]*dir[2]<0) return 0.0;
367  return TGeoShape::Big();
368  }
369  }
370  if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
371  if (checkout) {
372  if (rdotn>=0) return TGeoShape::Big();
373  return 0.0;
374  }
375  if (TGeoShape::IsSameWithinTolerance(rmin,0)) return 0.0;
376  if (rdotn>=0) return 0.0;
377  // Ray exiting rmin -> check (+) solution for inner tube
378  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
379  DistToTube(rsq, nsq, rdotn, rmin, b, d);
380  if (d>0) {
381  s=-b+d;
382  if (s>0) {
383  zi=point[2]+s*dir[2];
384  if (TMath::Abs(zi)<=dz) return s;
385  }
386  }
387  return TGeoShape::Big();
388  }
389  // Check outer cylinder (only r>rmax has to be considered)
390  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
391  if (!inrmax) {
392  DistToTube(rsq, nsq, rdotn, rmax, b, d);
393  if (d>0) {
394  s=-b-d;
395  if (s>0) {
396  zi=point[2]+s*dir[2];
397  if (TMath::Abs(zi)<=dz) return s;
398  }
399  }
400  }
401  // check inner cylinder
402  if (rmin>0) {
403  DistToTube(rsq, nsq, rdotn, rmin, b, d);
404  if (d>0) {
405  s=-b+d;
406  if (s>0) {
407  zi=point[2]+s*dir[2];
408  if (TMath::Abs(zi)<=dz) return s;
409  }
410  }
411  }
412  return TGeoShape::Big();
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// Compute distance from outside point to surface of the tube and safe distance
417 /// Boundary safe algorithm.
418 /// fist localize point w.r.t tube
419 
420 Double_t TGeoTube::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
421 {
422  if (iact<3 && safe) {
423  *safe = Safety(point, kFALSE);
424  if (iact==0) return TGeoShape::Big();
425  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
426  }
427 // Check if the bounding box is crossed within the requested distance
428  Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
429  if (sdist>=step) return TGeoShape::Big();
430  // find distance to shape
431  return DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Static method computing the distance to a tube with given radius, starting from
436 /// POINT along DIR director cosines. The distance is computed as :
437 /// RSQ = point[0]*point[0]+point[1]*point[1]
438 /// NSQ = dir[0]*dir[0]+dir[1]*dir[1] ---> should NOT be 0 !!!
439 /// RDOTN = point[0]*dir[0]+point[1]*dir[1]
440 /// The distance can be computed as :
441 /// D = -B +/- DELTA
442 /// where DELTA.GT.0 and D.GT.0
443 
444 void TGeoTube::DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta)
445 {
446  Double_t t1 = 1./nsq;
447  Double_t t3=rsq-(radius*radius);
448  b = t1*rdotn;
449  Double_t c =t1*t3;
450  delta = b*b-c;
451  if (delta>0) {
452  delta=TMath::Sqrt(delta);
453  } else {
454  delta = -1;
455  }
456 }
457 
458 ////////////////////////////////////////////////////////////////////////////////
459 ///--- Divide this tube shape belonging to volume "voldiv" into ndiv volumes
460 /// called divname, from start position with the given step. Returns pointer
461 /// to created division cell volume in case of Z divisions. For radial division
462 /// creates all volumes with different shapes and returns pointer to volume that
463 /// was divided. In case a wrong division axis is supplied, returns pointer to
464 /// volume that was divided.
465 
466 TGeoVolume *TGeoTube::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
467  Double_t start, Double_t step)
468 {
469  TGeoShape *shape; //--- shape to be created
470  TGeoVolume *vol; //--- division volume to be created
471  TGeoVolumeMulti *vmulti; //--- generic divided volume
472  TGeoPatternFinder *finder; //--- finder to be attached
473  TString opt = ""; //--- option to be attached
474  Int_t id;
475  Double_t end = start+ndiv*step;
476  switch (iaxis) {
477  case 1: //--- R division
478  finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
479  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
480  voldiv->SetFinder(finder);
481  finder->SetDivIndex(voldiv->GetNdaughters());
482  for (id=0; id<ndiv; id++) {
483  shape = new TGeoTube(start+id*step, start+(id+1)*step, fDz);
484  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
485  vmulti->AddVolume(vol);
486  opt = "R";
487  voldiv->AddNodeOffset(vol, id, 0, opt.Data());
488  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
489  }
490  return vmulti;
491  case 2: //--- Phi division
492  finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
493  voldiv->SetFinder(finder);
494  finder->SetDivIndex(voldiv->GetNdaughters());
495  shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
496  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
497  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
498  vmulti->AddVolume(vol);
499  opt = "Phi";
500  for (id=0; id<ndiv; id++) {
501  voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
502  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
503  }
504  return vmulti;
505  case 3: //--- Z division
506  finder = new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
507  voldiv->SetFinder(finder);
508  finder->SetDivIndex(voldiv->GetNdaughters());
509  shape = new TGeoTube(fRmin, fRmax, step/2);
510  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
511  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
512  vmulti->AddVolume(vol);
513  opt = "Z";
514  for (id=0; id<ndiv; id++) {
515  voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
516  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
517  }
518  return vmulti;
519  default:
520  Error("Divide", "In shape %s wrong axis type for division", GetName());
521  return 0;
522  }
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 /// Returns name of axis IAXIS.
527 
528 const char *TGeoTube::GetAxisName(Int_t iaxis) const
529 {
530  switch (iaxis) {
531  case 1:
532  return "R";
533  case 2:
534  return "PHI";
535  case 3:
536  return "Z";
537  default:
538  return "UNDEFINED";
539  }
540 }
541 
542 ////////////////////////////////////////////////////////////////////////////////
543 /// Get range of shape for a given axis.
544 
546 {
547  xlo = 0;
548  xhi = 0;
549  Double_t dx = 0;
550  switch (iaxis) {
551  case 1:
552  xlo = fRmin;
553  xhi = fRmax;
554  dx = xhi-xlo;
555  return dx;
556  case 2:
557  xlo = 0;
558  xhi = 360;
559  dx = 360;
560  return dx;
561  case 3:
562  xlo = -fDz;
563  xhi = fDz;
564  dx = xhi-xlo;
565  return dx;
566  }
567  return dx;
568 }
569 
570 ////////////////////////////////////////////////////////////////////////////////
571 ///--- Fill vector param[4] with the bounding cylinder parameters. The order
572 /// is the following : Rmin, Rmax, Phi1, Phi2, dZ
573 
575 {
576  param[0] = fRmin; // Rmin
577  param[0] *= param[0];
578  param[1] = fRmax; // Rmax
579  param[1] *= param[1];
580  param[2] = 0.; // Phi1
581  param[3] = 360.; // Phi2
582 }
583 
584 ////////////////////////////////////////////////////////////////////////////////
585 /// in case shape has some negative parameters, these has to be computed
586 /// in order to fit the mother
587 
589 {
590  if (!TestShapeBit(kGeoRunTimeShape)) return 0;
591  Double_t rmin, rmax, dz;
593  rmin = fRmin;
594  rmax = fRmax;
595  dz = fDz;
596  if (fDz<0) {
597  mother->GetAxisRange(3,xmin,xmax);
598  if (xmax<0) return 0;
599  dz=xmax;
600  }
601  mother->GetAxisRange(1,xmin,xmax);
602  if (fRmin<0) {
603  if (xmin<0) return 0;
604  rmin = xmin;
605  }
606  if (fRmax<0) {
607  if (xmax<=0) return 0;
608  rmax = xmax;
609  }
610 
611  return (new TGeoTube(GetName(), rmin, rmax, dz));
612 }
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 /// print shape parameters
616 
618 {
619  printf("*** Shape %s: TGeoTube ***\n", GetName());
620  printf(" Rmin = %11.5f\n", fRmin);
621  printf(" Rmax = %11.5f\n", fRmax);
622  printf(" dz = %11.5f\n", fDz);
623  printf(" Bounding box:\n");
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 /// Creates a TBuffer3D describing *this* shape.
629 /// Coordinates are in local reference frame.
630 
632 {
634  Int_t nbPnts = 4*n;
635  Int_t nbSegs = 8*n;
636  Int_t nbPols = 4*n;
637  if (!HasRmin()) {
638  nbPnts = 2*(n+1);
639  nbSegs = 5*n;
640  nbPols = 3*n;
641  }
643  nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
644  if (buff)
645  {
646  SetPoints(buff->fPnts);
647  SetSegsAndPols(*buff);
648  }
649 
650  return buff;
651 }
652 
653 ////////////////////////////////////////////////////////////////////////////////
654 /// Fill TBuffer3D structure for segments and polygons.
655 
657 {
658  Int_t i, j,indx;
660  Int_t c = (((buffer.fColor) %8) -1) * 4;
661  if (c < 0) c = 0;
662 
663  if (HasRmin()) {
664  // circle segments:
665  // lower rmin circle: i=0, (0, n-1)
666  // lower rmax circle: i=1, (n, 2n-1)
667  // upper rmin circle: i=2, (2n, 3n-1)
668  // upper rmax circle: i=1, (3n, 4n-1)
669  for (i = 0; i < 4; i++) {
670  for (j = 0; j < n; j++) {
671  indx = 3*(i*n+j);
672  buffer.fSegs[indx ] = c;
673  buffer.fSegs[indx+1] = i*n+j;
674  buffer.fSegs[indx+2] = i*n+(j+1)%n;
675  }
676  }
677  // Z-parallel segments
678  // inner: i=4, (4n, 5n-1)
679  // outer: i=5, (5n, 6n-1)
680  for (i = 4; i < 6; i++) {
681  for (j = 0; j < n; j++) {
682  indx = 3*(i*n+j);
683  buffer.fSegs[indx ] = c+1;
684  buffer.fSegs[indx+1] = (i-4)*n+j;
685  buffer.fSegs[indx+2] = (i-2)*n+j;
686  }
687  }
688  // Radial segments
689  // lower: i=6, (6n, 7n-1)
690  // upper: i=7, (7n, 8n-1)
691  for (i = 6; i < 8; i++) {
692  for (j = 0; j < n; j++) {
693  indx = 3*(i*n+j);
694  buffer.fSegs[indx ] = c;
695  buffer.fSegs[indx+1] = 2*(i-6)*n+j;
696  buffer.fSegs[indx+2] = (2*(i-6)+1)*n+j;
697  }
698  }
699  // Polygons
700  i=0;
701  // Inner lateral (0, n-1)
702  for (j = 0; j < n; j++) {
703  indx = 6*(i*n+j);
704  buffer.fPols[indx ] = c;
705  buffer.fPols[indx+1] = 4;
706  buffer.fPols[indx+2] = j;
707  buffer.fPols[indx+3] = 4*n+(j+1)%n;
708  buffer.fPols[indx+4] = 2*n+j;
709  buffer.fPols[indx+5] = 4*n+j;
710  }
711  i=1;
712  // Outer lateral (n,2n-1)
713  for (j = 0; j < n; j++) {
714  indx = 6*(i*n+j);
715  buffer.fPols[indx ] = c+1;
716  buffer.fPols[indx+1] = 4;
717  buffer.fPols[indx+2] = n+j;
718  buffer.fPols[indx+3] = 5*n+j;
719  buffer.fPols[indx+4] = 3*n+j;
720  buffer.fPols[indx+5] = 5*n+(j+1)%n;
721  }
722  i=2;
723  // lower disc (2n, 3n-1)
724  for (j = 0; j < n; j++) {
725  indx = 6*(i*n+j);
726  buffer.fPols[indx ] = c;
727  buffer.fPols[indx+1] = 4;
728  buffer.fPols[indx+2] = j;
729  buffer.fPols[indx+3] = 6*n+j;
730  buffer.fPols[indx+4] = n+j;
731  buffer.fPols[indx+5] = 6*n+(j+1)%n;
732  }
733  i=3;
734  // upper disc (3n, 4n-1)
735  for (j = 0; j < n; j++) {
736  indx = 6*(i*n+j);
737  buffer.fPols[indx ] = c;
738  buffer.fPols[indx+1] = 4;
739  buffer.fPols[indx+2] = 2*n+j;
740  buffer.fPols[indx+3] = 7*n+(j+1)%n;
741  buffer.fPols[indx+4] = 3*n+j;
742  buffer.fPols[indx+5] = 7*n+j;
743  }
744  return;
745  }
746  // Rmin=0 tubes
747  // circle segments
748  // lower rmax circle: i=0, (0, n-1)
749  // upper rmax circle: i=1, (n, 2n-1)
750  for (i = 0; i < 2; i++) {
751  for (j = 0; j < n; j++) {
752  indx = 3*(i*n+j);
753  buffer.fSegs[indx ] = c;
754  buffer.fSegs[indx+1] = 2+i*n+j;
755  buffer.fSegs[indx+2] = 2+i*n+(j+1)%n;
756  }
757  }
758  // Z-parallel segments (2n,3n-1)
759  for (j = 0; j < n; j++) {
760  indx = 3*(2*n+j);
761  buffer.fSegs[indx ] = c+1;
762  buffer.fSegs[indx+1] = 2+j;
763  buffer.fSegs[indx+2] = 2+n+j;
764  }
765  // Radial segments
766  // Lower circle: i=3, (3n,4n-1)
767  // Upper circle: i=4, (4n,5n-1)
768  for (i = 3; i < 5; i++) {
769  for (j = 0; j < n; j++) {
770  indx = 3*(i*n+j);
771  buffer.fSegs[indx ] = c;
772  buffer.fSegs[indx+1] = i-3;
773  buffer.fSegs[indx+2] = 2+(i-3)*n+j;
774  }
775  }
776  // Polygons
777  // lateral (0,n-1)
778  for (j = 0; j < n; j++) {
779  indx = 6*j;
780  buffer.fPols[indx ] = c+1;
781  buffer.fPols[indx+1] = 4;
782  buffer.fPols[indx+2] = j;
783  buffer.fPols[indx+3] = 2*n+j;
784  buffer.fPols[indx+4] = n+j;
785  buffer.fPols[indx+5] = 2*n+(j+1)%n;
786  }
787  // bottom triangles (n,2n-1)
788  for (j = 0; j < n; j++) {
789  indx = 6*n + 5*j;
790  buffer.fPols[indx ] = c;
791  buffer.fPols[indx+1] = 3;
792  buffer.fPols[indx+2] = j;
793  buffer.fPols[indx+3] = 3*n+(j+1)%n;
794  buffer.fPols[indx+4] = 3*n+j;
795  }
796  // top triangles (2n,3n-1)
797  for (j = 0; j < n; j++) {
798  indx = 6*n + 5*n + 5*j;
799  buffer.fPols[indx ] = c;
800  buffer.fPols[indx+1] = 3;
801  buffer.fPols[indx+2] = n+j;
802  buffer.fPols[indx+3] = 4*n+j;
803  buffer.fPols[indx+4] = 4*n+(j+1)%n;
804  }
805 }
806 
807 ////////////////////////////////////////////////////////////////////////////////
808 /// computes the closest distance from given point to this shape, according
809 /// to option. The matching point on the shape is stored in spoint.
810 
811 Double_t TGeoTube::Safety(const Double_t *point, Bool_t in) const
812 {
813 #ifndef NEVER
814  Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
815  Double_t safe, safrmin, safrmax;
816  if (in) {
817  safe = fDz-TMath::Abs(point[2]); // positive if inside
818  if (fRmin>1E-10) {
819  safrmin = r-fRmin;
820  if (safrmin < safe) safe = safrmin;
821  }
822  safrmax = fRmax-r;
823  if (safrmax < safe) safe = safrmax;
824  } else {
825  safe = -fDz+TMath::Abs(point[2]);
826  if (fRmin>1E-10) {
827  safrmin = -r+fRmin;
828  if (safrmin > safe) safe = safrmin;
829  }
830  safrmax = -fRmax+r;
831  if (safrmax > safe) safe = safrmax;
832  }
833  return safe;
834 #else
835  Double_t saf[3];
836  Double_t rsq = point[0]*point[0]+point[1]*point[1];
837  Double_t r = TMath::Sqrt(rsq);
838  saf[0] = fDz-TMath::Abs(point[2]); // positive if inside
839  saf[1] = (fRmin>1E-10)?(r-fRmin):TGeoShape::Big();
840  saf[2] = fRmax-r;
841  if (in) return saf[TMath::LocMin(3,saf)];
842  for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
843  return saf[TMath::LocMax(3,saf)];
844 #endif
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// computes the closest distance from given point to this shape, according
849 /// to option. The matching point on the shape is stored in spoint.
850 
851 Double_t TGeoTube::SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
852 {
853  Double_t saf[3];
854  Double_t rsq = point[0]*point[0]+point[1]*point[1];
855  Double_t r = TMath::Sqrt(rsq);
856  switch (skipz) {
857  case 1: // skip lower Z plane
858  saf[0] = dz - point[2];
859  break;
860  case 2: // skip upper Z plane
861  saf[0] = dz + point[2];
862  break;
863  case 3: // skip both
864  saf[0] = TGeoShape::Big();
865  break;
866  default:
867  saf[0] = dz-TMath::Abs(point[2]);
868  }
869  saf[1] = (rmin>1E-10)?(r-rmin):TGeoShape::Big();
870  saf[2] = rmax-r;
871 // printf("saf0=%g saf1=%g saf2=%g in=%d skipz=%d\n", saf[0],saf[1],saf[2],in,skipz);
872  if (in) return saf[TMath::LocMin(3,saf)];
873  for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
874  return saf[TMath::LocMax(3,saf)];
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// Save a primitive as a C++ statement(s) on output stream "out".
879 
880 void TGeoTube::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
881 {
882  if (TObject::TestBit(kGeoSavePrimitive)) return;
883  out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
884  out << " rmin = " << fRmin << ";" << std::endl;
885  out << " rmax = " << fRmax << ";" << std::endl;
886  out << " dz = " << fDz << ";" << std::endl;
887  out << " TGeoShape *" << GetPointerName() << " = new TGeoTube(\"" << GetName() << "\",rmin,rmax,dz);" << std::endl;
889 }
890 
891 ////////////////////////////////////////////////////////////////////////////////
892 /// Set tube dimensions.
893 
895 {
896  fRmin = rmin;
897  fRmax = rmax;
898  fDz = dz;
899  if (fRmin>0 && fRmax>0 && fRmin>=fRmax)
900  Error("SetTubeDimensions", "In shape %s wrong rmin=%g rmax=%g", GetName(), rmin,rmax);
901 }
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 /// Set tube dimensions starting from a list.
905 
907 {
908  Double_t rmin = param[0];
909  Double_t rmax = param[1];
910  Double_t dz = param[2];
911  SetTubeDimensions(rmin, rmax, dz);
912 }
913 
914 ////////////////////////////////////////////////////////////////////////////////
915 /// Fills array with n random points located on the line segments of the shape mesh.
916 /// The output array must be provided with a length of minimum 3*npoints. Returns
917 /// true if operation is implemented.
918 
920 {
921  if (npoints > (npoints/2)*2) {
922  Error("GetPointsOnSegments","Npoints must be even number");
923  return kFALSE;
924  }
925  Int_t nc = 0;
926  if (HasRmin()) nc = (Int_t)TMath::Sqrt(0.5*npoints);
927  else nc = (Int_t)TMath::Sqrt(1.*npoints);
928  Double_t dphi = TMath::TwoPi()/nc;
929  Double_t phi = 0;
930  Int_t ntop = 0;
931  if (HasRmin()) ntop = npoints/2 - nc*(nc-1);
932  else ntop = npoints - nc*(nc-1);
933  Double_t dz = 2*fDz/(nc-1);
934  Double_t z = 0;
935  Int_t icrt = 0;
936  Int_t nphi = nc;
937  // loop z sections
938  for (Int_t i=0; i<nc; i++) {
939  if (i == (nc-1)) nphi = ntop;
940  z = -fDz + i*dz;
941  // loop points on circle sections
942  for (Int_t j=0; j<nphi; j++) {
943  phi = j*dphi;
944  if (HasRmin()) {
945  array[icrt++] = fRmin * TMath::Cos(phi);
946  array[icrt++] = fRmin * TMath::Sin(phi);
947  array[icrt++] = z;
948  }
949  array[icrt++] = fRmax * TMath::Cos(phi);
950  array[icrt++] = fRmax * TMath::Sin(phi);
951  array[icrt++] = z;
952  }
953  }
954  return kTRUE;
955 }
956 
957 ////////////////////////////////////////////////////////////////////////////////
958 /// create tube mesh points
959 
961 {
962  Double_t dz;
963  Int_t j, n;
964  n = gGeoManager->GetNsegments();
965  Double_t dphi = 360./n;
966  Double_t phi = 0;
967  dz = fDz;
968  Int_t indx = 0;
969  if (points) {
970  if (HasRmin()) {
971  // 4*n points
972  // (0,n-1) lower rmin circle
973  // (2n, 3n-1) upper rmin circle
974  for (j = 0; j < n; j++) {
975  phi = j*dphi*TMath::DegToRad();
976  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
977  indx++;
978  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
979  indx++;
980  points[indx+6*n] = dz;
981  points[indx] =-dz;
982  indx++;
983  }
984  // (n, 2n-1) lower rmax circle
985  // (3n, 4n-1) upper rmax circle
986  for (j = 0; j < n; j++) {
987  phi = j*dphi*TMath::DegToRad();
988  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
989  indx++;
990  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
991  indx++;
992  points[indx+6*n]= dz;
993  points[indx] =-dz;
994  indx++;
995  }
996  } else {
997  // centers of lower/upper circles (0,1)
998  points[indx++] = 0.;
999  points[indx++] = 0.;
1000  points[indx++] = -dz;
1001  points[indx++] = 0.;
1002  points[indx++] = 0.;
1003  points[indx++] = dz;
1004  // lower rmax circle (2, 2+n-1)
1005  // upper rmax circle (2+n, 2+2n-1)
1006  for (j = 0; j < n; j++) {
1007  phi = j*dphi*TMath::DegToRad();
1008  points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1009  indx++;
1010  points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1011  indx++;
1012  points[indx+3*n]= dz;
1013  points[indx] =-dz;
1014  indx++;
1015  }
1016  }
1017  }
1018 }
1019 
1020 ////////////////////////////////////////////////////////////////////////////////
1021 /// create tube mesh points
1022 
1024 {
1025  Double_t dz;
1026  Int_t j, n;
1027  n = gGeoManager->GetNsegments();
1028  Double_t dphi = 360./n;
1029  Double_t phi = 0;
1030  dz = fDz;
1031  Int_t indx = 0;
1032  if (points) {
1033  if (HasRmin()) {
1034  // 4*n points
1035  // (0,n-1) lower rmin circle
1036  // (2n, 3n-1) upper rmin circle
1037  for (j = 0; j < n; j++) {
1038  phi = j*dphi*TMath::DegToRad();
1039  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
1040  indx++;
1041  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
1042  indx++;
1043  points[indx+6*n] = dz;
1044  points[indx] =-dz;
1045  indx++;
1046  }
1047  // (n, 2n-1) lower rmax circle
1048  // (3n, 4n-1) upper rmax circle
1049  for (j = 0; j < n; j++) {
1050  phi = j*dphi*TMath::DegToRad();
1051  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
1052  indx++;
1053  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
1054  indx++;
1055  points[indx+6*n]= dz;
1056  points[indx] =-dz;
1057  indx++;
1058  }
1059  } else {
1060  // centers of lower/upper circles (0,1)
1061  points[indx++] = 0.;
1062  points[indx++] = 0.;
1063  points[indx++] = -dz;
1064  points[indx++] = 0.;
1065  points[indx++] = 0.;
1066  points[indx++] = dz;
1067  // lower rmax circle (2, 2+n-1)
1068  // upper rmax circle (2+n, 2+2n-1)
1069  for (j = 0; j < n; j++) {
1070  phi = j*dphi*TMath::DegToRad();
1071  points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1072  indx++;
1073  points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1074  indx++;
1075  points[indx+3*n]= dz;
1076  points[indx] =-dz;
1077  indx++;
1078  }
1079  }
1080  }
1081 }
1082 
1083 ////////////////////////////////////////////////////////////////////////////////
1084 /// Return number of vertices of the mesh representation
1085 
1087 {
1089  Int_t numPoints = n*4;
1090  if (!HasRmin()) numPoints = 2*(n+1);
1091  return numPoints;
1092 }
1093 
1094 ////////////////////////////////////////////////////////////////////////////////
1095 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
1096 
1097 void TGeoTube::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
1098 {
1100  nvert = n*4;
1101  nsegs = n*8;
1102  npols = n*4;
1103  if (!HasRmin()) {
1104  nvert = 2*(n+1);
1105  nsegs = 5*n;
1106  npols = 3*n;
1107  } else {
1108  nvert = n*4;
1109  nsegs = n*8;
1110  npols = n*4;
1111  }
1112 }
1113 
1114 ////////////////////////////////////////////////////////////////////////////////
1115 ////// fill size of this 3-D object
1116 //// TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
1117 //// if (!painter) return;
1118 //// Int_t n = gGeoManager->GetNsegments();
1119 //// Int_t numPoints = n*4;
1120 //// Int_t numSegs = n*8;
1121 //// Int_t numPolys = n*4;
1122 //// painter->AddSize3D(numPoints, numSegs, numPolys);
1123 
1125 {
1126 }
1127 
1128 ////////////////////////////////////////////////////////////////////////////////
1129 /// Fills a static 3D buffer and returns a reference.
1130 
1131 const TBuffer3D & TGeoTube::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
1132 {
1133  static TBuffer3DTube buffer;
1134  TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1135 
1136  if (reqSections & TBuffer3D::kShapeSpecific) {
1137  buffer.fRadiusInner = fRmin;
1138  buffer.fRadiusOuter = fRmax;
1139  buffer.fHalfLength = fDz;
1140  buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
1141  }
1142  if (reqSections & TBuffer3D::kRawSizes) {
1144  Int_t nbPnts = 4*n;
1145  Int_t nbSegs = 8*n;
1146  Int_t nbPols = 4*n;
1147  if (!HasRmin()) {
1148  nbPnts = 2*(n+1);
1149  nbSegs = 5*n;
1150  nbPols = 3*n;
1151  }
1152  if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
1153  buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1154  }
1155  }
1156  if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1157  SetPoints(buffer.fPnts);
1158  if (!buffer.fLocalFrame) {
1159  TransformPoints(buffer.fPnts, buffer.NbPnts());
1160  }
1161  SetSegsAndPols(buffer);
1162  buffer.SetSectionsValid(TBuffer3D::kRaw);
1163  }
1164 
1165  return buffer;
1166 }
1167 
1168 ////////////////////////////////////////////////////////////////////////////////
1169 /// Check the inside status for each of the points in the array.
1170 /// Input: Array of point coordinates + vector size
1171 /// Output: Array of Booleans for the inside of each point
1172 
1173 void TGeoTube::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
1174 {
1175  for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
1176 }
1177 
1178 ////////////////////////////////////////////////////////////////////////////////
1179 /// Compute the normal for an array o points so that norm.dot.dir is positive
1180 /// Input: Arrays of point coordinates and directions + vector size
1181 /// Output: Array of normal directions
1182 
1183 void TGeoTube::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
1184 {
1185  for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////////
1189 /// Compute distance from array of input points having directions specisied by dirs. Store output in dists
1190 
1191 void TGeoTube::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
1192 {
1193  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
1194 }
1195 
1196 ////////////////////////////////////////////////////////////////////////////////
1197 /// Compute distance from array of input points having directions specisied by dirs. Store output in dists
1198 
1199 void TGeoTube::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
1200 {
1201  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
1202 }
1203 
1204 ////////////////////////////////////////////////////////////////////////////////
1205 /// Compute safe distance from each of the points in the input array.
1206 /// Input: Array of point coordinates, array of statuses for these points, size of the arrays
1207 /// Output: Safety values
1208 
1209 void TGeoTube::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
1210 {
1211  for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
1212 }
1213 
1215 
1216 ////////////////////////////////////////////////////////////////////////////////
1217 /// Default constructor
1218 
1220  :TGeoTube(),
1221  fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1222 {
1223  SetShapeBit(TGeoShape::kGeoTubeSeg);
1224 }
1225 
1226 ////////////////////////////////////////////////////////////////////////////////
1227 /// Default constructor specifying minimum and maximum radius.
1228 /// The segment will be from phiStart to phiEnd expressed in degree.
1229 
1231  Double_t phiStart, Double_t phiEnd)
1232  :TGeoTube(rmin, rmax, dz),
1233  fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1234 {
1236  SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1237  ComputeBBox();
1238 }
1239 
1240 ////////////////////////////////////////////////////////////////////////////////
1241 /// Default constructor specifying minimum and maximum radius
1242 /// The segment will be from phiStart to phiEnd expressed in degree.
1243 
1245  Double_t phiStart, Double_t phiEnd)
1246  :TGeoTube(name, rmin, rmax, dz)
1247 {
1249  SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1250  ComputeBBox();
1251 }
1252 
1253 ////////////////////////////////////////////////////////////////////////////////
1254 /// Default constructor specifying minimum and maximum radius
1255 /// param[0] = Rmin
1256 /// param[1] = Rmax
1257 /// param[2] = dz
1258 /// param[3] = phi1
1259 /// param[4] = phi2
1260 
1262  :TGeoTube(0, 0, 0)
1263 {
1265  SetDimensions(param);
1266  ComputeBBox();
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////////////////
1270 /// destructor
1271 
1273 {
1274 }
1275 
1276 ////////////////////////////////////////////////////////////////////////////////
1277 /// Function called after streaming an object of this class.
1278 
1280 {
1281  InitTrigonometry();
1282 }
1283 
1284 ////////////////////////////////////////////////////////////////////////////////
1285 /// Init frequently used trigonometric values
1286 
1288 {
1289  Double_t phi1 = fPhi1*TMath::DegToRad();
1290  Double_t phi2 = fPhi2*TMath::DegToRad();
1291  fC1 = TMath::Cos(phi1);
1292  fS1 = TMath::Sin(phi1);
1293  fC2 = TMath::Cos(phi2);
1294  fS2 = TMath::Sin(phi2);
1295  Double_t fio = 0.5*(phi1+phi2);
1296  fCm = TMath::Cos(fio);
1297  fSm = TMath::Sin(fio);
1298  Double_t dfi = 0.5*(phi2-phi1);
1299  fCdfi = TMath::Cos(dfi);
1300 }
1301 
1302 ////////////////////////////////////////////////////////////////////////////////
1303 /// Computes capacity of the shape in [length^3]
1304 
1306 {
1308 }
1309 
1310 ////////////////////////////////////////////////////////////////////////////////
1311 /// Computes capacity of the shape in [length^3]
1312 
1314 {
1315  Double_t capacity = TMath::Abs(phiEnd-phiStart)*TMath::DegToRad()*(rmax*rmax-rmin*rmin)*dz;
1316  return capacity;
1317 }
1318 
1319 ////////////////////////////////////////////////////////////////////////////////
1320 /// compute bounding box of the tube segment
1321 
1323 {
1324  Double_t xc[4];
1325  Double_t yc[4];
1326  xc[0] = fRmax*fC1;
1327  yc[0] = fRmax*fS1;
1328  xc[1] = fRmax*fC2;
1329  yc[1] = fRmax*fS2;
1330  xc[2] = fRmin*fC1;
1331  yc[2] = fRmin*fS1;
1332  xc[3] = fRmin*fC2;
1333  yc[3] = fRmin*fS2;
1334 
1335  Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
1336  Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
1337  Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
1338  Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
1339 
1340  Double_t dp = fPhi2-fPhi1;
1341  if (dp<0) dp+=360;
1342  Double_t ddp = -fPhi1;
1343  if (ddp<0) ddp+= 360;
1344  if (ddp>360) ddp-=360;
1345  if (ddp<=dp) xmax = fRmax;
1346  ddp = 90-fPhi1;
1347  if (ddp<0) ddp+= 360;
1348  if (ddp>360) ddp-=360;
1349  if (ddp<=dp) ymax = fRmax;
1350  ddp = 180-fPhi1;
1351  if (ddp<0) ddp+= 360;
1352  if (ddp>360) ddp-=360;
1353  if (ddp<=dp) xmin = -fRmax;
1354  ddp = 270-fPhi1;
1355  if (ddp<0) ddp+= 360;
1356  if (ddp>360) ddp-=360;
1357  if (ddp<=dp) ymin = -fRmax;
1358  fOrigin[0] = (xmax+xmin)/2;
1359  fOrigin[1] = (ymax+ymin)/2;
1360  fOrigin[2] = 0;
1361  fDX = (xmax-xmin)/2;
1362  fDY = (ymax-ymin)/2;
1363  fDZ = fDz;
1364 }
1365 
1366 ////////////////////////////////////////////////////////////////////////////////
1367 /// Compute normal to closest surface from POINT.
1368 
1370 {
1371  Double_t saf[3];
1372  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1373  Double_t r = TMath::Sqrt(rsq);
1374  saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
1375  saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
1376  saf[2] = TMath::Abs(fRmax-r);
1377  Int_t i = TMath::LocMin(3,saf);
1378  if (((fPhi2-fPhi1)<360.) && TGeoShape::IsCloseToPhi(saf[i], point,fC1,fS1,fC2,fS2)) {
1379  TGeoShape::NormalPhi(point,dir,norm,fC1,fS1,fC2,fS2);
1380  return;
1381  }
1382  if (i==0) {
1383  norm[0] = norm[1] = 0.;
1384  norm[2] = TMath::Sign(1.,dir[2]);
1385  return;
1386  };
1387  norm[2] = 0;
1388  Double_t phi = TMath::ATan2(point[1], point[0]);
1389  norm[0] = TMath::Cos(phi);
1390  norm[1] = TMath::Sin(phi);
1391  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1392  norm[0] = -norm[0];
1393  norm[1] = -norm[1];
1394  }
1395 }
1396 
1397 ////////////////////////////////////////////////////////////////////////////////
1398 /// Compute normal to closest surface from POINT.
1399 
1401  Double_t rmin, Double_t rmax, Double_t /*dz*/,
1403 {
1404  Double_t saf[2];
1405  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1406  Double_t r = TMath::Sqrt(rsq);
1407  saf[0] = (rmin>1E-10)?TMath::Abs(r-rmin):TGeoShape::Big();
1408  saf[1] = TMath::Abs(rmax-r);
1409  Int_t i = TMath::LocMin(2,saf);
1410  if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
1411  TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
1412  return;
1413  }
1414  norm[2] = 0;
1415  Double_t phi = TMath::ATan2(point[1], point[0]);
1416  norm[0] = TMath::Cos(phi);
1417  norm[1] = TMath::Sin(phi);
1418  if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1419  norm[0] = -norm[0];
1420  norm[1] = -norm[1];
1421  }
1422 }
1423 
1424 ////////////////////////////////////////////////////////////////////////////////
1425 /// test if point is inside this tube segment
1426 /// first check if point is inside the tube
1427 
1429 {
1430  if (!TGeoTube::Contains(point)) return kFALSE;
1431  return IsInPhiRange(point, fPhi1, fPhi2);
1432 }
1433 
1434 ////////////////////////////////////////////////////////////////////////////////
1435 /// compute closest distance from point px,py to each corner
1436 
1438 {
1440  const Int_t numPoints = 4*n;
1441  return ShapeDistancetoPrimitive(numPoints, px, py);
1442 }
1443 
1444 ////////////////////////////////////////////////////////////////////////////////
1445 /// Compute distance from inside point to surface of the tube segment (static)
1446 /// Boundary safe algorithm.
1447 /// Do Z
1448 
1450  Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
1451 {
1452  Double_t stube = TGeoTube::DistFromInsideS(point,dir,rmin,rmax,dz);
1453  if (stube<=0) return 0.0;
1454  Double_t sfmin = TGeoShape::Big();
1455  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1456  Double_t r = TMath::Sqrt(rsq);
1457  Double_t cpsi=point[0]*cm+point[1]*sm;
1458  if (cpsi>r*cdfi+TGeoShape::Tolerance()) {
1459  sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
1460  return TMath::Min(stube,sfmin);
1461  }
1462  // Point on the phi boundary or outside
1463  // which one: phi1 or phi2
1464  Double_t ddotn, xi, yi;
1465  if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
1466  ddotn = s1*dir[0]-c1*dir[1];
1467  if (ddotn>=0) return 0.0;
1468  ddotn = -s2*dir[0]+c2*dir[1];
1469  if (ddotn<=0) return stube;
1470  sfmin = s2*point[0]-c2*point[1];
1471  if (sfmin<=0) return stube;
1472  sfmin /= ddotn;
1473  if (sfmin >= stube) return stube;
1474  xi = point[0]+sfmin*dir[0];
1475  yi = point[1]+sfmin*dir[1];
1476  if (yi*cm-xi*sm<0) return stube;
1477  return sfmin;
1478  }
1479  ddotn = -s2*dir[0]+c2*dir[1];
1480  if (ddotn>=0) return 0.0;
1481  ddotn = s1*dir[0]-c1*dir[1];
1482  if (ddotn<=0) return stube;
1483  sfmin = -s1*point[0]+c1*point[1];
1484  if (sfmin<=0) return stube;
1485  sfmin /= ddotn;
1486  if (sfmin >= stube) return stube;
1487  xi = point[0]+sfmin*dir[0];
1488  yi = point[1]+sfmin*dir[1];
1489  if (yi*cm-xi*sm>0) return stube;
1490  return sfmin;
1491 }
1492 
1493 ////////////////////////////////////////////////////////////////////////////////
1494 /// Compute distance from inside point to surface of the tube segment
1495 /// Boundary safe algorithm.
1496 
1497 Double_t TGeoTubeSeg::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
1498 {
1499  if (iact<3 && safe) {
1500  *safe = SafetyS(point, kTRUE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1501  if (iact==0) return TGeoShape::Big();
1502  if ((iact==1) && (*safe>step)) return TGeoShape::Big();
1503  }
1504  if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromInsideS(point,dir,fRmin,fRmax,fDz);
1505 
1506  // compute distance to surface
1508 }
1509 
1510 ////////////////////////////////////////////////////////////////////////////////
1511 /// Static method to compute distance to arbitrary tube segment from outside point
1512 /// Boundary safe algorithm.
1513 
1516  Double_t cm, Double_t sm, Double_t cdfi)
1517 {
1518  Double_t r2, cpsi;
1519  // check Z planes
1520  Double_t xi, yi, zi;
1521  zi = dz - TMath::Abs(point[2]);
1522  Double_t rmaxsq = rmax*rmax;
1523  Double_t rminsq = rmin*rmin;
1524  Double_t s = TGeoShape::Big();
1525  Double_t snxt=TGeoShape::Big();
1526  Bool_t in = kFALSE;
1527  Bool_t inz = (zi<0)?kFALSE:kTRUE;
1528  if (!inz) {
1529  if (point[2]*dir[2]>=0) return TGeoShape::Big();
1530  s = -zi/TMath::Abs(dir[2]);
1531  xi = point[0]+s*dir[0];
1532  yi = point[1]+s*dir[1];
1533  r2=xi*xi+yi*yi;
1534  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1535  cpsi=(xi*cm+yi*sm)/TMath::Sqrt(r2);
1536  if (cpsi>=cdfi) return s;
1537  }
1538  }
1539 
1540  // check outer cyl. surface
1541  Double_t rsq = point[0]*point[0]+point[1]*point[1];
1542  Double_t r = TMath::Sqrt(rsq);
1543  Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
1544  Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
1545  Double_t b,d;
1546  Bool_t inrmax = kFALSE;
1547  Bool_t inrmin = kFALSE;
1548  Bool_t inphi = kFALSE;
1549  if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
1550  if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
1551  cpsi=point[0]*cm+point[1]*sm;
1552  if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
1553  in = inz & inrmin & inrmax & inphi;
1554  // If inside, we are most likely on a boundary within machine precision.
1555  if (in) {
1556  Bool_t checkout = kFALSE;
1557  Double_t safphi = (cpsi-r*cdfi)*TMath::Sqrt(1.-cdfi*cdfi);
1558 // Double_t sch, cch;
1559  // check if on Z boundaries
1560  if (zi<rmax-r) {
1561  if (TGeoShape::IsSameWithinTolerance(rmin,0) || (zi<r-rmin)) {
1562  if (zi<safphi) {
1563  if (point[2]*dir[2]<0) return 0.0;
1564  return TGeoShape::Big();
1565  }
1566  }
1567  }
1568  if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
1569  // check if on Rmax boundary
1570  if (checkout && (rmax-r<safphi)) {
1571  if (rdotn>=0) return TGeoShape::Big();
1572  return 0.0;
1573  }
1574  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
1575  // check if on phi boundary
1576  if (TGeoShape::IsSameWithinTolerance(rmin,0) || (safphi<r-rmin)) {
1577  // We may cross again a phi of rmin boundary
1578  // check first if we are on phi1 or phi2
1579  Double_t un;
1580  if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
1581  un = dir[0]*s1-dir[1]*c1;
1582  if (un < 0) return 0.0;
1583  if (cdfi>=0) return TGeoShape::Big();
1584  un = -dir[0]*s2+dir[1]*c2;
1585  if (un<0) {
1586  s = -point[0]*s2+point[1]*c2;
1587  if (s>0) {
1588  s /= (-un);
1589  zi = point[2]+s*dir[2];
1590  if (TMath::Abs(zi)<=dz) {
1591  xi = point[0]+s*dir[0];
1592  yi = point[1]+s*dir[1];
1593  r2=xi*xi+yi*yi;
1594  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1595  if ((yi*cm-xi*sm)>0) return s;
1596  }
1597  }
1598  }
1599  }
1600  } else {
1601  un = -dir[0]*s2+dir[1]*c2;
1602  if (un < 0) return 0.0;
1603  if (cdfi>=0) return TGeoShape::Big();
1604  un = dir[0]*s1-dir[1]*c1;
1605  if (un<0) {
1606  s = point[0]*s1-point[1]*c1;
1607  if (s>0) {
1608  s /= (-un);
1609  zi = point[2]+s*dir[2];
1610  if (TMath::Abs(zi)<=dz) {
1611  xi = point[0]+s*dir[0];
1612  yi = point[1]+s*dir[1];
1613  r2=xi*xi+yi*yi;
1614  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1615  if ((yi*cm-xi*sm)<0) return s;
1616  }
1617  }
1618  }
1619  }
1620  }
1621  // We may also cross rmin, (+) solution
1622  if (rdotn>=0) return TGeoShape::Big();
1623  if (cdfi>=0) return TGeoShape::Big();
1624  DistToTube(rsq, nsq, rdotn, rmin, b, d);
1625  if (d>0) {
1626  s=-b+d;
1627  if (s>0) {
1628  zi=point[2]+s*dir[2];
1629  if (TMath::Abs(zi)<=dz) {
1630  xi=point[0]+s*dir[0];
1631  yi=point[1]+s*dir[1];
1632  if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
1633  }
1634  }
1635  }
1636  return TGeoShape::Big();
1637  }
1638  // we are on rmin boundary: we may cross again rmin or a phi facette
1639  if (rdotn>=0) return 0.0;
1640  DistToTube(rsq, nsq, rdotn, rmin, b, d);
1641  if (d>0) {
1642  s=-b+d;
1643  if (s>0) {
1644  zi=point[2]+s*dir[2];
1645  if (TMath::Abs(zi)<=dz) {
1646  // now check phi range
1647  xi=point[0]+s*dir[0];
1648  yi=point[1]+s*dir[1];
1649  r2=xi*xi+yi*yi;
1650  if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
1651  // now we really have to check any phi crossing
1652  Double_t un=-dir[0]*s1+dir[1]*c1;
1653  if (un > 0) {
1654  s=point[0]*s1-point[1]*c1;
1655  if (s>=0) {
1656  s /= un;
1657  zi=point[2]+s*dir[2];
1658  if (TMath::Abs(zi)<=dz) {
1659  xi=point[0]+s*dir[0];
1660  yi=point[1]+s*dir[1];
1661  r2=xi*xi+yi*yi;
1662  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1663  if ((yi*cm-xi*sm)<=0) {
1664  if (s<snxt) snxt=s;
1665  }
1666  }
1667  }
1668  }
1669  }
1670  un=dir[0]*s2-dir[1]*c2;
1671  if (un > 0) {
1672  s=(point[1]*c2-point[0]*s2)/un;
1673  if (s>=0 && s<snxt) {
1674  zi=point[2]+s*dir[2];
1675  if (TMath::Abs(zi)<=dz) {
1676  xi=point[0]+s*dir[0];
1677  yi=point[1]+s*dir[1];
1678  r2=xi*xi+yi*yi;
1679  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1680  if ((yi*cm-xi*sm)>=0) {
1681  return s;
1682  }
1683  }
1684  }
1685  }
1686  }
1687  return snxt;
1688  }
1689  }
1690  }
1691  return TGeoShape::Big();
1692  }
1693  // only r>rmax has to be considered
1694  if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
1695  if (rsq>=rmax*rmax) {
1696  if (rdotn>=0) return TGeoShape::Big();
1697  TGeoTube::DistToTube(rsq, nsq, rdotn, rmax, b, d);
1698  if (d>0) {
1699  s=-b-d;
1700  if (s>0) {
1701  zi=point[2]+s*dir[2];
1702  if (TMath::Abs(zi)<=dz) {
1703  xi=point[0]+s*dir[0];
1704  yi=point[1]+s*dir[1];
1705  cpsi = xi*cm+yi*sm;
1706  if (cpsi>=rmax*cdfi) return s;
1707  }
1708  }
1709  }
1710  }
1711  // check inner cylinder
1712  if (rmin>0) {
1713  TGeoTube::DistToTube(rsq, nsq, rdotn, rmin, b, d);
1714  if (d>0) {
1715  s=-b+d;
1716  if (s>0) {
1717  zi=point[2]+s*dir[2];
1718  if (TMath::Abs(zi)<=dz) {
1719  xi=point[0]+s*dir[0];
1720  yi=point[1]+s*dir[1];
1721  cpsi = xi*cm+yi*sm;
1722  if (cpsi>=rmin*cdfi) snxt=s;
1723  }
1724  }
1725  }
1726  }
1727  // check phi planes
1728  Double_t un=-dir[0]*s1+dir[1]*c1;
1729  if (un > 0) {
1730  s=point[0]*s1-point[1]*c1;
1731  if (s>=0) {
1732  s /= un;
1733  zi=point[2]+s*dir[2];
1734  if (TMath::Abs(zi)<=dz) {
1735  xi=point[0]+s*dir[0];
1736  yi=point[1]+s*dir[1];
1737  r2=xi*xi+yi*yi;
1738  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1739  if ((yi*cm-xi*sm)<=0) {
1740  if (s<snxt) snxt=s;
1741  }
1742  }
1743  }
1744  }
1745  }
1746  un=dir[0]*s2-dir[1]*c2;
1747  if (un > 0) {
1748  s=point[1]*c2-point[0]*s2;
1749  if (s>=0) {
1750  s /= un;
1751  zi=point[2]+s*dir[2];
1752  if (TMath::Abs(zi)<=dz) {
1753  xi=point[0]+s*dir[0];
1754  yi=point[1]+s*dir[1];
1755  r2=xi*xi+yi*yi;
1756  if ((rminsq<=r2) && (r2<=rmaxsq)) {
1757  if ((yi*cm-xi*sm)>=0) {
1758  if (s<snxt) snxt=s;
1759  }
1760  }
1761  }
1762  }
1763  }
1764  return snxt;
1765 }
1766 
1767 ////////////////////////////////////////////////////////////////////////////////
1768 /// compute distance from outside point to surface of the tube segment
1769 /// fist localize point w.r.t tube
1770 
1771 Double_t TGeoTubeSeg::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
1772 {
1773  if (iact<3 && safe) {
1774  *safe = SafetyS(point, kFALSE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1775  if (iact==0) return TGeoShape::Big();
1776  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
1777  }
1778 // Check if the bounding box is crossed within the requested distance
1779  Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
1780  if (sdist>=step) return TGeoShape::Big();
1781  if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromOutsideS(point,dir,fRmin,fRmax,fDz);
1782 
1783  // find distance to shape
1784  return TGeoTubeSeg::DistFromOutsideS(point, dir, fRmin, fRmax, fDz, fC1, fS1, fC2, fS2, fCm, fSm, fCdfi);
1785 }
1786 
1787 ////////////////////////////////////////////////////////////////////////////////
1788 ///--- Divide this tube segment shape belonging to volume "voldiv" into ndiv volumes
1789 /// called divname, from start position with the given step. Returns pointer
1790 /// to created division cell volume in case of Z divisions. For radialdivision
1791 /// creates all volumes with different shapes and returns pointer to volume that
1792 /// was divided. In case a wrong division axis is supplied, returns pointer to
1793 /// volume that was divided.
1794 
1795 TGeoVolume *TGeoTubeSeg::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
1796  Double_t start, Double_t step)
1797 {
1798  TGeoShape *shape; //--- shape to be created
1799  TGeoVolume *vol; //--- division volume to be created
1800  TGeoVolumeMulti *vmulti; //--- generic divided volume
1801  TGeoPatternFinder *finder; //--- finder to be attached
1802  TString opt = ""; //--- option to be attached
1803  Double_t dphi;
1804  Int_t id;
1805  Double_t end = start+ndiv*step;
1806  switch (iaxis) {
1807  case 1: //--- R division
1808  finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
1809  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1810  voldiv->SetFinder(finder);
1811  finder->SetDivIndex(voldiv->GetNdaughters());
1812  for (id=0; id<ndiv; id++) {
1813  shape = new TGeoTubeSeg(start+id*step, start+(id+1)*step, fDz, fPhi1, fPhi2);
1814  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1815  vmulti->AddVolume(vol);
1816  opt = "R";
1817  voldiv->AddNodeOffset(vol, id, 0, opt.Data());
1818  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1819  }
1820  return vmulti;
1821  case 2: //--- Phi division
1822  dphi = fPhi2-fPhi1;
1823  if (dphi<0) dphi+=360.;
1824  if (step<=0) {step=dphi/ndiv; start=fPhi1; end=fPhi2;}
1825  finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
1826  voldiv->SetFinder(finder);
1827  finder->SetDivIndex(voldiv->GetNdaughters());
1828  shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
1829  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1830  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1831  vmulti->AddVolume(vol);
1832  opt = "Phi";
1833  for (id=0; id<ndiv; id++) {
1834  voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
1835  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1836  }
1837  return vmulti;
1838  case 3: //--- Z division
1839  finder = new TGeoPatternZ(voldiv, ndiv, start, end);
1840  voldiv->SetFinder(finder);
1841  finder->SetDivIndex(voldiv->GetNdaughters());
1842  shape = new TGeoTubeSeg(fRmin, fRmax, step/2, fPhi1, fPhi2);
1843  vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1844  vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1845  vmulti->AddVolume(vol);
1846  opt = "Z";
1847  for (id=0; id<ndiv; id++) {
1848  voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
1849  ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1850  }
1851  return vmulti;
1852  default:
1853  Error("Divide", "In shape %s wrong axis type for division", GetName());
1854  return 0;
1855  }
1856 }
1857 
1858 ////////////////////////////////////////////////////////////////////////////////
1859 /// Get range of shape for a given axis.
1860 
1862 {
1863  xlo = 0;
1864  xhi = 0;
1865  Double_t dx = 0;
1866  switch (iaxis) {
1867  case 1:
1868  xlo = fRmin;
1869  xhi = fRmax;
1870  dx = xhi-xlo;
1871  return dx;
1872  case 2:
1873  xlo = fPhi1;
1874  xhi = fPhi2;
1875  dx = xhi-xlo;
1876  return dx;
1877  case 3:
1878  xlo = -fDz;
1879  xhi = fDz;
1880  dx = xhi-xlo;
1881  return dx;
1882  }
1883  return dx;
1884 }
1885 
1886 ////////////////////////////////////////////////////////////////////////////////
1887 ///--- Fill vector param[4] with the bounding cylinder parameters. The order
1888 /// is the following : Rmin, Rmax, Phi1, Phi2
1889 
1891 {
1892  param[0] = fRmin;
1893  param[0] *= param[0];
1894  param[1] = fRmax;
1895  param[1] *= param[1];
1896  param[2] = fPhi1;
1897  param[3] = fPhi2;
1898 }
1899 
1900 ////////////////////////////////////////////////////////////////////////////////
1901 /// in case shape has some negative parameters, these has to be computed
1902 /// in order to fit the mother
1903 
1905 {
1906  if (!TestShapeBit(kGeoRunTimeShape)) return 0;
1907  if (!mother->TestShapeBit(kGeoTube)) {
1908  Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
1909  return 0;
1910  }
1911  Double_t rmin, rmax, dz;
1912  rmin = fRmin;
1913  rmax = fRmax;
1914  dz = fDz;
1915  if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
1916  if (fRmin<0)
1917  rmin = ((TGeoTube*)mother)->GetRmin();
1918  if ((fRmax<0) || (fRmax<=fRmin))
1919  rmax = ((TGeoTube*)mother)->GetRmax();
1920 
1921  return (new TGeoTubeSeg(GetName(),rmin, rmax, dz, fPhi1, fPhi2));
1922 }
1923 
1924 ////////////////////////////////////////////////////////////////////////////////
1925 /// print shape parameters
1926 
1928 {
1929  printf("*** Shape %s: TGeoTubeSeg ***\n", GetName());
1930  printf(" Rmin = %11.5f\n", fRmin);
1931  printf(" Rmax = %11.5f\n", fRmax);
1932  printf(" dz = %11.5f\n", fDz);
1933  printf(" phi1 = %11.5f\n", fPhi1);
1934  printf(" phi2 = %11.5f\n", fPhi2);
1935  printf(" Bounding box:\n");
1937 }
1938 
1939 ////////////////////////////////////////////////////////////////////////////////
1940 /// Creates a TBuffer3D describing *this* shape.
1941 /// Coordinates are in local reference frame.
1942 
1944 {
1946  Int_t nbPnts = 4*n;
1947  Int_t nbSegs = 2*nbPnts;
1948  Int_t nbPols = nbPnts-2;
1949 
1951  nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
1952  if (buff)
1953  {
1954  SetPoints(buff->fPnts);
1955  SetSegsAndPols(*buff);
1956  }
1957 
1958  return buff;
1959 }
1960 
1961 ////////////////////////////////////////////////////////////////////////////////
1962 /// Fill TBuffer3D structure for segments and polygons.
1963 
1965 {
1966  Int_t i, j;
1968  Int_t c = GetBasicColor();
1969 
1970  memset(buff.fSegs, 0, buff.NbSegs()*3*sizeof(Int_t));
1971  for (i = 0; i < 4; i++) {
1972  for (j = 1; j < n; j++) {
1973  buff.fSegs[(i*n+j-1)*3 ] = c;
1974  buff.fSegs[(i*n+j-1)*3+1] = i*n+j-1;
1975  buff.fSegs[(i*n+j-1)*3+2] = i*n+j;
1976  }
1977  }
1978  for (i = 4; i < 6; i++) {
1979  for (j = 0; j < n; j++) {
1980  buff.fSegs[(i*n+j)*3 ] = c+1;
1981  buff.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
1982  buff.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
1983  }
1984  }
1985  for (i = 6; i < 8; i++) {
1986  for (j = 0; j < n; j++) {
1987  buff.fSegs[(i*n+j)*3 ] = c;
1988  buff.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
1989  buff.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
1990  }
1991  }
1992 
1993  Int_t indx = 0;
1994  memset(buff.fPols, 0, buff.NbPols()*6*sizeof(Int_t));
1995  i = 0;
1996  for (j = 0; j < n-1; j++) {
1997  buff.fPols[indx++] = c;
1998  buff.fPols[indx++] = 4;
1999  buff.fPols[indx++] = (4+i)*n+j+1;
2000  buff.fPols[indx++] = (2+i)*n+j;
2001  buff.fPols[indx++] = (4+i)*n+j;
2002  buff.fPols[indx++] = i*n+j;
2003  }
2004  i = 1;
2005  for (j = 0; j < n-1; j++) {
2006  buff.fPols[indx++] = c;
2007  buff.fPols[indx++] = 4;
2008  buff.fPols[indx++] = i*n+j;
2009  buff.fPols[indx++] = (4+i)*n+j;
2010  buff.fPols[indx++] = (2+i)*n+j;
2011  buff.fPols[indx++] = (4+i)*n+j+1;
2012  }
2013  i = 2;
2014  for (j = 0; j < n-1; j++) {
2015  buff.fPols[indx++] = c+i;
2016  buff.fPols[indx++] = 4;
2017  buff.fPols[indx++] = (i-2)*2*n+j;
2018  buff.fPols[indx++] = (4+i)*n+j;
2019  buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2020  buff.fPols[indx++] = (4+i)*n+j+1;
2021  }
2022  i = 3;
2023  for (j = 0; j < n-1; j++) {
2024  buff.fPols[indx++] = c+i;
2025  buff.fPols[indx++] = 4;
2026  buff.fPols[indx++] = (4+i)*n+j+1;
2027  buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2028  buff.fPols[indx++] = (4+i)*n+j;
2029  buff.fPols[indx++] = (i-2)*2*n+j;
2030  }
2031  buff.fPols[indx++] = c+2;
2032  buff.fPols[indx++] = 4;
2033  buff.fPols[indx++] = 6*n;
2034  buff.fPols[indx++] = 4*n;
2035  buff.fPols[indx++] = 7*n;
2036  buff.fPols[indx++] = 5*n;
2037  buff.fPols[indx++] = c+2;
2038  buff.fPols[indx++] = 4;
2039  buff.fPols[indx++] = 6*n-1;
2040  buff.fPols[indx++] = 8*n-1;
2041  buff.fPols[indx++] = 5*n-1;
2042  buff.fPols[indx++] = 7*n-1;
2043 }
2044 
2045 ////////////////////////////////////////////////////////////////////////////////
2046 /// computes the closest distance from given point InitTrigonometry();to this shape, according
2047 /// to option. The matching point on the shape is stored in spoint.
2048 
2050 {
2051  Double_t safe = TGeoShape::Big();
2052  Double_t saf[3];
2053  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2054  Double_t r = TMath::Sqrt(rsq);
2055  if (in) {
2056  saf[0] = fDz-TMath::Abs(point[2]);
2057  saf[1] = r-fRmin;
2058  saf[2] = fRmax-r;
2059  safe = saf[TMath::LocMin(3,saf)];
2060  if ((fPhi2-fPhi1)>=360.) return safe;
2061  Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2062  return TMath::Min(safe, safphi);
2063  }
2064  // Point expected to be outside
2065  Bool_t inphi = kFALSE;
2066  Double_t cpsi=point[0]*fCm+point[1]*fSm;
2067  saf[0] = TMath::Abs(point[2])-fDz;
2068  if (cpsi>r*fCdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2069  if (inphi) {
2070  saf[1] = fRmin-r;
2071  saf[2] = r-fRmax;
2072  safe = saf[TMath::LocMax(3,saf)];
2073  safe = TMath::Max(0., safe);
2074  return safe;
2075  }
2076  // Point outside the phi range
2077  // Compute projected radius of the (r,phi) position vector onto
2078  // phi1 and phi2 edges and take the maximum for chosing the side.
2079  Double_t rproj = TMath::Max(point[0]*fC1+point[1]*fS1, point[0]*fC2+point[1]*fS2);
2080  saf[1] = fRmin-rproj;
2081  saf[2] = rproj-fRmax;
2082  safe = TMath::Max(saf[1], saf[2]);
2083  if ((fPhi2-fPhi1)>=360.) return TMath::Max(safe,saf[0]);
2084  if (safe>0) {
2085  // rproj not within (rmin,rmax) - > no need to calculate safphi
2086  safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2087  return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2088  }
2089  Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2090  return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2091 }
2092 
2093 ////////////////////////////////////////////////////////////////////////////////
2094 /// Static method to compute the closest distance from given point to this shape.
2095 
2097  Double_t phi1d, Double_t phi2d, Int_t skipz)
2098 {
2099  Double_t safe = TGeoShape::Big();
2100  Double_t saf[3];
2101  Double_t rsq = point[0]*point[0]+point[1]*point[1];
2102  Double_t r = TMath::Sqrt(rsq);
2103 
2104  switch (skipz) {
2105  case 1: // skip lower Z plane
2106  saf[0] = dz - point[2];
2107  break;
2108  case 2: // skip upper Z plane
2109  saf[0] = dz + point[2];
2110  break;
2111  case 3: // skip both
2112  saf[0] = TGeoShape::Big();
2113  break;
2114  default:
2115  saf[0] = dz-TMath::Abs(point[2]);
2116  }
2117 
2118  if (in) {
2119  saf[1] = r-rmin;
2120  saf[2] = rmax-r;
2121  safe = saf[TMath::LocMin(3,saf)];
2122  if ((phi2d-phi1d)>=360.) return safe;
2123  Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2124  return TMath::Min(safe, safphi);
2125  }
2126  // Point expected to be outside
2127  saf[0] = -saf[0];
2128  Bool_t inphi = kFALSE;
2129  Double_t phi1 = phi1d*TMath::DegToRad();
2130  Double_t phi2 = phi2d*TMath::DegToRad();
2131 
2132  Double_t fio = 0.5*(phi1+phi2);
2133  Double_t cm = TMath::Cos(fio);
2134  Double_t sm = TMath::Sin(fio);
2135  Double_t cpsi=point[0]*cm+point[1]*sm;
2136  Double_t dfi = 0.5*(phi2-phi1);
2137  Double_t cdfi = TMath::Cos(dfi);
2138  if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2139  if (inphi) {
2140  saf[1] = rmin-r;
2141  saf[2] = r-rmax;
2142  safe = saf[TMath::LocMax(3,saf)];
2143  safe = TMath::Max(0., safe);
2144  return safe;
2145  }
2146  // Point outside the phi range
2147  // Compute projected radius of the (r,phi) position vector onto
2148  // phi1 and phi2 edges and take the maximum for chosing the side.
2149  Double_t c1 = TMath::Cos(phi1);
2150  Double_t s1 = TMath::Sin(phi1);
2151  Double_t c2 = TMath::Cos(phi2);
2152  Double_t s2 = TMath::Sin(phi2);
2153 
2154  Double_t rproj = TMath::Max(point[0]*c1+point[1]*s1, point[0]*c2+point[1]*s2);
2155  saf[1] = rmin-rproj;
2156  saf[2] = rproj-rmax;
2157  safe = TMath::Max(saf[1], saf[2]);
2158  if ((phi2d-phi1d)>=360.) return TMath::Max(safe,saf[0]);
2159  if (safe>0) {
2160  // rproj not within (rmin,rmax) - > no need to calculate safphi
2161  safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2162  return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2163  }
2164  Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2165  return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2166 }
2167 
2168 ////////////////////////////////////////////////////////////////////////////////
2169 /// Save a primitive as a C++ statement(s) on output stream "out".
2170 
2171 void TGeoTubeSeg::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2172 {
2173  if (TObject::TestBit(kGeoSavePrimitive)) return;
2174  out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2175  out << " rmin = " << fRmin << ";" << std::endl;
2176  out << " rmax = " << fRmax << ";" << std::endl;
2177  out << " dz = " << fDz << ";" << std::endl;
2178  out << " phi1 = " << fPhi1 << ";" << std::endl;
2179  out << " phi2 = " << fPhi2 << ";" << std::endl;
2180  out << " TGeoShape *" << GetPointerName() << " = new TGeoTubeSeg(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2);" << std::endl;
2182 }
2183 
2184 ////////////////////////////////////////////////////////////////////////////////
2185 /// Set dimensions of the tube segment.
2186 /// The segment will be from phiStart to phiEnd expressed in degree.
2187 
2189  Double_t phiStart, Double_t phiEnd)
2190 {
2191  fRmin = rmin;
2192  fRmax = rmax;
2193  fDz = dz;
2194  fPhi1 = phiStart;
2195  if (fPhi1 < 0) fPhi1 += 360.;
2196  fPhi2 = phiEnd;
2197  while (fPhi2<=fPhi1) fPhi2+=360.;
2198  if (TGeoShape::IsSameWithinTolerance(fPhi1,fPhi2)) Fatal("SetTubsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
2199  InitTrigonometry();
2200 }
2201 
2202 ////////////////////////////////////////////////////////////////////////////////
2203 /// Set dimensions of the tube segment starting from a list.
2204 
2206 {
2207  Double_t rmin = param[0];
2208  Double_t rmax = param[1];
2209  Double_t dz = param[2];
2210  Double_t phi1 = param[3];
2211  Double_t phi2 = param[4];
2212  SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
2213 }
2214 
2215 ////////////////////////////////////////////////////////////////////////////////
2216 /// Fills array with n random points located on the line segments of the shape mesh.
2217 /// The output array must be provided with a length of minimum 3*npoints. Returns
2218 /// true if operation is implemented.
2219 
2221 {
2222  if (npoints > (npoints/2)*2) {
2223  Error("GetPointsOnSegments","Npoints must be even number");
2224  return kFALSE;
2225  }
2226  Int_t nc = (Int_t)TMath::Sqrt(0.5*npoints);
2227  Double_t dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nc-1);
2228  Double_t phi = 0;
2229  Double_t phi1 = fPhi1 * TMath::DegToRad();
2230  Int_t ntop = npoints/2 - nc*(nc-1);
2231  Double_t dz = 2*fDz/(nc-1);
2232  Double_t z = 0;
2233  Int_t icrt = 0;
2234  Int_t nphi = nc;
2235  // loop z sections
2236  for (Int_t i=0; i<nc; i++) {
2237  if (i == (nc-1)) {
2238  nphi = ntop;
2239  dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nphi-1);
2240  }
2241  z = -fDz + i*dz;
2242  // loop points on circle sections
2243  for (Int_t j=0; j<nphi; j++) {
2244  phi = phi1 + j*dphi;
2245  array[icrt++] = fRmin * TMath::Cos(phi);
2246  array[icrt++] = fRmin * TMath::Sin(phi);
2247  array[icrt++] = z;
2248  array[icrt++] = fRmax * TMath::Cos(phi);
2249  array[icrt++] = fRmax * TMath::Sin(phi);
2250  array[icrt++] = z;
2251  }
2252  }
2253  return kTRUE;
2254 }
2255 
2256 ////////////////////////////////////////////////////////////////////////////////
2257 /// Create tube segment mesh points.
2258 
2260 {
2261  Double_t dz;
2262  Int_t j, n;
2263  Double_t phi, phi1, phi2, dphi;
2264  phi1 = fPhi1;
2265  phi2 = fPhi2;
2266  if (phi2<phi1) phi2+=360.;
2267  n = gGeoManager->GetNsegments()+1;
2268 
2269  dphi = (phi2-phi1)/(n-1);
2270  dz = fDz;
2271 
2272  if (points) {
2273  Int_t indx = 0;
2274 
2275  for (j = 0; j < n; j++) {
2276  phi = (phi1+j*dphi)*TMath::DegToRad();
2277  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2278  indx++;
2279  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2280  indx++;
2281  points[indx+6*n] = dz;
2282  points[indx] =-dz;
2283  indx++;
2284  }
2285  for (j = 0; j < n; j++) {
2286  phi = (phi1+j*dphi)*TMath::DegToRad();
2287  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2288  indx++;
2289  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2290  indx++;
2291  points[indx+6*n]= dz;
2292  points[indx] =-dz;
2293  indx++;
2294  }
2295  }
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// Create tube segment mesh points.
2300 
2302 {
2303  Double_t dz;
2304  Int_t j, n;
2305  Double_t phi, phi1, phi2, dphi;
2306  phi1 = fPhi1;
2307  phi2 = fPhi2;
2308  if (phi2<phi1) phi2+=360.;
2309  n = gGeoManager->GetNsegments()+1;
2310 
2311  dphi = (phi2-phi1)/(n-1);
2312  dz = fDz;
2313 
2314  if (points) {
2315  Int_t indx = 0;
2316 
2317  for (j = 0; j < n; j++) {
2318  phi = (phi1+j*dphi)*TMath::DegToRad();
2319  points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2320  indx++;
2321  points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2322  indx++;
2323  points[indx+6*n] = dz;
2324  points[indx] =-dz;
2325  indx++;
2326  }
2327  for (j = 0; j < n; j++) {
2328  phi = (phi1+j*dphi)*TMath::DegToRad();
2329  points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2330  indx++;
2331  points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2332  indx++;
2333  points[indx+6*n]= dz;
2334  points[indx] =-dz;
2335  indx++;
2336  }
2337  }
2338 }
2339 
2340 ////////////////////////////////////////////////////////////////////////////////
2341 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
2342 
2343 void TGeoTubeSeg::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
2344 {
2346  nvert = n*4;
2347  nsegs = n*8;
2348  npols = n*4 - 2;
2349 }
2350 
2351 ////////////////////////////////////////////////////////////////////////////////
2352 /// Return number of vertices of the mesh representation
2353 
2355 {
2357  Int_t numPoints = n*4;
2358  return numPoints;
2359 }
2360 
2361 ////////////////////////////////////////////////////////////////////////////////
2362 ////// fill size of this 3-D object
2363 //// TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
2364 //// if (!painter) return;
2365 ////
2366 //// Int_t n = gGeoManager->GetNsegments()+1;
2367 //// Int_t numPoints = n*4;
2368 //// Int_t numSegs = n*8;
2369 //// Int_t numPolys = n*4-2;
2370 ////
2371 //// painter->AddSize3D(numPoints, numSegs, numPolys);
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 specisied 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 specisied 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 
2463 TGeoCtub::TGeoCtub()
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;
2774  Double_t s = TGeoShape::Big();
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];
2922  Double_t sr=TGeoShape::Big();
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 specisied 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 specisied 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 }
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:2380
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:157
Double_t fHighPlaneNorm[3]
Definition: TBuffer3D.h:226
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:1428
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:1199
Double_t fRadiusInner
Definition: TBuffer3D.h:176
Double_t fCm
sin(0.5*(phi1+phi2))
Definition: TGeoTube.h:120
Double_t fPhi2
Definition: TGeoTube.h:113
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:2354
float xmin
Definition: THbookFile.cxx:93
Double_t fPhi1
Definition: TGeoTube.h:112
virtual void SetPoints(Double_t *points) const
Create tube segment mesh points.
Definition: TGeoTube.cxx:2259
Int_t GetNsegments() const
Get number of segments approximating circles.
Long64_t LocMax(Long64_t n, const T *a)
Definition: TMath.h:724
T1 Sign(T1 a, T2 b)
Definition: TMathBase.h:155
void SetFinder(TGeoPatternFinder *finder)
Definition: TGeoVolume.h:247
virtual void ComputeBBox()
compute bounding box of the tube
Definition: TGeoTube.cxx:194
void InitTrigonometry()
cos(0.5*(phi1-phi2))
Definition: TGeoTube.cxx:1287
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
float Float_t
Definition: RtypesCore.h:53
Double_t fS1
Definition: TGeoTube.h:115
void AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset=0, Option_t *option="")
Add a division node to the list of nodes.
Definition: TGeoVolume.cxx:987
const char Option_t
Definition: RtypesCore.h:62
Tube segment description class - see TBuffer3DTypes for producer classes.
Definition: TBuffer3D.h:185
virtual void SetPoints(Double_t *points) const
Create mesh points for the cut tube.
Definition: TGeoTube.cxx:3089
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:1369
TCanvas * c1
Definition: legend1.C:2
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Compute normal to closest surface from POINT.
Definition: TGeoTube.cxx:203
float ymin
Definition: THbookFile.cxx:93
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:919
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
Int_t GetBasicColor() const
Get the basic color (0-7).
Definition: TGeoShape.cxx:671
virtual void Sizeof3D() const
Definition: TGeoTube.cxx:2373
Double_t DegToRad()
Definition: TMath.h:50
virtual void ComputeBBox()
compute bounding box of the tube segment
Definition: TGeoTube.cxx:1322
Double_t fC2
sin(phi2)
Definition: TGeoTube.h:118
virtual Bool_t Contains(const Double_t *point) const
test if point is inside this tube
Definition: TGeoTube.cxx:246
virtual void ComputeBBox()
compute minimum bounding box of the ctub
Definition: TGeoTube.cxx:2535
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:1131
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
Double_t fOrigin[3]
Definition: TGeoBBox.h:36
Double_t RadToDeg()
Definition: TMath.h:49
Basic string class.
Definition: TString.h:137
UInt_t NbSegs() const
Definition: TBuffer3D.h:83
Cut tube segment description class - see TBuffer3DTypes for producer classes.
Definition: TBuffer3D.h:212
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
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:463
virtual void GetBoundingCylinder(Double_t *param) const
— Fill vector param[4] with the bounding cylinder parameters.
Definition: TGeoTube.cxx:1890
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:1400
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:3263
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
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:386
TLatex * t1
Definition: textangle.C:20
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:2188
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Int_t GetNdaughters() const
Definition: TGeoVolume.h:362
static Bool_t IsSameWithinTolerance(Double_t a, Double_t b)
Check if two numbers differ with less than a tolerance.
Definition: TGeoShape.cxx:325
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
TObjArray * GetNodes()
Definition: TGeoVolume.h:183
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
compute closest distance from point px,py to each corner
Definition: TGeoTube.cxx:1437
static Double_t Tolerance()
Definition: TGeoShape.h:101
const char * Data() const
Definition: TString.h:349
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:946
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoTube.cxx:2171
Double_t fDZ
Definition: TGeoBBox.h:35
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
compute closest distance from point px,py to each corner
Definition: TGeoTube.cxx:257
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
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Fills a static 3D buffer and returns a reference.
Definition: TGeoTube.cxx:3191
void AddVolume(TGeoVolume *vol)
Add a volume with valid shape to the list of volumes.
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:2987
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
Double_t * fPnts
Definition: TBuffer3D.h:114
virtual void SetSegsAndPols(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons.
Definition: TGeoTube.cxx:656
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
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:454
XFontStruct * id
Definition: TGX11.cxx:108
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Double_t TwoPi()
Definition: TMath.h:45
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:617
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:1209
Double_t fDz
Definition: TGeoTube.h:34
UInt_t NbPols() const
Definition: TBuffer3D.h:84
virtual void SetDimensions(Double_t *param)
Set tube dimensions starting from a list.
Definition: TGeoTube.cxx:906
char * out
Definition: TBase64.cxx:29
void SetSectionsValid(UInt_t mask)
Definition: TBuffer3D.h:67
Int_t * fPols
Definition: TBuffer3D.h:116
Bool_t fLocalFrame
Definition: TBuffer3D.h:92
point * points
Definition: X3DBuffer.c:20
Double_t fRadiusOuter
Definition: TBuffer3D.h:177
void TransformPoints(Double_t *points, UInt_t NbPoints) const
Tranform a set of points (LocalToMaster)
Definition: TGeoShape.cxx:550
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:1514
Double_t fHalfLength
Definition: TBuffer3D.h:178
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:3255
Double_t fC1
sin(phi1)
Definition: TGeoTube.h:116
float ymax
Definition: THbookFile.cxx:93
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 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
Double_t fNhigh[3]
Definition: TGeoTube.h:204
ROOT::R::TRInterface & r
Definition: Object.C:4
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:271
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:2446
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
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:811
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TGeoTube.cxx:880
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
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:404
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:444
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
virtual void SetDimensions(Double_t *param)
Set dimensions of the cut tube starting from a list.
Definition: TGeoTube.cxx:3069
Double_t E()
Definition: TMath.h:54
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:357
virtual void InspectShape() const
print shape parameters
Definition: TGeoTube.cxx:1927
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:282
Generic 3D primitive description class.
Definition: TBuffer3D.h:19
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:230
float xmax
Definition: THbookFile.cxx:93
Double_t fCdfi
cos(0.5*(phi1+phi2))
Definition: TGeoTube.h:121
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:466
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
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
void SetDivIndex(Int_t index)
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:1097
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:1183
virtual const char * GetName() const
Get the shape name.
Definition: TGeoShape.cxx:247
Double_t Cos(Double_t)
Definition: TMath.h:424
Double_t Pi()
Definition: TMath.h:44
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:851
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
virtual void Sizeof3D() const
Definition: TGeoTube.cxx:1124
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:420
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:268
virtual void InspectShape() const
Prints shape parameters.
Definition: TGeoBBox.cxx:749
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:1086
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:1449
virtual TBuffer3D * MakeBuffer3D() const
Creates a TBuffer3D describing this shape.
Definition: TGeoTube.cxx:631
R__EXTERN TGeoManager * gGeoManager
Definition: TGeoManager.h:556
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:1904
double Double_t
Definition: RtypesCore.h:55
Double_t fLowPlaneNorm[3]
Definition: TBuffer3D.h:225
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:989
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
Double_t fPhiMax
Definition: TBuffer3D.h:205
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
Int_t fColor
Definition: TBuffer3D.h:90
Double_t fS2
cos(phi1)
Definition: TGeoTube.h:117
Int_t ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
Returns distance to shape primitive mesh.
Definition: TGeoShape.cxx:258
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:2220
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:2049
virtual void AfterStreamer()
Function called after streaming an object of this class.
Definition: TGeoTube.cxx:1279
Double_t fSm
cos(phi2)
Definition: TGeoTube.h:119
Bool_t HasRmin() const
Definition: TGeoTube.h:80
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:2096
const char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoShape.cxx:697
static Double_t Big()
Definition: TGeoShape.h:98
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 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:1497
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:588
Double_t fDY
Definition: TGeoBBox.h:34
#define name(a, b)
Definition: linkTestLib0.cpp:5
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
virtual TBuffer3D * MakeBuffer3D() const
Creates a TBuffer3D describing this shape.
Definition: TGeoTube.cxx:1943
ClassImp(TGeoTube) TGeoTube
Default constructor.
Definition: TGeoTube.cxx:107
void SetShapeBit(UInt_t f, Bool_t set)
Equivalent of TObject::SetBit.
Definition: TGeoShape.cxx:522
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:545
virtual Int_t GetNmeshVertices() const
Return number of vertices of the mesh representation.
Definition: TGeoTube.cxx:3181
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:1795
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:1771
Int_t * fSegs
Definition: TBuffer3D.h:115
Double_t fRmin
Definition: TGeoTube.h:32
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
Double_t fPhiMin
Definition: TBuffer3D.h:204
virtual const char * GetAxisName(Int_t iaxis) const
Returns name of axis IAXIS.
Definition: TGeoTube.cxx:528
virtual ~TGeoCtub()
destructor
Definition: TGeoTube.cxx:2519
Bool_t TestShapeBit(UInt_t f) const
Definition: TGeoShape.h:172
UInt_t NbPnts() const
Definition: TBuffer3D.h:82
virtual void SetSegsAndPols(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons.
Definition: TGeoTube.cxx:1964
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:1173
TGeoMedium * GetMedium() const
Definition: TGeoVolume.h:189
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
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:332
virtual void GetBoundingCylinder(Double_t *param) const
— Fill vector param[4] with the bounding cylinder parameters.
Definition: TGeoTube.cxx:574
Double_t Sin(Double_t)
Definition: TMath.h:421
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:1191
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const =0
Double_t fDX
Definition: TGeoBBox.h:33
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:436
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:316
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:2526
Double_t fNlow[3]
Definition: TGeoTube.h:203
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:1305
virtual void SetDimensions(Double_t *param)
Set dimensions of the tube segment starting from a list.
Definition: TGeoTube.cxx:2205
Long64_t LocMin(Long64_t n, const T *a)
Definition: TMath.h:695
const Bool_t kTRUE
Definition: Rtypes.h:91
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:1861
virtual ~TGeoTube()
destructor
Definition: TGeoTube.cxx:170
double norm(double *x, double *p)
Definition: unuranDistr.cxx:40
virtual ~TGeoTubeSeg()
destructor
Definition: TGeoTube.cxx:1272
const Int_t n
Definition: legend1.C:16
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 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:2343
void SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz)
Set tube dimensions.
Definition: TGeoTube.cxx:894
unsigned int r2[N_CITIES]
Definition: simanTSP.cxx:322
Double_t fRmax
Definition: TGeoTube.h:33
virtual Double_t Capacity() const
Computes capacity of the shape in [length^3].
Definition: TGeoTube.cxx:177
virtual void SetPoints(Double_t *points) const
create tube mesh points
Definition: TGeoTube.cxx:960
Bool_t SectionsValid(UInt_t mask) const
Definition: TBuffer3D.h:69
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 specisied by dirs. Store output in dist...
Definition: TGeoTube.cxx:2438
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904