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