Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoPcon.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 24/10/01
3// TGeoPcon::Contains() 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 TGeoPcon
14\ingroup Shapes_classes
15
16A polycone is represented by a sequence of tubes/cones, glued together
17at defined Z planes. The polycone might have a phi segmentation, which
18globally applies to all the pieces. It has to be defined in two steps:
19
201. First call the TGeoPcon constructor to define a polycone:
21
22 ~~~{.cpp}
23 TGeoPcon(Double_t phi1,Double_t dphi,Int_t nz
24 ~~~
25
26 - `phi1:` starting phi angle in degrees
27 - `dphi:` total phi range
28 - `nz:` number of Z planes defining polycone sections (minimum 2)
29
302. Define one by one all sections [0, nz-1]
31
32~~~{.cpp}
33void TGeoPcon::DefineSection(Int_t i,Double_t z,
34Double_t rmin, Double_t rmax);
35~~~
36
37 - `i:` section index [0, nz-1]
38 - `z:` z coordinate of the section
39 - `rmin:` minimum radius corresponding too this section
40 - `rmax:` maximum radius.
41
42The first section (`i=0`) has to be positioned always the lowest Z
43coordinate. It defines the radii of the first cone/tube segment at its
44lower Z. The next section defines the end-cap of the first segment, but
45it can represent also the beginning of the next one. Any discontinuity
46in the radius has to be represented by a section defined at the same Z
47coordinate as the previous one. The Z coordinates of all sections must
48be sorted in increasing order. Any radius or Z coordinate of a given
49plane have corresponding getters:
50
51~~~{.cpp}
52Double_t TGeoPcon::GetRmin(Int_t i);
53Double_t TGeoPcon::GetRmax(Int_t i);
54Double_t TGeoPcon::GetZ(Int_t i);
55~~~
56
57Note that the last section should be defined last, since it triggers the
58computation of the bounding box of the polycone.
59
60Begin_Macro
61{
62 TCanvas *c = new TCanvas("c", "c",0,0,600,600);
63 new TGeoManager("pcon", "poza10");
64 TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
65 TGeoMedium *med = new TGeoMedium("MED",1,mat);
66 TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
67 gGeoManager->SetTopVolume(top);
68 TGeoVolume *vol = gGeoManager->MakePcon("PCON",med, -30.0,300,4);
69 TGeoPcon *pcon = (TGeoPcon*)(vol->GetShape());
70 pcon->DefineSection(0,0,15,20);
71 pcon->DefineSection(1,20,15,20);
72 pcon->DefineSection(2,20,15,25);
73 pcon->DefineSection(3,50,15,20);
74 vol->SetLineWidth(2);
75 top->AddNode(vol,1);
76 gGeoManager->CloseGeometry();
77 gGeoManager->SetNsegments(30);
78 top->Draw();
79 TView *view = gPad->GetView();
80 if (view) view->ShowAxis();
81}
82End_Macro
83*/
84
85#include "TGeoPcon.h"
86
87#include <iostream>
88
89#include "TBuffer.h"
90#include "TGeoManager.h"
91#include "TGeoVolume.h"
92#include "TVirtualGeoPainter.h"
93#include "TGeoTube.h"
94#include "TGeoCone.h"
95#include "TBuffer3D.h"
96#include "TBuffer3DTypes.h"
97#include "TMath.h"
98
99////////////////////////////////////////////////////////////////////////////////
100/// dummy ctor
101
103 : TGeoBBox(),
104 fNz(0),
105 fPhi1(0.),
106 fDphi(0.),
107 fRmin(nullptr),
108 fRmax(nullptr),
109 fZ(nullptr),
110 fFullPhi(kFALSE),
111 fC1(0.),
112 fS1(0.),
113 fC2(0.),
114 fS2(0.),
115 fCm(0.),
116 fSm(0.),
117 fCdphi(0.)
118{
120}
121
122////////////////////////////////////////////////////////////////////////////////
123/// Default constructor
124
126 : TGeoBBox(0, 0, 0),
127 fNz(nz),
128 fPhi1(phi),
129 fDphi(dphi),
130 fRmin(nullptr),
131 fRmax(nullptr),
132 fZ(nullptr),
133 fFullPhi(kFALSE),
134 fC1(0.),
135 fS1(0.),
136 fC2(0.),
137 fS2(0.),
138 fCm(0.),
139 fSm(0.),
140 fCdphi(0.)
141{
143 while (fPhi1 < 0)
144 fPhi1 += 360.;
145 fRmin = new Double_t[nz];
146 fRmax = new Double_t[nz];
147 fZ = new Double_t[nz];
148 memset(fRmin, 0, nz * sizeof(Double_t));
149 memset(fRmax, 0, nz * sizeof(Double_t));
150 memset(fZ, 0, nz * sizeof(Double_t));
152 fFullPhi = kTRUE;
155 Double_t phim = 0.5 * (phi1 + phi2);
163}
164
165////////////////////////////////////////////////////////////////////////////////
166/// Default constructor
167
169 : TGeoBBox(name, 0, 0, 0),
170 fNz(nz),
171 fPhi1(phi),
172 fDphi(dphi),
173 fRmin(nullptr),
174 fRmax(nullptr),
175 fZ(nullptr),
176 fFullPhi(kFALSE),
177 fC1(0.),
178 fS1(0.),
179 fC2(0.),
180 fS2(0.),
181 fCm(0.),
182 fSm(0.),
183 fCdphi(0.)
184{
186 while (fPhi1 < 0)
187 fPhi1 += 360.;
188 fRmin = new Double_t[nz];
189 fRmax = new Double_t[nz];
190 fZ = new Double_t[nz];
191 memset(fRmin, 0, nz * sizeof(Double_t));
192 memset(fRmax, 0, nz * sizeof(Double_t));
193 memset(fZ, 0, nz * sizeof(Double_t));
195 fFullPhi = kTRUE;
198 Double_t phim = 0.5 * (phi1 + phi2);
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Default constructor in GEANT3 style
210/// - param[0] = phi1
211/// - param[1] = dphi
212/// - param[2] = nz
213/// - param[3] = z1
214/// - param[4] = Rmin1
215/// - param[5] = Rmax1
216/// ...
217
219 : TGeoBBox(0, 0, 0),
220 fNz(0),
221 fPhi1(0.),
222 fDphi(0.),
223 fRmin(nullptr),
224 fRmax(nullptr),
225 fZ(nullptr),
226 fFullPhi(kFALSE),
227 fC1(0.),
228 fS1(0.),
229 fC2(0.),
230 fS2(0.),
231 fCm(0.),
232 fSm(0.),
233 fCdphi(0.)
234{
236 SetDimensions(param);
237 ComputeBBox();
238}
239
240////////////////////////////////////////////////////////////////////////////////
241/// destructor
242
244{
245 if (fRmin) {
246 delete[] fRmin;
247 fRmin = nullptr;
248 }
249 if (fRmax) {
250 delete[] fRmax;
251 fRmax = nullptr;
252 }
253 if (fZ) {
254 delete[] fZ;
255 fZ = nullptr;
256 }
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Computes capacity of the shape in [length^3]
261
263{
264 Int_t ipl;
266 Double_t capacity = 0.;
267 phi1 = fPhi1;
268 phi2 = fPhi1 + fDphi;
269 for (ipl = 0; ipl < fNz - 1; ipl++) {
270 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
271 if (dz < TGeoShape::Tolerance())
272 continue;
273 rmin1 = fRmin[ipl];
274 rmax1 = fRmax[ipl];
275 rmin2 = fRmin[ipl + 1];
276 rmax2 = fRmax[ipl + 1];
278 }
279 return capacity;
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// compute bounding box of the pcon
284/// Check if the sections are in increasing Z order
285
287{
288 for (Int_t isec = 0; isec < fNz - 1; isec++) {
289 if (TMath::Abs(fZ[isec] - fZ[isec + 1]) < TGeoShape::Tolerance()) {
290 fZ[isec + 1] = fZ[isec];
293 InspectShape();
294 Error("ComputeBBox", "Duplicated section %d/%d for shape %s", isec, isec + 1, GetName());
295 }
296 }
297 if (fZ[isec] > fZ[isec + 1]) {
298 InspectShape();
299 Fatal("ComputeBBox", "Wrong section order");
300 }
301 }
302 // Check if the last sections are valid
303 if (TMath::Abs(fZ[1] - fZ[0]) < TGeoShape::Tolerance() ||
304 TMath::Abs(fZ[fNz - 1] - fZ[fNz - 2]) < TGeoShape::Tolerance()) {
305 InspectShape();
306 Fatal("ComputeBBox", "Shape %s at index %d: Not allowed first two or last two sections at same Z", GetName(),
308 }
309 Double_t zmin = TMath::Min(fZ[0], fZ[fNz - 1]);
310 Double_t zmax = TMath::Max(fZ[0], fZ[fNz - 1]);
311 // find largest rmax an smallest rmin
315
316 Double_t xc[4];
317 Double_t yc[4];
318 xc[0] = rmax * fC1;
319 yc[0] = rmax * fS1;
320 xc[1] = rmax * fC2;
321 yc[1] = rmax * fS2;
322 xc[2] = rmin * fC1;
323 yc[2] = rmin * fS1;
324 xc[3] = rmin * fC2;
325 yc[3] = rmin * fS2;
326
327 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
328 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
329 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
330 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
331
332 Double_t ddp = -fPhi1;
333 if (ddp < 0)
334 ddp += 360;
335 if (ddp <= fDphi)
336 xmax = rmax;
337 ddp = 90 - fPhi1;
338 if (ddp < 0)
339 ddp += 360;
340 if (ddp <= fDphi)
341 ymax = rmax;
342 ddp = 180 - fPhi1;
343 if (ddp < 0)
344 ddp += 360;
345 if (ddp <= fDphi)
346 xmin = -rmax;
347 ddp = 270 - fPhi1;
348 if (ddp < 0)
349 ddp += 360;
350 if (ddp <= fDphi)
351 ymin = -rmax;
352 fOrigin[0] = (xmax + xmin) / 2;
353 fOrigin[1] = (ymax + ymin) / 2;
354 fOrigin[2] = (zmax + zmin) / 2;
355 fDX = (xmax - xmin) / 2;
356 fDY = (ymax - ymin) / 2;
357 fDZ = (zmax - zmin) / 2;
359}
360
361////////////////////////////////////////////////////////////////////////////////
362/// Compute normal to closest surface from POINT.
363
364void TGeoPcon::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
365{
366 memset(norm, 0, 3 * sizeof(Double_t));
367 Double_t r;
368 Double_t ptnew[3];
371 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
372 if (ipl == (fNz - 1) || ipl < 0) {
373 // point outside Z range
374 norm[2] = TMath::Sign(1., dir[2]);
375 return;
376 }
378 if ((fZ[ipl + 1] - point[2]) < (point[2] - fZ[ipl]))
379 iplclose++;
380 dz = TMath::Abs(fZ[iplclose] - point[2]);
381 if (dz < 1E-5) {
382 if (iplclose == 0 || iplclose == (fNz - 1)) {
383 norm[2] = TMath::Sign(1., dir[2]);
384 return;
385 }
387 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
388 if (r < TMath::Max(fRmin[ipl], fRmin[ipl - 1]) || r > TMath::Min(fRmax[ipl], fRmax[ipl - 1])) {
389 norm[2] = TMath::Sign(1., dir[2]);
390 return;
391 }
392 } else {
394 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
395 if (r < TMath::Max(fRmin[iplclose], fRmin[iplclose + 1]) ||
397 norm[2] = TMath::Sign(1., dir[2]);
398 return;
399 }
400 }
401 }
402 } //-> Z done
403 memcpy(ptnew, point, 3 * sizeof(Double_t));
404 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
406 norm[2] = TMath::Sign(1., dir[2]);
407 return;
408 }
409 ptnew[2] -= 0.5 * (fZ[ipl] + fZ[ipl + 1]);
410 rmin1 = fRmin[ipl];
411 rmax1 = fRmax[ipl];
412 rmin2 = fRmin[ipl + 1];
413 rmax2 = fRmax[ipl + 1];
415 ? kTRUE
416 : kFALSE;
417 if (!fFullPhi) {
418 if (is_tube)
420 else
422 } else {
423 if (is_tube)
425 else
427 }
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// test if point is inside this shape
432/// check total z range
433
435{
436 if ((point[2] < fZ[0]) || (point[2] > fZ[fNz - 1]))
437 return kFALSE;
438 // check R squared
439 Double_t r2 = point[0] * point[0] + point[1] * point[1];
440
441 Int_t izl = 0;
442 Int_t izh = fNz - 1;
443 Int_t izt = (fNz - 1) / 2;
444 while ((izh - izl) > 1) {
445 if (point[2] > fZ[izt])
446 izl = izt;
447 else
448 izh = izt;
449 izt = (izl + izh) >> 1;
450 }
451 // the point is in the section bounded by izl and izh Z planes
452
453 // compute Rmin and Rmax and test the value of R squared
458 } else {
459 Double_t dz = fZ[izh] - fZ[izl];
460 Double_t dz1 = point[2] - fZ[izl];
461 rmin = (fRmin[izl] * (dz - dz1) + fRmin[izh] * dz1) / dz;
462 rmax = (fRmax[izl] * (dz - dz1) + fRmax[izh] * dz1) / dz;
463 }
464 if ((r2 < rmin * rmin) || (r2 > rmax * rmax))
465 return kFALSE;
466 // now check phi
468 return kTRUE;
469 if (r2 < 1E-10)
470 return kTRUE;
471 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
472 if (phi < 0)
473 phi += 360.0;
474 Double_t ddp = phi - fPhi1;
475 if (ddp < 0)
476 ddp += 360.;
477 if (ddp <= fDphi)
478 return kTRUE;
479 return kFALSE;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// compute closest distance from point px,py to each corner
484
486{
488 const Int_t numPoints = 2 * n * fNz;
489 return ShapeDistancetoPrimitive(numPoints, px, py);
490}
491
492////////////////////////////////////////////////////////////////////////////////
493/// compute distance from inside point to surface of the polycone
494
497{
498 if (iact < 3 && safe) {
499 *safe = Safety(point, kTRUE);
500 if (iact == 0)
501 return TGeoShape::Big();
502 if ((iact == 1) && (*safe > step))
503 return TGeoShape::Big();
504 }
506 Double_t sstep = 1E-6;
508 // determine which z segment contains the point
509 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2] + TMath::Sign(1.E-10, dir[2]));
510 if (ipl < 0)
511 ipl = 0;
512 if (ipl == (fNz - 1))
513 ipl--;
514 Double_t dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
516 if (dz < 1e-9) {
517 // radius changing segment, make sure track is not in the XY plane
518 if (TGeoShape::IsSameWithinTolerance(dir[2], 0)) {
520 } else {
521 // check if a close point is still contained
522 point_new[0] = point[0] + sstep * dir[0];
523 point_new[1] = point[1] + sstep * dir[1];
524 point_new[2] = point[2] + sstep * dir[2];
525 if (!Contains(point_new))
526 return 0.;
527 return (DistFromInside(point_new, dir, iact, step, safe) + sstep);
528 }
529 }
530 // determine if the current segment is a tube or a cone
533 intub = kFALSE;
535 intub = kFALSE;
536 // determine phi segmentation
537 memcpy(point_new, point, 2 * sizeof(Double_t));
538 // new point in reference system of the current segment
539 point_new[2] = point[2] - 0.5 * (fZ[ipl] + fZ[ipl + 1]);
540
541 if (special_case) {
542 if (!fFullPhi)
544 TMath::Max(fRmax[ipl], fRmax[ipl + 1]), dz, fC1, fS1, fC2, fS2, fCm, fSm,
545 fCdphi);
546 else
548 TMath::Max(fRmax[ipl], fRmax[ipl + 1]), dz);
549 return snxt;
550 }
551 if (intub) {
552 if (!fFullPhi)
554 fCdphi);
555 else
557 } else {
558 if (!fFullPhi)
560 fC1, fS1, fC2, fS2, fCm, fSm, fCdphi);
561 else
563 }
564
565 for (Int_t i = 0; i < 3; i++)
566 point_new[i] = point[i] + (snxt + 1E-6) * dir[i];
567 if (!Contains(&point_new[0]))
568 return snxt;
569
570 snxt += DistFromInside(&point_new[0], dir, 3) + 1E-6;
571 return snxt;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// compute distance to a pcon Z slice. Segment iz must be valid
576
577Double_t TGeoPcon::DistToSegZ(const Double_t *point, const Double_t *dir, Int_t &iz) const
578{
579 Double_t zmin = fZ[iz];
580 Double_t zmax = fZ[iz + 1];
581 if (TGeoShape::IsSameWithinTolerance(zmin, zmax)) {
583 return TGeoShape::Big();
584 Int_t istep = (dir[2] > 0) ? 1 : -1;
585 iz += istep;
586 if (iz < 0 || iz > (fNz - 2))
587 return TGeoShape::Big();
588 return DistToSegZ(point, dir, iz);
589 }
590 Double_t dz = 0.5 * (zmax - zmin);
591 Double_t local[3];
592 memcpy(&local[0], point, 3 * sizeof(Double_t));
593 local[2] = point[2] - 0.5 * (zmin + zmax);
595 Double_t rmin1 = fRmin[iz];
596 Double_t rmax1 = fRmax[iz];
597 Double_t rmin2 = fRmin[iz + 1];
598 Double_t rmax2 = fRmax[iz + 1];
599
601 if (fFullPhi)
603 else
605 } else {
606 if (fFullPhi)
608 else
610 fCdphi);
611 }
612 if (snxt < 1E20)
613 return snxt;
614 // check next segment
616 return TGeoShape::Big();
617 Int_t istep = (dir[2] > 0) ? 1 : -1;
618 iz += istep;
619 if (iz < 0 || iz > (fNz - 2))
620 return TGeoShape::Big();
621 return DistToSegZ(point, dir, iz);
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// compute distance from outside point to surface of the tube
626
629{
630 if ((iact < 3) && safe) {
631 *safe = Safety(point, kFALSE);
632 if ((iact == 1) && (*safe > step))
633 return TGeoShape::Big();
634 if (iact == 0)
635 return TGeoShape::Big();
636 }
637 // check if ray intersect outscribed cylinder
638 if ((point[2] < fZ[0]) && (dir[2] <= 0))
639 return TGeoShape::Big();
640 if ((point[2] > fZ[fNz - 1]) && (dir[2] >= 0))
641 return TGeoShape::Big();
642 // Check if the bounding box is crossed within the requested distance
643 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
644 if (sdist >= step)
645 return TGeoShape::Big();
646
647 Double_t r2 = point[0] * point[0] + point[1] * point[1];
648 Double_t radmax = 0;
650 if (r2 > (radmax * radmax)) {
651 Double_t rpr = -point[0] * dir[0] - point[1] * dir[1];
652 Double_t nxy = dir[0] * dir[0] + dir[1] * dir[1];
653 if (rpr < TMath::Sqrt((r2 - radmax * radmax) * nxy))
654 return TGeoShape::Big();
655 }
656
657 // find in which Z segment we are
658 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
659 Int_t ifirst = ipl;
660 if (ifirst < 0) {
661 ifirst = 0;
662 } else if (ifirst >= (fNz - 1)) {
663 ifirst = fNz - 2;
664 }
665 // find if point is in the phi gap
666 Double_t phi = 0;
667 if (!fFullPhi) {
668 phi = TMath::ATan2(point[1], point[0]);
669 if (phi < 0)
670 phi += 2. * TMath::Pi();
671 }
672
673 // compute distance to boundary
674 return DistToSegZ(point, dir, ifirst);
675}
676
677////////////////////////////////////////////////////////////////////////////////
678/// Defines z position of a section plane, rmin and rmax at this z. Sections
679/// should be defined in increasing or decreasing Z order and the last section
680/// HAS to be snum = fNz-1
681
683{
684 if ((snum < 0) || (snum >= fNz))
685 return;
686 fZ[snum] = z;
687 fRmin[snum] = rmin;
688 fRmax[snum] = rmax;
689 if (rmin > rmax)
690 Warning("DefineSection", "Shape %s: invalid rmin=%g rmax=%g", GetName(), rmin, rmax);
691 if (snum == (fNz - 1)) {
692 // Reorder sections in increasing Z order
693 if (fZ[0] > fZ[snum]) {
694 Int_t iz = 0;
695 Int_t izi = fNz - 1;
696 Double_t temp;
697 while (iz < izi) {
698 temp = fZ[iz];
699 fZ[iz] = fZ[izi];
700 fZ[izi] = temp;
701 temp = fRmin[iz];
702 fRmin[iz] = fRmin[izi];
703 fRmin[izi] = temp;
704 temp = fRmax[iz];
705 fRmax[iz] = fRmax[izi];
706 fRmax[izi] = temp;
707 iz++;
708 izi--;
709 }
710 }
711 ComputeBBox();
712 }
713}
714
715////////////////////////////////////////////////////////////////////////////////
716/// Returns number of segments on each mesh circle segment.
717
719{
720 return gGeoManager->GetNsegments();
721}
722
723////////////////////////////////////////////////////////////////////////////////
724/// Divide this polycone shape belonging to volume "voldiv" into ndiv volumes
725/// called divname, from start position with the given step. Returns pointer
726/// to created division cell volume in case of Z divisions. Z divisions can be
727/// performed if the divided range is in between two consecutive Z planes.
728/// In case a wrong division axis is supplied, returns pointer to
729/// volume that was divided.
730
733{
734 TGeoShape *shape; //--- shape to be created
735 TGeoVolume *vol; //--- division volume to be created
736 TGeoVolumeMulti *vmulti; //--- generic divided volume
737 TGeoPatternFinder *finder; //--- finder to be attached
738 TString opt = ""; //--- option to be attached
739 Double_t zmin = start;
740 Double_t zmax = start + ndiv * step;
741 Int_t isect = -1;
742 Int_t is, id, ipl;
743 switch (iaxis) {
744 case 1: //--- R division
745 Error("Divide", "Shape %s: cannot divide a pcon on radius", GetName());
746 return nullptr;
747 case 2: //--- Phi division
748 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, start + ndiv * step);
750 voldiv->SetFinder(finder);
751 finder->SetDivIndex(voldiv->GetNdaughters());
752 shape = new TGeoPcon(-step / 2, step, fNz);
753 for (is = 0; is < fNz; is++)
754 ((TGeoPcon *)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
755 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
756 vmulti->AddVolume(vol);
757 opt = "Phi";
758 for (id = 0; id < ndiv; id++) {
759 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
760 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
761 }
762 return vmulti;
763 case 3: //--- Z division
764 // find start plane
765 for (ipl = 0; ipl < fNz - 1; ipl++) {
766 if (start < fZ[ipl])
767 continue;
768 else {
769 if ((start + ndiv * step) > fZ[ipl + 1])
770 continue;
771 }
772 isect = ipl;
773 zmin = fZ[isect];
774 zmax = fZ[isect + 1];
775 break;
776 }
777 if (isect < 0) {
778 Error("Divide", "Shape %s: cannot divide pcon on Z if divided region is not between 2 planes", GetName());
779 return nullptr;
780 }
781 finder = new TGeoPatternZ(voldiv, ndiv, start, start + ndiv * step);
783 voldiv->SetFinder(finder);
784 finder->SetDivIndex(voldiv->GetNdaughters());
785 opt = "Z";
786 for (id = 0; id < ndiv; id++) {
787 Double_t z1 = start + id * step;
788 Double_t z2 = start + (id + 1) * step;
789 Double_t rmin1 = (fRmin[isect] * (zmax - z1) - fRmin[isect + 1] * (zmin - z1)) / (zmax - zmin);
790 Double_t rmax1 = (fRmax[isect] * (zmax - z1) - fRmax[isect + 1] * (zmin - z1)) / (zmax - zmin);
791 Double_t rmin2 = (fRmin[isect] * (zmax - z2) - fRmin[isect + 1] * (zmin - z2)) / (zmax - zmin);
792 Double_t rmax2 = (fRmax[isect] * (zmax - z2) - fRmax[isect + 1] * (zmin - z2)) / (zmax - zmin);
795 ? kTRUE
796 : kFALSE;
797 Bool_t is_seg = (fDphi < 360) ? kTRUE : kFALSE;
798 if (is_seg) {
799 if (is_tube)
800 shape = new TGeoTubeSeg(fRmin[isect], fRmax[isect], step / 2, fPhi1, fPhi1 + fDphi);
801 else
802 shape = new TGeoConeSeg(step / 2, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi1 + fDphi);
803 } else {
804 if (is_tube)
805 shape = new TGeoTube(fRmin[isect], fRmax[isect], step / 2);
806 else
807 shape = new TGeoCone(step / 2, rmin1, rmax1, rmin2, rmax2);
808 }
809 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
810 vmulti->AddVolume(vol);
811 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
812 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
813 }
814 return vmulti;
815 default: Error("Divide", "Shape %s: Wrong axis %d for division", GetName(), iaxis); return nullptr;
816 }
817}
818
819////////////////////////////////////////////////////////////////////////////////
820/// Returns name of axis IAXIS.
821
823{
824 switch (iaxis) {
825 case 1: return "R";
826 case 2: return "PHI";
827 case 3: return "Z";
828 default: return "UNDEFINED";
829 }
830}
831
832////////////////////////////////////////////////////////////////////////////////
833/// Get range of shape for a given axis.
834
836{
837 xlo = 0;
838 xhi = 0;
839 Double_t dx = 0;
840 switch (iaxis) {
841 case 2:
842 xlo = fPhi1;
843 xhi = fPhi1 + fDphi;
844 dx = fDphi;
845 return dx;
846 case 3:
847 xlo = fZ[0];
848 xhi = fZ[fNz - 1];
849 dx = xhi - xlo;
850 return dx;
851 }
852 return dx;
853}
854
855////////////////////////////////////////////////////////////////////////////////
856/// Fill vector param[4] with the bounding cylinder parameters. The order
857/// is the following : Rmin, Rmax, Phi1, Phi2
858
860{
861 param[0] = fRmin[0]; // Rmin
862 param[1] = fRmax[0]; // Rmax
863 for (Int_t i = 1; i < fNz; i++) {
864 if (fRmin[i] < param[0])
865 param[0] = fRmin[i];
866 if (fRmax[i] > param[1])
867 param[1] = fRmax[i];
868 }
869 param[0] *= param[0];
870 param[1] *= param[1];
872 param[2] = 0.;
873 param[3] = 360.;
874 return;
875 }
876 param[2] = (fPhi1 < 0) ? (fPhi1 + 360.) : fPhi1; // Phi1
877 param[3] = param[2] + fDphi; // Phi2
878}
879
880////////////////////////////////////////////////////////////////////////////////
881/// Returns Rmin for Z segment IPL.
882
884{
885 if (ipl < 0 || ipl > (fNz - 1)) {
886 Error("GetRmin", "ipl=%i out of range (0,%i) in shape %s", ipl, fNz - 1, GetName());
887 return 0.;
888 }
889 return fRmin[ipl];
890}
891
892////////////////////////////////////////////////////////////////////////////////
893/// Returns Rmax for Z segment IPL.
894
896{
897 if (ipl < 0 || ipl > (fNz - 1)) {
898 Error("GetRmax", "ipl=%i out of range (0,%i) in shape %s", ipl, fNz - 1, GetName());
899 return 0.;
900 }
901 return fRmax[ipl];
902}
903
904////////////////////////////////////////////////////////////////////////////////
905/// Returns Z for segment IPL.
906
908{
909 if (ipl < 0 || ipl > (fNz - 1)) {
910 Error("GetZ", "ipl=%i out of range (0,%i) in shape %s", ipl, fNz - 1, GetName());
911 return 0.;
912 }
913 return fZ[ipl];
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// print shape parameters
918
920{
921 printf("*** Shape %s: TGeoPcon ***\n", GetName());
922 printf(" Nz = %i\n", fNz);
923 printf(" phi1 = %11.5f\n", fPhi1);
924 printf(" dphi = %11.5f\n", fDphi);
925 for (Int_t ipl = 0; ipl < fNz; ipl++)
926 printf(" plane %i: z=%11.5f Rmin=%11.5f Rmax=%11.5f\n", ipl, fZ[ipl], fRmin[ipl], fRmax[ipl]);
927 printf(" Bounding box:\n");
929}
930
931////////////////////////////////////////////////////////////////////////////////
932/// Creates a TBuffer3D describing *this* shape.
933/// Coordinates are in local reference frame.
934
936{
939 if (nbPnts <= 0)
940 return nullptr;
941
942 TBuffer3D *buff =
944 if (buff) {
945 SetPoints(buff->fPnts);
947 }
948
949 return buff;
950}
951
952////////////////////////////////////////////////////////////////////////////////
953/// Fill TBuffer3D structure for segments and polygons.
954
956{
957 if (!HasInsideSurface()) {
959 return;
960 }
961
962 Int_t i, j;
963 const Int_t n = gGeoManager->GetNsegments() + 1;
964 Int_t nz = GetNz();
965 if (nz < 2)
966 return;
967 Int_t nbPnts = nz * 2 * n;
968 if (nbPnts <= 0)
969 return;
971
974
975 Int_t indx = 0, indx2, k;
976
977 // inside & outside circles, number of segments: 2*nz*(n-1)
978 // special case number of segments: 2*nz*n
979 for (i = 0; i < nz * 2; i++) {
980 indx2 = i * n;
981 for (j = 1; j < n; j++) {
982 buff.fSegs[indx++] = c;
983 buff.fSegs[indx++] = indx2 + j - 1;
984 buff.fSegs[indx++] = indx2 + j;
985 }
986 if (specialCase) {
987 buff.fSegs[indx++] = c;
988 buff.fSegs[indx++] = indx2 + j - 1;
989 buff.fSegs[indx++] = indx2;
990 }
991 }
992
993 // bottom & top lines, number of segments: 2*n
994 for (i = 0; i < 2; i++) {
995 indx2 = i * (nz - 1) * 2 * n;
996 for (j = 0; j < n; j++) {
997 buff.fSegs[indx++] = c;
998 buff.fSegs[indx++] = indx2 + j;
999 buff.fSegs[indx++] = indx2 + n + j;
1000 }
1001 }
1002
1003 // inside & outside cylinders, number of segments: 2*(nz-1)*n
1004 for (i = 0; i < (nz - 1); i++) {
1005 // inside cylinder
1006 indx2 = i * n * 2;
1007 for (j = 0; j < n; j++) {
1008 buff.fSegs[indx++] = c + 2;
1009 buff.fSegs[indx++] = indx2 + j;
1010 buff.fSegs[indx++] = indx2 + n * 2 + j;
1011 }
1012 // outside cylinder
1013 indx2 = i * n * 2 + n;
1014 for (j = 0; j < n; j++) {
1015 buff.fSegs[indx++] = c + 3;
1016 buff.fSegs[indx++] = indx2 + j;
1017 buff.fSegs[indx++] = indx2 + n * 2 + j;
1018 }
1019 }
1020
1021 // left & right sections, number of segments: 2*(nz-2)
1022 // special case number of segments: 0
1023 if (!specialCase) {
1024 for (i = 1; i < (nz - 1); i++) {
1025 for (j = 0; j < 2; j++) {
1026 buff.fSegs[indx++] = c;
1027 buff.fSegs[indx++] = 2 * i * n + j * (n - 1);
1028 buff.fSegs[indx++] = (2 * i + 1) * n + j * (n - 1);
1029 }
1030 }
1031 }
1032
1033 Int_t m = n - 1 + (specialCase ? 1 : 0);
1034 indx = 0;
1035
1036 // bottom & top, number of polygons: 2*(n-1)
1037 // special case number of polygons: 2*n
1038 for (j = 0; j < n - 1; j++) {
1039 buff.fPols[indx++] = c + 3;
1040 buff.fPols[indx++] = 4;
1041 buff.fPols[indx++] = 2 * nz * m + j;
1042 buff.fPols[indx++] = m + j;
1043 buff.fPols[indx++] = 2 * nz * m + j + 1;
1044 buff.fPols[indx++] = j;
1045 }
1046 for (j = 0; j < n - 1; j++) {
1047 buff.fPols[indx++] = c + 3;
1048 buff.fPols[indx++] = 4;
1049 buff.fPols[indx++] = 2 * nz * m + n + j;
1050 buff.fPols[indx++] = (nz * 2 - 2) * m + j;
1051 buff.fPols[indx++] = 2 * nz * m + n + j + 1;
1052 buff.fPols[indx++] = (nz * 2 - 2) * m + m + j;
1053 }
1054 if (specialCase) {
1055 buff.fPols[indx++] = c + 3;
1056 buff.fPols[indx++] = 4;
1057 buff.fPols[indx++] = 2 * nz * m + j;
1058 buff.fPols[indx++] = m + j;
1059 buff.fPols[indx++] = 2 * nz * m;
1060 buff.fPols[indx++] = j;
1061
1062 buff.fPols[indx++] = c + 3;
1063 buff.fPols[indx++] = 4;
1064 buff.fPols[indx++] = 2 * nz * m + n + j;
1065 buff.fPols[indx++] = (nz * 2 - 2) * m + m + j;
1066 buff.fPols[indx++] = 2 * nz * m + n;
1067 buff.fPols[indx++] = (nz * 2 - 2) * m + j;
1068 }
1069
1070 // inside & outside, number of polygons: (nz-1)*2*(n-1)
1071 for (k = 0; k < (nz - 1); k++) {
1072 for (j = 0; j < n - 1; j++) {
1073 buff.fPols[indx++] = c;
1074 buff.fPols[indx++] = 4;
1075 buff.fPols[indx++] = 2 * k * m + j;
1076 buff.fPols[indx++] = nz * 2 * m + (2 * k + 2) * n + j + 1;
1077 buff.fPols[indx++] = (2 * k + 2) * m + j;
1078 buff.fPols[indx++] = nz * 2 * m + (2 * k + 2) * n + j;
1079 }
1080 for (j = 0; j < n - 1; j++) {
1081 buff.fPols[indx++] = c + 1;
1082 buff.fPols[indx++] = 4;
1083 buff.fPols[indx++] = (2 * k + 1) * m + j;
1084 buff.fPols[indx++] = nz * 2 * m + (2 * k + 3) * n + j;
1085 buff.fPols[indx++] = (2 * k + 3) * m + j;
1086 buff.fPols[indx++] = nz * 2 * m + (2 * k + 3) * n + j + 1;
1087 }
1088 if (specialCase) {
1089 buff.fPols[indx++] = c;
1090 buff.fPols[indx++] = 4;
1091 buff.fPols[indx++] = 2 * k * m + j;
1092 buff.fPols[indx++] = nz * 2 * m + (2 * k + 2) * n;
1093 buff.fPols[indx++] = (2 * k + 2) * m + j;
1094 buff.fPols[indx++] = nz * 2 * m + (2 * k + 2) * n + j;
1095
1096 buff.fPols[indx++] = c + 1;
1097 buff.fPols[indx++] = 4;
1098 buff.fPols[indx++] = (2 * k + 1) * m + j;
1099 buff.fPols[indx++] = nz * 2 * m + (2 * k + 3) * n + j;
1100 buff.fPols[indx++] = (2 * k + 3) * m + j;
1101 buff.fPols[indx++] = nz * 2 * m + (2 * k + 3) * n;
1102 }
1103 }
1104
1105 // left & right sections, number of polygons: 2*(nz-1)
1106 // special case number of polygons: 0
1107 if (!specialCase) {
1108 indx2 = nz * 2 * (n - 1);
1109 for (k = 0; k < (nz - 1); k++) {
1110 buff.fPols[indx++] = c + 2;
1111 buff.fPols[indx++] = 4;
1112 buff.fPols[indx++] = k == 0 ? indx2 : indx2 + 2 * nz * n + 2 * (k - 1);
1113 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n;
1114 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k;
1115 buff.fPols[indx++] = indx2 + (2 * k + 3) * n;
1116
1117 buff.fPols[indx++] = c + 2;
1118 buff.fPols[indx++] = 4;
1119 buff.fPols[indx++] = k == 0 ? indx2 + n - 1 : indx2 + 2 * nz * n + 2 * (k - 1) + 1;
1120 buff.fPols[indx++] = indx2 + (2 * k + 3) * n + n - 1;
1121 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k + 1;
1122 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n + n - 1;
1123 }
1124 buff.fPols[indx - 8] = indx2 + n;
1125 buff.fPols[indx - 2] = indx2 + 2 * n - 1;
1126 }
1127}
1128
1129////////////////////////////////////////////////////////////////////////////////
1130/// Fill TBuffer3D structure for segments and polygons, when no inner surface exists
1131
1133{
1134 const Int_t n = gGeoManager->GetNsegments() + 1;
1135 const Int_t nz = GetNz();
1136 const Int_t nbPnts = nz * n + 2;
1137
1138 if ((nz < 2) || (nbPnts <= 0) || (n < 2))
1139 return;
1140
1141 Int_t c = GetBasicColor();
1142
1143 Int_t indx = 0, indx1 = 0, indx2 = 0, i, j;
1144
1145 // outside circles, number of segments: nz*n
1146 for (i = 0; i < nz; i++) {
1147 indx2 = i * n;
1148 for (j = 1; j < n; j++) {
1149 buff.fSegs[indx++] = c;
1150 buff.fSegs[indx++] = indx2 + j - 1;
1151 buff.fSegs[indx++] = indx2 + j % (n - 1);
1152 }
1153 }
1154
1155 indx2 = 0;
1156 // bottom lines
1157 for (j = 0; j < n; j++) {
1158 buff.fSegs[indx++] = c;
1159 buff.fSegs[indx++] = indx2 + j % (n - 1);
1160 buff.fSegs[indx++] = nbPnts - 2;
1161 }
1162
1163 indx2 = (nz - 1) * n;
1164 // top lines
1165 for (j = 0; j < n; j++) {
1166 buff.fSegs[indx++] = c;
1167 buff.fSegs[indx++] = indx2 + j % (n - 1);
1168 buff.fSegs[indx++] = nbPnts - 1;
1169 }
1170
1171 // outside cylinders, number of segments: (nz-1)*n
1172 for (i = 0; i < (nz - 1); i++) {
1173 // outside cylinder
1174 indx2 = i * n;
1175 for (j = 0; j < n; j++) {
1176 buff.fSegs[indx++] = c;
1177 buff.fSegs[indx++] = indx2 + j % (n - 1);
1178 buff.fSegs[indx++] = indx2 + n + j % (n - 1);
1179 }
1180 }
1181
1182 indx = 0;
1183
1184 // bottom cap
1185 indx1 = 0; // start of first z layer
1186 indx2 = nz * (n - 1);
1187 for (j = 0; j < n - 1; j++) {
1188 buff.fPols[indx++] = c;
1189 buff.fPols[indx++] = 3;
1190 buff.fPols[indx++] = indx1 + j;
1191 buff.fPols[indx++] = indx2 + j + 1;
1192 buff.fPols[indx++] = indx2 + j;
1193 }
1194
1195 // top cap
1196 indx1 = (nz - 1) * (n - 1); // start last z layer
1197 indx2 = nz * (n - 1) + n;
1198 for (j = 0; j < n - 1; j++) {
1199 buff.fPols[indx++] = c;
1200 buff.fPols[indx++] = 3;
1201 buff.fPols[indx++] = indx1 + j; // last z layer
1202 buff.fPols[indx++] = indx2 + j;
1203 buff.fPols[indx++] = indx2 + j + 1;
1204 }
1205
1206 // outside, number of polygons: (nz-1)*(n-1)
1207 for (Int_t k = 0; k < (nz - 1); k++) {
1208 indx1 = k * (n - 1);
1209 indx2 = nz * (n - 1) + n * 2 + k * n;
1210 for (j = 0; j < n - 1; j++) {
1211 buff.fPols[indx++] = c;
1212 buff.fPols[indx++] = 4;
1213 buff.fPols[indx++] = indx1 + j;
1214 buff.fPols[indx++] = indx2 + j;
1215 buff.fPols[indx++] = indx1 + j + (n - 1);
1216 buff.fPols[indx++] = indx2 + j + 1;
1217 }
1218 }
1219}
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
1223
1225{
1226 if (ipl < 0 || ipl > fNz - 2)
1227 return (safmin + 1.); // error in input plane
1228 // Get info about segment.
1229 Double_t dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1230 if (dz < 1E-9)
1231 return 1E9; // radius-changing segment
1232 Double_t ptnew[3];
1233 memcpy(ptnew, point, 3 * sizeof(Double_t));
1234 ptnew[2] -= 0.5 * (fZ[ipl] + fZ[ipl + 1]);
1236 if (safe > safmin)
1237 return TGeoShape::Big(); // means: stop checking further segments
1240 Double_t rmin2 = fRmin[ipl + 1];
1241 Double_t rmax2 = fRmax[ipl + 1];
1243 ? kTRUE
1244 : kFALSE;
1245 if (!fFullPhi) {
1246 if (is_tube)
1248 else
1250 } else {
1251 if (is_tube)
1253 else
1255 }
1256 if (safe < 0)
1257 safe = 0;
1258 return safe;
1259}
1260
1261////////////////////////////////////////////////////////////////////////////////
1262/// computes the closest distance from given point to this shape, according
1263/// to option. The matching point on the shape is stored in spoint.
1264/// localize the Z segment
1265
1267{
1269 Double_t dz;
1270 Int_t ipl, iplane;
1271
1272 if (in) {
1273 //---> point is inside pcon
1274 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1275 if (ipl == (fNz - 1))
1276 return 0; // point on last Z boundary
1277 if (ipl < 0)
1278 return 0; // point on first Z boundary
1279 if (ipl > 0 && TGeoShape::IsSameWithinTolerance(fZ[ipl - 1], fZ[ipl]) &&
1280 TGeoShape::IsSameWithinTolerance(point[2], fZ[ipl - 1]))
1281 ipl--;
1282 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1283 if (dz < 1E-8) {
1284 // Point on a segment-changing plane
1285 safmin = TMath::Min(point[2] - fZ[ipl - 1], fZ[ipl + 2] - point[2]);
1287 if (fDphi < 360)
1289 if (saftmp < safmin)
1290 safmin = saftmp;
1291 Double_t radius = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1292 if (fRmin[ipl] > 0)
1294 if (fRmin[ipl + 1] > 0)
1298 if (safmin < 0)
1299 safmin = 0;
1300 return safmin;
1301 }
1302 // Check safety for current segment
1303 safmin = SafetyToSegment(point, ipl);
1304 if (safmin > 1E10) {
1305 // something went wrong - point is not inside current segment
1306 return 0.;
1307 }
1308 if (safmin < 1E-6)
1309 return TMath::Abs(safmin); // point on radius-changing plane
1310 // check increasing iplanes
1311 /*
1312 iplane = ipl+1;
1313 saftmp = 0.;
1314 while ((iplane<fNz-1) && saftmp<1E10) {
1315 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
1316 if (saftmp<safmin) safmin=saftmp;
1317 iplane++;
1318 }
1319 // now decreasing nplanes
1320 iplane = ipl-1;
1321 saftmp = 0.;
1322 while ((iplane>=0) && saftmp<1E10) {
1323 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
1324 if (saftmp<safmin) safmin=saftmp;
1325 iplane--;
1326 }
1327 */
1328 return safmin;
1329 }
1330 //---> point is outside pcon
1331 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1332 if (ipl < 0)
1333 ipl = 0;
1334 else if (ipl == fNz - 1)
1335 ipl = fNz - 2;
1336 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1337 if (dz < 1E-8 && (ipl + 2 < fNz)) {
1338 ipl++;
1339 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1340 }
1341 // Check safety for current segment
1342 safmin = SafetyToSegment(point, ipl, kFALSE);
1343 if (safmin < 1E-6)
1344 return TMath::Abs(safmin); // point on radius-changing plane
1345 saftmp = 0.;
1346 // check increasing iplanes
1347 iplane = ipl + 1;
1348 saftmp = 0.;
1349 while ((iplane < fNz - 1) && saftmp < 1E10) {
1351 if (saftmp < safmin)
1352 safmin = saftmp;
1353 iplane++;
1354 }
1355 // now decreasing nplanes
1356 iplane = ipl - 1;
1357 saftmp = 0.;
1358 while ((iplane >= 0) && saftmp < 1E10) {
1360 if (saftmp < safmin)
1361 safmin = saftmp;
1362 iplane--;
1363 }
1364 return safmin;
1365}
1366
1367////////////////////////////////////////////////////////////////////////////////
1368/// Save a primitive as a C++ statement(s) on output stream "out".
1369
1370void TGeoPcon::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
1371{
1373 return;
1374 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
1375 out << " phi1 = " << fPhi1 << ";" << std::endl;
1376 out << " dphi = " << fDphi << ";" << std::endl;
1377 out << " nz = " << fNz << ";" << std::endl;
1378 out << " auto " << GetPointerName() << " = new TGeoPcon(\"" << GetName() << "\", phi1, dphi, nz);" << std::endl;
1379 for (Int_t i = 0; i < fNz; i++) {
1380 out << " z = " << fZ[i] << ";" << std::endl;
1381 out << " rmin = " << fRmin[i] << ";" << std::endl;
1382 out << " rmax = " << fRmax[i] << ";" << std::endl;
1383 out << " " << GetPointerName() << "->DefineSection(" << i << ", z,rmin,rmax);" << std::endl;
1384 }
1386}
1387
1388////////////////////////////////////////////////////////////////////////////////
1389/// Set polycone dimensions starting from an array.
1390
1392{
1393 fPhi1 = param[0];
1394 while (fPhi1 < 0)
1395 fPhi1 += 360.;
1396 fDphi = param[1];
1397 fNz = (Int_t)param[2];
1398 if (fNz < 2) {
1399 Error("SetDimensions", "Pcon %s: Number of Z sections must be > 2", GetName());
1400 return;
1401 }
1402 if (fRmin)
1403 delete[] fRmin;
1404 if (fRmax)
1405 delete[] fRmax;
1406 if (fZ)
1407 delete[] fZ;
1408 fRmin = new Double_t[fNz];
1409 fRmax = new Double_t[fNz];
1410 fZ = new Double_t[fNz];
1411 memset(fRmin, 0, fNz * sizeof(Double_t));
1412 memset(fRmax, 0, fNz * sizeof(Double_t));
1413 memset(fZ, 0, fNz * sizeof(Double_t));
1415 fFullPhi = kTRUE;
1417 Double_t phi2 = phi1 + fDphi;
1418 Double_t phim = 0.5 * (phi1 + phi2);
1426
1427 for (Int_t i = 0; i < fNz; i++)
1428 DefineSection(i, param[3 + 3 * i], param[4 + 3 * i], param[5 + 3 * i]);
1429}
1430
1431////////////////////////////////////////////////////////////////////////////////
1432/// create polycone mesh points
1433
1435{
1436 Double_t phi, dphi;
1438 dphi = fDphi / (n - 1);
1439 Int_t i, j;
1440 Int_t indx = 0;
1441
1443
1444 if (points) {
1445 for (i = 0; i < fNz; i++) {
1446 if (hasInside)
1447 for (j = 0; j < n; j++) {
1448 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1449 points[indx++] = fRmin[i] * TMath::Cos(phi);
1450 points[indx++] = fRmin[i] * TMath::Sin(phi);
1451 points[indx++] = fZ[i];
1452 }
1453 for (j = 0; j < n; j++) {
1454 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1455 points[indx++] = fRmax[i] * TMath::Cos(phi);
1456 points[indx++] = fRmax[i] * TMath::Sin(phi);
1457 points[indx++] = fZ[i];
1458 }
1459 }
1460 if (!hasInside) {
1461 points[indx++] = 0;
1462 points[indx++] = 0;
1463 points[indx++] = fZ[0];
1464
1465 points[indx++] = 0;
1466 points[indx++] = 0;
1467 points[indx++] = fZ[GetNz() - 1];
1468 }
1469 }
1470}
1471
1472////////////////////////////////////////////////////////////////////////////////
1473/// create polycone mesh points
1474
1476{
1477 Double_t phi, dphi;
1479 dphi = fDphi / (n - 1);
1480 Int_t i, j;
1481 Int_t indx = 0;
1482
1484
1485 if (points) {
1486 for (i = 0; i < fNz; i++) {
1487 if (hasInside)
1488 for (j = 0; j < n; j++) {
1489 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1490 points[indx++] = fRmin[i] * TMath::Cos(phi);
1491 points[indx++] = fRmin[i] * TMath::Sin(phi);
1492 points[indx++] = fZ[i];
1493 }
1494 for (j = 0; j < n; j++) {
1495 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1496 points[indx++] = fRmax[i] * TMath::Cos(phi);
1497 points[indx++] = fRmax[i] * TMath::Sin(phi);
1498 points[indx++] = fZ[i];
1499 }
1500 }
1501 if (!hasInside) {
1502 points[indx++] = 0;
1503 points[indx++] = 0;
1504 points[indx++] = fZ[0];
1505
1506 points[indx++] = 0;
1507 points[indx++] = 0;
1508 points[indx++] = fZ[GetNz() - 1];
1509 }
1510 }
1511}
1512////////////////////////////////////////////////////////////////////////////////
1513/// Return number of vertices of the mesh representation
1514
1516{
1519 return nvert;
1520}
1521
1522////////////////////////////////////////////////////////////////////////////////
1523/// Fills array with n random points located on the line segments of the shape mesh.
1524/// The output array must be provided with a length of minimum 3*npoints. Returns
1525/// true if operation is implemented.
1526
1528{
1529 if (!array || npoints <= 0)
1530 return kFALSE;
1531
1532 if (fNz < 2)
1533 return kFALSE;
1534
1535 // Angular span (degrees). In SetPoints it is fDphi/(n-1) with n = Nsegments+1.
1536 // Here we sample generator centers, so we use nGen generators and step = fDphi/nGen.
1537 const Double_t phi1Deg = fPhi1;
1538 const Double_t dPhiDeg = fDphi;
1539 if (!(dPhiDeg > 0.0))
1540 return kFALSE;
1541
1543
1544 // Build list of active Z-segments (dz != 0) and their lengths
1545 struct ZSeg {
1546 Int_t i; // segment index from i -> i+1
1547 Double_t z0, z1;
1549 };
1550 std::vector<ZSeg> zsegs;
1551 zsegs.reserve(fNz - 1);
1552
1553 Double_t sumLen = 0.0;
1554 for (Int_t i = 0; i < fNz - 1; ++i) {
1555 const Double_t z0 = fZ[i];
1556 const Double_t z1 = fZ[i + 1];
1557 const Double_t dz = z1 - z0;
1558 if (dz == 0.0)
1559 continue;
1560 const Double_t len = std::abs(dz);
1561 zsegs.push_back({i, z0, z1, len});
1562 sumLen += len;
1563 }
1564 if (zsegs.empty() || sumLen <= 0.0)
1565 return kFALSE;
1566
1567 // Split point budget between outer/inner surfaces
1569 Int_t inPoints = 0;
1570 if (hasInside) {
1571 outPoints = (npoints + 1) / 2; // outer gets extra if odd
1573 }
1574
1575 // Helper: distribute N points over K segments proportionally to segment length (|dz|)
1576 auto distributeOverZ = [&](Int_t N) {
1577 std::vector<Int_t> perZ(zsegs.size(), 0);
1578 if (N <= 0)
1579 return perZ;
1580
1581 // First pass: floor
1582 Int_t assigned = 0;
1583 std::vector<Double_t> frac(zsegs.size(), 0.0);
1584 for (size_t k = 0; k < zsegs.size(); ++k) {
1585 const Double_t ideal = (Double_t)N * (zsegs[k].dzAbs / sumLen);
1586 const Int_t base = (Int_t)std::floor(ideal);
1587 perZ[k] = base;
1588 assigned += base;
1589 frac[k] = ideal - base;
1590 }
1591
1592 // Remainder: give to largest fractional parts
1593 Int_t rem = N - assigned;
1594 if (rem > 0) {
1595 std::vector<size_t> idx(zsegs.size());
1596 for (size_t k = 0; k < zsegs.size(); ++k)
1597 idx[k] = k;
1598 std::sort(idx.begin(), idx.end(), [&](size_t a, size_t b) { return frac[a] > frac[b]; });
1599 for (Int_t r = 0; r < rem; ++r)
1600 perZ[idx[r % idx.size()]]++;
1601 }
1602 return perZ;
1603 };
1604
1605 // Helper: fill points on one surface (outer or inner) along generators in Z
1606 auto fillSurface = [&](Int_t N, const Double_t *rArr, Int_t &icrt) -> Bool_t {
1607 if (N <= 0)
1608 return kTRUE;
1609
1610 auto perZ = distributeOverZ(N);
1611
1612 for (size_t kz = 0; kz < zsegs.size(); ++kz) {
1613 const Int_t segPts = perZ[kz];
1614 if (segPts <= 0)
1615 continue;
1616
1617 const Int_t i = zsegs[kz].i;
1618 const Double_t z0 = zsegs[kz].z0;
1619 const Double_t z1 = zsegs[kz].z1;
1620
1621 const Double_t r0 = rArr[i];
1622 const Double_t r1 = rArr[i + 1];
1623 // If radius is non-positive everywhere, nothing to sample
1624 if (r0 <= 0.0 && r1 <= 0.0)
1625 continue;
1626
1627 // Choose number of generators for this Z segment ~ sqrt(points), clamp
1629 if (nGen < 1)
1630 nGen = 1;
1631 if (nGen > segPts)
1632 nGen = segPts;
1633
1634 const Int_t q = segPts / nGen;
1635 const Int_t rem = segPts % nGen;
1636
1637 const Double_t dphi = dPhiDeg / (Double_t)nGen;
1638
1639 for (Int_t ig = 0; ig < nGen; ++ig) {
1640 const Int_t m = q + (ig < rem ? 1 : 0);
1641 if (m <= 0)
1642 continue;
1643
1644 // Generator center angle: avoids phi endpoints
1645 const Double_t phi = (phi1Deg + (ig + 0.5) * dphi) * TMath::DegToRad();
1646 const Double_t c = TMath::Cos(phi);
1647 const Double_t s = TMath::Sin(phi);
1648
1649 // Interior points along Z (no endpoints)
1650 for (Int_t j = 0; j < m; ++j) {
1651 if (icrt + 3 > 3 * npoints)
1652 return kFALSE;
1653
1654 const Double_t t = (Double_t)(j + 1) / (Double_t)(m + 1); // in (0,1)
1655 const Double_t z = z0 + t * (z1 - z0);
1656 const Double_t r = r0 + t * (r1 - r0);
1657
1658 array[icrt++] = r * c;
1659 array[icrt++] = r * s;
1660 array[icrt++] = z;
1661 }
1662 }
1663 }
1664
1665 return kTRUE;
1666 };
1667
1668 Int_t icrt = 0;
1669
1670 // Outer surface (Rmax profile)
1672 return kFALSE;
1673
1674 // Inner surface (Rmin profile), if any
1675 if (hasInside) {
1677 return kFALSE;
1678 }
1679
1680 // Contract: must fill exactly npoints
1681 return (icrt == 3 * npoints) ? kTRUE : kFALSE;
1682}
1683
1684////////////////////////////////////////////////////////////////////////////////
1685/// fill size of this 3-D object
1686
1687void TGeoPcon::Sizeof3D() const {}
1688
1689////////////////////////////////////////////////////////////////////////////////
1690/// Returns true when pgon has internal surface
1691/// It will be only disabled when all Rmin values are 0
1692
1694{
1695 // only when full 360 is used, internal part can be excluded
1697 if (!specialCase)
1698 return kTRUE;
1699
1700 for (Int_t i = 0; i < GetNz(); i++)
1701 if (fRmin[i] > 0.)
1702 return kTRUE;
1703
1704 return kFALSE;
1705}
1706
1707////////////////////////////////////////////////////////////////////////////////
1708/// Returns numbers of vertices, segments and polygons composing the shape mesh.
1709
1711{
1712 nvert = nsegs = npols = 0;
1713
1715 Int_t nz = GetNz();
1716 if (nz < 2)
1717 return;
1718
1719 if (HasInsideSurface()) {
1721 nvert = nz * 2 * n;
1722 nsegs = 4 * (nz * n - 1 + (specialCase ? 1 : 0));
1723 npols = 2 * (nz * n - 1 + (specialCase ? 1 : 0));
1724 } else {
1725 nvert = nz * n + 2;
1726 nsegs = nz * (n - 1) + n * 2 + (nz - 1) * n;
1727 npols = 2 * (n - 1) + (nz - 1) * (n - 1);
1728 }
1729}
1730
1731////////////////////////////////////////////////////////////////////////////////
1732/// Fills a static 3D buffer and returns a reference.
1733
1735{
1736 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1737
1739
1743 if (nbPnts > 0) {
1744 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
1746 }
1747 }
1748 }
1749 // TODO: Push down to TGeoShape?? Would have to do raw sizes set first..
1750 // can rest of TGeoShape be deferred until after this?
1752 SetPoints(buffer.fPnts);
1753 if (!buffer.fLocalFrame) {
1754 TransformPoints(buffer.fPnts, buffer.NbPnts());
1755 }
1756
1757 SetSegsAndPols(buffer);
1759 }
1760
1761 return buffer;
1762}
1763
1764////////////////////////////////////////////////////////////////////////////////
1765/// Stream an object of class TGeoPcon.
1766
1768{
1769 if (R__b.IsReading()) {
1770 R__b.ReadClassBuffer(TGeoPcon::Class(), this);
1772 fFullPhi = kTRUE;
1774 Double_t phi2 = phi1 + fDphi;
1775 Double_t phim = 0.5 * (phi1 + phi2);
1783 } else {
1784 R__b.WriteClassBuffer(TGeoPcon::Class(), this);
1785 }
1786}
1787
1788////////////////////////////////////////////////////////////////////////////////
1789/// Check the inside status for each of the points in the array.
1790/// Input: Array of point coordinates + vector size
1791/// Output: Array of Booleans for the inside of each point
1792
1794{
1795 for (Int_t i = 0; i < vecsize; i++)
1796 inside[i] = Contains(&points[3 * i]);
1797}
1798
1799////////////////////////////////////////////////////////////////////////////////
1800/// Compute the normal for an array o points so that norm.dot.dir is positive
1801/// Input: Arrays of point coordinates and directions + vector size
1802/// Output: Array of normal directions
1803
1805{
1806 for (Int_t i = 0; i < vecsize; i++)
1807 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
1808}
1809
1810////////////////////////////////////////////////////////////////////////////////
1811/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1812
1814 Double_t *step) const
1815{
1816 for (Int_t i = 0; i < vecsize; i++)
1817 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1818}
1819
1820////////////////////////////////////////////////////////////////////////////////
1821/// Compute distance from array of input points having directions specified by dirs. Store output in dists
1822
1824 Double_t *step) const
1825{
1826 for (Int_t i = 0; i < vecsize; i++)
1827 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
1828}
1829
1830////////////////////////////////////////////////////////////////////////////////
1831/// Compute safe distance from each of the points in the input array.
1832/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
1833/// Output: Safety values
1834
1836{
1837 for (Int_t i = 0; i < vecsize; i++)
1838 safe[i] = Safety(&points[3 * i], inside[i]);
1839}
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
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.
#define N
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 Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
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
Generic 3D primitive description class.
Definition TBuffer3D.h:18
UInt_t NbPnts() const
Definition TBuffer3D.h:80
Bool_t SectionsValid(UInt_t mask) const
Definition TBuffer3D.h:67
void SetSectionsValid(UInt_t mask)
Definition TBuffer3D.h:65
Bool_t fLocalFrame
Definition TBuffer3D.h:90
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
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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
A cone segment is a cone having a range in phi.
Definition TGeoCone.h:99
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Compute normal to closest surface from POINT.
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
compute distance from outside point to surface of arbitrary tube
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2, Int_t skipz=0)
Static method to compute the closest distance from given point to this shape.
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 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
The cones are defined by 5 parameters:
Definition TGeoCone.h:17
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute normal to closest surface from POINT.
Definition TGeoCone.cxx:232
static Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute distance from inside point to surface of the cone (static) Boundary safe algorithm.
Definition TGeoCone.cxx:285
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
Compute distance from outside point to surface of the tube Boundary safe algorithm.
Definition TGeoCone.cxx:387
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Int_t skipz=0)
computes the closest distance from given point to this shape, according to option.
Definition TGeoCone.cxx:958
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
TObjArray * GetListOfShapes() const
Int_t GetNsegments() const
Get number of segments approximating circles.
Node containing an offset.
Definition TGeoNode.h:185
a cylindrical phi divison pattern
base finder class for patterns. A pattern is specifying a division type
a Z axis divison pattern
A polycone is represented by a sequence of tubes/cones, glued together at defined Z planes.
Definition TGeoPcon.h:17
Double_t fSm
Cosine of (phi1+phi2)/2.
Definition TGeoPcon.h:32
Double_t * GetRmax() const
Definition TGeoPcon.h:82
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 GetDphi() const
Definition TGeoPcon.h:77
Double_t SafetyToSegment(const Double_t *point, Int_t ipl, Bool_t in=kTRUE, Double_t safmin=TGeoShape::Big()) const
Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
Compute normal to closest surface from POINT.
Definition TGeoPcon.cxx:364
Double_t * fRmax
Definition TGeoPcon.h:24
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
void SetPoints(Double_t *points) const override
create polycone mesh points
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.
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
Definition TGeoPcon.cxx:628
TBuffer3D * MakeBuffer3D() const override
Creates a TBuffer3D describing this shape.
Definition TGeoPcon.cxx:935
Bool_t Contains(const Double_t *point) const override
test if point is inside this shape check total z range
Definition TGeoPcon.cxx:434
const char * GetAxisName(Int_t iaxis) const override
Returns name of axis IAXIS.
Definition TGeoPcon.cxx:822
Double_t * fRmin
Definition TGeoPcon.h:23
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
Definition TGeoPcon.cxx:262
void Streamer(TBuffer &) override
Stream an object of class TGeoPcon.
Int_t GetNmeshVertices() const override
Return number of vertices of the mesh representation.
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.
Int_t fNz
Definition TGeoPcon.h:20
Double_t * fZ
Definition TGeoPcon.h:25
virtual void DefineSection(Int_t snum, Double_t z, Double_t rmin, Double_t rmax)
Defines z position of a section plane, rmin and rmax at this z.
Definition TGeoPcon.cxx:682
Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const override
Get range of shape for a given axis.
Definition TGeoPcon.cxx:835
Double_t fC1
Full phi range flag.
Definition TGeoPcon.h:27
void InspectShape() const override
print shape parameters
Definition TGeoPcon.cxx:919
void SetDimensions(Double_t *param) override
Set polycone dimensions starting from an array.
Double_t fCdphi
Sine of (phi1+phi2)/2.
Definition TGeoPcon.h:33
Bool_t fFullPhi
Definition TGeoPcon.h:26
Double_t fS1
Cosine of phi1.
Definition TGeoPcon.h:28
TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step) override
Divide this polycone shape belonging to volume "voldiv" into ndiv volumes called divname,...
Definition TGeoPcon.cxx:732
Double_t DistToSegZ(const Double_t *point, const Double_t *dir, Int_t &iz) const
compute distance to a pcon Z slice. Segment iz must be valid
Definition TGeoPcon.cxx:577
Double_t fCm
Sine of phi1+dphi.
Definition TGeoPcon.h:31
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute closest distance from point px,py to each corner
Definition TGeoPcon.cxx:485
~TGeoPcon() override
destructor
Definition TGeoPcon.cxx:243
Double_t * GetZ() const
Definition TGeoPcon.h:84
static TClass * Class()
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 polycone
Definition TGeoPcon.cxx:496
Bool_t HasInsideSurface() const
Returns true when pgon has internal surface It will be only disabled when all Rmin values are 0.
virtual Int_t GetNsegments() const
Returns number of segments on each mesh circle segment.
Definition TGeoPcon.cxx:718
Double_t fPhi1
Definition TGeoPcon.h:21
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Returns numbers of vertices, segments and polygons composing the shape mesh.
Double_t fS2
Cosine of phi1+dphi.
Definition TGeoPcon.h:30
void SetSegsAndPolsNoInside(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons, when no inner surface exists.
Double_t fDphi
Definition TGeoPcon.h:22
void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const override
Compute safe distance from each of the points in the input array.
void ComputeBBox() override
compute bounding box of the pcon Check if the sections are in increasing Z order
Definition TGeoPcon.cxx:286
Double_t fC2
Sine of phi1.
Definition TGeoPcon.h:29
void Sizeof3D() const override
fill size of this 3-D object
void SetSegsAndPols(TBuffer3D &buff) const override
Fill TBuffer3D structure for segments and polygons.
Definition TGeoPcon.cxx:955
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Fills a static 3D buffer and returns a reference.
void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Compute distance from array of input points having directions specified by dirs. Store output in dist...
Int_t GetNz() const
Definition TGeoPcon.h:78
void GetBoundingCylinder(Double_t *param) const override
Fill vector param[4] with the bounding cylinder parameters.
Definition TGeoPcon.cxx:859
Double_t * GetRmin() const
Definition TGeoPcon.h:80
TGeoPcon()
dummy ctor
Definition TGeoPcon.cxx:102
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.
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...
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 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.
Int_t ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
Returns distance to shape primitive mesh.
const char * GetName() const override
Get the shape name.
@ kGeoClosedShape
Definition TGeoShape.h:59
@ kGeoSavePrimitive
Definition TGeoShape.h:65
static Double_t Tolerance()
Definition TGeoShape.h:98
A tube segment is a tube having a range in phi.
Definition TGeoTube.h:94
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.
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...
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.
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.
Cylindrical tube class.
Definition TGeoTube.h:17
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
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
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
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
Volume families.
Definition TGeoVolume.h:267
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
Int_t IndexOf(const TObject *obj) const override
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
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1074
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
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1116
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
const Int_t n
Definition legend1.C:16
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
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
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
TMarker m
Definition textangle.C:8