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{
119 SetShapeBit(TGeoShape::kGeoPcon);
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{
142 SetShapeBit(TGeoShape::kGeoPcon);
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));
151 if (TGeoShape::IsSameWithinTolerance(fDphi, 360))
152 fFullPhi = kTRUE;
153 Double_t phi1 = fPhi1;
154 Double_t phi2 = phi1 + fDphi;
155 Double_t phim = 0.5 * (phi1 + phi2);
156 fC1 = TMath::Cos(phi1 * TMath::DegToRad());
157 fS1 = TMath::Sin(phi1 * TMath::DegToRad());
158 fC2 = TMath::Cos(phi2 * TMath::DegToRad());
159 fS2 = TMath::Sin(phi2 * TMath::DegToRad());
160 fCm = TMath::Cos(phim * TMath::DegToRad());
161 fSm = TMath::Sin(phim * TMath::DegToRad());
162 fCdphi = TMath::Cos(0.5 * fDphi * TMath::DegToRad());
163}
164
165////////////////////////////////////////////////////////////////////////////////
166/// Default constructor
167
168TGeoPcon::TGeoPcon(const char *name, Double_t phi, Double_t dphi, Int_t nz)
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{
185 SetShapeBit(TGeoShape::kGeoPcon);
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));
194 if (TGeoShape::IsSameWithinTolerance(fDphi, 360))
195 fFullPhi = kTRUE;
196 Double_t phi1 = fPhi1;
197 Double_t phi2 = phi1 + fDphi;
198 Double_t phim = 0.5 * (phi1 + phi2);
199 fC1 = TMath::Cos(phi1 * TMath::DegToRad());
200 fS1 = TMath::Sin(phi1 * TMath::DegToRad());
201 fC2 = TMath::Cos(phi2 * TMath::DegToRad());
202 fS2 = TMath::Sin(phi2 * TMath::DegToRad());
203 fCm = TMath::Cos(phim * TMath::DegToRad());
204 fSm = TMath::Sin(phim * TMath::DegToRad());
205 fCdphi = TMath::Cos(0.5 * fDphi * TMath::DegToRad());
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{
235 SetShapeBit(TGeoShape::kGeoPcon);
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;
265 Double_t rmin1, rmax1, rmin2, rmax2, phi1, phi2, dz;
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];
277 capacity += TGeoConeSeg::Capacity(dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2);
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];
291 if (IsSameWithinTolerance(fRmin[isec], fRmin[isec + 1]) &&
292 IsSameWithinTolerance(fRmax[isec], fRmax[isec + 1])) {
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(),
307 gGeoManager->GetListOfShapes()->IndexOf(this));
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
312 Double_t rmin, rmax;
313 rmin = fRmin[TMath::LocMin(fNz, fRmin)];
314 rmax = fRmax[TMath::LocMax(fNz, fRmax)];
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];
369 Double_t dz, rmin1, rmax1, rmin2, rmax2;
370 Bool_t is_tube;
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 }
377 Int_t iplclose = ipl;
378 if ((fZ[ipl + 1] - point[2]) < (point[2] - fZ[ipl]))
379 iplclose++;
381 if (dz < 1E-5) {
382 if (iplclose == 0 || iplclose == (fNz - 1)) {
383 norm[2] = TMath::Sign(1., dir[2]);
384 return;
385 }
386 if (iplclose == ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
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 {
393 if (TGeoShape::IsSameWithinTolerance(fZ[iplclose], fZ[iplclose + 1])) {
394 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
395 if (r < TMath::Max(fRmin[iplclose], fRmin[iplclose + 1]) ||
396 r > TMath::Min(fRmax[iplclose], fRmax[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];
414 is_tube = (TGeoShape::IsSameWithinTolerance(rmin1, rmin2) && TGeoShape::IsSameWithinTolerance(rmax1, rmax2))
415 ? kTRUE
416 : kFALSE;
417 if (!fFullPhi) {
418 if (is_tube)
419 TGeoTubeSeg::ComputeNormalS(ptnew, dir, norm, rmin1, rmax1, dz, fC1, fS1, fC2, fS2);
420 else
421 TGeoConeSeg::ComputeNormalS(ptnew, dir, norm, dz, rmin1, rmax1, rmin2, rmax2, fC1, fS1, fC2, fS2);
422 } else {
423 if (is_tube)
424 TGeoTube::ComputeNormalS(ptnew, dir, norm, rmin1, rmax1, dz);
425 else
426 TGeoCone::ComputeNormalS(ptnew, dir, norm, dz, rmin1, rmax1, rmin2, rmax2);
427 }
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// test if point is inside this shape
432/// check total z range
433
434Bool_t TGeoPcon::Contains(const Double_t *point) const
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
454 Double_t rmin, rmax;
455 if (TGeoShape::IsSameWithinTolerance(fZ[izl], fZ[izh]) && TGeoShape::IsSameWithinTolerance(point[2], fZ[izl])) {
456 rmin = TMath::Min(fRmin[izl], fRmin[izh]);
457 rmax = TMath::Max(fRmax[izl], fRmax[izh]);
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{
487 Int_t n = gGeoManager->GetNsegments() + 1;
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
496TGeoPcon::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
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 }
505 Double_t snxt = TGeoShape::Big();
506 Double_t sstep = 1E-6;
507 Double_t point_new[3];
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]);
515 Bool_t special_case = kFALSE;
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)) {
519 special_case = kTRUE;
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
531 Bool_t intub = kTRUE;
532 if (!TGeoShape::IsSameWithinTolerance(fRmin[ipl], fRmin[ipl + 1]))
533 intub = kFALSE;
534 else if (!TGeoShape::IsSameWithinTolerance(fRmax[ipl], fRmax[ipl + 1]))
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)
543 snxt = TGeoTubeSeg::DistFromInsideS(point_new, dir, TMath::Min(fRmin[ipl], fRmin[ipl + 1]),
544 TMath::Max(fRmax[ipl], fRmax[ipl + 1]), dz, fC1, fS1, fC2, fS2, fCm, fSm,
545 fCdphi);
546 else
547 snxt = TGeoTube::DistFromInsideS(point_new, dir, TMath::Min(fRmin[ipl], fRmin[ipl + 1]),
548 TMath::Max(fRmax[ipl], fRmax[ipl + 1]), dz);
549 return snxt;
550 }
551 if (intub) {
552 if (!fFullPhi)
553 snxt = TGeoTubeSeg::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl], dz, fC1, fS1, fC2, fS2, fCm, fSm,
554 fCdphi);
555 else
556 snxt = TGeoTube::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl], dz);
557 } else {
558 if (!fFullPhi)
559 snxt = TGeoConeSeg::DistFromInsideS(point_new, dir, dz, fRmin[ipl], fRmax[ipl], fRmin[ipl + 1], fRmax[ipl + 1],
560 fC1, fS1, fC2, fS2, fCm, fSm, fCdphi);
561 else
562 snxt = TGeoCone::DistFromInsideS(point_new, dir, dz, fRmin[ipl], fRmax[ipl], fRmin[ipl + 1], fRmax[ipl + 1]);
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);
594 Double_t snxt;
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
600 if (TGeoShape::IsSameWithinTolerance(rmin1, rmin2) && TGeoShape::IsSameWithinTolerance(rmax1, rmax2)) {
601 if (fFullPhi)
602 snxt = TGeoTube::DistFromOutsideS(local, dir, rmin1, rmax1, dz);
603 else
604 snxt = TGeoTubeSeg::DistFromOutsideS(local, dir, rmin1, rmax1, dz, fC1, fS1, fC2, fS2, fCm, fSm, fCdphi);
605 } else {
606 if (fFullPhi)
607 snxt = TGeoCone::DistFromOutsideS(local, dir, dz, rmin1, rmax1, rmin2, rmax2);
608 else
609 snxt = TGeoConeSeg::DistFromOutsideS(local, dir, dz, rmin1, rmax1, rmin2, rmax2, fC1, fS1, fC2, fS2, fCm, fSm,
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
628TGeoPcon::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
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;
649 radmax = fRmax[TMath::LocMax(fNz, fRmax)];
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;
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
732TGeoPcon::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step)
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);
749 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
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);
782 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
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);
793 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(fRmin[isect], fRmin[isect + 1]) &&
794 TGeoShape::IsSameWithinTolerance(fRmax[isect], fRmax[isect + 1]))
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
822const char *TGeoPcon::GetAxisName(Int_t iaxis) const
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
919void TGeoPcon::InspectShape() const
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{
937 Int_t nbPnts, nbSegs, nbPols;
938 GetMeshNumbers(nbPnts, nbSegs, nbPols);
939 if (nbPnts <= 0)
940 return nullptr;
941
942 TBuffer3D *buff =
943 new TBuffer3D(TBuffer3DTypes::kGeneric, nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols);
944 if (buff) {
945 SetPoints(buff->fPnts);
946 SetSegsAndPols(*buff);
947 }
948
949 return buff;
950}
951
952////////////////////////////////////////////////////////////////////////////////
953/// Fill TBuffer3D structure for segments and polygons.
954
955void TGeoPcon::SetSegsAndPols(TBuffer3D &buff) const
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;
970 Double_t dphi = GetDphi();
971
972 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(dphi, 360);
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
1224Double_t TGeoPcon::SafetyToSegment(const Double_t *point, Int_t ipl, Bool_t in, Double_t safmin) const
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]);
1235 Double_t safe = TMath::Abs(ptnew[2]) - dz;
1236 if (safe > safmin)
1237 return TGeoShape::Big(); // means: stop checking further segments
1238 Double_t rmin1 = fRmin[ipl];
1239 Double_t rmax1 = fRmax[ipl];
1240 Double_t rmin2 = fRmin[ipl + 1];
1241 Double_t rmax2 = fRmax[ipl + 1];
1242 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(rmin1, rmin2) && TGeoShape::IsSameWithinTolerance(rmax1, rmax2))
1243 ? kTRUE
1244 : kFALSE;
1245 if (!fFullPhi) {
1246 if (is_tube)
1247 safe = TGeoTubeSeg::SafetyS(ptnew, in, rmin1, rmax1, dz, fPhi1, fPhi1 + fDphi, 0);
1248 else
1249 safe = TGeoConeSeg::SafetyS(ptnew, in, dz, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi1 + fDphi, 0);
1250 } else {
1251 if (is_tube)
1252 safe = TGeoTube::SafetyS(ptnew, in, rmin1, rmax1, dz, 0);
1253 else
1254 safe = TGeoCone::SafetyS(ptnew, in, dz, rmin1, rmax1, rmin2, rmax2, 0);
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
1266Double_t TGeoPcon::Safety(const Double_t *point, Bool_t in) const
1267{
1268 Double_t safmin, saftmp;
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]);
1286 saftmp = TGeoShape::Big();
1287 if (fDphi < 360)
1288 saftmp = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi1 + fDphi);
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)
1293 safmin = TMath::Min(safmin, radius - fRmin[ipl]);
1294 if (fRmin[ipl + 1] > 0)
1295 safmin = TMath::Min(safmin, radius - fRmin[ipl + 1]);
1296 safmin = TMath::Min(safmin, fRmax[ipl] - radius);
1297 safmin = TMath::Min(safmin, fRmax[ipl + 1] - radius);
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) {
1350 saftmp = TMath::Abs(SafetyToSegment(point, iplane, kFALSE, safmin));
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) {
1359 saftmp = TMath::Abs(SafetyToSegment(point, iplane, kFALSE, safmin));
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;
1416 Double_t phi1 = fPhi1;
1417 Double_t phi2 = phi1 + fDphi;
1418 Double_t phim = 0.5 * (phi1 + phi2);
1419 fC1 = TMath::Cos(phi1 * TMath::DegToRad());
1420 fS1 = TMath::Sin(phi1 * TMath::DegToRad());
1421 fC2 = TMath::Cos(phi2 * TMath::DegToRad());
1422 fS2 = TMath::Sin(phi2 * TMath::DegToRad());
1423 fCm = TMath::Cos(phim * TMath::DegToRad());
1424 fSm = TMath::Sin(phim * TMath::DegToRad());
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;
1437 Int_t n = gGeoManager->GetNsegments() + 1;
1438 dphi = fDphi / (n - 1);
1439 Int_t i, j;
1440 Int_t indx = 0;
1441
1442 Bool_t hasInside = HasInsideSurface();
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;
1478 Int_t n = gGeoManager->GetNsegments() + 1;
1479 dphi = fDphi / (n - 1);
1480 Int_t i, j;
1481 Int_t indx = 0;
1482
1483 Bool_t hasInside = HasInsideSurface();
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{
1517 Int_t nvert, nsegs, npols;
1518 GetMeshNumbers(nvert, nsegs, npols);
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
1542 const Bool_t hasInside = HasInsideSurface();
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;
1548 Double_t dzAbs;
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
1568 Int_t outPoints = npoints;
1569 Int_t inPoints = 0;
1570 if (hasInside) {
1571 outPoints = (npoints + 1) / 2; // outer gets extra if odd
1572 inPoints = npoints - outPoints;
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
1628 Int_t nGen = (Int_t)TMath::Sqrt((Double_t)segPts);
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)
1671 if (!fillSurface(outPoints, fRmax, icrt))
1672 return kFALSE;
1673
1674 // Inner surface (Rmin profile), if any
1675 if (hasInside) {
1676 if (!fillSurface(inPoints, fRmin, icrt))
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
1696 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(), 360);
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
1710void TGeoPcon::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
1711{
1712 nvert = nsegs = npols = 0;
1713
1714 Int_t n = gGeoManager->GetNsegments() + 1;
1715 Int_t nz = GetNz();
1716 if (nz < 2)
1717 return;
1718
1719 if (HasInsideSurface()) {
1720 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(), 360);
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
1734const TBuffer3D &TGeoPcon::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
1735{
1736 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1737
1738 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1739
1740 if (reqSections & TBuffer3D::kRawSizes) {
1741 Int_t nbPnts, nbSegs, nbPols;
1742 GetMeshNumbers(nbPnts, nbSegs, nbPols);
1743 if (nbPnts > 0) {
1744 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
1745 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
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?
1751 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1752 SetPoints(buffer.fPnts);
1753 if (!buffer.fLocalFrame) {
1754 TransformPoints(buffer.fPnts, buffer.NbPnts());
1755 }
1756
1757 SetSegsAndPols(buffer);
1758 buffer.SetSectionsValid(TBuffer3D::kRaw);
1759 }
1760
1761 return buffer;
1762}
1763
1764////////////////////////////////////////////////////////////////////////////////
1765/// Stream an object of class TGeoPcon.
1766
1767void TGeoPcon::Streamer(TBuffer &R__b)
1768{
1769 if (R__b.IsReading()) {
1770 R__b.ReadClassBuffer(TGeoPcon::Class(), this);
1772 fFullPhi = kTRUE;
1773 Double_t phi1 = fPhi1;
1774 Double_t phi2 = phi1 + fDphi;
1775 Double_t phim = 0.5 * (phi1 + phi2);
1776 fC1 = TMath::Cos(phi1 * TMath::DegToRad());
1777 fS1 = TMath::Sin(phi1 * TMath::DegToRad());
1778 fC2 = TMath::Cos(phi2 * TMath::DegToRad());
1779 fS2 = TMath::Sin(phi2 * TMath::DegToRad());
1780 fCm = TMath::Cos(phim * TMath::DegToRad());
1781 fSm = TMath::Sin(phim * TMath::DegToRad());
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
1793void TGeoPcon::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
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
1804void TGeoPcon::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
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
1813void TGeoPcon::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize,
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
1823void TGeoPcon::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize,
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
1835void TGeoPcon::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
1836{
1837 for (Int_t i = 0; i < vecsize; i++)
1838 safe[i] = Safety(&points[3 * i], inside[i]);
1839}
ROOT::R::TRInterface & r
Definition Object.C:4
#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
start
Definition Rotated.cxx:223
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
float Float_t
Float 4 bytes (float).
Definition RtypesCore.h:71
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char).
Definition RtypesCore.h:80
#define N
XFontStruct * id
Definition TGX11.cxx:147
char name[80]
Definition TGX11.cxx:148
externTGeoManager * gGeoManager
float xmin
float * q
float ymin
float xmax
float ymax
point * points
Definition X3DBuffer.c:22
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t * fPols
Definition TBuffer3D.h:124
Int_t * fSegs
Definition TBuffer3D.h:123
Double_t * fPnts
Definition TBuffer3D.h:122
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const override
Fill 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
Double_t fOrigin[3]
Definition TGeoBBox.h:24
void InspectShape() const override
Double_t fDY
Definition TGeoBBox.h:22
Double_t fDZ
Definition TGeoBBox.h:23
Double_t Capacity() const override
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)
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 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)
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)
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)
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)
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)
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)
void SetDivIndex(Int_t index)
Double_t fSm
! Sine 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
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
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
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
virtual Int_t GetNsegments() const
Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const override
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
TBuffer3D * MakeBuffer3D() const override
Bool_t Contains(const Double_t *point) const override
const char * GetAxisName(Int_t iaxis) const override
Double_t * fRmin
Definition TGeoPcon.h:23
Double_t Capacity() const override
void Streamer(TBuffer &) override
Stream an object of class TObject.
Int_t GetNmeshVertices() const override
void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const override
Int_t fNz
Definition TGeoPcon.h:20
Double_t * fZ
Definition TGeoPcon.h:25
Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const override
Double_t fC1
! Cosine of phi1
Definition TGeoPcon.h:27
void InspectShape() const override
void SetDimensions(Double_t *param) override
Double_t fCdphi
! Cosine of dphi
Definition TGeoPcon.h:33
Bool_t fFullPhi
! Full phi range flag
Definition TGeoPcon.h:26
Double_t fS1
! Sine 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
Double_t DistToSegZ(const Double_t *point, const Double_t *dir, Int_t &iz) const
Double_t fCm
! Cosine of (phi1+phi2)/2
Definition TGeoPcon.h:31
TGeoPcon(const TGeoPcon &)=delete
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Computes distance from point (px,py) to the object.
~TGeoPcon() override
virtual void DefineSection(Int_t snum, Double_t z, Double_t rmin, Double_t rmax)
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
Bool_t HasInsideSurface() const
Double_t fPhi1
Definition TGeoPcon.h:21
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Double_t fS2
! Sine of phi1+dphi
Definition TGeoPcon.h:30
void SetSegsAndPolsNoInside(TBuffer3D &buff) const
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
void ComputeBBox() override
Double_t fC2
! Cosine of phi1+dphi
Definition TGeoPcon.h:29
void Sizeof3D() const override
void SetSegsAndPols(TBuffer3D &buff) const override
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Stub implementation to avoid forcing implementation at this stage.
void DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const override
Int_t GetNz() const
Definition TGeoPcon.h:78
void GetBoundingCylinder(Double_t *param) const override
Double_t * GetRmin() const
Definition TGeoPcon.h:80
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize) override
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.
TGeoShape()
Default constructor.
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
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)
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)
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 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 Double_t DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
static Double_t DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
static void ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t rmin, Double_t rmax, Double_t dz)
static Double_t SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz=0)
void AddVolume(TGeoVolume *vol)
Add a volume with valid shape to the list of volumes.
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
void AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset=0, Option_t *option="")
Add a division node to the list of nodes.
TGeoMedium * GetMedium() const
Definition TGeoVolume.h:176
void SetFinder(TGeoPatternFinder *finder)
Definition TGeoVolume.h:245
Int_t GetNdaughters() const
Definition TGeoVolume.h:363
TObjArray * GetNodes()
Definition TGeoVolume.h:170
TObject * At(Int_t idx) const override
Definition TObjArray.h:170
Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1126
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 E()
Base of natural log: .
Definition TMath.h:96
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