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/// Default constructor
144
146{
148 fRmin = 0.0;
149 fRmax = 0.0;
150 fDz = 0.0;
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Default constructor specifying minimum and maximum radius
155
157{
160 if ((fDz < 0) || (fRmin < 0) || (fRmax < 0)) {
162 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
163 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
164 }
165 ComputeBBox();
166}
167////////////////////////////////////////////////////////////////////////////////
168/// Default constructor specifying minimum and maximum radius
169
171{
174 if ((fDz < 0) || (fRmin < 0) || (fRmax < 0)) {
176 // if (fRmax<=fRmin) SetShapeBit(kGeoInvalidShape);
177 // printf("tube : dz=%f rmin=%f rmax=%f\n", dz, rmin, rmax);
178 }
179 ComputeBBox();
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Default constructor specifying minimum and maximum radius
184/// - param[0] = Rmin
185/// - param[1] = Rmax
186/// - param[2] = dz
187
189{
191 SetDimensions(param);
192 if ((fDz < 0) || (fRmin < 0) || (fRmax < 0))
194 ComputeBBox();
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// destructor
199
201
202////////////////////////////////////////////////////////////////////////////////
203/// Computes capacity of the shape in [length^3]
204
209
210////////////////////////////////////////////////////////////////////////////////
211/// Computes capacity of the shape in [length^3]
212
214{
215 Double_t capacity = 2. * TMath::Pi() * (rmax * rmax - rmin * rmin) * dz;
216 return capacity;
217}
218
219////////////////////////////////////////////////////////////////////////////////
220/// compute bounding box of the tube
221
223{
224 fDX = fDY = fRmax;
225 fDZ = fDz;
226}
227
228////////////////////////////////////////////////////////////////////////////////
229/// Compute normal to closest surface from POINT.
230
231void TGeoTube::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
232{
233 Double_t saf[3];
234 Double_t rsq = point[0] * point[0] + point[1] * point[1];
236 saf[0] = TMath::Abs(fDz - TMath::Abs(point[2]));
237 saf[1] = (fRmin > 1E-10) ? TMath::Abs(r - fRmin) : TGeoShape::Big();
238 saf[2] = TMath::Abs(fRmax - r);
239 Int_t i = TMath::LocMin(3, saf);
240 if (i == 0) {
241 norm[0] = norm[1] = 0.;
242 norm[2] = TMath::Sign(1., dir[2]);
243 return;
244 }
245 norm[2] = 0;
246 Double_t phi = TMath::ATan2(point[1], point[0]);
247 norm[0] = TMath::Cos(phi);
248 norm[1] = TMath::Sin(phi);
249 if (norm[0] * dir[0] + norm[1] * dir[1] < 0) {
250 norm[0] = -norm[0];
251 norm[1] = -norm[1];
252 }
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Compute normal to closest surface from POINT.
257
258void TGeoTube::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t /*rmin*/,
259 Double_t /*rmax*/, Double_t /*dz*/)
260{
261 norm[2] = 0;
262 Double_t phi = TMath::ATan2(point[1], point[0]);
263 norm[0] = TMath::Cos(phi);
264 norm[1] = TMath::Sin(phi);
265 if (norm[0] * dir[0] + norm[1] * dir[1] < 0) {
266 norm[0] = -norm[0];
267 norm[1] = -norm[1];
268 }
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// test if point is inside this tube
273
275{
276 if (TMath::Abs(point[2]) > fDz)
277 return kFALSE;
278 Double_t r2 = point[0] * point[0] + point[1] * point[1];
279 if ((r2 < fRmin * fRmin) || (r2 > fRmax * fRmax))
280 return kFALSE;
281 return kTRUE;
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// compute closest distance from point px,py to each corner
286
288{
290 Int_t numPoints = 4 * n;
291 if (!HasRmin())
292 numPoints = 2 * (n + 1);
293 return ShapeDistancetoPrimitive(numPoints, px, py);
294}
295
296////////////////////////////////////////////////////////////////////////////////
297/// Compute distance from inside point to surface of the tube (static)
298/// Boundary safe algorithm.
299/// compute distance to surface
300/// Do Z
301
304{
306 if (dir[2]) {
307 sz = (TMath::Sign(dz, dir[2]) - point[2]) / dir[2];
308 if (sz <= 0)
309 return 0.0;
310 }
311 // Do R
312 Double_t nsq = dir[0] * dir[0] + dir[1] * dir[1];
314 return sz;
315 Double_t rsq = point[0] * point[0] + point[1] * point[1];
316 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
317 Double_t b, d;
318 // inner cylinder
319 if (rmin > 0) {
320 // Protection in case point is actually outside the tube
321 if (rsq <= rmin * rmin + TGeoShape::Tolerance()) {
322 if (rdotn < 0)
323 return 0.0;
324 } else {
325 if (rdotn < 0) {
326 DistToTube(rsq, nsq, rdotn, rmin, b, d);
327 if (d > 0) {
328 Double_t sr = -b - d;
329 if (sr > 0)
330 return TMath::Min(sz, sr);
331 }
332 }
333 }
334 }
335 // outer cylinder
336 if (rsq >= rmax * rmax - TGeoShape::Tolerance()) {
337 if (rdotn >= 0)
338 return 0.0;
339 }
340 DistToTube(rsq, nsq, rdotn, rmax, b, d);
341 if (d > 0) {
342 Double_t sr = -b + d;
343 if (sr > 0)
344 return TMath::Min(sz, sr);
345 }
346 return 0.;
347}
348
349////////////////////////////////////////////////////////////////////////////////
350/// Compute distance from inside point to surface of the tube
351/// Boundary safe algorithm.
352
355{
356 if (iact < 3 && safe) {
357 *safe = Safety(point, kTRUE);
358 if (iact == 0)
359 return TGeoShape::Big();
360 if ((iact == 1) && (*safe > step))
361 return TGeoShape::Big();
362 }
363 // compute distance to surface
364 return DistFromInsideS(point, dir, fRmin, fRmax, fDz);
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// Static method to compute distance from outside point to a tube with given parameters
369/// Boundary safe algorithm.
370/// check Z planes
371
374{
375 Double_t xi, yi, zi;
378 zi = dz - TMath::Abs(point[2]);
379 Bool_t in = kFALSE;
380 Bool_t inz = (zi < 0) ? kFALSE : kTRUE;
381 if (!inz) {
382 if (point[2] * dir[2] >= 0)
383 return TGeoShape::Big();
384 Double_t s = -zi / TMath::Abs(dir[2]);
385 xi = point[0] + s * dir[0];
386 yi = point[1] + s * dir[1];
387 Double_t r2 = xi * xi + yi * yi;
388 if ((rminsq <= r2) && (r2 <= rmaxsq))
389 return s;
390 }
391
392 Double_t rsq = point[0] * point[0] + point[1] * point[1];
393 // check outer cyl. surface
394 Double_t nsq = dir[0] * dir[0] + dir[1] * dir[1];
395 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
396 Double_t b, d;
400 inrmax = kTRUE;
402 inrmin = kTRUE;
403 in = inz & inrmin & inrmax;
404 // If inside, we are most likely on a boundary within machine precision.
405 if (in) {
408 if (zi < rmax - r) {
409 if ((TGeoShape::IsSameWithinTolerance(rmin, 0)) || (zi < r - rmin)) {
410 if (point[2] * dir[2] < 0)
411 return 0.0;
412 return TGeoShape::Big();
413 }
414 }
415 if ((rmaxsq - rsq) < (rsq - rminsq))
416 checkout = kTRUE;
417 if (checkout) {
418 if (rdotn >= 0)
419 return TGeoShape::Big();
420 return 0.0;
421 }
423 return 0.0;
424 if (rdotn >= 0)
425 return 0.0;
426 // Ray exiting rmin -> check (+) solution for inner tube
428 return TGeoShape::Big();
429 DistToTube(rsq, nsq, rdotn, rmin, b, d);
430 if (d > 0) {
431 Double_t s = -b + d;
432 if (s > 0) {
433 zi = point[2] + s * dir[2];
434 if (TMath::Abs(zi) <= dz)
435 return s;
436 }
437 }
438 return TGeoShape::Big();
439 }
440 // Check outer cylinder (only r>rmax has to be considered)
442 return TGeoShape::Big();
443 if (!inrmax) {
444 DistToTube(rsq, nsq, rdotn, rmax, b, d);
445 if (d > 0) {
446 Double_t s = -b - d;
447 if (s > 0) {
448 zi = point[2] + s * dir[2];
449 if (TMath::Abs(zi) <= dz)
450 return s;
451 }
452 }
453 }
454 // check inner cylinder
455 if (rmin > 0) {
456 DistToTube(rsq, nsq, rdotn, rmin, b, d);
457 if (d > 0) {
458 Double_t s = -b + d;
459 if (s > 0) {
460 zi = point[2] + s * dir[2];
461 if (TMath::Abs(zi) <= dz)
462 return s;
463 }
464 }
465 }
466 return TGeoShape::Big();
467}
468
469////////////////////////////////////////////////////////////////////////////////
470/// Compute distance from outside point to surface of the tube and safe distance
471/// Boundary safe algorithm.
472/// fist localize point w.r.t tube
473
476{
477 if (iact < 3 && safe) {
478 *safe = Safety(point, kFALSE);
479 if (iact == 0)
480 return TGeoShape::Big();
481 if ((iact == 1) && (step <= *safe))
482 return TGeoShape::Big();
483 }
484 // Check if the bounding box is crossed within the requested distance
485 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
486 if (sdist >= step)
487 return TGeoShape::Big();
488 // find distance to shape
489 return DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// Static method computing the distance to a tube with given radius, starting from
494/// POINT along DIR director cosines. The distance is computed as :
495/// RSQ = point[0]*point[0]+point[1]*point[1]
496/// NSQ = dir[0]*dir[0]+dir[1]*dir[1] ---> should NOT be 0 !!!
497/// RDOTN = point[0]*dir[0]+point[1]*dir[1]
498/// The distance can be computed as :
499/// D = -B +/- DELTA
500/// where DELTA.GT.0 and D.GT.0
501
503{
504 Double_t t1 = 1. / nsq;
505 Double_t t3 = rsq - (radius * radius);
506 b = t1 * rdotn;
507 Double_t c = t1 * t3;
508 delta = b * b - c;
509 if (delta > 0) {
510 delta = TMath::Sqrt(delta);
511 } else {
512 delta = -1;
513 }
514}
515
516////////////////////////////////////////////////////////////////////////////////
517/// Divide this tube shape belonging to volume "voldiv" into ndiv volumes
518/// called divname, from start position with the given step. Returns pointer
519/// to created division cell volume in case of Z divisions. For radial division
520/// creates all volumes with different shapes and returns pointer to volume that
521/// was divided. In case a wrong division axis is supplied, returns pointer to
522/// volume that was divided.
523
526{
527 TGeoShape *shape; //--- shape to be created
528 TGeoVolume *vol; //--- division volume to be created
529 TGeoVolumeMulti *vmulti; //--- generic divided volume
530 TGeoPatternFinder *finder; //--- finder to be attached
531 TString opt = ""; //--- option to be attached
532 Int_t id;
533 Double_t end = start + ndiv * step;
534 switch (iaxis) {
535 case 1: //--- R division
536 finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
538 voldiv->SetFinder(finder);
539 finder->SetDivIndex(voldiv->GetNdaughters());
540 for (id = 0; id < ndiv; id++) {
541 shape = new TGeoTube(start + id * step, start + (id + 1) * step, fDz);
542 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
543 vmulti->AddVolume(vol);
544 opt = "R";
545 voldiv->AddNodeOffset(vol, id, 0, opt.Data());
546 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
547 }
548 return vmulti;
549 case 2: //--- Phi division
550 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
551 voldiv->SetFinder(finder);
552 finder->SetDivIndex(voldiv->GetNdaughters());
553 shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step / 2, step / 2);
554 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
556 vmulti->AddVolume(vol);
557 opt = "Phi";
558 for (id = 0; id < ndiv; id++) {
559 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
560 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
561 }
562 return vmulti;
563 case 3: //--- Z division
564 finder = new TGeoPatternZ(voldiv, ndiv, start, start + ndiv * step);
565 voldiv->SetFinder(finder);
566 finder->SetDivIndex(voldiv->GetNdaughters());
567 shape = new TGeoTube(fRmin, fRmax, step / 2);
568 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
570 vmulti->AddVolume(vol);
571 opt = "Z";
572 for (id = 0; id < ndiv; id++) {
573 voldiv->AddNodeOffset(vol, id, start + step / 2 + id * step, opt.Data());
574 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
575 }
576 return vmulti;
577 default: Error("Divide", "In shape %s wrong axis type for division", GetName()); return nullptr;
578 }
579}
580
581////////////////////////////////////////////////////////////////////////////////
582/// Returns name of axis IAXIS.
583
585{
586 switch (iaxis) {
587 case 1: return "R";
588 case 2: return "PHI";
589 case 3: return "Z";
590 default: return "UNDEFINED";
591 }
592}
593
594////////////////////////////////////////////////////////////////////////////////
595/// Get range of shape for a given axis.
596
598{
599 xlo = 0;
600 xhi = 0;
601 Double_t dx = 0;
602 switch (iaxis) {
603 case 1:
604 xlo = fRmin;
605 xhi = fRmax;
606 dx = xhi - xlo;
607 return dx;
608 case 2:
609 xlo = 0;
610 xhi = 360;
611 dx = 360;
612 return dx;
613 case 3:
614 xlo = -fDz;
615 xhi = fDz;
616 dx = xhi - xlo;
617 return dx;
618 }
619 return dx;
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Fill vector param[4] with the bounding cylinder parameters. The order
624/// is the following : Rmin, Rmax, Phi1, Phi2, dZ
625
627{
628 param[0] = fRmin; // Rmin
629 param[0] *= param[0];
630 param[1] = fRmax; // Rmax
631 param[1] *= param[1];
632 param[2] = 0.; // Phi1
633 param[3] = 360.; // Phi2
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// in case shape has some negative parameters, these has to be computed
638/// in order to fit the mother
639
641{
643 return nullptr;
646 rmin = fRmin;
647 rmax = fRmax;
648 dz = fDz;
649 if (fDz < 0) {
650 mother->GetAxisRange(3, xmin, xmax);
651 if (xmax < 0)
652 return nullptr;
653 dz = xmax;
654 }
655 mother->GetAxisRange(1, xmin, xmax);
656 if (fRmin < 0) {
657 if (xmin < 0)
658 return nullptr;
659 rmin = xmin;
660 }
661 if (fRmax < 0) {
662 if (xmax <= 0)
663 return nullptr;
664 rmax = xmax;
665 }
666
667 return (new TGeoTube(GetName(), rmin, rmax, dz));
668}
669
670////////////////////////////////////////////////////////////////////////////////
671/// print shape parameters
672
674{
675 printf("*** Shape %s: TGeoTube ***\n", GetName());
676 printf(" Rmin = %11.5f\n", fRmin);
677 printf(" Rmax = %11.5f\n", fRmax);
678 printf(" dz = %11.5f\n", fDz);
679 printf(" Bounding box:\n");
681}
682
683////////////////////////////////////////////////////////////////////////////////
684/// Fill TBuffer3D structure for segments and polygons.
685
687{
688 Int_t i, j, indx;
690 Int_t c = (((buffer.fColor) % 8) - 1) * 4;
691 if (c < 0)
692 c = 0;
693
694 if (HasRmin()) {
695 // circle segments:
696 // lower rmin circle: i=0, (0, n-1)
697 // lower rmax circle: i=1, (n, 2n-1)
698 // upper rmin circle: i=2, (2n, 3n-1)
699 // upper rmax circle: i=1, (3n, 4n-1)
700 for (i = 0; i < 4; i++) {
701 for (j = 0; j < n; j++) {
702 indx = 3 * (i * n + j);
703 buffer.fSegs[indx] = c;
704 buffer.fSegs[indx + 1] = i * n + j;
705 buffer.fSegs[indx + 2] = i * n + (j + 1) % n;
706 }
707 }
708 // Z-parallel segments
709 // inner: i=4, (4n, 5n-1)
710 // outer: i=5, (5n, 6n-1)
711 for (i = 4; i < 6; i++) {
712 for (j = 0; j < n; j++) {
713 indx = 3 * (i * n + j);
714 buffer.fSegs[indx] = c + 1;
715 buffer.fSegs[indx + 1] = (i - 4) * n + j;
716 buffer.fSegs[indx + 2] = (i - 2) * n + j;
717 }
718 }
719 // Radial segments
720 // lower: i=6, (6n, 7n-1)
721 // upper: i=7, (7n, 8n-1)
722 for (i = 6; i < 8; i++) {
723 for (j = 0; j < n; j++) {
724 indx = 3 * (i * n + j);
725 buffer.fSegs[indx] = c;
726 buffer.fSegs[indx + 1] = 2 * (i - 6) * n + j;
727 buffer.fSegs[indx + 2] = (2 * (i - 6) + 1) * n + j;
728 }
729 }
730 // Polygons
731 i = 0;
732 // Inner lateral (0, n-1)
733 for (j = 0; j < n; j++) {
734 indx = 6 * (i * n + j);
735 buffer.fPols[indx] = c;
736 buffer.fPols[indx + 1] = 4;
737 buffer.fPols[indx + 2] = j;
738 buffer.fPols[indx + 3] = 4 * n + (j + 1) % n;
739 buffer.fPols[indx + 4] = 2 * n + j;
740 buffer.fPols[indx + 5] = 4 * n + j;
741 }
742 i = 1;
743 // Outer lateral (n,2n-1)
744 for (j = 0; j < n; j++) {
745 indx = 6 * (i * n + j);
746 buffer.fPols[indx] = c + 1;
747 buffer.fPols[indx + 1] = 4;
748 buffer.fPols[indx + 2] = n + j;
749 buffer.fPols[indx + 3] = 5 * n + j;
750 buffer.fPols[indx + 4] = 3 * n + j;
751 buffer.fPols[indx + 5] = 5 * n + (j + 1) % n;
752 }
753 i = 2;
754 // lower disc (2n, 3n-1)
755 for (j = 0; j < n; j++) {
756 indx = 6 * (i * n + j);
757 buffer.fPols[indx] = c;
758 buffer.fPols[indx + 1] = 4;
759 buffer.fPols[indx + 2] = j;
760 buffer.fPols[indx + 3] = 6 * n + j;
761 buffer.fPols[indx + 4] = n + j;
762 buffer.fPols[indx + 5] = 6 * n + (j + 1) % n;
763 }
764 i = 3;
765 // upper disc (3n, 4n-1)
766 for (j = 0; j < n; j++) {
767 indx = 6 * (i * n + j);
768 buffer.fPols[indx] = c;
769 buffer.fPols[indx + 1] = 4;
770 buffer.fPols[indx + 2] = 2 * n + j;
771 buffer.fPols[indx + 3] = 7 * n + (j + 1) % n;
772 buffer.fPols[indx + 4] = 3 * n + j;
773 buffer.fPols[indx + 5] = 7 * n + j;
774 }
775 return;
776 }
777 // Rmin=0 tubes
778 // circle segments
779 // lower rmax circle: i=0, (0, n-1)
780 // upper rmax circle: i=1, (n, 2n-1)
781 for (i = 0; i < 2; i++) {
782 for (j = 0; j < n; j++) {
783 indx = 3 * (i * n + j);
784 buffer.fSegs[indx] = c;
785 buffer.fSegs[indx + 1] = 2 + i * n + j;
786 buffer.fSegs[indx + 2] = 2 + i * n + (j + 1) % n;
787 }
788 }
789 // Z-parallel segments (2n,3n-1)
790 for (j = 0; j < n; j++) {
791 indx = 3 * (2 * n + j);
792 buffer.fSegs[indx] = c + 1;
793 buffer.fSegs[indx + 1] = 2 + j;
794 buffer.fSegs[indx + 2] = 2 + n + j;
795 }
796 // Radial segments
797 // Lower circle: i=3, (3n,4n-1)
798 // Upper circle: i=4, (4n,5n-1)
799 for (i = 3; i < 5; i++) {
800 for (j = 0; j < n; j++) {
801 indx = 3 * (i * n + j);
802 buffer.fSegs[indx] = c;
803 buffer.fSegs[indx + 1] = i - 3;
804 buffer.fSegs[indx + 2] = 2 + (i - 3) * n + j;
805 }
806 }
807 // Polygons
808 // lateral (0,n-1)
809 for (j = 0; j < n; j++) {
810 indx = 6 * j;
811 buffer.fPols[indx] = c + 1;
812 buffer.fPols[indx + 1] = 4;
813 buffer.fPols[indx + 2] = j;
814 buffer.fPols[indx + 3] = 2 * n + j;
815 buffer.fPols[indx + 4] = n + j;
816 buffer.fPols[indx + 5] = 2 * n + (j + 1) % n;
817 }
818 // bottom triangles (n,2n-1)
819 for (j = 0; j < n; j++) {
820 indx = 6 * n + 5 * j;
821 buffer.fPols[indx] = c;
822 buffer.fPols[indx + 1] = 3;
823 buffer.fPols[indx + 2] = j;
824 buffer.fPols[indx + 3] = 3 * n + (j + 1) % n;
825 buffer.fPols[indx + 4] = 3 * n + j;
826 }
827 // top triangles (2n,3n-1)
828 for (j = 0; j < n; j++) {
829 indx = 6 * n + 5 * n + 5 * j;
830 buffer.fPols[indx] = c;
831 buffer.fPols[indx + 1] = 3;
832 buffer.fPols[indx + 2] = n + j;
833 buffer.fPols[indx + 3] = 4 * n + j;
834 buffer.fPols[indx + 4] = 4 * n + (j + 1) % n;
835 }
836}
837
838////////////////////////////////////////////////////////////////////////////////
839/// computes the closest distance from given point to this shape, according
840/// to option. The matching point on the shape is stored in spoint.
841
843{
844#ifndef NEVER
845 Double_t r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
847 if (in) {
848 safe = fDz - TMath::Abs(point[2]); // positive if inside
849 if (fRmin > 1E-10) {
850 safrmin = r - fRmin;
851 if (safrmin < safe)
852 safe = safrmin;
853 }
854 safrmax = fRmax - r;
855 if (safrmax < safe)
856 safe = safrmax;
857 } else {
858 safe = -fDz + TMath::Abs(point[2]);
859 if (fRmin > 1E-10) {
860 safrmin = -r + fRmin;
861 if (safrmin > safe)
862 safe = safrmin;
863 }
864 safrmax = -fRmax + r;
865 if (safrmax > safe)
866 safe = safrmax;
867 }
868 return safe;
869#else
870 Double_t saf[3];
871 Double_t rsq = point[0] * point[0] + point[1] * point[1];
873 saf[0] = fDz - TMath::Abs(point[2]); // positive if inside
874 saf[1] = (fRmin > 1E-10) ? (r - fRmin) : TGeoShape::Big();
875 saf[2] = fRmax - r;
876 if (in)
877 return saf[TMath::LocMin(3, saf)];
878 for (Int_t i = 0; i < 3; i++)
879 saf[i] = -saf[i];
880 return saf[TMath::LocMax(3, saf)];
881#endif
882}
883
884////////////////////////////////////////////////////////////////////////////////
885/// computes the closest distance from given point to this shape, according
886/// to option. The matching point on the shape is stored in spoint.
887
889{
890 Double_t saf[3];
891 Double_t rsq = point[0] * point[0] + point[1] * point[1];
893 switch (skipz) {
894 case 1: // skip lower Z plane
895 saf[0] = dz - point[2];
896 break;
897 case 2: // skip upper Z plane
898 saf[0] = dz + point[2];
899 break;
900 case 3: // skip both
901 saf[0] = TGeoShape::Big();
902 break;
903 default: saf[0] = dz - TMath::Abs(point[2]);
904 }
905 saf[1] = (rmin > 1E-10) ? (r - rmin) : TGeoShape::Big();
906 saf[2] = rmax - r;
907 // printf("saf0=%g saf1=%g saf2=%g in=%d skipz=%d\n", saf[0],saf[1],saf[2],in,skipz);
908 if (in)
909 return saf[TMath::LocMin(3, saf)];
910 for (Int_t i = 0; i < 3; i++)
911 saf[i] = -saf[i];
912 return saf[TMath::LocMax(3, saf)];
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// Save a primitive as a C++ statement(s) on output stream "out".
917
918void TGeoTube::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
919{
921 return;
922 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
923 out << " rmin = " << fRmin << ";" << std::endl;
924 out << " rmax = " << fRmax << ";" << std::endl;
925 out << " dz = " << fDz << ";" << std::endl;
926 out << " TGeoShape *" << GetPointerName() << " = new TGeoTube(\"" << GetName() << "\",rmin,rmax,dz);" << std::endl;
928}
929
930////////////////////////////////////////////////////////////////////////////////
931/// Set tube dimensions.
932
934{
935 fRmin = rmin;
936 fRmax = rmax;
937 fDz = dz;
938 if (fRmin > 0 && fRmax > 0 && fRmin >= fRmax)
939 Error("SetTubeDimensions", "In shape %s wrong rmin=%g rmax=%g", GetName(), rmin, rmax);
940}
941
942////////////////////////////////////////////////////////////////////////////////
943/// Set tube dimensions starting from a list.
944
946{
947 Double_t rmin = param[0];
948 Double_t rmax = param[1];
949 Double_t dz = param[2];
951}
952
953////////////////////////////////////////////////////////////////////////////////
954/// Fills array with n random points located on the line segments of the shape mesh.
955/// The output array must be provided with a length of minimum 3*npoints. Returns
956/// true if operation is implemented.
957
959{
960 if (!array || npoints <= 0)
961 return kFALSE;
962 if (fDz <= 0.0 || fRmax <= 0.0)
963 return kFALSE;
964
965 const Bool_t hasInner = HasRmin() && (fRmin > 0.0);
966
967 // Split budget: outer gets the extra point if odd
969 Int_t inPoints = 0;
970 if (hasInner) {
971 outPoints = (npoints + 1) / 2;
973 }
974
975 auto fillCyl = [&](Int_t nSurfPoints, Double_t r, Int_t &icrt) -> Bool_t {
976 if (nSurfPoints <= 0)
977 return kTRUE;
978 if (r <= 0.0)
979 return kFALSE;
980
981 // Number of generators ~ sqrt(n), clamp to [1, nSurfPoints]
983 if (nGen < 1)
984 nGen = 1;
985 if (nGen > nSurfPoints)
987
988 const Int_t q = nSurfPoints / nGen;
989 const Int_t rem = nSurfPoints % nGen;
990
991 // Full phi, but use bin centers to avoid endpoints (phi=0 and 2pi)
993
994 for (Int_t ig = 0; ig < nGen; ++ig) {
995 const Int_t m = q + (ig < rem ? 1 : 0); // points on this generator
996 if (m <= 0)
997 continue;
998
999 const Double_t phi = (ig + 0.5) * dphi; // never exactly 0 or 2pi
1000 const Double_t c = TMath::Cos(phi);
1001 const Double_t s = TMath::Sin(phi);
1002
1003 // Interior in z: t in (0,1) => avoids z=±dz
1004 for (Int_t j = 0; j < m; ++j) {
1005 if (icrt + 3 > 3 * npoints)
1006 return kFALSE; // overflow guard
1007
1008 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1);
1009 const Double_t z = -fDz + t * (2.0 * fDz);
1010
1011 array[icrt++] = r * c;
1012 array[icrt++] = r * s;
1013 array[icrt++] = z;
1014 }
1015 }
1016 return kTRUE;
1017 };
1018
1019 Int_t icrt = 0;
1020
1021 // Outer cylindrical surface
1022 if (!fillCyl(outPoints, fRmax, icrt))
1023 return kFALSE;
1024
1025 // Inner cylindrical surface (if hollow)
1026 if (hasInner) {
1027 if (!fillCyl(inPoints, fRmin, icrt))
1028 return kFALSE;
1029 }
1030
1031 // Contract: must fill exactly npoints
1032 return (icrt == 3 * npoints) ? kTRUE : kFALSE;
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// create tube mesh points
1037
1039{
1040 Double_t dz;
1041 Int_t j, n;
1043 Double_t dphi = 360. / n;
1044 Double_t phi = 0;
1045 dz = fDz;
1046 Int_t indx = 0;
1047 if (points) {
1048 if (HasRmin()) {
1049 // 4*n points
1050 // (0,n-1) lower rmin circle
1051 // (2n, 3n-1) upper rmin circle
1052 for (j = 0; j < n; j++) {
1053 phi = j * dphi * TMath::DegToRad();
1054 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
1055 indx++;
1056 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
1057 indx++;
1058 points[indx + 6 * n] = dz;
1059 points[indx] = -dz;
1060 indx++;
1061 }
1062 // (n, 2n-1) lower rmax circle
1063 // (3n, 4n-1) upper rmax circle
1064 for (j = 0; j < n; j++) {
1065 phi = j * dphi * TMath::DegToRad();
1066 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
1067 indx++;
1068 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
1069 indx++;
1070 points[indx + 6 * n] = dz;
1071 points[indx] = -dz;
1072 indx++;
1073 }
1074 } else {
1075 // centers of lower/upper circles (0,1)
1076 points[indx++] = 0.;
1077 points[indx++] = 0.;
1078 points[indx++] = -dz;
1079 points[indx++] = 0.;
1080 points[indx++] = 0.;
1081 points[indx++] = dz;
1082 // lower rmax circle (2, 2+n-1)
1083 // upper rmax circle (2+n, 2+2n-1)
1084 for (j = 0; j < n; j++) {
1085 phi = j * dphi * TMath::DegToRad();
1086 points[indx + 3 * n] = points[indx] = fRmax * TMath::Cos(phi);
1087 indx++;
1088 points[indx + 3 * n] = points[indx] = fRmax * TMath::Sin(phi);
1089 indx++;
1090 points[indx + 3 * n] = dz;
1091 points[indx] = -dz;
1092 indx++;
1093 }
1094 }
1095 }
1096}
1097
1098////////////////////////////////////////////////////////////////////////////////
1099/// create tube mesh points
1100
1102{
1103 Double_t dz;
1104 Int_t j, n;
1106 Double_t dphi = 360. / n;
1107 Double_t phi = 0;
1108 dz = fDz;
1109 Int_t indx = 0;
1110 if (points) {
1111 if (HasRmin()) {
1112 // 4*n points
1113 // (0,n-1) lower rmin circle
1114 // (2n, 3n-1) upper rmin circle
1115 for (j = 0; j < n; j++) {
1116 phi = j * dphi * TMath::DegToRad();
1117 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
1118 indx++;
1119 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
1120 indx++;
1121 points[indx + 6 * n] = dz;
1122 points[indx] = -dz;
1123 indx++;
1124 }
1125 // (n, 2n-1) lower rmax circle
1126 // (3n, 4n-1) upper rmax circle
1127 for (j = 0; j < n; j++) {
1128 phi = j * dphi * TMath::DegToRad();
1129 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
1130 indx++;
1131 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
1132 indx++;
1133 points[indx + 6 * n] = dz;
1134 points[indx] = -dz;
1135 indx++;
1136 }
1137 } else {
1138 // centers of lower/upper circles (0,1)
1139 points[indx++] = 0.;
1140 points[indx++] = 0.;
1141 points[indx++] = -dz;
1142 points[indx++] = 0.;
1143 points[indx++] = 0.;
1144 points[indx++] = dz;
1145 // lower rmax circle (2, 2+n-1)
1146 // upper rmax circle (2+n, 2+2n-1)
1147 for (j = 0; j < n; j++) {
1148 phi = j * dphi * TMath::DegToRad();
1149 points[indx + 3 * n] = points[indx] = fRmax * TMath::Cos(phi);
1150 indx++;
1151 points[indx + 3 * n] = points[indx] = fRmax * TMath::Sin(phi);
1152 indx++;
1153 points[indx + 3 * n] = dz;
1154 points[indx] = -dz;
1155 indx++;
1156 }
1157 }
1158 }
1159}
1160
1161////////////////////////////////////////////////////////////////////////////////
1162/// Return number of vertices of the mesh representation
1163
1165{
1167 Int_t numPoints = n * 4;
1168 if (!HasRmin())
1169 numPoints = 2 * (n + 1);
1170 return numPoints;
1171}
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Returns numbers of vertices, segments and polygons composing the shape mesh.
1175
1177{
1179 nvert = n * 4;
1180 nsegs = n * 8;
1181 npols = n * 4;
1182 if (!HasRmin()) {
1183 nvert = 2 * (n + 1);
1184 nsegs = 5 * n;
1185 npols = 3 * n;
1186 } else {
1187 nvert = n * 4;
1188 nsegs = n * 8;
1189 npols = n * 4;
1190 }
1191}
1192
1193////////////////////////////////////////////////////////////////////////////////
1194/// fill size of this 3-D object
1195
1196void TGeoTube::Sizeof3D() const {}
1197
1198////////////////////////////////////////////////////////////////////////////////
1199/// Fills a static 3D buffer and returns a reference.
1200
1202{
1203 static TBuffer3DTube buffer;
1205
1207 buffer.fRadiusInner = fRmin;
1208 buffer.fRadiusOuter = fRmax;
1209 buffer.fHalfLength = fDz;
1211 }
1214 Int_t nbPnts = 4 * n;
1215 Int_t nbSegs = 8 * n;
1216 Int_t nbPols = 4 * n;
1217 if (!HasRmin()) {
1218 nbPnts = 2 * (n + 1);
1219 nbSegs = 5 * n;
1220 nbPols = 3 * n;
1221 }
1222 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
1224 }
1225 }
1227 SetPoints(buffer.fPnts);
1228 if (!buffer.fLocalFrame) {
1229 TransformPoints(buffer.fPnts, buffer.NbPnts());
1230 }
1231 SetSegsAndPols(buffer);
1233 }
1234
1235 return buffer;
1236}
1237
1238////////////////////////////////////////////////////////////////////////////////
1239/// Check the inside status for each of the points in the array.
1240/// Input: Array of point coordinates + vector size
1241/// Output: Array of Booleans for the inside of each point
1242
1244{
1245 for (Int_t i = 0; i < vecsize; i++)
1246 inside[i] = Contains(&points[3 * i]);
1247}
1248
1249////////////////////////////////////////////////////////////////////////////////
1250/// Compute the normal for an array o points so that norm.dot.dir is positive
1251/// Input: Arrays of point coordinates and directions + vector size
1252/// Output: Array of normal directions
1253
1255{
1256 for (Int_t i = 0; i < vecsize; i++)
1257 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
1258}
1259
1260////////////////////////////////////////////////////////////////////////////////
1261/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1262
1264 Double_t *step) const
1265{
1266 for (Int_t i = 0; i < vecsize; i++)
1267 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1268}
1269
1270////////////////////////////////////////////////////////////////////////////////
1271/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1272
1274 Double_t *step) const
1275{
1276 for (Int_t i = 0; i < vecsize; i++)
1277 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1278}
1279
1280////////////////////////////////////////////////////////////////////////////////
1281/// Compute safe distance from each of the points in the input array.
1282/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
1283/// Output: Safety values
1284
1286{
1287 for (Int_t i = 0; i < vecsize; i++)
1288 safe[i] = Safety(&points[3 * i], inside[i]);
1289}
1290
1291////////////////////////////////////////////////////////////////////////////////
1292/// Default constructor
1293
1295 : TGeoTube(), fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1296{
1298}
1299
1300////////////////////////////////////////////////////////////////////////////////
1301/// Default constructor specifying minimum and maximum radius.
1302/// The segment will be from phiStart to phiEnd expressed in degree.
1303
1305 : TGeoTube(rmin, rmax, dz), fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1306{
1309 ComputeBBox();
1310}
1311
1312////////////////////////////////////////////////////////////////////////////////
1313/// Default constructor specifying minimum and maximum radius
1314/// The segment will be from phiStart to phiEnd expressed in degree.
1315
1324
1325////////////////////////////////////////////////////////////////////////////////
1326/// Default constructor specifying minimum and maximum radius
1327/// - param[0] = Rmin
1328/// - param[1] = Rmax
1329/// - param[2] = dz
1330/// - param[3] = phi1
1331/// - param[4] = phi2
1332
1339
1340////////////////////////////////////////////////////////////////////////////////
1341/// destructor
1342
1344
1345////////////////////////////////////////////////////////////////////////////////
1346/// Function called after streaming an object of this class.
1347
1352
1353////////////////////////////////////////////////////////////////////////////////
1354/// Init frequently used trigonometric values
1355
1357{
1360 fC1 = TMath::Cos(phi1);
1361 fS1 = TMath::Sin(phi1);
1362 fC2 = TMath::Cos(phi2);
1363 fS2 = TMath::Sin(phi2);
1364 Double_t fio = 0.5 * (phi1 + phi2);
1365 fCm = TMath::Cos(fio);
1366 fSm = TMath::Sin(fio);
1367 Double_t dfi = 0.5 * (phi2 - phi1);
1368 fCdfi = TMath::Cos(dfi);
1369}
1370
1371////////////////////////////////////////////////////////////////////////////////
1372/// Computes capacity of the shape in [length^3]
1373
1378
1379////////////////////////////////////////////////////////////////////////////////
1380/// Computes capacity of the shape in [length^3]
1381
1387
1388////////////////////////////////////////////////////////////////////////////////
1389/// compute bounding box of the tube segment
1390
1392{
1393 Double_t xc[4];
1394 Double_t yc[4];
1395 xc[0] = fRmax * fC1;
1396 yc[0] = fRmax * fS1;
1397 xc[1] = fRmax * fC2;
1398 yc[1] = fRmax * fS2;
1399 xc[2] = fRmin * fC1;
1400 yc[2] = fRmin * fS1;
1401 xc[3] = fRmin * fC2;
1402 yc[3] = fRmin * fS2;
1403
1404 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
1405 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
1406 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
1407 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
1408
1409 Double_t dp = fPhi2 - fPhi1;
1410 if (dp < 0)
1411 dp += 360;
1412 Double_t ddp = -fPhi1;
1413 if (ddp < 0)
1414 ddp += 360;
1415 if (ddp > 360)
1416 ddp -= 360;
1417 if (ddp <= dp)
1418 xmax = fRmax;
1419 ddp = 90 - fPhi1;
1420 if (ddp < 0)
1421 ddp += 360;
1422 if (ddp > 360)
1423 ddp -= 360;
1424 if (ddp <= dp)
1425 ymax = fRmax;
1426 ddp = 180 - fPhi1;
1427 if (ddp < 0)
1428 ddp += 360;
1429 if (ddp > 360)
1430 ddp -= 360;
1431 if (ddp <= dp)
1432 xmin = -fRmax;
1433 ddp = 270 - fPhi1;
1434 if (ddp < 0)
1435 ddp += 360;
1436 if (ddp > 360)
1437 ddp -= 360;
1438 if (ddp <= dp)
1439 ymin = -fRmax;
1440 fOrigin[0] = (xmax + xmin) / 2;
1441 fOrigin[1] = (ymax + ymin) / 2;
1442 fOrigin[2] = 0;
1443 fDX = (xmax - xmin) / 2;
1444 fDY = (ymax - ymin) / 2;
1445 fDZ = fDz;
1446}
1447
1448////////////////////////////////////////////////////////////////////////////////
1449/// Compute normal to closest surface from POINT.
1450
1451void TGeoTubeSeg::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
1452{
1453 Double_t saf[3];
1454 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1456 saf[0] = TMath::Abs(fDz - TMath::Abs(point[2]));
1457 saf[1] = (fRmin > 1E-10) ? TMath::Abs(r - fRmin) : TGeoShape::Big();
1458 saf[2] = TMath::Abs(fRmax - r);
1459 Int_t i = TMath::LocMin(3, saf);
1460 if (((fPhi2 - fPhi1) < 360.) && TGeoShape::IsCloseToPhi(saf[i], point, fC1, fS1, fC2, fS2)) {
1461 TGeoShape::NormalPhi(point, dir, norm, fC1, fS1, fC2, fS2);
1462 return;
1463 }
1464 if (i == 0) {
1465 norm[0] = norm[1] = 0.;
1466 norm[2] = TMath::Sign(1., dir[2]);
1467 return;
1468 };
1469 norm[2] = 0;
1470 Double_t phi = TMath::ATan2(point[1], point[0]);
1471 norm[0] = TMath::Cos(phi);
1472 norm[1] = TMath::Sin(phi);
1473 if (norm[0] * dir[0] + norm[1] * dir[1] < 0) {
1474 norm[0] = -norm[0];
1475 norm[1] = -norm[1];
1476 }
1477}
1478
1479////////////////////////////////////////////////////////////////////////////////
1480/// Compute normal to closest surface from POINT.
1481
1484{
1485 Double_t saf[2];
1486 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1488 saf[0] = (rmin > 1E-10) ? TMath::Abs(r - rmin) : TGeoShape::Big();
1489 saf[1] = TMath::Abs(rmax - r);
1490 Int_t i = TMath::LocMin(2, saf);
1491 if (TGeoShape::IsCloseToPhi(saf[i], point, c1, s1, c2, s2)) {
1492 TGeoShape::NormalPhi(point, dir, norm, c1, s1, c2, s2);
1493 return;
1494 }
1495 norm[2] = 0;
1496 Double_t phi = TMath::ATan2(point[1], point[0]);
1497 norm[0] = TMath::Cos(phi);
1498 norm[1] = TMath::Sin(phi);
1499 if (norm[0] * dir[0] + norm[1] * dir[1] < 0) {
1500 norm[0] = -norm[0];
1501 norm[1] = -norm[1];
1502 }
1503}
1504
1505////////////////////////////////////////////////////////////////////////////////
1506/// test if point is inside this tube segment
1507/// first check if point is inside the tube
1508
1510{
1511 if (!TGeoTube::Contains(point))
1512 return kFALSE;
1513 return IsInPhiRange(point, fPhi1, fPhi2);
1514}
1515
1516////////////////////////////////////////////////////////////////////////////////
1517/// compute closest distance from point px,py to each corner
1518
1520{
1522 const Int_t numPoints = 4 * n;
1523 return ShapeDistancetoPrimitive(numPoints, px, py);
1524}
1525
1526////////////////////////////////////////////////////////////////////////////////
1527/// Compute distance from inside point to surface of the tube segment (static)
1528/// Boundary safe algorithm.
1529/// Do Z
1530
1534{
1536 if (stube <= 0)
1537 return 0.0;
1538 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1540 Double_t cpsi = point[0] * cm + point[1] * sm;
1541 if (cpsi > r * cdfi + TGeoShape::Tolerance()) {
1542 Double_t sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
1543 return TMath::Min(stube, sfmin);
1544 }
1545 // Point on the phi boundary or outside
1546 // which one: phi1 or phi2
1547 Double_t ddotn, xi, yi;
1548 if (TMath::Abs(point[1] - s1 * r) < TMath::Abs(point[1] - s2 * r)) {
1549 ddotn = s1 * dir[0] - c1 * dir[1];
1550 if (ddotn >= 0)
1551 return 0.0;
1552 ddotn = -s2 * dir[0] + c2 * dir[1];
1553 if (ddotn <= 0)
1554 return stube;
1555 Double_t sfmin = s2 * point[0] - c2 * point[1];
1556 if (sfmin <= 0)
1557 return stube;
1558 sfmin /= ddotn;
1559 if (sfmin >= stube)
1560 return stube;
1561 xi = point[0] + sfmin * dir[0];
1562 yi = point[1] + sfmin * dir[1];
1563 if (yi * cm - xi * sm < 0)
1564 return stube;
1565 return sfmin;
1566 }
1567 ddotn = -s2 * dir[0] + c2 * dir[1];
1568 if (ddotn >= 0)
1569 return 0.0;
1570 ddotn = s1 * dir[0] - c1 * dir[1];
1571 if (ddotn <= 0)
1572 return stube;
1573 Double_t sfmin = -s1 * point[0] + c1 * point[1];
1574 if (sfmin <= 0)
1575 return stube;
1576 sfmin /= ddotn;
1577 if (sfmin >= stube)
1578 return stube;
1579 xi = point[0] + sfmin * dir[0];
1580 yi = point[1] + sfmin * dir[1];
1581 if (yi * cm - xi * sm > 0)
1582 return stube;
1583 return sfmin;
1584}
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Compute distance from inside point to surface of the tube segment
1588/// Boundary safe algorithm.
1589
1592{
1593 if (iact < 3 && safe) {
1594 *safe = SafetyS(point, kTRUE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1595 if (iact == 0)
1596 return TGeoShape::Big();
1597 if ((iact == 1) && (*safe > step))
1598 return TGeoShape::Big();
1599 }
1600 if ((fPhi2 - fPhi1) >= 360.)
1601 return TGeoTube::DistFromInsideS(point, dir, fRmin, fRmax, fDz);
1602
1603 // compute distance to surface
1604 return TGeoTubeSeg::DistFromInsideS(point, dir, fRmin, fRmax, fDz, fC1, fS1, fC2, fS2, fCm, fSm, fCdfi);
1605}
1606
1607////////////////////////////////////////////////////////////////////////////////
1608/// Static method to compute distance to arbitrary tube segment from outside point
1609/// Boundary safe algorithm.
1610
1614{
1615 Double_t r2, cpsi, s;
1616 // check Z planes
1617 Double_t xi, yi, zi;
1618 zi = dz - TMath::Abs(point[2]);
1622 Bool_t in = kFALSE;
1623 Bool_t inz = (zi < 0) ? kFALSE : kTRUE;
1624 if (!inz) {
1625 if (point[2] * dir[2] >= 0)
1626 return TGeoShape::Big();
1627 s = -zi / TMath::Abs(dir[2]);
1628 xi = point[0] + s * dir[0];
1629 yi = point[1] + s * dir[1];
1630 r2 = xi * xi + yi * yi;
1631 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1632 cpsi = (xi * cm + yi * sm) / TMath::Sqrt(r2);
1633 if (cpsi >= cdfi)
1634 return s;
1635 }
1636 }
1637
1638 // check outer cyl. surface
1639 Double_t rsq = point[0] * point[0] + point[1] * point[1];
1641 Double_t nsq = dir[0] * dir[0] + dir[1] * dir[1];
1642 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
1643 Double_t b, d;
1647 if (rsq <= rmaxsq + TGeoShape::Tolerance())
1648 inrmax = kTRUE;
1649 if (rsq >= rminsq - TGeoShape::Tolerance())
1650 inrmin = kTRUE;
1651 cpsi = point[0] * cm + point[1] * sm;
1652 if (cpsi > r * cdfi - TGeoShape::Tolerance())
1653 inphi = kTRUE;
1654 in = inz & inrmin & inrmax & inphi;
1655 // If inside, we are most likely on a boundary within machine precision.
1656 if (in) {
1658 Double_t safphi = (cpsi - r * cdfi) * TMath::Sqrt(1. - cdfi * cdfi);
1659 // Double_t sch, cch;
1660 // check if on Z boundaries
1661 if (zi < rmax - r) {
1662 if (TGeoShape::IsSameWithinTolerance(rmin, 0) || (zi < r - rmin)) {
1663 if (zi < safphi) {
1664 if (point[2] * dir[2] < 0)
1665 return 0.0;
1666 return TGeoShape::Big();
1667 }
1668 }
1669 }
1670 if ((rmaxsq - rsq) < (rsq - rminsq))
1671 checkout = kTRUE;
1672 // check if on Rmax boundary
1673 if (checkout && (rmax - r < safphi)) {
1674 if (rdotn >= 0)
1675 return TGeoShape::Big();
1676 return 0.0;
1677 }
1679 return TGeoShape::Big();
1680 // check if on phi boundary
1682 // We may cross again a phi of rmin boundary
1683 // check first if we are on phi1 or phi2
1684 Double_t un;
1685 if (point[0] * c1 + point[1] * s1 > point[0] * c2 + point[1] * s2) {
1686 un = dir[0] * s1 - dir[1] * c1;
1687 if (un < 0)
1688 return 0.0;
1689 if (cdfi >= 0)
1690 return TGeoShape::Big();
1691 un = -dir[0] * s2 + dir[1] * c2;
1692 if (un < 0) {
1693 s = -point[0] * s2 + point[1] * c2;
1694 if (s > 0) {
1695 s /= (-un);
1696 zi = point[2] + s * dir[2];
1697 if (TMath::Abs(zi) <= dz) {
1698 xi = point[0] + s * dir[0];
1699 yi = point[1] + s * dir[1];
1700 r2 = xi * xi + yi * yi;
1701 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1702 if ((yi * cm - xi * sm) > 0)
1703 return s;
1704 }
1705 }
1706 }
1707 }
1708 } else {
1709 un = -dir[0] * s2 + dir[1] * c2;
1710 if (un < 0)
1711 return 0.0;
1712 if (cdfi >= 0)
1713 return TGeoShape::Big();
1714 un = dir[0] * s1 - dir[1] * c1;
1715 if (un < 0) {
1716 s = point[0] * s1 - point[1] * c1;
1717 if (s > 0) {
1718 s /= (-un);
1719 zi = point[2] + s * dir[2];
1720 if (TMath::Abs(zi) <= dz) {
1721 xi = point[0] + s * dir[0];
1722 yi = point[1] + s * dir[1];
1723 r2 = xi * xi + yi * yi;
1724 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1725 if ((yi * cm - xi * sm) < 0)
1726 return s;
1727 }
1728 }
1729 }
1730 }
1731 }
1732 // We may also cross rmin, (+) solution
1733 if (rdotn >= 0)
1734 return TGeoShape::Big();
1735 if (cdfi >= 0)
1736 return TGeoShape::Big();
1737 DistToTube(rsq, nsq, rdotn, rmin, b, d);
1738 if (d > 0) {
1739 s = -b + d;
1740 if (s > 0) {
1741 zi = point[2] + s * dir[2];
1742 if (TMath::Abs(zi) <= dz) {
1743 xi = point[0] + s * dir[0];
1744 yi = point[1] + s * dir[1];
1745 if ((xi * cm + yi * sm) >= rmin * cdfi)
1746 return s;
1747 }
1748 }
1749 }
1750 return TGeoShape::Big();
1751 }
1752 // we are on rmin boundary: we may cross again rmin or a phi facette
1753 if (rdotn >= 0)
1754 return 0.0;
1755 DistToTube(rsq, nsq, rdotn, rmin, b, d);
1756 if (d > 0) {
1757 s = -b + d;
1758 if (s > 0) {
1759 zi = point[2] + s * dir[2];
1760 if (TMath::Abs(zi) <= dz) {
1761 // now check phi range
1762 xi = point[0] + s * dir[0];
1763 yi = point[1] + s * dir[1];
1764 if ((xi * cm + yi * sm) >= rmin * cdfi)
1765 return s;
1766 // now we really have to check any phi crossing
1767 Double_t un = -dir[0] * s1 + dir[1] * c1;
1768 if (un > 0) {
1769 s = point[0] * s1 - point[1] * c1;
1770 if (s >= 0) {
1771 s /= un;
1772 zi = point[2] + s * dir[2];
1773 if (TMath::Abs(zi) <= dz) {
1774 xi = point[0] + s * dir[0];
1775 yi = point[1] + s * dir[1];
1776 r2 = xi * xi + yi * yi;
1777 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1778 if ((yi * cm - xi * sm) <= 0) {
1779 if (s < snxt)
1780 snxt = s;
1781 }
1782 }
1783 }
1784 }
1785 }
1786 un = dir[0] * s2 - dir[1] * c2;
1787 if (un > 0) {
1788 s = (point[1] * c2 - point[0] * s2) / un;
1789 if (s >= 0 && s < snxt) {
1790 zi = point[2] + s * dir[2];
1791 if (TMath::Abs(zi) <= dz) {
1792 xi = point[0] + s * dir[0];
1793 yi = point[1] + s * dir[1];
1794 r2 = xi * xi + yi * yi;
1795 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1796 if ((yi * cm - xi * sm) >= 0) {
1797 return s;
1798 }
1799 }
1800 }
1801 }
1802 }
1803 return snxt;
1804 }
1805 }
1806 }
1807 return TGeoShape::Big();
1808 }
1809 // only r>rmax has to be considered
1811 return TGeoShape::Big();
1812 if (rsq >= rmax * rmax) {
1813 if (rdotn >= 0)
1814 return TGeoShape::Big();
1816 if (d > 0) {
1817 s = -b - d;
1818 if (s > 0) {
1819 zi = point[2] + s * dir[2];
1820 if (TMath::Abs(zi) <= dz) {
1821 xi = point[0] + s * dir[0];
1822 yi = point[1] + s * dir[1];
1823 cpsi = xi * cm + yi * sm;
1824 if (cpsi >= rmax * cdfi)
1825 return s;
1826 }
1827 }
1828 }
1829 }
1830 // check inner cylinder
1831 if (rmin > 0) {
1833 if (d > 0) {
1834 s = -b + d;
1835 if (s > 0) {
1836 zi = point[2] + s * dir[2];
1837 if (TMath::Abs(zi) <= dz) {
1838 xi = point[0] + s * dir[0];
1839 yi = point[1] + s * dir[1];
1840 cpsi = xi * cm + yi * sm;
1841 if (cpsi >= rmin * cdfi)
1842 snxt = s;
1843 }
1844 }
1845 }
1846 }
1847 // check phi planes
1848 Double_t un = -dir[0] * s1 + dir[1] * c1;
1849 if (un > 0) {
1850 s = point[0] * s1 - point[1] * c1;
1851 if (s >= 0) {
1852 s /= un;
1853 zi = point[2] + s * dir[2];
1854 if (TMath::Abs(zi) <= dz) {
1855 xi = point[0] + s * dir[0];
1856 yi = point[1] + s * dir[1];
1857 r2 = xi * xi + yi * yi;
1858 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1859 if ((yi * cm - xi * sm) <= 0) {
1860 if (s < snxt)
1861 snxt = s;
1862 }
1863 }
1864 }
1865 }
1866 }
1867 un = dir[0] * s2 - dir[1] * c2;
1868 if (un > 0) {
1869 s = point[1] * c2 - point[0] * s2;
1870 if (s >= 0) {
1871 s /= un;
1872 zi = point[2] + s * dir[2];
1873 if (TMath::Abs(zi) <= dz) {
1874 xi = point[0] + s * dir[0];
1875 yi = point[1] + s * dir[1];
1876 r2 = xi * xi + yi * yi;
1877 if ((rminsq <= r2) && (r2 <= rmaxsq)) {
1878 if ((yi * cm - xi * sm) >= 0) {
1879 if (s < snxt)
1880 snxt = s;
1881 }
1882 }
1883 }
1884 }
1885 }
1886 return snxt;
1887}
1888
1889////////////////////////////////////////////////////////////////////////////////
1890/// compute distance from outside point to surface of the tube segment
1891/// fist localize point w.r.t tube
1892
1894 Double_t *safe) const
1895{
1896 if (iact < 3 && safe) {
1897 *safe = SafetyS(point, kFALSE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1898 if (iact == 0)
1899 return TGeoShape::Big();
1900 if ((iact == 1) && (step <= *safe))
1901 return TGeoShape::Big();
1902 }
1903 // Check if the bounding box is crossed within the requested distance
1904 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
1905 if (sdist >= step)
1906 return TGeoShape::Big();
1907 if ((fPhi2 - fPhi1) >= 360.)
1908 return TGeoTube::DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
1909
1910 // find distance to shape
1911 return TGeoTubeSeg::DistFromOutsideS(point, dir, fRmin, fRmax, fDz, fC1, fS1, fC2, fS2, fCm, fSm, fCdfi);
1912}
1913
1914////////////////////////////////////////////////////////////////////////////////
1915/// Divide this tube segment shape belonging to volume "voldiv" into ndiv volumes
1916/// called divname, from start position with the given step. Returns pointer
1917/// to created division cell volume in case of Z divisions. For radialdivision
1918/// creates all volumes with different shapes and returns pointer to volume that
1919/// was divided. In case a wrong division axis is supplied, returns pointer to
1920/// volume that was divided.
1921
1922TGeoVolume *
1924{
1925 TGeoShape *shape; //--- shape to be created
1926 TGeoVolume *vol; //--- division volume to be created
1927 TGeoVolumeMulti *vmulti; //--- generic divided volume
1928 TGeoPatternFinder *finder; //--- finder to be attached
1929 TString opt = ""; //--- option to be attached
1930 Double_t dphi;
1931 Int_t id;
1932 Double_t end = start + ndiv * step;
1933 switch (iaxis) {
1934 case 1: //--- R division
1935 finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
1937 voldiv->SetFinder(finder);
1938 finder->SetDivIndex(voldiv->GetNdaughters());
1939 for (id = 0; id < ndiv; id++) {
1940 shape = new TGeoTubeSeg(start + id * step, start + (id + 1) * step, fDz, fPhi1, fPhi2);
1941 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1942 vmulti->AddVolume(vol);
1943 opt = "R";
1944 voldiv->AddNodeOffset(vol, id, 0, opt.Data());
1945 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1946 }
1947 return vmulti;
1948 case 2: //--- Phi division
1949 dphi = fPhi2 - fPhi1;
1950 if (dphi < 0)
1951 dphi += 360.;
1952 if (step <= 0) {
1953 step = dphi / ndiv;
1954 start = fPhi1;
1955 end = fPhi2;
1956 }
1957 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
1958 voldiv->SetFinder(finder);
1959 finder->SetDivIndex(voldiv->GetNdaughters());
1960 shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step / 2, step / 2);
1961 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1963 vmulti->AddVolume(vol);
1964 opt = "Phi";
1965 for (id = 0; id < ndiv; id++) {
1966 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
1967 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1968 }
1969 return vmulti;
1970 case 3: //--- Z division
1971 finder = new TGeoPatternZ(voldiv, ndiv, start, end);
1972 voldiv->SetFinder(finder);
1973 finder->SetDivIndex(voldiv->GetNdaughters());
1974 shape = new TGeoTubeSeg(fRmin, fRmax, step / 2, fPhi1, fPhi2);
1975 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1977 vmulti->AddVolume(vol);
1978 opt = "Z";
1979 for (id = 0; id < ndiv; id++) {
1980 voldiv->AddNodeOffset(vol, id, start + step / 2 + id * step, opt.Data());
1981 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1982 }
1983 return vmulti;
1984 default: Error("Divide", "In shape %s wrong axis type for division", GetName()); return nullptr;
1985 }
1986}
1987
1988////////////////////////////////////////////////////////////////////////////////
1989/// Get range of shape for a given axis.
1990
1992{
1993 xlo = 0;
1994 xhi = 0;
1995 Double_t dx = 0;
1996 switch (iaxis) {
1997 case 1:
1998 xlo = fRmin;
1999 xhi = fRmax;
2000 dx = xhi - xlo;
2001 return dx;
2002 case 2:
2003 xlo = fPhi1;
2004 xhi = fPhi2;
2005 dx = xhi - xlo;
2006 return dx;
2007 case 3:
2008 xlo = -fDz;
2009 xhi = fDz;
2010 dx = xhi - xlo;
2011 return dx;
2012 }
2013 return dx;
2014}
2015
2016////////////////////////////////////////////////////////////////////////////////
2017/// Fill vector param[4] with the bounding cylinder parameters. The order
2018/// is the following : Rmin, Rmax, Phi1, Phi2
2019
2021{
2022 param[0] = fRmin;
2023 param[0] *= param[0];
2024 param[1] = fRmax;
2025 param[1] *= param[1];
2026 param[2] = fPhi1;
2027 param[3] = fPhi2;
2028}
2029
2030////////////////////////////////////////////////////////////////////////////////
2031/// in case shape has some negative parameters, these has to be computed
2032/// in order to fit the mother
2033
2035{
2037 return nullptr;
2038 if (!mother->TestShapeBit(kGeoTube)) {
2039 Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
2040 return nullptr;
2041 }
2042 Double_t rmin, rmax, dz;
2043 rmin = fRmin;
2044 rmax = fRmax;
2045 dz = fDz;
2046 if (fDz < 0)
2047 dz = ((TGeoTube *)mother)->GetDz();
2048 if (fRmin < 0)
2049 rmin = ((TGeoTube *)mother)->GetRmin();
2050 if ((fRmax < 0) || (fRmax <= fRmin))
2051 rmax = ((TGeoTube *)mother)->GetRmax();
2052
2053 return (new TGeoTubeSeg(GetName(), rmin, rmax, dz, fPhi1, fPhi2));
2054}
2055
2056////////////////////////////////////////////////////////////////////////////////
2057/// print shape parameters
2058
2060{
2061 printf("*** Shape %s: TGeoTubeSeg ***\n", GetName());
2062 printf(" Rmin = %11.5f\n", fRmin);
2063 printf(" Rmax = %11.5f\n", fRmax);
2064 printf(" dz = %11.5f\n", fDz);
2065 printf(" phi1 = %11.5f\n", fPhi1);
2066 printf(" phi2 = %11.5f\n", fPhi2);
2067 printf(" Bounding box:\n");
2069}
2070
2071////////////////////////////////////////////////////////////////////////////////
2072/// Fill TBuffer3D structure for segments and polygons.
2073
2075{
2076 Int_t i, j;
2078 Int_t c = GetBasicColor();
2079
2080 memset(buff.fSegs, 0, buff.NbSegs() * 3 * sizeof(Int_t));
2081 for (i = 0; i < 4; i++) {
2082 for (j = 1; j < n; j++) {
2083 buff.fSegs[(i * n + j - 1) * 3] = c;
2084 buff.fSegs[(i * n + j - 1) * 3 + 1] = i * n + j - 1;
2085 buff.fSegs[(i * n + j - 1) * 3 + 2] = i * n + j;
2086 }
2087 }
2088 for (i = 4; i < 6; i++) {
2089 for (j = 0; j < n; j++) {
2090 buff.fSegs[(i * n + j) * 3] = c + 1;
2091 buff.fSegs[(i * n + j) * 3 + 1] = (i - 4) * n + j;
2092 buff.fSegs[(i * n + j) * 3 + 2] = (i - 2) * n + j;
2093 }
2094 }
2095 for (i = 6; i < 8; i++) {
2096 for (j = 0; j < n; j++) {
2097 buff.fSegs[(i * n + j) * 3] = c;
2098 buff.fSegs[(i * n + j) * 3 + 1] = 2 * (i - 6) * n + j;
2099 buff.fSegs[(i * n + j) * 3 + 2] = (2 * (i - 6) + 1) * n + j;
2100 }
2101 }
2102
2103 Int_t indx = 0;
2104 memset(buff.fPols, 0, buff.NbPols() * 6 * sizeof(Int_t));
2105 i = 0;
2106 for (j = 0; j < n - 1; j++) {
2107 buff.fPols[indx++] = c;
2108 buff.fPols[indx++] = 4;
2109 buff.fPols[indx++] = (4 + i) * n + j + 1;
2110 buff.fPols[indx++] = (2 + i) * n + j;
2111 buff.fPols[indx++] = (4 + i) * n + j;
2112 buff.fPols[indx++] = i * n + j;
2113 }
2114 i = 1;
2115 for (j = 0; j < n - 1; j++) {
2116 buff.fPols[indx++] = c;
2117 buff.fPols[indx++] = 4;
2118 buff.fPols[indx++] = i * n + j;
2119 buff.fPols[indx++] = (4 + i) * n + j;
2120 buff.fPols[indx++] = (2 + i) * n + j;
2121 buff.fPols[indx++] = (4 + i) * n + j + 1;
2122 }
2123 i = 2;
2124 for (j = 0; j < n - 1; j++) {
2125 buff.fPols[indx++] = c + i;
2126 buff.fPols[indx++] = 4;
2127 buff.fPols[indx++] = (i - 2) * 2 * n + j;
2128 buff.fPols[indx++] = (4 + i) * n + j;
2129 buff.fPols[indx++] = ((i - 2) * 2 + 1) * n + j;
2130 buff.fPols[indx++] = (4 + i) * n + j + 1;
2131 }
2132 i = 3;
2133 for (j = 0; j < n - 1; j++) {
2134 buff.fPols[indx++] = c + i;
2135 buff.fPols[indx++] = 4;
2136 buff.fPols[indx++] = (4 + i) * n + j + 1;
2137 buff.fPols[indx++] = ((i - 2) * 2 + 1) * n + j;
2138 buff.fPols[indx++] = (4 + i) * n + j;
2139 buff.fPols[indx++] = (i - 2) * 2 * n + j;
2140 }
2141 buff.fPols[indx++] = c + 2;
2142 buff.fPols[indx++] = 4;
2143 buff.fPols[indx++] = 6 * n;
2144 buff.fPols[indx++] = 4 * n;
2145 buff.fPols[indx++] = 7 * n;
2146 buff.fPols[indx++] = 5 * n;
2147 buff.fPols[indx++] = c + 2;
2148 buff.fPols[indx++] = 4;
2149 buff.fPols[indx++] = 6 * n - 1;
2150 buff.fPols[indx++] = 8 * n - 1;
2151 buff.fPols[indx++] = 5 * n - 1;
2152 buff.fPols[indx++] = 7 * n - 1;
2153}
2154
2155////////////////////////////////////////////////////////////////////////////////
2156/// computes the closest distance from given point InitTrigonometry();to this shape, according
2157/// to option. The matching point on the shape is stored in spoint.
2158
2160{
2161 Double_t saf[3];
2162 Double_t rsq = point[0] * point[0] + point[1] * point[1];
2164 if (in) {
2165 saf[0] = fDz - TMath::Abs(point[2]);
2166 saf[1] = r - fRmin;
2167 saf[2] = fRmax - r;
2169 if ((fPhi2 - fPhi1) >= 360.)
2170 return safe;
2172 return TMath::Min(safe, safphi);
2173 }
2174 // Point expected to be outside
2176 Double_t cpsi = point[0] * fCm + point[1] * fSm;
2177 saf[0] = TMath::Abs(point[2]) - fDz;
2178 if (cpsi > r * fCdfi - TGeoShape::Tolerance())
2179 inphi = kTRUE;
2180 if (inphi) {
2181 saf[1] = fRmin - r;
2182 saf[2] = r - fRmax;
2184 safe = TMath::Max(0., safe);
2185 return safe;
2186 }
2187 // Point outside the phi range
2188 // Compute projected radius of the (r,phi) position vector onto
2189 // phi1 and phi2 edges and take the maximum for choosing the side.
2190 Double_t rproj = TMath::Max(point[0] * fC1 + point[1] * fS1, point[0] * fC2 + point[1] * fS2);
2191 saf[1] = fRmin - rproj;
2192 saf[2] = rproj - fRmax;
2193 Double_t safe = TMath::Max(saf[1], saf[2]);
2194 if ((fPhi2 - fPhi1) >= 360.)
2195 return TMath::Max(safe, saf[0]);
2196 if (safe > 0) {
2197 // rproj not within (rmin,rmax) - > no need to calculate safphi
2198 safe = TMath::Sqrt(rsq - rproj * rproj + safe * safe);
2199 return (saf[0] < 0) ? safe : TMath::Sqrt(safe * safe + saf[0] * saf[0]);
2200 }
2202 return (saf[0] < 0) ? safphi : TMath::Sqrt(saf[0] * saf[0] + safphi * safphi);
2203}
2204
2205////////////////////////////////////////////////////////////////////////////////
2206/// Static method to compute the closest distance from given point to this shape.
2207
2210{
2211 Double_t saf[3];
2212 Double_t rsq = point[0] * point[0] + point[1] * point[1];
2214
2215 switch (skipz) {
2216 case 1: // skip lower Z plane
2217 saf[0] = dz - point[2];
2218 break;
2219 case 2: // skip upper Z plane
2220 saf[0] = dz + point[2];
2221 break;
2222 case 3: // skip both
2223 saf[0] = TGeoShape::Big();
2224 break;
2225 default: saf[0] = dz - TMath::Abs(point[2]);
2226 }
2227
2228 if (in) {
2229 saf[1] = r - rmin;
2230 saf[2] = rmax - r;
2232 if ((phi2d - phi1d) >= 360.)
2233 return safe;
2235 return TMath::Min(safe, safphi);
2236 }
2237 // Point expected to be outside
2238 saf[0] = -saf[0];
2242
2243 Double_t fio = 0.5 * (phi1 + phi2);
2244 Double_t cm = TMath::Cos(fio);
2246 Double_t cpsi = point[0] * cm + point[1] * sm;
2247 Double_t dfi = 0.5 * (phi2 - phi1);
2249 if (cpsi > r * cdfi - TGeoShape::Tolerance())
2250 inphi = kTRUE;
2251 if (inphi) {
2252 saf[1] = rmin - r;
2253 saf[2] = r - rmax;
2255 safe = TMath::Max(0., safe);
2256 return safe;
2257 }
2258 // Point outside the phi range
2259 // Compute projected radius of the (r,phi) position vector onto
2260 // phi1 and phi2 edges and take the maximum for choosing the side.
2265
2266 Double_t rproj = TMath::Max(point[0] * c1 + point[1] * s1, point[0] * c2 + point[1] * s2);
2267 saf[1] = rmin - rproj;
2268 saf[2] = rproj - rmax;
2269 Double_t safe = TMath::Max(saf[1], saf[2]);
2270 if ((phi2d - phi1d) >= 360.)
2271 return TMath::Max(safe, saf[0]);
2272 if (safe > 0) {
2273 // rproj not within (rmin,rmax) - > no need to calculate safphi
2274 safe = TMath::Sqrt(rsq - rproj * rproj + safe * safe);
2275 return (saf[0] < 0) ? safe : TMath::Sqrt(safe * safe + saf[0] * saf[0]);
2276 }
2278 return (saf[0] < 0) ? safphi : TMath::Sqrt(saf[0] * saf[0] + safphi * safphi);
2279}
2280
2281////////////////////////////////////////////////////////////////////////////////
2282/// Save a primitive as a C++ statement(s) on output stream "out".
2283
2284void TGeoTubeSeg::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2285{
2287 return;
2288 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2289 out << " rmin = " << fRmin << ";" << std::endl;
2290 out << " rmax = " << fRmax << ";" << std::endl;
2291 out << " dz = " << fDz << ";" << std::endl;
2292 out << " phi1 = " << fPhi1 << ";" << std::endl;
2293 out << " phi2 = " << fPhi2 << ";" << std::endl;
2294 out << " TGeoShape *" << GetPointerName() << " = new TGeoTubeSeg(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2);"
2295 << std::endl;
2297}
2298
2299////////////////////////////////////////////////////////////////////////////////
2300/// Set dimensions of the tube segment.
2301/// The segment will be from phiStart to phiEnd expressed in degree.
2302
2304{
2305 fRmin = rmin;
2306 fRmax = rmax;
2307 fDz = dz;
2308 fPhi1 = phiStart;
2309 if (fPhi1 < 0)
2310 fPhi1 += 360.;
2311 fPhi2 = phiEnd;
2312 while (fPhi2 <= fPhi1)
2313 fPhi2 += 360.;
2315 Fatal("SetTubsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
2317}
2318
2319////////////////////////////////////////////////////////////////////////////////
2320/// Set dimensions of the tube segment starting from a list.
2321
2323{
2324 Double_t rmin = param[0];
2325 Double_t rmax = param[1];
2326 Double_t dz = param[2];
2327 Double_t phi1 = param[3];
2328 Double_t phi2 = param[4];
2330}
2331
2332////////////////////////////////////////////////////////////////////////////////
2333/// Fills array with n random points located on the line segments of the shape mesh.
2334/// The output array must be provided with a length of minimum 3*npoints. Returns
2335/// true if operation is implemented.
2336
2338{
2339 if (!array || npoints <= 0)
2340 return kFALSE;
2341
2342 if (fDz <= 0.0 || fRmax <= 0.0)
2343 return kFALSE;
2344
2345 // Angular span in radians
2346 const Double_t phi1 = fPhi1 * TMath::DegToRad();
2347 const Double_t phi2 = fPhi2 * TMath::DegToRad();
2348 const Double_t dPhiTot = phi2 - phi1;
2349
2350 // Must have a non-degenerate segment
2351 if (!(dPhiTot > 0.0))
2352 return kFALSE;
2353
2354 const Bool_t hasInner = (fRmin > 0.0);
2355
2356 // Split budget: outer gets the extra point if odd
2358 Int_t inPoints = 0;
2359 if (hasInner) {
2360 outPoints = (npoints + 1) / 2;
2362 }
2363
2365 if (nSurfPoints <= 0)
2366 return kTRUE;
2367 if (r <= 0.0)
2368 return kFALSE;
2369
2370 // Number of generators ~ sqrt(n), clamp to [1, nSurfPoints]
2372 if (nGen < 1)
2373 nGen = 1;
2374 if (nGen > nSurfPoints)
2375 nGen = nSurfPoints;
2376
2377 const Int_t q = nSurfPoints / nGen;
2378 const Int_t rem = nSurfPoints % nGen;
2379
2380 // Use generator centers: never exactly phi1 or phi2
2381 const Double_t dphi = dPhiTot / (Double_t)nGen;
2382
2383 for (Int_t ig = 0; ig < nGen; ++ig) {
2384 const Int_t m = q + (ig < rem ? 1 : 0);
2385 if (m <= 0)
2386 continue;
2387
2388 const Double_t phi = phi1 + (ig + 0.5) * dphi; // avoid endpoints
2389 const Double_t c = TMath::Cos(phi);
2390 const Double_t s = TMath::Sin(phi);
2391
2392 // Interior z: t in (0,1) => avoids z=±dz
2393 for (Int_t j = 0; j < m; ++j) {
2394 if (icrt + 3 > 3 * npoints)
2395 return kFALSE; // overflow guard
2396
2397 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1);
2398 const Double_t z = -fDz + t * (2.0 * fDz);
2399
2400 array[icrt++] = r * c;
2401 array[icrt++] = r * s;
2402 array[icrt++] = z;
2403 }
2404 }
2405 return kTRUE;
2406 };
2407
2408 Int_t icrt = 0;
2409
2410 // Outer cylindrical surface first
2412 return kFALSE;
2413
2414 // Inner cylindrical surface (if any)
2415 if (hasInner) {
2416 if (!fillCylSeg(inPoints, fRmin, icrt))
2417 return kFALSE;
2418 }
2419
2420 // Contract: must fill exactly npoints
2421 return (icrt == 3 * npoints) ? kTRUE : kFALSE;
2422}
2423
2424////////////////////////////////////////////////////////////////////////////////
2425/// Create tube segment mesh points.
2426
2428{
2429 Double_t dz;
2430 Int_t j, n;
2431 Double_t phi, phi1, phi2, dphi;
2432 phi1 = fPhi1;
2433 phi2 = fPhi2;
2434 if (phi2 < phi1)
2435 phi2 += 360.;
2436 n = gGeoManager->GetNsegments() + 1;
2437
2438 dphi = (phi2 - phi1) / (n - 1);
2439 dz = fDz;
2440
2441 if (points) {
2442 Int_t indx = 0;
2443
2444 for (j = 0; j < n; j++) {
2445 phi = (phi1 + j * dphi) * TMath::DegToRad();
2446 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
2447 indx++;
2448 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
2449 indx++;
2450 points[indx + 6 * n] = dz;
2451 points[indx] = -dz;
2452 indx++;
2453 }
2454 for (j = 0; j < n; j++) {
2455 phi = (phi1 + j * dphi) * TMath::DegToRad();
2456 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
2457 indx++;
2458 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
2459 indx++;
2460 points[indx + 6 * n] = dz;
2461 points[indx] = -dz;
2462 indx++;
2463 }
2464 }
2465}
2466
2467////////////////////////////////////////////////////////////////////////////////
2468/// Create tube segment mesh points.
2469
2471{
2472 Double_t dz;
2473 Int_t j, n;
2474 Double_t phi, phi1, phi2, dphi;
2475 phi1 = fPhi1;
2476 phi2 = fPhi2;
2477 if (phi2 < phi1)
2478 phi2 += 360.;
2479 n = gGeoManager->GetNsegments() + 1;
2480
2481 dphi = (phi2 - phi1) / (n - 1);
2482 dz = fDz;
2483
2484 if (points) {
2485 Int_t indx = 0;
2486
2487 for (j = 0; j < n; j++) {
2488 phi = (phi1 + j * dphi) * TMath::DegToRad();
2489 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
2490 indx++;
2491 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
2492 indx++;
2493 points[indx + 6 * n] = dz;
2494 points[indx] = -dz;
2495 indx++;
2496 }
2497 for (j = 0; j < n; j++) {
2498 phi = (phi1 + j * dphi) * TMath::DegToRad();
2499 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
2500 indx++;
2501 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
2502 indx++;
2503 points[indx + 6 * n] = dz;
2504 points[indx] = -dz;
2505 indx++;
2506 }
2507 }
2508}
2509
2510////////////////////////////////////////////////////////////////////////////////
2511/// Returns numbers of vertices, segments and polygons composing the shape mesh.
2512
2514{
2516 nvert = n * 4;
2517 nsegs = n * 8;
2518 npols = n * 4 - 2;
2519}
2520
2521////////////////////////////////////////////////////////////////////////////////
2522/// Return number of vertices of the mesh representation
2523
2525{
2527 Int_t numPoints = n * 4;
2528 return numPoints;
2529}
2530
2531////////////////////////////////////////////////////////////////////////////////
2532/// fill size of this 3-D object
2533
2535
2536////////////////////////////////////////////////////////////////////////////////
2537/// Fills a static 3D buffer and returns a reference.
2538
2540{
2541 static TBuffer3DTubeSeg buffer;
2543
2545 // These from TBuffer3DTube / TGeoTube
2546 buffer.fRadiusInner = fRmin;
2547 buffer.fRadiusOuter = fRmax;
2548 buffer.fHalfLength = fDz;
2549 buffer.fPhiMin = fPhi1;
2550 buffer.fPhiMax = fPhi2;
2552 }
2555 Int_t nbPnts = 4 * n;
2556 Int_t nbSegs = 2 * nbPnts;
2557 Int_t nbPols = nbPnts - 2;
2558 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
2560 }
2561 }
2563 SetPoints(buffer.fPnts);
2564 if (!buffer.fLocalFrame) {
2565 TransformPoints(buffer.fPnts, buffer.NbPnts());
2566 }
2567 SetSegsAndPols(buffer);
2569 }
2570
2571 return buffer;
2572}
2573
2574////////////////////////////////////////////////////////////////////////////////
2575/// Check the inside status for each of the points in the array.
2576/// Input: Array of point coordinates + vector size
2577/// Output: Array of Booleans for the inside of each point
2578
2580{
2581 for (Int_t i = 0; i < vecsize; i++)
2582 inside[i] = Contains(&points[3 * i]);
2583}
2584
2585////////////////////////////////////////////////////////////////////////////////
2586/// Compute the normal for an array o points so that norm.dot.dir is positive
2587/// Input: Arrays of point coordinates and directions + vector size
2588/// Output: Array of normal directions
2589
2591{
2592 for (Int_t i = 0; i < vecsize; i++)
2593 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
2594}
2595
2596////////////////////////////////////////////////////////////////////////////////
2597/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2598
2600 Double_t *step) const
2601{
2602 for (Int_t i = 0; i < vecsize; i++)
2603 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2604}
2605
2606////////////////////////////////////////////////////////////////////////////////
2607/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2608
2610 Double_t *step) const
2611{
2612 for (Int_t i = 0; i < vecsize; i++)
2613 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2614}
2615
2616////////////////////////////////////////////////////////////////////////////////
2617/// Compute safe distance from each of the points in the input array.
2618/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
2619/// Output: Safety values
2620
2622{
2623 for (Int_t i = 0; i < vecsize; i++)
2624 safe[i] = Safety(&points[3 * i], inside[i]);
2625}
2626
2628{
2629 // default ctor
2630 fNlow[0] = fNlow[1] = fNhigh[0] = fNhigh[1] = 0.;
2631 fNlow[2] = -1;
2632 fNhigh[2] = 1;
2633}
2634
2635////////////////////////////////////////////////////////////////////////////////
2636/// constructor
2637
2641{
2642 fNlow[0] = lx;
2643 fNlow[1] = ly;
2644 fNlow[2] = lz;
2645 fNhigh[0] = tx;
2646 fNhigh[1] = ty;
2647 fNhigh[2] = tz;
2649 ComputeBBox();
2650}
2651
2652////////////////////////////////////////////////////////////////////////////////
2653/// constructor
2654
2658{
2659 fNlow[0] = lx;
2660 fNlow[1] = ly;
2661 fNlow[2] = lz;
2662 fNhigh[0] = tx;
2663 fNhigh[1] = ty;
2664 fNhigh[2] = tz;
2666 ComputeBBox();
2667}
2668
2669////////////////////////////////////////////////////////////////////////////////
2670/// ctor with parameters
2671
2672TGeoCtub::TGeoCtub(Double_t *params) : TGeoTubeSeg(0, 0, 0, 0, 0)
2673{
2674 SetCtubDimensions(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8],
2675 params[9], params[10]);
2677}
2678
2679////////////////////////////////////////////////////////////////////////////////
2680/// destructor
2681
2683
2684////////////////////////////////////////////////////////////////////////////////
2685/// Computes capacity of the shape in [length^3]
2686
2688{
2689 Double_t capacity = TGeoTubeSeg::Capacity();
2690 return capacity;
2691}
2692
2693////////////////////////////////////////////////////////////////////////////////
2694/// compute minimum bounding box of the ctub
2695
2697{
2699 if ((fNlow[2] > -(1E-10)) || (fNhigh[2] < 1E-10)) {
2700 Error("ComputeBBox", "In shape %s wrong definition of cut planes", GetName());
2701 return;
2702 }
2703 Double_t xc = 0, yc = 0;
2704 Double_t zmin = 0, zmax = 0;
2705 Double_t z1;
2706 Double_t z[8];
2707 // check if nxy is in the phi range
2712
2713 Int_t i;
2714 for (i = 0; i < 2; i++) {
2715 if (phi_low < 0)
2716 phi_low += 360.;
2718 if (dphi < 0)
2719 dphi += 360.;
2721 if (ddp < 0)
2722 ddp += 360.;
2723 if (ddp <= dphi) {
2726 z1 = GetZcoord(xc, yc, -fDz);
2729 z1 = TMath::Min(z1, GetZcoord(xc, yc, -fDz));
2730 if (in_range_low)
2731 zmin = TMath::Min(zmin, z1);
2732 else
2733 zmin = z1;
2735 }
2736 phi_low += 180;
2737 if (phi_low > 360)
2738 phi_low -= 360.;
2739 }
2740
2741 for (i = 0; i < 2; i++) {
2742 if (phi_hi < 0)
2743 phi_hi += 360.;
2745 if (dphi < 0)
2746 dphi += 360.;
2748 if (ddp < 0)
2749 ddp += 360.;
2750 if (ddp <= dphi) {
2753 z1 = GetZcoord(xc, yc, fDz);
2756 z1 = TMath::Max(z1, GetZcoord(xc, yc, fDz));
2757 if (in_range_hi)
2758 zmax = TMath::Max(zmax, z1);
2759 else
2760 zmax = z1;
2762 }
2763 phi_hi += 180;
2764 if (phi_hi > 360)
2765 phi_hi -= 360.;
2766 }
2767
2768 xc = fRmin * fC1;
2769 yc = fRmin * fS1;
2770 z[0] = GetZcoord(xc, yc, -fDz);
2771 z[4] = GetZcoord(xc, yc, fDz);
2772
2773 xc = fRmin * fC2;
2774 yc = fRmin * fS2;
2775 z[1] = GetZcoord(xc, yc, -fDz);
2776 z[5] = GetZcoord(xc, yc, fDz);
2777
2778 xc = fRmax * fC1;
2779 yc = fRmax * fS1;
2780 z[2] = GetZcoord(xc, yc, -fDz);
2781 z[6] = GetZcoord(xc, yc, fDz);
2782
2783 xc = fRmax * fC2;
2784 yc = fRmax * fS2;
2785 z[3] = GetZcoord(xc, yc, -fDz);
2786 z[7] = GetZcoord(xc, yc, fDz);
2787
2788 z1 = z[TMath::LocMin(4, &z[0])];
2789 if (in_range_low)
2790 zmin = TMath::Min(zmin, z1);
2791 else
2792 zmin = z1;
2793
2794 z1 = z[TMath::LocMax(4, &z[4]) + 4];
2795 if (in_range_hi)
2796 zmax = TMath::Max(zmax, z1);
2797 else
2798 zmax = z1;
2799
2800 fDZ = 0.5 * (zmax - zmin);
2801 fOrigin[2] = 0.5 * (zmax + zmin);
2802}
2803
2804////////////////////////////////////////////////////////////////////////////////
2805/// Compute normal to closest surface from POINT.
2806
2807void TGeoCtub::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
2808{
2809 Double_t saf[4];
2810 Bool_t isseg = kTRUE;
2811 if (TMath::Abs(fPhi2 - fPhi1 - 360.) < 1E-8)
2812 isseg = kFALSE;
2813 Double_t rsq = point[0] * point[0] + point[1] * point[1];
2815
2816 saf[0] = TMath::Abs(point[0] * fNlow[0] + point[1] * fNlow[1] + (fDz + point[2]) * fNlow[2]);
2817 saf[1] = TMath::Abs(point[0] * fNhigh[0] + point[1] * fNhigh[1] - (fDz - point[2]) * fNhigh[2]);
2818 saf[2] = (fRmin > 1E-10) ? TMath::Abs(r - fRmin) : TGeoShape::Big();
2819 saf[3] = TMath::Abs(fRmax - r);
2820 Int_t i = TMath::LocMin(4, saf);
2821 if (isseg) {
2822 if (TGeoShape::IsCloseToPhi(saf[i], point, fC1, fS1, fC2, fS2)) {
2823 TGeoShape::NormalPhi(point, dir, norm, fC1, fS1, fC2, fS2);
2824 return;
2825 }
2826 }
2827 if (i == 0) {
2828 memcpy(norm, fNlow, 3 * sizeof(Double_t));
2829 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
2830 norm[0] = -norm[0];
2831 norm[1] = -norm[1];
2832 norm[2] = -norm[2];
2833 }
2834 return;
2835 }
2836 if (i == 1) {
2837 memcpy(norm, fNhigh, 3 * sizeof(Double_t));
2838 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
2839 norm[0] = -norm[0];
2840 norm[1] = -norm[1];
2841 norm[2] = -norm[2];
2842 }
2843 return;
2844 }
2845
2846 norm[2] = 0;
2847 Double_t phi = TMath::ATan2(point[1], point[0]);
2848 norm[0] = TMath::Cos(phi);
2849 norm[1] = TMath::Sin(phi);
2850 if (norm[0] * dir[0] + norm[1] * dir[1] < 0) {
2851 norm[0] = -norm[0];
2852 norm[1] = -norm[1];
2853 }
2854}
2855
2856////////////////////////////////////////////////////////////////////////////////
2857/// check if point is contained in the cut tube
2858/// check the lower cut plane
2859
2861{
2862 Double_t zin = point[0] * fNlow[0] + point[1] * fNlow[1] + (point[2] + fDz) * fNlow[2];
2863 if (zin > 0)
2864 return kFALSE;
2865 // check the higher cut plane
2866 zin = point[0] * fNhigh[0] + point[1] * fNhigh[1] + (point[2] - fDz) * fNhigh[2];
2867 if (zin > 0)
2868 return kFALSE;
2869 // check radius
2870 Double_t r2 = point[0] * point[0] + point[1] * point[1];
2871 if ((r2 < fRmin * fRmin) || (r2 > fRmax * fRmax))
2872 return kFALSE;
2873 // check phi
2874 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
2875 if (phi < 0)
2876 phi += 360.;
2878 Double_t ddp = phi - fPhi1;
2879 if (ddp < 0)
2880 ddp += 360.;
2881 // if (ddp>360) ddp-=360;
2882 if (ddp > dphi)
2883 return kFALSE;
2884 return kTRUE;
2885}
2886
2887////////////////////////////////////////////////////////////////////////////////
2888/// Get range of shape for a given axis.
2889
2891{
2892 xlo = 0;
2893 xhi = 0;
2894 Double_t dx = 0;
2895 switch (iaxis) {
2896 case 1:
2897 xlo = fRmin;
2898 xhi = fRmax;
2899 dx = xhi - xlo;
2900 return dx;
2901 case 2:
2902 xlo = fPhi1;
2903 xhi = fPhi2;
2904 dx = xhi - xlo;
2905 return dx;
2906 }
2907 return dx;
2908}
2909
2910////////////////////////////////////////////////////////////////////////////////
2911/// compute real Z coordinate of a point belonging to either lower or
2912/// higher caps (z should be either +fDz or -fDz)
2913
2915{
2916 Double_t newz = 0;
2917 if (zc < 0)
2918 newz = -fDz - (xc * fNlow[0] + yc * fNlow[1]) / fNlow[2];
2919 else
2920 newz = fDz - (xc * fNhigh[0] + yc * fNhigh[1]) / fNhigh[2];
2921 return newz;
2922}
2923
2924////////////////////////////////////////////////////////////////////////////////
2925/// compute distance from outside point to surface of the cut tube
2926
2929{
2930 if (iact < 3 && safe) {
2931 *safe = Safety(point, kFALSE);
2932 if (iact == 0)
2933 return TGeoShape::Big();
2934 if ((iact == 1) && (step <= *safe))
2935 return TGeoShape::Big();
2936 }
2937 // Check if the bounding box is crossed within the requested distance
2938 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
2939 if (sdist >= step)
2940 return TGeoShape::Big();
2941 Double_t saf[2];
2942 saf[0] = point[0] * fNlow[0] + point[1] * fNlow[1] + (fDz + point[2]) * fNlow[2];
2943 saf[1] = point[0] * fNhigh[0] + point[1] * fNhigh[1] + (point[2] - fDz) * fNhigh[2];
2944 Double_t rsq = point[0] * point[0] + point[1] * point[1];
2946 Double_t cpsi = 0;
2947 Bool_t tub = kFALSE;
2948 if (TMath::Abs(fPhi2 - fPhi1 - 360.) < 1E-8)
2949 tub = kTRUE;
2950
2951 // find distance to shape
2952 Double_t r2;
2953 Double_t calf = dir[0] * fNlow[0] + dir[1] * fNlow[1] + dir[2] * fNlow[2];
2954 // check Z planes
2955 Double_t xi, yi, zi, s;
2956 if (saf[0] > 0) {
2957 if (calf < 0) {
2958 s = -saf[0] / calf;
2959 xi = point[0] + s * dir[0];
2960 yi = point[1] + s * dir[1];
2961 r2 = xi * xi + yi * yi;
2962 if (((fRmin * fRmin) <= r2) && (r2 <= (fRmax * fRmax))) {
2963 if (tub)
2964 return s;
2965 cpsi = (xi * fCm + yi * fSm) / TMath::Sqrt(r2);
2966 if (cpsi >= fCdfi)
2967 return s;
2968 }
2969 }
2970 }
2971 calf = dir[0] * fNhigh[0] + dir[1] * fNhigh[1] + dir[2] * fNhigh[2];
2972 if (saf[1] > 0) {
2973 if (calf < 0) {
2974 s = -saf[1] / calf;
2975 xi = point[0] + s * dir[0];
2976 yi = point[1] + s * dir[1];
2977 r2 = xi * xi + yi * yi;
2978 if (((fRmin * fRmin) <= r2) && (r2 <= (fRmax * fRmax))) {
2979 if (tub)
2980 return s;
2981 cpsi = (xi * fCm + yi * fSm) / TMath::Sqrt(r2);
2982 if (cpsi >= fCdfi)
2983 return s;
2984 }
2985 }
2986 }
2987
2988 // check outer cyl. surface
2989 Double_t nsq = dir[0] * dir[0] + dir[1] * dir[1];
2990 if (TMath::Abs(nsq) < 1E-10)
2991 return TGeoShape::Big();
2992 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
2993 Double_t b, d;
2994 // only r>fRmax coming inwards has to be considered
2995 if (r > fRmax && rdotn < 0) {
2997 if (d > 0) {
2998 s = -b - d;
2999 if (s > 0) {
3000 xi = point[0] + s * dir[0];
3001 yi = point[1] + s * dir[1];
3002 zi = point[2] + s * dir[2];
3003 if ((-xi * fNlow[0] - yi * fNlow[1] - (zi + fDz) * fNlow[2]) > 0) {
3004 if ((-xi * fNhigh[0] - yi * fNhigh[1] + (fDz - zi) * fNhigh[2]) > 0) {
3005 if (tub)
3006 return s;
3007 cpsi = (xi * fCm + yi * fSm) / fRmax;
3008 if (cpsi >= fCdfi)
3009 return s;
3010 }
3011 }
3012 }
3013 }
3014 }
3015 // check inner cylinder
3017 if (fRmin > 0) {
3019 if (d > 0) {
3020 s = -b + d;
3021 if (s > 0) {
3022 xi = point[0] + s * dir[0];
3023 yi = point[1] + s * dir[1];
3024 zi = point[2] + s * dir[2];
3025 if ((-xi * fNlow[0] - yi * fNlow[1] - (zi + fDz) * fNlow[2]) > 0) {
3026 if ((-xi * fNhigh[0] - yi * fNhigh[1] + (fDz - zi) * fNhigh[2]) > 0) {
3027 if (tub)
3028 return s;
3029 cpsi = (xi * fCm + yi * fSm) / fRmin;
3030 if (cpsi >= fCdfi)
3031 snxt = s;
3032 }
3033 }
3034 }
3035 }
3036 }
3037 // check phi planes
3038 if (tub)
3039 return snxt;
3040 Double_t un = dir[0] * fS1 - dir[1] * fC1;
3041 if (un < -TGeoShape::Tolerance()) {
3042 s = (point[1] * fC1 - point[0] * fS1) / un;
3043 if (s >= 0) {
3044 xi = point[0] + s * dir[0];
3045 yi = point[1] + s * dir[1];
3046 zi = point[2] + s * dir[2];
3047 if ((-xi * fNlow[0] - yi * fNlow[1] - (zi + fDz) * fNlow[2]) > 0) {
3048 if ((-xi * fNhigh[0] - yi * fNhigh[1] + (fDz - zi) * fNhigh[2]) > 0) {
3049 r2 = xi * xi + yi * yi;
3050 if ((fRmin * fRmin <= r2) && (r2 <= fRmax * fRmax)) {
3051 if ((yi * fCm - xi * fSm) <= 0) {
3052 if (s < snxt)
3053 snxt = s;
3054 }
3055 }
3056 }
3057 }
3058 }
3059 }
3060 un = dir[0] * fS2 - dir[1] * fC2;
3061 if (un > TGeoShape::Tolerance()) {
3062 s = (point[1] * fC2 - point[0] * fS2) / un;
3063 if (s >= 0) {
3064 xi = point[0] + s * dir[0];
3065 yi = point[1] + s * dir[1];
3066 zi = point[2] + s * dir[2];
3067 if ((-xi * fNlow[0] - yi * fNlow[1] - (zi + fDz) * fNlow[2]) > 0) {
3068 if ((-xi * fNhigh[0] - yi * fNhigh[1] + (fDz - zi) * fNhigh[2]) > 0) {
3069 r2 = xi * xi + yi * yi;
3070 if ((fRmin * fRmin <= r2) && (r2 <= fRmax * fRmax)) {
3071 if ((yi * fCm - xi * fSm) >= 0) {
3072 if (s < snxt)
3073 snxt = s;
3074 }
3075 }
3076 }
3077 }
3078 }
3079 }
3080 return snxt;
3081}
3082
3083////////////////////////////////////////////////////////////////////////////////
3084/// compute distance from inside point to surface of the cut tube
3085
3088{
3089 if (iact < 3 && safe)
3090 *safe = Safety(point, kTRUE);
3091 if (iact == 0)
3092 return TGeoShape::Big();
3093 if ((iact == 1) && (*safe > step))
3094 return TGeoShape::Big();
3095 Double_t rsq = point[0] * point[0] + point[1] * point[1];
3096 Bool_t tub = kFALSE;
3097 if (TMath::Abs(fPhi2 - fPhi1 - 360.) < 1E-8)
3098 tub = kTRUE;
3099 // compute distance to surface
3100 // Do Z
3102 Double_t saf[2];
3103 saf[0] = -point[0] * fNlow[0] - point[1] * fNlow[1] - (fDz + point[2]) * fNlow[2];
3104 saf[1] = -point[0] * fNhigh[0] - point[1] * fNhigh[1] + (fDz - point[2]) * fNhigh[2];
3105 Double_t calf = dir[0] * fNlow[0] + dir[1] * fNlow[1] + dir[2] * fNlow[2];
3106 if (calf > 0)
3107 sz = saf[0] / calf;
3108
3109 calf = dir[0] * fNhigh[0] + dir[1] * fNhigh[1] + dir[2] * fNhigh[2];
3110 if (calf > 0) {
3111 Double_t sz1 = saf[1] / calf;
3112 if (sz1 < sz)
3113 sz = sz1;
3114 }
3115
3116 // Do R
3117 Double_t nsq = dir[0] * dir[0] + dir[1] * dir[1];
3118 // track parallel to Z
3119 if (TMath::Abs(nsq) < 1E-10)
3120 return sz;
3121 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
3122 Double_t sr = TGeoShape::Big();
3123 Double_t b, d;
3125 // inner cylinder
3126 if (fRmin > 1E-10) {
3128 if (d > 0) {
3129 sr = -b - d;
3130 if (sr > 0)
3131 skip_outer = kTRUE;
3132 }
3133 }
3134 // outer cylinder
3135 if (!skip_outer) {
3137 if (d > 0) {
3138 sr = -b + d;
3139 if (sr < 0)
3140 sr = TGeoShape::Big();
3141 } else {
3142 return 0.; // already outside
3143 }
3144 }
3145 // phi planes
3147 if (!tub)
3148 sfmin = TGeoShape::DistToPhiMin(point, dir, fS1, fC1, fS2, fC2, fSm, fCm);
3149 return TMath::Min(TMath::Min(sz, sr), sfmin);
3150}
3151
3152////////////////////////////////////////////////////////////////////////////////
3153/// Divide the tube along one axis.
3154
3155TGeoVolume *TGeoCtub::Divide(TGeoVolume * /*voldiv*/, const char * /*divname*/, Int_t /*iaxis*/, Int_t /*ndiv*/,
3156 Double_t /*start*/, Double_t /*step*/)
3157{
3158 Warning("Divide", "In shape %s division of a cut tube not implemented", GetName());
3159 return nullptr;
3160}
3161
3162////////////////////////////////////////////////////////////////////////////////
3163/// in case shape has some negative parameters, these has to be computed
3164/// in order to fit the mother
3165
3167{
3169 return nullptr;
3170 if (!mother->TestShapeBit(kGeoTube)) {
3171 Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
3172 return nullptr;
3173 }
3174 Double_t rmin, rmax, dz;
3175 rmin = fRmin;
3176 rmax = fRmax;
3177 dz = fDz;
3178 if (fDz < 0)
3179 dz = ((TGeoTube *)mother)->GetDz();
3180 if (fRmin < 0)
3181 rmin = ((TGeoTube *)mother)->GetRmin();
3182 if ((fRmax < 0) || (fRmax <= fRmin))
3183 rmax = ((TGeoTube *)mother)->GetRmax();
3184
3185 return (new TGeoCtub(rmin, rmax, dz, fPhi1, fPhi2, fNlow[0], fNlow[1], fNlow[2], fNhigh[0], fNhigh[1], fNhigh[2]));
3186}
3187
3188////////////////////////////////////////////////////////////////////////////////
3189/// print shape parameters
3190
3192{
3193 printf("*** Shape %s: TGeoCtub ***\n", GetName());
3194 printf(" lx = %11.5f\n", fNlow[0]);
3195 printf(" ly = %11.5f\n", fNlow[1]);
3196 printf(" lz = %11.5f\n", fNlow[2]);
3197 printf(" tx = %11.5f\n", fNhigh[0]);
3198 printf(" ty = %11.5f\n", fNhigh[1]);
3199 printf(" tz = %11.5f\n", fNhigh[2]);
3201}
3202
3203////////////////////////////////////////////////////////////////////////////////
3204/// computes the closest distance from given point to this shape, according
3205/// to option. The matching point on the shape is stored in spoint.
3206
3208{
3209 Double_t saf[4];
3210 Double_t rsq = point[0] * point[0] + point[1] * point[1];
3212 Bool_t isseg = kTRUE;
3213 if (TMath::Abs(fPhi2 - fPhi1 - 360.) < 1E-8)
3214 isseg = kFALSE;
3215
3216 saf[0] = -point[0] * fNlow[0] - point[1] * fNlow[1] - (fDz + point[2]) * fNlow[2];
3217 saf[1] = -point[0] * fNhigh[0] - point[1] * fNhigh[1] + (fDz - point[2]) * fNhigh[2];
3218 saf[2] = (fRmin < 1E-10 && !isseg) ? TGeoShape::Big() : (r - fRmin);
3219 saf[3] = fRmax - r;
3221 if (isseg)
3223
3224 if (in) {
3226 return TMath::Min(safe, safphi);
3227 }
3228 for (Int_t i = 0; i < 4; i++)
3229 saf[i] = -saf[i];
3231 if (isseg)
3232 return TMath::Max(safe, safphi);
3233 return safe;
3234}
3235
3236////////////////////////////////////////////////////////////////////////////////
3237/// set dimensions of a cut tube
3238
3251
3252////////////////////////////////////////////////////////////////////////////////
3253/// Save a primitive as a C++ statement(s) on output stream "out".
3254
3255void TGeoCtub::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
3256{
3258 return;
3259 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
3260 out << " rmin = " << fRmin << ";" << std::endl;
3261 out << " rmax = " << fRmax << ";" << std::endl;
3262 out << " dz = " << fDz << ";" << std::endl;
3263 out << " phi1 = " << fPhi1 << ";" << std::endl;
3264 out << " phi2 = " << fPhi2 << ";" << std::endl;
3265 out << " lx = " << fNlow[0] << ";" << std::endl;
3266 out << " ly = " << fNlow[1] << ";" << std::endl;
3267 out << " lz = " << fNlow[2] << ";" << std::endl;
3268 out << " tx = " << fNhigh[0] << ";" << std::endl;
3269 out << " ty = " << fNhigh[1] << ";" << std::endl;
3270 out << " tz = " << fNhigh[2] << ";" << std::endl;
3271 out << " TGeoShape *" << GetPointerName() << " = new TGeoCtub(\"" << GetName()
3272 << "\",rmin,rmax,dz,phi1,phi2,lx,ly,lz,tx,ty,tz);" << std::endl;
3274}
3275
3276////////////////////////////////////////////////////////////////////////////////
3277/// Set dimensions of the cut tube starting from a list.
3278
3280{
3281 SetCtubDimensions(param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7], param[8], param[9],
3282 param[10]);
3283 ComputeBBox();
3284}
3285
3286////////////////////////////////////////////////////////////////////////////////
3287/// Fills array with n random points located on the line segments of the shape mesh.
3288/// The output array must be provided with a length of minimum 3*npoints. Returns
3289/// true if operation is implemented.
3290
3292{
3293 if (!array || npoints <= 0)
3294 return kFALSE;
3295
3296 if (fDz <= 0.0 || fRmax <= 0.0)
3297 return kFALSE;
3298
3299 // Angular span in radians
3302 if (phi2 < phi1)
3303 phi2 += TMath::TwoPi();
3304 const Double_t dPhiTot = phi2 - phi1;
3305
3306 if (!(dPhiTot > 0.0))
3307 return kFALSE;
3308
3309 const Bool_t hasInner = (fRmin > 0.0);
3310
3311 // Split budget: outer gets the extra point if odd
3313 Int_t inPoints = 0;
3314 if (hasInner) {
3315 outPoints = (npoints + 1) / 2;
3317 }
3318
3320 if (nSurfPoints <= 0)
3321 return kTRUE;
3322 if (r <= 0.0)
3323 return kFALSE;
3324
3325 // Number of generators ~ sqrt(n), clamp to [1, nSurfPoints]
3327 if (nGen < 1)
3328 nGen = 1;
3329 if (nGen > nSurfPoints)
3330 nGen = nSurfPoints;
3331
3332 const Int_t q = nSurfPoints / nGen;
3333 const Int_t rem = nSurfPoints % nGen;
3334
3335 // Use generator centers: never exactly phi1 or phi2
3336 const Double_t dphi = dPhiTot / (Double_t)nGen;
3337
3338 for (Int_t ig = 0; ig < nGen; ++ig) {
3339 const Int_t m = q + (ig < rem ? 1 : 0);
3340 if (m <= 0)
3341 continue;
3342
3343 const Double_t phi = phi1 + (ig + 0.5) * dphi; // avoid endpoints
3344 const Double_t c = TMath::Cos(phi);
3345 const Double_t s = TMath::Sin(phi);
3346
3347 const Double_t x = r * c;
3348 const Double_t y = r * s;
3349
3350 // Cut-plane endpoints for this generator
3351 const Double_t z0 = GetZcoord(x, y, -fDz);
3352 const Double_t z1 = GetZcoord(x, y, +fDz);
3353
3354 if (!(z1 > z0)) // degenerate / invalid for this (x,y)
3355 return kFALSE;
3356
3357 // Interior z: t in (0,1) => avoids endpoints
3358 for (Int_t j = 0; j < m; ++j) {
3359 if (icrt + 3 > 3 * npoints)
3360 return kFALSE;
3361
3362 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1);
3363 const Double_t z = z0 + t * (z1 - z0);
3364
3365 array[icrt++] = x;
3366 array[icrt++] = y;
3367 array[icrt++] = z;
3368 }
3369 }
3370
3371 return kTRUE;
3372 };
3373
3374 Int_t icrt = 0;
3375
3376 // Outer curved surface
3378 return kFALSE;
3379
3380 // Inner curved surface (if any)
3381 if (hasInner) {
3382 if (!fillCylCut(inPoints, fRmin, icrt))
3383 return kFALSE;
3384 }
3385
3386 // Contract: fill exactly npoints
3387 return (icrt == 3 * npoints) ? kTRUE : kFALSE;
3388}
3389
3390////////////////////////////////////////////////////////////////////////////////
3391/// Create mesh points for the cut tube.
3392
3394{
3395 Double_t dz;
3396 Int_t j, n;
3397 Double_t phi, phi1, phi2, dphi;
3398 phi1 = fPhi1;
3399 phi2 = fPhi2;
3400 if (phi2 < phi1)
3401 phi2 += 360.;
3402 n = gGeoManager->GetNsegments() + 1;
3403
3404 dphi = (phi2 - phi1) / (n - 1);
3405 dz = fDz;
3406
3407 if (points) {
3408 Int_t indx = 0;
3409
3410 for (j = 0; j < n; j++) {
3411 phi = (phi1 + j * dphi) * TMath::DegToRad();
3412 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
3413 indx++;
3414 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
3415 indx++;
3416 points[indx + 6 * n] = GetZcoord(points[indx - 2], points[indx - 1], dz);
3417 points[indx] = GetZcoord(points[indx - 2], points[indx - 1], -dz);
3418 indx++;
3419 }
3420 for (j = 0; j < n; j++) {
3421 phi = (phi1 + j * dphi) * TMath::DegToRad();
3422 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
3423 indx++;
3424 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
3425 indx++;
3426 points[indx + 6 * n] = GetZcoord(points[indx - 2], points[indx - 1], dz);
3427 points[indx] = GetZcoord(points[indx - 2], points[indx - 1], -dz);
3428 indx++;
3429 }
3430 }
3431}
3432
3433////////////////////////////////////////////////////////////////////////////////
3434/// Create mesh points for the cut tube.
3435
3437{
3438 Double_t dz;
3439 Int_t j, n;
3440 Double_t phi, phi1, phi2, dphi;
3441 phi1 = fPhi1;
3442 phi2 = fPhi2;
3443 if (phi2 < phi1)
3444 phi2 += 360.;
3445 n = gGeoManager->GetNsegments() + 1;
3446
3447 dphi = (phi2 - phi1) / (n - 1);
3448 dz = fDz;
3449
3450 if (points) {
3451 Int_t indx = 0;
3452
3453 for (j = 0; j < n; j++) {
3454 phi = (phi1 + j * dphi) * TMath::DegToRad();
3455 points[indx + 6 * n] = points[indx] = fRmin * TMath::Cos(phi);
3456 indx++;
3457 points[indx + 6 * n] = points[indx] = fRmin * TMath::Sin(phi);
3458 indx++;
3459 points[indx + 6 * n] = GetZcoord(points[indx - 2], points[indx - 1], dz);
3460 points[indx] = GetZcoord(points[indx - 2], points[indx - 1], -dz);
3461 indx++;
3462 }
3463 for (j = 0; j < n; j++) {
3464 phi = (phi1 + j * dphi) * TMath::DegToRad();
3465 points[indx + 6 * n] = points[indx] = fRmax * TMath::Cos(phi);
3466 indx++;
3467 points[indx + 6 * n] = points[indx] = fRmax * TMath::Sin(phi);
3468 indx++;
3469 points[indx + 6 * n] = GetZcoord(points[indx - 2], points[indx - 1], dz);
3470 points[indx] = GetZcoord(points[indx - 2], points[indx - 1], -dz);
3471 indx++;
3472 }
3473 }
3474}
3475
3476////////////////////////////////////////////////////////////////////////////////
3477/// Fills a static 3D buffer and returns a reference.
3478
3480{
3481 static TBuffer3DCutTube buffer;
3482
3484
3486 // These from TBuffer3DCutTube / TGeoCtub
3487 buffer.fRadiusInner = fRmin;
3488 buffer.fRadiusOuter = fRmax;
3489 buffer.fHalfLength = fDz;
3490 buffer.fPhiMin = fPhi1;
3491 buffer.fPhiMax = fPhi2;
3492
3493 for (UInt_t i = 0; i < 3; i++) {
3494 buffer.fLowPlaneNorm[i] = fNlow[i];
3495 buffer.fHighPlaneNorm[i] = fNhigh[i];
3496 }
3498 }
3501 Int_t nbPnts = 4 * n;
3502 Int_t nbSegs = 2 * nbPnts;
3503 Int_t nbPols = nbPnts - 2;
3504 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
3506 }
3507 }
3509 SetPoints(buffer.fPnts);
3510 if (!buffer.fLocalFrame) {
3511 TransformPoints(buffer.fPnts, buffer.NbPnts());
3512 }
3513 SetSegsAndPols(buffer);
3515 }
3516
3517 return buffer;
3518}
3519
3520////////////////////////////////////////////////////////////////////////////////
3521/// Check the inside status for each of the points in the array.
3522/// Input: Array of point coordinates + vector size
3523/// Output: Array of Booleans for the inside of each point
3524
3526{
3527 for (Int_t i = 0; i < vecsize; i++)
3528 inside[i] = Contains(&points[3 * i]);
3529}
3530
3531////////////////////////////////////////////////////////////////////////////////
3532/// Compute the normal for an array o points so that norm.dot.dir is positive
3533/// Input: Arrays of point coordinates and directions + vector size
3534/// Output: Array of normal directions
3535
3537{
3538 for (Int_t i = 0; i < vecsize; i++)
3539 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
3540}
3541
3542////////////////////////////////////////////////////////////////////////////////
3543/// Compute distance from array of input points having directions specified by dirs. Store output in dists
3544
3546 Double_t *step) const
3547{
3548 for (Int_t i = 0; i < vecsize; i++)
3549 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
3550}
3551
3552////////////////////////////////////////////////////////////////////////////////
3553/// Compute distance from array of input points having directions specified by dirs. Store output in dists
3554
3556 Double_t *step) const
3557{
3558 for (Int_t i = 0; i < vecsize; i++)
3559 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
3560}
3561
3562////////////////////////////////////////////////////////////////////////////////
3563/// Compute safe distance from each of the points in the input array.
3564/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
3565/// Output: Safety values
3566
3568{
3569 for (Int_t i = 0; i < vecsize; i++)
3570 safe[i] = Safety(&points[3 * i], inside[i]);
3571}
#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 * q
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:18
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:21
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:431
Double_t fOrigin[3]
Definition TGeoBBox.h:24
void InspectShape() const override
Prints shape parameters.
Definition TGeoBBox.cxx:845
Double_t fDY
Definition TGeoBBox.h:22
Double_t fDZ
Definition TGeoBBox.h:23
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
~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...
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:177
Double_t fNhigh[3]
Definition TGeoTube.h:178
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:39
Node containing an offset.
Definition TGeoNode.h:185
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:95
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:65
@ kGeoTubeSeg
Definition TGeoShape.h:47
@ kGeoRunTimeShape
Definition TGeoShape.h:40
static Double_t Tolerance()
Definition TGeoShape.h:98
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:177
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
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:626
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:231
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:502
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:597
void SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz)
Set tube dimensions.
Definition TGeoTube.cxx:933
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute closest distance from point px,py to each corner
Definition TGeoTube.cxx:287
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:475
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:373
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
Definition TGeoTube.cxx:918
void ComputeBBox() override
compute bounding box of the tube
Definition TGeoTube.cxx:222
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:888
void InspectShape() const override
print shape parameters
Definition TGeoTube.cxx:673
Bool_t Contains(const Double_t *point) const override
test if point is inside this tube
Definition TGeoTube.cxx:274
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:686
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:958
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:525
void SetDimensions(Double_t *param) override
Set tube dimensions starting from a list.
Definition TGeoTube.cxx:945
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
Definition TGeoTube.cxx:205
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:258
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:842
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:354
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:640
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:584
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:200
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:303
TGeoTube()
Default constructor.
Definition TGeoTube.cxx:145
Volume families.
Definition TGeoVolume.h:267
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:881
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1088
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
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:249
T1 Sign(T1 a, T2 b)
Returns a value with the magnitude of a and the sign of b.
Definition TMathBase.h:174
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:197
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:122
constexpr Double_t TwoPi()
Definition TMath.h:47
TMarker m
Definition textangle.C:8
auto * t1
Definition textangle.C:20