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