Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGeoPgon.cxx
Go to the documentation of this file.
1// @(#)root/geom:$Id$
2// Author: Andrei Gheata 31/01/02
3// TGeoPgon::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 TGeoPgon
14\ingroup Shapes_classes
15
16Polygons are defined in the same way as polycones, the difference being
17just that the segments between consecutive Z planes are regular
18polygons. The phi segmentation is preserved and the shape is defined in
19a similar manner, just that `rmin` and `rmax` represent the radii of the
20circles inscribed in the inner/outer polygon.
21
22Begin_Macro
23{
24 TCanvas *c = new TCanvas("c", "c",0,0,600,600);
25 new TGeoManager("pgon", "poza11");
26 TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
27 TGeoMedium *med = new TGeoMedium("MED",1,mat);
28 TGeoVolume *top = gGeoManager->MakeBox("TOP",med,150,150,100);
29 gGeoManager->SetTopVolume(top);
30 TGeoVolume *vol = gGeoManager->MakePgon("PGON",med, -45.0,270.0,4,4);
31 TGeoPgon *pgon = (TGeoPgon*)(vol->GetShape());
32 pgon->DefineSection(0,-70,45,50);
33 pgon->DefineSection(1,0,35,40);
34 pgon->DefineSection(2,0,30,35);
35 pgon->DefineSection(3,70,90,100);
36 vol->SetLineWidth(2);
37 top->AddNode(vol,1);
38 gGeoManager->CloseGeometry();
39 gGeoManager->SetNsegments(80);
40 top->Draw();
41 TView *view = gPad->GetView();
42 if (view) view->ShowAxis();
43}
44End_Macro
45
46The constructor of a polygon has the form:
47
48~~~{.cpp}
49TGeoPgon(Double_t phi1,Double_t dphi,Int_t nedges,Int_t nz);
50~~~
51
52The extra parameter `nedges` represent the number of equal edges of the
53polygons, between `phi1` and `phi1+dphi.`
54
55*/
56
57#include "TGeoPgon.h"
58
59#include <iostream>
60
61#include "TGeoManager.h"
62#include "TGeoVolume.h"
63#include "TVirtualGeoPainter.h"
64#include "TGeoTube.h"
65#include "TBuffer3D.h"
66#include "TBuffer3DTypes.h"
67#include "TMath.h"
68
69std::atomic<UInt_t> TGeoPgon::fgInstanceCount{0};
70
72 std::unique_ptr<Int_t[]> fIntBuffer;
73 std::unique_ptr<Double_t[]> fDblBuffer;
74
76};
77
78////////////////////////////////////////////////////////////////////////////////
79/// (Re)build the per-thread scratch buffers for this shape into the given slot.
80/// Cold path: runs once per (thread, shape, generation).
81
83{
84 auto data = std::make_unique<OwnedThreadData_t>(fNedges + 10);
85 Int_t *intBuffer = data->fIntBuffer.get();
86 Double_t *dblBuffer = data->fDblBuffer.get();
87
88 std::lock_guard<std::mutex> guard(fOwnedDataMutex);
89 fOwnedData.push_back(std::move(data));
90 td.fIntBuffer = intBuffer;
91 td.fDblBuffer = dblBuffer;
92 td.fInitGen = fGeneration.load(std::memory_order_acquire);
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Release the large scratch buffers. Navigation using this shape must not be active.
97
99{
100 std::lock_guard<std::mutex> guard(fOwnedDataMutex);
101 fOwnedData.clear();
102 fGeneration.fetch_add(1, std::memory_order_release);
103}
104
105////////////////////////////////////////////////////////////////////////////////
106/// dummy ctor
107
113
114////////////////////////////////////////////////////////////////////////////////
115/// Default constructor
116
122
123////////////////////////////////////////////////////////////////////////////////
124/// Default constructor
125
132
133////////////////////////////////////////////////////////////////////////////////
134/// Default constructor in GEANT3 style
135/// - param[0] = phi1
136/// - param[1] = dphi
137/// - param[2] = nedges
138/// - param[3] = nz
139/// - param[4] = z1
140/// - param[5] = Rmin1
141/// - param[6] = Rmax1
142/// ...
143
150
151////////////////////////////////////////////////////////////////////////////////
152/// destructor
153
158
159////////////////////////////////////////////////////////////////////////////////
160/// Computes capacity of the shape in [length^3]
161
163{
164 Int_t ipl;
166 Double_t capacity = 0.;
167 dphi = fDphi / fNedges; // [deg]
169 for (ipl = 0; ipl < fNz - 1; ipl++) {
170 dz = fZ[ipl + 1] - fZ[ipl];
171 if (dz < TGeoShape::Tolerance())
172 continue;
173 rmin1 = fRmin[ipl];
174 rmax1 = fRmax[ipl];
175 rmin2 = fRmin[ipl + 1];
176 rmax2 = fRmax[ipl + 1];
177 capacity += fNedges * (tphi2 / 3.) * dz *
178 (rmax1 * rmax1 + rmax1 * rmax2 + rmax2 * rmax2 - rmin1 * rmin1 - rmin1 * rmin2 - rmin2 * rmin2);
179 }
180 return capacity;
181}
182
183////////////////////////////////////////////////////////////////////////////////
184/// compute bounding box for a polygone
185/// Check if the sections are in increasing Z order
186
188{
189 for (Int_t isec = 0; isec < fNz - 1; isec++) {
190 if (fZ[isec] > fZ[isec + 1]) {
191 InspectShape();
192 Fatal("ComputeBBox", "Wrong section order");
193 }
194 }
195 // Check if the last sections are valid
196 if (TMath::Abs(fZ[1] - fZ[0]) < TGeoShape::Tolerance() ||
197 TMath::Abs(fZ[fNz - 1] - fZ[fNz - 2]) < TGeoShape::Tolerance()) {
198 InspectShape();
199 Fatal("ComputeBBox", "Shape %s at index %d: Not allowed first two or last two sections at same Z", GetName(),
201 }
202 Double_t zmin = TMath::Min(fZ[0], fZ[fNz - 1]);
203 Double_t zmax = TMath::Max(fZ[0], fZ[fNz - 1]);
204 // find largest rmax an smallest rmin
207 // find the radius of the outscribed circle
213
214 Double_t xc[4];
215 Double_t yc[4];
224
225 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
226 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
227 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
228 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
229
230 Double_t ddp = -phi1;
231 if (ddp < 0)
232 ddp += 360;
233 if (ddp <= fDphi)
234 xmax = rmax;
235 ddp = 90 - phi1;
236 if (ddp < 0)
237 ddp += 360;
238 if (ddp <= fDphi)
239 ymax = rmax;
240 ddp = 180 - phi1;
241 if (ddp < 0)
242 ddp += 360;
243 if (ddp <= fDphi)
244 xmin = -rmax;
245 ddp = 270 - phi1;
246 if (ddp < 0)
247 ddp += 360;
248 if (ddp <= fDphi)
249 ymin = -rmax;
250 fOrigin[0] = 0.5 * (xmax + xmin);
251 fOrigin[1] = 0.5 * (ymax + ymin);
252 fOrigin[2] = 0.5 * (zmax + zmin);
253 fDX = 0.5 * (xmax - xmin);
254 fDY = 0.5 * (ymax - ymin);
255 fDZ = 0.5 * (zmax - zmin);
257}
258
259////////////////////////////////////////////////////////////////////////////////
260/// Compute normal to closest surface from POINT.
261
262void TGeoPgon::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const
263{
264 memset(norm, 0, 3 * sizeof(Double_t));
265 Double_t phi1 = 0, phi2 = 0, c1 = 0, s1 = 0, c2 = 0, s2 = 0;
267 Bool_t is_seg = (fDphi < 360) ? kTRUE : kFALSE;
268 if (is_seg) {
269 phi1 = fPhi1;
270 if (phi1 < 0)
271 phi1 += 360;
272 phi2 = phi1 + fDphi;
275 c1 = TMath::Cos(phi1);
276 s1 = TMath::Sin(phi1);
277 c2 = TMath::Cos(phi2);
278 s2 = TMath::Sin(phi2);
279 if (TGeoShape::IsCloseToPhi(1E-5, point, c1, s1, c2, s2)) {
280 TGeoShape::NormalPhi(point, dir, norm, c1, s1, c2, s2);
281 return;
282 }
283 } // Phi done
284
285 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
286 if (ipl == (fNz - 1) || ipl < 0) {
287 // point outside Z range
288 norm[2] = TMath::Sign(1., dir[2]);
289 return;
290 }
292 if ((fZ[ipl + 1] - point[2]) < (point[2] - fZ[ipl]))
293 iplclose++;
294 dz = TMath::Abs(fZ[iplclose] - point[2]);
295
297 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
298 while (phi < fPhi1)
299 phi += 360.;
300 Double_t ddp = phi - fPhi1;
302 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
303 // compute projected distance
305 r = TMath::Abs(point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0));
306 if (dz < 1E-5) {
307 if (iplclose == 0 || iplclose == (fNz - 1)) {
308 norm[2] = TMath::Sign(1., dir[2]);
309 return;
310 }
312 if (r < TMath::Max(fRmin[ipl], fRmin[ipl - 1]) || r > TMath::Min(fRmax[ipl], fRmax[ipl - 1])) {
313 norm[2] = TMath::Sign(1., dir[2]);
314 return;
315 }
316 } else {
318 if (r < TMath::Max(fRmin[iplclose], fRmin[iplclose + 1]) ||
320 norm[2] = TMath::Sign(1., dir[2]);
321 return;
322 }
323 }
324 }
325 } //-> Z done
326
327 dz = fZ[ipl + 1] - fZ[ipl];
328 rmin1 = fRmin[ipl];
329 rmin2 = fRmin[ipl + 1];
330 rsum = rmin1 + rmin2;
332 if (rsum > 1E-10) {
333 ta = (rmin2 - rmin1) / dz;
334 calf = 1. / TMath::Sqrt(1 + ta * ta);
335 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
336 safe = TMath::Abs(r - rpgon);
337 norm[0] = calf * TMath::Cos(ph0);
338 norm[1] = calf * TMath::Sin(ph0);
339 norm[2] = -calf * ta;
340 }
341 ta = (fRmax[ipl + 1] - fRmax[ipl]) / dz;
342 calf = 1. / TMath::Sqrt(1 + ta * ta);
343 rpgon = fRmax[ipl] + (point[2] - fZ[ipl]) * ta;
344 if (safe > TMath::Abs(rpgon - r)) {
345 norm[0] = calf * TMath::Cos(ph0);
346 norm[1] = calf * TMath::Sin(ph0);
347 norm[2] = -calf * ta;
348 }
349 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
350 norm[0] = -norm[0];
351 norm[1] = -norm[1];
352 norm[2] = -norm[2];
353 }
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// test if point is inside this shape
358/// check total z range
359
361{
362 if (point[2] < fZ[0])
363 return kFALSE;
364 if (point[2] > fZ[fNz - 1])
365 return kFALSE;
367 // now check phi
368 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
369 while (phi < fPhi1)
370 phi += 360.0;
371 Double_t ddp = phi - fPhi1;
372 if (ddp > fDphi)
373 return kFALSE;
374 // now find phi division
376 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
377 // now check projected distance
378 Double_t r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
379 // find in which Z section the point is in
380 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
381 if (iz == fNz - 1) {
382 if (r < fRmin[iz])
383 return kFALSE;
384 if (r > fRmax[iz])
385 return kFALSE;
386 return kTRUE;
387 }
388 Double_t dz = fZ[iz + 1] - fZ[iz];
390 if (dz < 1E-8) {
391 // we are at a radius-changing plane
392 rmin = TMath::Min(fRmin[iz], fRmin[iz + 1]);
393 rmax = TMath::Max(fRmax[iz], fRmax[iz + 1]);
394 if (r < rmin)
395 return kFALSE;
396 if (r > rmax)
397 return kFALSE;
398 return kTRUE;
399 }
400 // now compute rmin and rmax and test the value of r
401 Double_t dzrat = (point[2] - fZ[iz]) / dz;
402 rmin = fRmin[iz] + dzrat * (fRmin[iz + 1] - fRmin[iz]);
403 // is the point inside the 'hole' at the center of the volume ?
404 if (r < rmin)
405 return kFALSE;
406 rmax = fRmax[iz] + dzrat * (fRmax[iz + 1] - fRmax[iz]);
407 if (r > rmax)
408 return kFALSE;
409
410 return kTRUE;
411}
412
413////////////////////////////////////////////////////////////////////////////////
414/// compute distance from inside point to surface of the polygone
415/// first find out in which Z section the point is in
416
419{
420 if (iact < 3 && safe) {
421 *safe = Safety(point, kTRUE);
422 if (iact == 0)
423 return TGeoShape::Big();
424 if (iact == 1 && step < *safe)
425 return TGeoShape::Big();
426 }
427 // find current Z section
428 Int_t ipl, ipsec;
429 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
430 if (ipl == fNz - 1) {
431 if (dir[2] >= 0)
432 return 0.;
433 ipl--;
434 }
435 if (ipl < 0) {
436 // point out
437 if (dir[2] <= 0)
438 return 0.;
439 ipl++;
440 }
441 Double_t stepmax = step;
443 Double_t *sph = td.fDblBuffer;
444 Int_t *iph = td.fIntBuffer;
445 // locate current phi sector [0,fNedges-1]; -1 for dead region
446 LocatePhi(point, ipsec);
447 if (ipsec < 0) {
448 // Point on a phi boundary - entering or exiting ?
451 if ((point[0] * dir[1] - point[1] * dir[0]) > 0) {
452 // phi1 next crossing
453 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) <
454 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
455 // close to phimax
456 return 0.0;
457 } else {
458 // close to phi1 - ignore it
459 ipsec = 0;
460 }
461 } else {
462 // phimax next crossing
463 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) >
464 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
465 // close to phi1
466 return 0.0;
467 } else {
468 // close to phimax - ignore it
469 ipsec = fNedges - 1;
470 }
471 }
472 }
473 Int_t ipln = -1;
475 ipln = ipl;
476 } else {
477 if (fNz > 3 && ipl >= 0 && ipl < fNz - 3 && TGeoShape::IsSameWithinTolerance(fZ[ipl + 1], fZ[ipl + 2]) &&
478 TMath::Abs(point[2] - fZ[ipl + 1]) < 1.E-8) {
479 ipln = ipl + 1;
480 } else {
481 if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1]) &&
482 TMath::Abs(point[2] - fZ[ipl]) < 1.E-8)
483 ipln = ipl - 1;
484 }
485 }
486 if (ipln > 0) {
487 // point between segments
489 Double_t phi = (fPhi1 + (ipsec + 0.5) * divphi) * TMath::DegToRad();
490 Double_t cphi = TMath::Cos(phi);
491 Double_t sphi = TMath::Sin(phi);
492 Double_t rproj = point[0] * cphi + point[1] * sphi;
493 if (dir[2] > 0) {
494 ipl = ipln + 1;
495 if (rproj > fRmin[ipln] && rproj < fRmin[ipln + 1])
496 return 0.0;
497 if (rproj < fRmax[ipln] && rproj > fRmax[ipln + 1])
498 return 0.0;
499 } else {
500 ipl = ipln - 1;
501 if (rproj < fRmin[ipln] && rproj > fRmin[ipln + 1])
502 return 0.0;
503 if (rproj > fRmax[ipln] && rproj < fRmax[ipln + 1])
504 return 0.0;
505 }
506 }
507
509 icrossed = GetPhiCrossList(point, dir, ipsec, sph, iph, stepmax);
511 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
512 if (SliceCrossingInZ(point, dir, icrossed, iph, sph, snext, stepmax))
513 return snext;
515 return TGeoShape::Big();
516 return 0.;
517 }
518 if (SliceCrossingIn(point, dir, ipl, icrossed, iph, sph, snext, stepmax))
519 return snext;
521 return TGeoShape::Big();
522 return 0.;
523}
524
525////////////////////////////////////////////////////////////////////////////////
526/// Locates index IPSEC of the phi sector containing POINT.
527
528void TGeoPgon::LocatePhi(const Double_t *point, Int_t &ipsec) const
529{
530 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
531 while (phi < fPhi1)
532 phi += 360.;
533 ipsec = Int_t(fNedges * (phi - fPhi1) / fDphi); // [0, fNedges-1]
534 if (ipsec > fNedges - 1)
535 ipsec = -1; // in gap
536}
537
538////////////////////////////////////////////////////////////////////////////////
539/// Returns lists of PGON phi crossings for a ray starting from POINT.
540
542 Double_t stepmax) const
543{
544 Double_t rxy, phi, cph, sph;
545 Int_t icrossed = 0;
546 if ((1. - TMath::Abs(dir[2])) < 1E-8) {
547 // ray is going parallel with Z
548 iphi[0] = istart;
549 sphi[0] = stepmax;
550 return 1;
551 }
552 Bool_t shootorig = (TMath::Abs(point[0] * dir[1] - point[1] * dir[0]) < 1E-8) ? kTRUE : kFALSE;
554 if (shootorig) {
555 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
556 if (rdotn > 0) {
557 sphi[0] = stepmax;
558 iphi[0] = istart;
559 return 1;
560 }
561 sphi[0] = TMath::Sqrt((point[0] * point[0] + point[1] * point[1]) / (1. - dir[2] * dir[2]));
562 iphi[0] = istart;
563 if (sphi[0] > stepmax) {
564 sphi[0] = stepmax;
565 return 1;
566 }
567 phi = TMath::ATan2(dir[1], dir[0]) * TMath::RadToDeg();
568 while (phi < fPhi1)
569 phi += 360.;
570 istart = Int_t((phi - fPhi1) / divphi);
571 if (istart > fNedges - 1)
572 istart = -1;
573 iphi[1] = istart;
574 sphi[1] = stepmax;
575 return 2;
576 }
577 Int_t incsec = Int_t(TMath::Sign(1., point[0] * dir[1] - point[1] * dir[0]));
578 Int_t ist;
579 if (istart < 0)
580 ist = (incsec > 0) ? 0 : fNedges;
581 else
582 ist = (incsec > 0) ? (istart + 1) : istart;
587 while (crossing) {
588 if (istart < 0)
589 gapdone = kTRUE;
590 phi = phi1 + ist * divphi;
591 cph = TMath::Cos(phi);
592 sph = TMath::Sin(phi);
594 if (!crossing)
596 iphi[icrossed++] = istart;
597 if (crossing) {
598 if (sphi[icrossed - 1] > stepmax) {
599 sphi[icrossed - 1] = stepmax;
600 return icrossed;
601 }
602 if (istart < 0) {
603 istart = (incsec > 0) ? 0 : (fNedges - 1);
604 } else {
605 istart += incsec;
606 if (istart > fNedges - 1)
607 istart = (fDphi < 360.) ? (-1) : 0;
608 else if (istart < 0 && TGeoShape::IsSameWithinTolerance(fDphi, 360))
609 istart = fNedges - 1;
610 }
611 if (istart < 0) {
612 if (gapdone)
613 return icrossed;
614 ist = (incsec > 0) ? 0 : fNedges;
615 } else {
616 ist = (incsec > 0) ? (istart + 1) : istart;
617 }
618 }
619 }
620 return icrossed;
621}
622
623////////////////////////////////////////////////////////////////////////////////
624/// Performs ray propagation between Z segments.
625
628{
629 snext = 0.;
630 if (!nphi)
631 return kFALSE;
632 Int_t i;
635 Double_t pt[3];
636 if (iphi[0] < 0 && nphi == 1)
637 return kFALSE;
638 // Get current Z segment
639 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
640 if (ipl < 0 || ipl == fNz - 1)
641 return kFALSE;
642 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
643 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
644 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
645 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
646 } else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
647 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
648 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
649 } else {
650 rmin = fRmin[ipl];
651 rmax = fRmax[ipl];
652 }
653 } else {
654 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
655 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
656 }
659 Double_t rproj, ndot, dist;
662 Double_t snextphi = 0.;
663 Double_t step = 0;
664 Double_t phi;
665 memcpy(pt, point, 3 * sizeof(Double_t));
666 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
667 if (step > stepmax) {
668 snext = step;
669 return kFALSE;
670 }
671 if (iphi[iphcrt] < 0) {
672 snext = step;
673 return kTRUE;
674 }
675 // check crossing
677 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
678 cosph = TMath::Cos(phi);
679 sinph = TMath::Sin(phi);
680 rproj = pt[0] * cosph + pt[1] * sinph;
681 dist = TGeoShape::Big();
682 ndot = dir[0] * cosph + dir[1] * sinph;
684 dist = (ndot > 0) ? ((rmax - rproj) / ndot) : ((rmin - rproj) / ndot);
685 if (dist < 0)
686 dist = 0.;
687 }
688 if (dist < (snextphi - step)) {
689 snext = step + dist;
690 if (snext < stepmax)
691 return kTRUE;
692 return kFALSE;
693 }
694 step = snextphi;
695 for (i = 0; i < 3; i++)
696 pt[i] = point[i] + step * dir[i];
697 }
698 snext = step;
699 return kFALSE;
700}
701
702////////////////////////////////////////////////////////////////////////////////
703/// Performs ray propagation between Z segments.
704
707{
708 if (!nphi)
709 return kFALSE;
710 Int_t i;
713 Double_t pt[3];
714 if (iphi[0] < 0 && nphi == 1)
715 return kFALSE;
716 // Get current Z segment
717 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
718 if (ipl < 0 || ipl == fNz - 1)
719 return kFALSE;
720 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
721 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
722 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
723 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
724 } else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
725 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
726 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
727 } else {
728 rmin = fRmin[ipl];
729 rmax = fRmax[ipl];
730 }
731 } else {
732 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
733 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
734 }
737 Double_t rproj, ndot, dist;
740 Double_t snextphi = 0.;
741 Double_t step = 0;
742 Double_t phi;
743 memcpy(pt, point, 3 * sizeof(Double_t));
744 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
745 if (step > stepmax)
746 return kFALSE;
748 if (iphi[iphcrt] < 0) {
749 if (iphcrt == nphi - 1)
750 return kFALSE;
751 if (snextphi > stepmax)
752 return kFALSE;
753 for (i = 0; i < 3; i++)
754 pt[i] = point[i] + snextphi * dir[i];
755 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
756 cosph = TMath::Cos(phi);
757 sinph = TMath::Sin(phi);
758 rproj = pt[0] * cosph + pt[1] * sinph;
760 step = snextphi;
761 continue;
762 }
763 snext = snextphi;
764 return kTRUE;
765 }
766 // check crossing
767 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
768 cosph = TMath::Cos(phi);
769 sinph = TMath::Sin(phi);
770 rproj = pt[0] * cosph + pt[1] * sinph;
771 dist = TGeoShape::Big();
772 ndot = dir[0] * cosph + dir[1] * sinph;
773 if (rproj < rmin) {
774 dist = (ndot > 0) ? ((rmin - rproj) / ndot) : TGeoShape::Big();
775 } else {
776 dist = (ndot < 0) ? ((rmax - rproj) / ndot) : TGeoShape::Big();
777 }
778 if (dist < 1E10) {
779 snext = step + dist;
780 if (snext < stepmax)
781 return kTRUE;
782 }
783 step = snextphi;
784 for (i = 0; i < 3; i++)
785 pt[i] = point[i] + step * dir[i];
786 }
787 return kFALSE;
788}
789
790////////////////////////////////////////////////////////////////////////////////
791/// Check boundary crossing inside phi slices. Return distance snext to first crossing
792/// if smaller than stepmax.
793/// Protection in case point is in phi gap or close to phi boundaries and exiting
794
797{
798 snext = 0.;
799 if (!nphi)
800 return kFALSE;
801 Int_t i;
802 Int_t iphstart = 0;
803 Double_t pt[3];
804 if (iphi[0] < 0) {
805 if (stepphi[0] > TGeoShape::Tolerance())
806 return kFALSE;
807 iphstart = 1;
808 }
809 if (nphi > 1 && iphi[1] < 0 && stepphi[0] < TGeoShape::Tolerance()) {
810 snext = stepphi[0];
811 return kTRUE;
812 }
813 // Get current Z segment
814 Double_t snextphi = 0.;
815 Double_t step = 0;
816 Int_t incseg = (dir[2] > 0) ? 1 : -1; // dir[2] is never 0 here
817 // Compute the projected radius from starting point
819 Int_t iphcrt = 0;
820 Double_t apr = TGeoShape::Big(), bpr = 0, db = 0;
821 Double_t rpg = 0, rnew = 0, znew = 0;
822 Double_t rpgin = 0, rpgout = 0, apgin = 0, apgout = 0, bpgin = 0, bpgout = 0;
825 Double_t phi = 0, dz = 0;
826 Double_t cosph = 0, sinph = 0;
827 Double_t distz = 0, distr = 0, din = 0, dout = 0;
828 Double_t invdir = 1. / dir[2];
829 memcpy(pt, point, 3 * sizeof(Double_t));
830 for (iphcrt = iphstart; iphcrt < nphi; iphcrt++) {
831 // check if step to current checked slice is too big
832 if (step > stepmax) {
833 snext = step;
834 return kFALSE;
835 }
836 if (iphi[iphcrt] < 0) {
837 snext = snextphi;
838 return kTRUE;
839 }
841 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
842 cosph = TMath::Cos(phi);
843 sinph = TMath::Sin(phi);
844 Double_t rproj = Rproj(pt[2], pt, dir, cosph, sinph, apr, bpr);
845 // compute distance to next Z plane
846 while (ipl >= 0 && ipl < fNz - 1) {
847 din = dout = TGeoShape::Big();
848 // dist to last boundary of current segment according dir
849 distz = (fZ[ipl + ((1 + incseg) >> 1)] - pt[2]) * invdir;
850 // length of current segment
851 dz = fZ[ipl + 1] - fZ[ipl];
852 if (dz < TGeoShape::Tolerance()) {
853 rnew = apr + bpr * fZ[ipl];
854 rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
855 if (rpg <= 0)
856 din = distz;
857 rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
858 if (rpg <= 0)
859 dout = distz;
861 } else {
862 rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
863 db = bpgin - bpr;
865 znew = (apr - apgin) / db;
866 din = (znew - pt[2]) * invdir;
867 }
868 rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
869 db = bpgout - bpr;
871 znew = (apr - apgout) / db;
872 dout = (znew - pt[2]) * invdir;
873 }
874 // protection for the first segment
878 if (iphcrt == iphstart && ipl == iplstart) {
879 if (rproj < rpgin + 1.E-8) {
880 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
881 if (ndotd < 0) {
882 snext = (din < 0) ? step : (step + din);
883 return kTRUE;
884 } else {
885 // Ignore din
886 din = -TGeoShape::Big();
887 }
891 } else if (rproj > rpgout - 1.E-8) {
892 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
893 if (ndotd > 0) {
894 snext = (dout < 0) ? step : (step + dout);
895 return kTRUE;
896 } else {
897 // Ignore dout
898 dout = -TGeoShape::Big();
899 }
903 }
904 }
905 }
908 if (snextphi < step + TMath::Min(distz, distr)) {
909 for (i = 0; i < 3; i++)
910 pt[i] = point[i] + snextphi * dir[i];
911 step = snextphi;
912 snext = 0.0;
913 break;
914 }
915 if (distr <= distz + TGeoShape::Tolerance()) {
916 step += distr;
917 snext = step;
918 return (step > stepmax) ? kFALSE : kTRUE;
919 }
920 // we have crossed a Z boundary
921 snext = distz;
922 if ((ipl + incseg < 0) || (ipl + incseg > fNz - 2)) {
923 // it was the last boundary
924 step += distz;
925 snext = step;
926 return (step > stepmax) ? kFALSE : kTRUE;
927 }
928 ipl += incseg;
929 } // end loop Z
930 } // end loop phi
932 return kFALSE;
933}
934
935////////////////////////////////////////////////////////////////////////////////
936/// Check boundary crossing inside phi slices. Return distance snext to first crossing
937/// if smaller than stepmax.
938
941{
942 if (!nphi)
943 return kFALSE;
944 Int_t i;
945 Double_t pt[3];
946 if (iphi[0] < 0 && nphi == 1)
947 return kFALSE;
948
949 Double_t snextphi = 0.;
950 Double_t step = 0;
951 // Get current Z segment
952 Int_t incseg = (dir[2] > 0) ? 1 : -1; // dir[2] is never 0 here
953 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
954 if (ipl < 0) {
955 ipl = 0; // this should never happen
956 if (incseg < 0)
957 return kFALSE;
958 } else {
959 if (ipl == fNz - 1) {
960 ipl = fNz - 2; // nor this
961 if (incseg > 0)
962 return kFALSE;
963 } else {
964 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
965 // we are at the sector edge, but never inside the pgon
966 if ((ipl + incseg) < 0 || (ipl + incseg) > fNz - 1)
967 return kFALSE;
969 ipl += incseg;
970 // move to next clean segment if downwards
971 if (incseg < 0) {
973 ipl--;
974 }
975 }
976 }
977 }
978 // Compute the projected radius from starting point
985 Double_t phi;
988 memcpy(pt, point, 3 * sizeof(Double_t));
989 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
990 // check if step to current checked slice is too big
991 if (step > stepmax)
992 return kFALSE;
993 // jump over the dead sector
995 if (iphi[iphcrt] < 0) {
996 if (iphcrt == nphi - 1)
997 return kFALSE;
998 if (snextphi > stepmax)
999 return kFALSE;
1000 for (i = 0; i < 3; i++)
1001 pt[i] = point[i] + snextphi * dir[i];
1002 // we have a new z, so check again iz
1003 if (incseg > 0) {
1004 // loop z planes
1005 while (pt[2] > fZ[ipl + 1]) {
1006 ipl++;
1007 if (ipl > fNz - 2)
1008 return kFALSE;
1009 }
1010 } else {
1011 while (pt[2] < fZ[ipl]) {
1012 ipl--;
1013 if (ipl < 0)
1014 return kFALSE;
1015 }
1016 }
1017 // check if we have a crossing when entering new sector
1018 rpgin = Rpg(pt[2], ipl, kTRUE, apg, bpg);
1019 rpgout = Rpg(pt[2], ipl, kFALSE, apg, bpg);
1020 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
1021 cosph = TMath::Cos(phi);
1022 sinph = TMath::Sin(phi);
1023
1024 rproj = pt[0] * cosph + pt[1] * sinph;
1026 step = snextphi;
1027 continue;
1028 }
1029 snext = snextphi;
1030 return kTRUE;
1031 }
1032 if (IsCrossingSlice(point, dir, iphi[iphcrt], step, ipl, snext, TMath::Min(snextphi, stepmax)))
1033 return kTRUE;
1034 step = snextphi;
1035 }
1036 return kFALSE;
1037}
1038
1039////////////////////////////////////////////////////////////////////////////////
1040/// Check crossing of a given pgon slice, from a starting point inside the slice
1041
1044{
1045 if (ipl < 0 || ipl > fNz - 2)
1046 return kFALSE;
1047 if (sstart > stepmax)
1048 return kFALSE;
1049 Double_t pt[3];
1050 memcpy(pt, point, 3 * sizeof(Double_t));
1051 if (sstart > 0)
1052 for (Int_t i = 0; i < 3; i++)
1053 pt[i] += sstart * dir[i];
1054 stepmax -= sstart;
1055 Double_t step;
1056 Int_t incseg = (dir[2] > 0) ? 1 : -1;
1057 Double_t invdir = 1. / dir[2];
1059 Double_t phi = fPhi1 * TMath::DegToRad() + (iphi + 0.5) * divphi;
1060 Double_t cphi = TMath::Cos(phi);
1061 Double_t sphi = TMath::Sin(phi);
1063 Double_t bpr = 0.;
1064 Rproj(pt[2], point, dir, cphi, sphi, apr, bpr);
1065 Double_t dz;
1066 // loop segments
1067 Int_t icrtseg = ipl;
1069 Int_t iseglast = (incseg > 0) ? (fNz - 1) : -1;
1071
1072 for (ipl = isegstart; ipl != iseglast; ipl += incseg) {
1073 step = (fZ[ipl + 1 - ((1 + incseg) >> 1)] - pt[2]) * invdir;
1074 if (step > 0) {
1075 if (step > stepmax) {
1076 ipl = icrtseg;
1077 return kFALSE;
1078 }
1079 icrtseg = ipl;
1080 }
1081 din = dout = TGeoShape::Big();
1082 dz = fZ[ipl + 1] - fZ[ipl];
1083
1084 // rdot = (rproj-fRmin[ipl])*dz - (pt[2]-fZ[ipl])*(fRmin[ipl+1]-fRmin[ipl]);
1086 rdot = dir[2] * TMath::Sign(1., fRmin[ipl] - fRmin[ipl + 1]);
1087 else
1088 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
1089 if (rdot > 0) {
1090 // inner surface visible ->check crossing
1091 // printf(" inner visible\n");
1093 rnew = apr + bpr * fZ[ipl];
1094 Double_t rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
1095 if (rpg <= 0)
1096 din = (fZ[ipl] - pt[2]) * invdir;
1097 } else {
1098 Rpg(pt[2], ipl, kTRUE, apg, bpg);
1099 db = bpg - bpr;
1101 znew = (apr - apg) / db;
1102 if (znew > fZ[ipl] && znew < fZ[ipl + 1]) {
1103 din = (znew - pt[2]) * invdir;
1104 if (din < 0)
1105 din = TGeoShape::Big();
1106 }
1107 }
1108 }
1109 }
1110 // printf(" din=%f\n", din);
1111 // rdot = (rproj-fRmax[ipl])*dz - (pt[2]-fZ[ipl])*(fRmax[ipl+1]-fRmax[ipl]);
1113 rdot = dir[2] * TMath::Sign(1., fRmax[ipl] - fRmax[ipl + 1]);
1114 else
1115 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
1116 if (rdot < 0) {
1117 // printf(" outer visible\n");
1118 // outer surface visible ->check crossing
1120 rnew = apr + bpr * fZ[ipl];
1121 Double_t rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
1122 if (rpg <= 0)
1123 dout = (fZ[ipl] - pt[2]) * invdir;
1124 } else {
1125 Rpg(pt[2], ipl, kFALSE, apg, bpg);
1126 db = bpg - bpr;
1128 znew = (apr - apg) / db;
1129 if (znew > fZ[ipl] && znew < fZ[ipl + 1])
1130 dout = (znew - pt[2]) * invdir;
1131 if (dout < 0)
1132 dout = TGeoShape::Big();
1133 }
1134 }
1135 }
1136 // printf(" dout=%f\n", dout);
1137 step = TMath::Min(din, dout);
1138 if (step < 1E10) {
1139 // there is a crossing within this segment
1140 if (step > stepmax) {
1141 ipl = icrtseg;
1142 return kFALSE;
1143 }
1144 snext = sstart + step;
1145 return kTRUE;
1146 }
1147 }
1148 ipl = icrtseg;
1149 return kFALSE;
1150}
1151
1152////////////////////////////////////////////////////////////////////////////////
1153/// Compute distance from outside point to surface of the polygone
1154
1157{
1158 if (iact < 3 && safe) {
1159 *safe = Safety(point, kFALSE);
1160 if (iact == 0)
1161 return TGeoShape::Big(); // just safety computed
1162 if (iact == 1 && step < *safe)
1163 return TGeoShape::Big(); // safety mode
1164 }
1165 // Check if the bounding box is crossed within the requested distance
1166 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
1167 if (sdist >= step)
1168 return TGeoShape::Big();
1169 // Protection for points on last Z sections
1170 if (dir[2] <= 0 && TMath::Abs(point[2] - fZ[0]) < TGeoShape::Tolerance())
1171 return TGeoShape::Big();
1172 if (dir[2] >= 0 && TMath::Abs(point[2] - fZ[fNz - 1]) < TGeoShape::Tolerance())
1173 return TGeoShape::Big();
1174 // copy the current point
1175 Double_t pt[3];
1176 memcpy(pt, point, 3 * sizeof(Double_t));
1177 // find current Z section
1178 Int_t ipl;
1179 Int_t i, ipsec;
1181
1183 // check if ray may intersect outer cylinder
1184 Double_t snext = 0.;
1185 Double_t stepmax = step;
1187 Double_t r2 = pt[0] * pt[0] + pt[1] * pt[1];
1190 radmax += 1E-8;
1191 if (r2 > (radmax * radmax) || pt[2] < fZ[0] || pt[2] > fZ[fNz - 1]) {
1192 pt[2] -= 0.5 * (fZ[0] + fZ[fNz - 1]);
1193 snext = TGeoTube::DistFromOutsideS(pt, dir, 0., radmax, 0.5 * (fZ[fNz - 1] - fZ[0]));
1194 if (snext > 1E10)
1195 return TGeoShape::Big();
1196 if (snext > stepmax)
1197 return TGeoShape::Big();
1198 stepmax -= snext;
1199 pt[2] = point[2];
1200 for (i = 0; i < 3; i++)
1201 pt[i] += snext * dir[i];
1202 Bool_t checkz = (ipl < 0 && TMath::Abs(pt[2] - fZ[0]) < 1E-8) ? kTRUE : kFALSE;
1203 if (!checkz)
1204 checkz = (ipl == fNz - 1 && TMath::Abs(pt[2] - fZ[fNz - 1]) < 1E-8) ? kTRUE : kFALSE;
1205 if (checkz) {
1207 if (ipl < 0) {
1208 rmin = fRmin[0];
1209 rmax = fRmax[0];
1210 } else {
1211 rmin = fRmin[fNz - 1];
1212 rmax = fRmax[fNz - 1];
1213 }
1214 Double_t phi = TMath::ATan2(pt[1], pt[0]) * TMath::RadToDeg();
1215 while (phi < fPhi1)
1216 phi += 360.0;
1217 Double_t ddp = phi - fPhi1;
1218 if (ddp <= fDphi) {
1219 ipsec = Int_t(ddp / divphi);
1220 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
1221 rpr = pt[0] * TMath::Cos(ph0) + pt[1] * TMath::Sin(ph0);
1222 if (rpr >= rmin && rpr <= rmax)
1223 return snext;
1224 }
1225 }
1226 }
1228 Double_t *sph = td.fDblBuffer;
1229 Int_t *iph = td.fIntBuffer;
1231 // locate current phi sector [0,fNedges-1]; -1 for dead region
1232 // if ray is perpendicular to Z, solve this particular case
1233 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1234 LocatePhi(pt, ipsec);
1237 return (snext + snewcross);
1238 return TGeoShape::Big();
1239 }
1240 // Locate phi and get the phi crossing list
1242 Bool_t inphi = kTRUE;
1244 while (ph < fPhi1)
1245 ph += 360.;
1246 ipsec = Int_t(fNedges * (ph - fPhi1) / fDphi); // [0, fNedges-1]
1247 if (ipsec > fNedges - 1)
1248 ipsec = -1; // in gap
1249 Double_t phim = fPhi1 + 0.5 * fDphi;
1251 if (fDphi < 360.0) {
1252 inphi = (ddp < 0.5 * fDphi + TGeoShape::Tolerance()) ? kTRUE : kFALSE;
1253 }
1255 if (ipl < 0)
1256 ipl = 0;
1257 if (ipl == fNz - 1)
1258 ipl--;
1259 Bool_t inz = kTRUE;
1260 if (pt[2] > fZ[fNz - 1] + TGeoShape::Tolerance())
1261 inz = kFALSE;
1262 if (pt[2] < fZ[0] - TGeoShape::Tolerance())
1263 inz = kFALSE;
1265 if (inphi && inz) {
1266 Bool_t done = kFALSE;
1267 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1268 Double_t phi = fPhi1 * TMath::DegToRad() + (ipsec + 0.5) * divphi;
1269 Double_t cphi = TMath::Cos(phi);
1270 Double_t sphi = TMath::Sin(phi);
1271 Double_t rproj = pt[0] * cphi + pt[1] * sphi;
1273 if (rproj < fRmin[ipl] && rproj > fRmin[ipl + 1] && dir[2] > 0)
1274 return 0.0;
1275 if (rproj > fRmin[ipl] && rproj < fRmin[ipl + 1] && dir[2] < 0)
1276 return 0.0;
1277 if (rproj > fRmax[ipl] && rproj < fRmax[ipl + 1] && dir[2] > 0)
1278 return 0.0;
1279 if (rproj < fRmax[ipl] && rproj > fRmax[ipl + 1] && dir[2] < 0)
1280 return 0.0;
1281 done = kTRUE;
1282 }
1283 if (!done) {
1286 if (rproj < rpgout + 1.E-8) {
1288 Double_t rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
1289 if (rproj > rpgin - 1.E-8) {
1292 Double_t safz = TMath::Min(pt[2] - fZ[ipl], fZ[ipl + 1] - pt[2]);
1294 if (fDphi < 360) {
1295 safphi = rproj * TMath::Sin((ddp - 0.5 * fDphi) * TMath::DegToRad());
1297 }
1298 // printf("inside pgon: safrmin=%f, safrmax=%f, safphi=%f,
1299 // safz=%f\n",safrmin,safrmax,safphi,safz);
1300 Double_t dzinv = 1. / dz;
1301 if (safrmin < safz && safrmin < safrmax && safrmin < safphi) {
1302 // on inner boundary
1303 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) * dzinv;
1304 // printf(" - inner ndotd=%f (>0 ->0)\n",ndotd);
1305 if (ndotd > 0)
1306 return snext;
1307 done = kTRUE;
1308 }
1309 if (!done && safrmax < safz && safrmax < safphi) {
1310 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) * dzinv;
1311 // printf(" - outer ndotd=%f (<0 ->0)\n",ndotd);
1312 if (ndotd < 0)
1313 return snext;
1314 done = kTRUE;
1315 }
1316 if (!done && safz < safphi) {
1317 done = kTRUE;
1318 Int_t iplc = ipl;
1319 if (TMath::Abs(pt[2] - fZ[ipl]) > TMath::Abs(fZ[ipl + 1] - pt[2]))
1320 iplc++;
1321 if (iplc == 0 || iplc == fNz - 1) {
1322 if (pt[2] * dir[2] < 0)
1323 return snext;
1324 return TGeoShape::Big();
1325 } else {
1327 if (dir[2] > 0) {
1328 if (rproj < fRmin[iplc] && rproj > fRmin[iplc + 1])
1329 return snext;
1330 if (rproj > fRmax[iplc] && rproj < fRmax[iplc + 1])
1331 return snext;
1332 } else {
1333 if (rproj > fRmin[iplc] && rproj < fRmin[iplc + 1])
1334 return snext;
1335 if (rproj < fRmax[iplc] && rproj > fRmax[iplc + 1])
1336 return snext;
1337 }
1338 } else if (TGeoShape::IsSameWithinTolerance(fZ[iplc], fZ[iplc - 1])) {
1339 if (dir[2] > 0) {
1340 if (rproj < fRmin[iplc - 1] && rproj > fRmin[iplc])
1341 return snext;
1342 if (rproj > fRmax[iplc - 1] && rproj < fRmax[iplc])
1343 return snext;
1344 } else {
1345 if (rproj > fRmin[iplc - 1] && rproj < fRmin[iplc])
1346 return snext;
1347 if (rproj < fRmax[iplc - 1] && rproj > fRmax[iplc])
1348 return snext;
1349 }
1350 }
1351 }
1352 }
1353 if (!done) {
1354 // point on phi boundary
1355 onphi = kTRUE;
1356 }
1357 }
1358 }
1359 }
1360 }
1362 if (onphi) {
1363 if (!icrossed)
1364 return snext;
1365 if (iph[0] < 0 && sph[0] < TGeoShape::Tolerance())
1366 return (snext + sph[0]);
1367 if (iph[0] >= 0 && sph[0] > 1.E-8)
1368 return snext;
1369 }
1370 // Fire-up slice crossing algorithm
1371 if (SliceCrossing(pt, dir, icrossed, iph, sph, snewcross, stepmax)) {
1372 snext += snewcross;
1373 return snext;
1374 }
1375 return TGeoShape::Big();
1376}
1377
1378////////////////////////////////////////////////////////////////////////////////
1379/// compute closest distance from point px,py to each corner
1380
1382{
1383 Int_t n = fNedges + 1;
1384 const Int_t numPoints = 2 * n * fNz;
1385 return ShapeDistancetoPrimitive(numPoints, px, py);
1386}
1387
1388////////////////////////////////////////////////////////////////////////////////
1389/// Divide this polygone shape belonging to volume "voldiv" into ndiv volumes
1390/// called divname, from start position with the given step. Returns pointer
1391/// to created division cell volume in case of Z divisions. Phi divisions are
1392/// allowed only if nedges%ndiv=0 and create polygone "segments" with nedges/ndiv edges.
1393/// Z divisions can be performed if the divided range is in between two consecutive Z planes.
1394/// In case a wrong division axis is supplied, returns pointer to volume that was divided.
1395
1396TGeoVolume *
1398{
1399 // printf("Dividing %s : nz=%d nedges=%d phi1=%g dphi=%g (ndiv=%d iaxis=%d start=%g step=%g)\n",
1400 // voldiv->GetName(), fNz, fNedges, fPhi1, fDphi, ndiv, iaxis, start, step);
1401 TGeoShape *shape; //--- shape to be created
1402 TGeoVolume *vol; //--- division volume to be created
1403 TGeoVolumeMulti *vmulti; //--- generic divided volume
1404 TGeoPatternFinder *finder; //--- finder to be attached
1405 TString opt = ""; //--- option to be attached
1407 Double_t zmin = start;
1408 Double_t zmax = start + ndiv * step;
1409 Int_t isect = -1;
1410 Int_t is, id, ipl;
1411 switch (iaxis) {
1412 case 1: //--- R division
1413 Error("Divide", "makes no sense dividing a pgon on radius");
1414 return nullptr;
1415 case 2: //--- Phi division
1416 if (fNedges % ndiv) {
1417 Error("Divide", "ndiv should divide number of pgon edges");
1418 return nullptr;
1419 }
1420 nedges = fNedges / ndiv;
1421 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, start + ndiv * step);
1423 voldiv->SetFinder(finder);
1424 finder->SetDivIndex(voldiv->GetNdaughters());
1425 shape = new TGeoPgon(-step / 2, step, nedges, fNz);
1426 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1427 vmulti->AddVolume(vol);
1428 for (is = 0; is < fNz; is++)
1429 ((TGeoPgon *)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
1430 opt = "Phi";
1431 for (id = 0; id < ndiv; id++) {
1432 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
1433 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1434 }
1435 return vmulti;
1436 case 3: // --- Z division
1437 // find start plane
1438 for (ipl = 0; ipl < fNz - 1; ipl++) {
1439 if (start < fZ[ipl])
1440 continue;
1441 else {
1442 if ((start + ndiv * step) > fZ[ipl + 1])
1443 continue;
1444 }
1445 isect = ipl;
1446 zmin = fZ[isect];
1447 zmax = fZ[isect + 1];
1448 break;
1449 }
1450 if (isect < 0) {
1451 Error("Divide", "cannot divide pcon on Z if divided region is not between 2 consecutive planes");
1452 return nullptr;
1453 }
1454 finder = new TGeoPatternZ(voldiv, ndiv, start, start + ndiv * step);
1456 voldiv->SetFinder(finder);
1457 finder->SetDivIndex(voldiv->GetNdaughters());
1458 opt = "Z";
1459 for (id = 0; id < ndiv; id++) {
1460 Double_t z1 = start + id * step;
1461 Double_t z2 = start + (id + 1) * step;
1462 Double_t rmin1 = (fRmin[isect] * (zmax - z1) - fRmin[isect + 1] * (zmin - z1)) / (zmax - zmin);
1463 Double_t rmax1 = (fRmax[isect] * (zmax - z1) - fRmax[isect + 1] * (zmin - z1)) / (zmax - zmin);
1464 Double_t rmin2 = (fRmin[isect] * (zmax - z2) - fRmin[isect + 1] * (zmin - z2)) / (zmax - zmin);
1465 Double_t rmax2 = (fRmax[isect] * (zmax - z2) - fRmax[isect + 1] * (zmin - z2)) / (zmax - zmin);
1466 shape = new TGeoPgon(fPhi1, fDphi, nedges, 2);
1467 ((TGeoPgon *)shape)->DefineSection(0, -step / 2, rmin1, rmax1);
1468 ((TGeoPgon *)shape)->DefineSection(1, step / 2, rmin2, rmax2);
1469 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1470 vmulti->AddVolume(vol);
1471 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
1472 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1473 }
1474 return vmulti;
1475 default: Error("Divide", "Wrong axis type for division"); return nullptr;
1476 }
1477}
1478
1479////////////////////////////////////////////////////////////////////////////////
1480/// Fill vector param[4] with the bounding cylinder parameters. The order
1481/// is the following : Rmin, Rmax, Phi1, Phi2
1482
1484{
1485 param[0] = fRmin[0]; // Rmin
1486 param[1] = fRmax[0]; // Rmax
1487 for (Int_t i = 1; i < fNz; i++) {
1488 if (fRmin[i] < param[0])
1489 param[0] = fRmin[i];
1490 if (fRmax[i] > param[1])
1491 param[1] = fRmax[i];
1492 }
1494 param[1] /= TMath::Cos(0.5 * divphi * TMath::DegToRad());
1495 param[0] *= param[0];
1496 param[1] *= param[1];
1498 param[2] = 0.;
1499 param[3] = 360.;
1500 return;
1501 }
1502 param[2] = (fPhi1 < 0) ? (fPhi1 + 360.) : fPhi1; // Phi1
1503 param[3] = param[2] + fDphi; // Phi2
1504}
1505
1506////////////////////////////////////////////////////////////////////////////////
1507/// Inspect the PGON parameters.
1508
1510{
1511 printf("*** Shape %s: TGeoPgon ***\n", GetName());
1512 printf(" Nedges = %i\n", fNedges);
1514}
1515
1516////////////////////////////////////////////////////////////////////////////////
1517/// Creates a TBuffer3D describing *this* shape.
1518/// Coordinates are in local reference frame.
1519
1521{
1524
1525 if (nbPnts <= 0)
1526 return nullptr;
1527
1528 TBuffer3D *buff =
1530 if (buff) {
1531 SetPoints(buff->fPnts);
1533 }
1534
1535 return buff;
1536}
1537
1538////////////////////////////////////////////////////////////////////////////////
1539/// Fill TBuffer3D structure for segments and polygons.
1540
1542{
1543 if (!HasInsideSurface()) {
1545 return;
1546 }
1547
1548 Int_t i, j;
1549 const Int_t n = GetNedges() + 1;
1550 Int_t nz = GetNz();
1551 if (nz < 2)
1552 return;
1553 Int_t nbPnts = nz * 2 * n;
1554 if (nbPnts <= 0)
1555 return;
1556 Double_t dphi = GetDphi();
1558
1559 Int_t c = GetBasicColor();
1560
1561 Int_t indx = 0, indx2, k;
1562
1563 // inside & outside circles, number of segments: 2*nz*(n-1)
1564 // special case number of segments: 2*nz*n
1565 for (i = 0; i < nz * 2; i++) {
1566 indx2 = i * n;
1567 for (j = 1; j < n; j++) {
1568 buff.fSegs[indx++] = c;
1569 buff.fSegs[indx++] = indx2 + j - 1;
1570 buff.fSegs[indx++] = indx2 + j;
1571 }
1572 if (specialCase) {
1573 buff.fSegs[indx++] = c;
1574 buff.fSegs[indx++] = indx2 + j - 1;
1575 buff.fSegs[indx++] = indx2;
1576 }
1577 }
1578
1579 // bottom & top lines, number of segments: 2*n
1580 for (i = 0; i < 2; i++) {
1581 indx2 = i * (nz - 1) * 2 * n;
1582 for (j = 0; j < n; j++) {
1583 buff.fSegs[indx++] = c;
1584 buff.fSegs[indx++] = indx2 + j;
1585 buff.fSegs[indx++] = indx2 + n + j;
1586 }
1587 }
1588
1589 // inside & outside cylinders, number of segments: 2*(nz-1)*n
1590 for (i = 0; i < (nz - 1); i++) {
1591 // inside cylinder
1592 indx2 = i * n * 2;
1593 for (j = 0; j < n; j++) {
1594 buff.fSegs[indx++] = c + 2;
1595 buff.fSegs[indx++] = indx2 + j;
1596 buff.fSegs[indx++] = indx2 + n * 2 + j;
1597 }
1598 // outside cylinder
1599 indx2 = i * n * 2 + n;
1600 for (j = 0; j < n; j++) {
1601 buff.fSegs[indx++] = c + 3;
1602 buff.fSegs[indx++] = indx2 + j;
1603 buff.fSegs[indx++] = indx2 + n * 2 + j;
1604 }
1605 }
1606
1607 // left & right sections, number of segments: 2*(nz-2)
1608 // special case number of segments: 0
1609 if (!specialCase) {
1610 for (i = 1; i < (nz - 1); i++) {
1611 for (j = 0; j < 2; j++) {
1612 buff.fSegs[indx++] = c;
1613 buff.fSegs[indx++] = 2 * i * n + j * (n - 1);
1614 buff.fSegs[indx++] = (2 * i + 1) * n + j * (n - 1);
1615 }
1616 }
1617 }
1618
1619 Int_t m = n - 1 + (specialCase ? 1 : 0);
1620 indx = 0;
1621
1622 // bottom & top, number of polygons: 2*(n-1)
1623 // special case number of polygons: 2*n
1624 i = 0;
1625 for (j = 0; j < n - 1; j++) {
1626 buff.fPols[indx++] = c + 3;
1627 buff.fPols[indx++] = 4;
1628 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1629 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1630 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1631 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1632 }
1633 if (specialCase) {
1634 buff.fPols[indx++] = c + 3;
1635 buff.fPols[indx++] = 4;
1636 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1637 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1638 buff.fPols[indx++] = 2 * nz * m + i * n;
1639 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1640 }
1641 i = 1;
1642 for (j = 0; j < n - 1; j++) {
1643 buff.fPols[indx++] = c + 3;
1644 buff.fPols[indx++] = 4;
1645 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1646 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1647 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1648 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1649 }
1650 if (specialCase) {
1651 buff.fPols[indx++] = c + 3;
1652 buff.fPols[indx++] = 4;
1653 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1654 buff.fPols[indx++] = 2 * nz * m + i * n;
1655 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1656 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1657 }
1658
1659 // inside & outside, number of polygons: (nz-1)*2*(n-1)
1660 for (k = 0; k < (nz - 1); k++) {
1661 i = 0;
1662 for (j = 0; j < n - 1; j++) {
1663 buff.fPols[indx++] = c + i;
1664 buff.fPols[indx++] = 4;
1665 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1666 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1667 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1668 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1669 }
1670 if (specialCase) {
1671 buff.fPols[indx++] = c + i;
1672 buff.fPols[indx++] = 4;
1673 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1674 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1675 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1676 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1677 }
1678 i = 1;
1679 for (j = 0; j < n - 1; j++) {
1680 buff.fPols[indx++] = c + i;
1681 buff.fPols[indx++] = 4;
1682 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1683 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1684 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1685 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1686 }
1687 if (specialCase) {
1688 buff.fPols[indx++] = c + i;
1689 buff.fPols[indx++] = 4;
1690 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1691 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1692 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1693 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1694 }
1695 }
1696
1697 // left & right sections, number of polygons: 2*(nz-1)
1698 // special case number of polygons: 0
1699 if (!specialCase) {
1700 indx2 = nz * 2 * (n - 1);
1701 for (k = 0; k < (nz - 1); k++) {
1702 buff.fPols[indx++] = c + 2;
1703 buff.fPols[indx++] = 4;
1704 buff.fPols[indx++] = k == 0 ? indx2 : indx2 + 2 * nz * n + 2 * (k - 1);
1705 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n;
1706 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k;
1707 buff.fPols[indx++] = indx2 + (2 * k + 3) * n;
1708
1709 buff.fPols[indx++] = c + 2;
1710 buff.fPols[indx++] = 4;
1711 buff.fPols[indx++] = k == 0 ? indx2 + n - 1 : indx2 + 2 * nz * n + 2 * (k - 1) + 1; // a
1712 buff.fPols[indx++] = indx2 + (2 * k + 3) * n + n - 1; // d
1713 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k + 1; // c
1714 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n + n - 1; // b
1715 }
1716 buff.fPols[indx - 8] = indx2 + n;
1717 buff.fPols[indx - 2] = indx2 + 2 * n - 1;
1718 }
1719}
1720
1721////////////////////////////////////////////////////////////////////////////////
1722/// Fill TBuffer3D structure for segments and polygons, when no inner surface exists
1723
1725{
1726 const Int_t n = GetNedges() + 1;
1727 const Int_t nz = GetNz();
1728 const Int_t nbPnts = nz * n + 2;
1729
1730 if ((nz < 2) || (nbPnts <= 0) || (n < 2))
1731 return;
1732
1733 Int_t c = GetBasicColor();
1734
1735 Int_t indx = 0, indx1 = 0, indx2 = 0, i, j;
1736
1737 // outside circles, number of segments: nz*n
1738 for (i = 0; i < nz; i++) {
1739 indx2 = i * n;
1740 for (j = 1; j < n; j++) {
1741 buff.fSegs[indx++] = c;
1742 buff.fSegs[indx++] = indx2 + j - 1;
1743 buff.fSegs[indx++] = indx2 + j % (n - 1);
1744 }
1745 }
1746
1747 indx2 = 0;
1748 // bottom lines
1749 for (j = 0; j < n; j++) {
1750 buff.fSegs[indx++] = c;
1751 buff.fSegs[indx++] = indx2 + j % (n - 1);
1752 buff.fSegs[indx++] = nbPnts - 2;
1753 }
1754
1755 indx2 = (nz - 1) * n;
1756 // top lines
1757 for (j = 0; j < n; j++) {
1758 buff.fSegs[indx++] = c;
1759 buff.fSegs[indx++] = indx2 + j % (n - 1);
1760 buff.fSegs[indx++] = nbPnts - 1;
1761 }
1762
1763 // outside cylinders, number of segments: (nz-1)*n
1764 for (i = 0; i < (nz - 1); i++) {
1765 // outside cylinder
1766 indx2 = i * n;
1767 for (j = 0; j < n; j++) {
1768 buff.fSegs[indx++] = c;
1769 buff.fSegs[indx++] = indx2 + j % (n - 1);
1770 buff.fSegs[indx++] = indx2 + n + j % (n - 1);
1771 }
1772 }
1773
1774 indx = 0;
1775
1776 // bottom cap
1777 indx1 = 0; // start of first z layer
1778 indx2 = nz * (n - 1);
1779 for (j = 0; j < n - 1; j++) {
1780 buff.fPols[indx++] = c;
1781 buff.fPols[indx++] = 3;
1782 buff.fPols[indx++] = indx1 + j;
1783 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1784 buff.fPols[indx++] = indx2 + j;
1785 }
1786
1787 // top cap
1788 indx1 = (nz - 1) * (n - 1); // start last z layer
1789 indx2 = nz * (n - 1) + n;
1790 for (j = 0; j < n - 1; j++) {
1791 buff.fPols[indx++] = c;
1792 buff.fPols[indx++] = 3;
1793 buff.fPols[indx++] = indx1 + j; // last z layer
1794 buff.fPols[indx++] = indx2 + j;
1795 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1796 }
1797
1798 // outside, number of polygons: (nz-1)*(n-1)
1799 for (Int_t k = 0; k < (nz - 1); k++) {
1800 indx1 = k * (n - 1);
1801 indx2 = nz * (n - 1) + n * 2 + k * n;
1802 for (j = 0; j < n - 1; j++) {
1803 buff.fPols[indx++] = c;
1804 buff.fPols[indx++] = 4;
1805 buff.fPols[indx++] = indx1 + j;
1806 buff.fPols[indx++] = indx2 + j;
1807 buff.fPols[indx++] = indx1 + j + (n - 1);
1808 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1809 }
1810 }
1811}
1812
1813////////////////////////////////////////////////////////////////////////////////
1814/// Computes projected pgon radius (inner or outer) corresponding to a given Z
1815/// value. Fills corresponding coefficients of:
1816/// `Rpg(z) = a + b*z`
1817///
1818/// Note: ipl must be in range [0,fNz-2]
1819
1821{
1822 Double_t rpg;
1823 if (ipl < 0 || ipl > fNz - 2) {
1824 Fatal("Rpg", "Plane index parameter ipl=%i out of range\n", ipl);
1825 return 0;
1826 }
1827 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1828 if (dz < TGeoShape::Tolerance()) {
1829 // radius-changing region
1830 rpg = (inner) ? TMath::Min(fRmin[ipl], fRmin[ipl + 1]) : TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
1831 a = rpg;
1832 b = 0.;
1833 return rpg;
1834 }
1835 Double_t r1 = 0, r2 = 0;
1836 if (inner) {
1837 r1 = fRmin[ipl];
1838 r2 = fRmin[ipl + 1];
1839 } else {
1840 r1 = fRmax[ipl];
1841 r2 = fRmax[ipl + 1];
1842 }
1843 Double_t dzinv = 1. / dz;
1844 a = (r1 * fZ[ipl + 1] - r2 * fZ[ipl]) * dzinv;
1845 b = (r2 - r1) * dzinv;
1846 return (a + b * z);
1847}
1848
1849////////////////////////////////////////////////////////////////////////////////
1850/// Computes projected distance at a given Z for a given ray inside a given sector
1851/// and fills coefficients:
1852/// `Rproj = a + b*z`
1853
1855 Double_t &a, Double_t &b) const
1856{
1857 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1858 a = b = TGeoShape::Big();
1859 return TGeoShape::Big();
1860 }
1861 Double_t invdirz = 1. / dir[2];
1862 a = ((point[0] * dir[2] - point[2] * dir[0]) * cphi + (point[1] * dir[2] - point[2] * dir[1]) * sphi) * invdirz;
1863 b = (dir[0] * cphi + dir[1] * sphi) * invdirz;
1864 return (a + b * z);
1865}
1866
1867////////////////////////////////////////////////////////////////////////////////
1868/// Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
1869
1871 Double_t safmin) const
1872{
1873 Double_t saf[3];
1874 Double_t safe;
1875 Int_t i;
1876 Double_t r, rpgon, ta, calf;
1877 if (ipl < 0 || ipl > fNz - 2)
1878 return (safmin + 1.); // error in input plane
1879 // Get info about segment.
1880 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1881 if (dz < 1E-9)
1882 return 1E9; // skip radius-changing segment
1883 Double_t znew = point[2] - 0.5 * (fZ[ipl] + fZ[ipl + 1]);
1884 saf[0] = 0.5 * dz - TMath::Abs(znew);
1885 if (-saf[0] > safmin)
1886 return TGeoShape::Big(); // means: stop checking further segments
1889 Double_t rmin2 = fRmin[ipl + 1];
1890 Double_t rmax2 = fRmax[ipl + 1];
1892 if (iphi < 0) {
1893 Double_t f = 1. / TMath::Cos(0.5 * divphi * TMath::DegToRad());
1894 rmax1 *= f;
1895 rmax2 *= f;
1896 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1897 Double_t ro1 = 0.5 * (rmin1 + rmin2);
1898 Double_t tg1 = (rmin2 - rmin1) / dz;
1899 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
1900 Double_t ro2 = 0.5 * (rmax1 + rmax2);
1901 Double_t tg2 = (rmax2 - rmax1) / dz;
1902 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
1903 Double_t rin = tg1 * znew + ro1;
1904 Double_t rout = tg2 * znew + ro2;
1905 saf[1] = (ro1 > 0) ? ((r - rin) * cr1) : TGeoShape::Big();
1906 saf[2] = (rout - r) * cr2;
1907 for (i = 0; i < 3; i++)
1908 saf[i] = -saf[i];
1909 safe = saf[TMath::LocMax(3, saf)];
1911 if (safe < 0)
1912 safe = 0;
1913 return safe;
1914 }
1915 Double_t ph0 = (fPhi1 + divphi * (iphi + 0.5)) * TMath::DegToRad();
1916 r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
1917 if (rmin1 + rmin2 > 1E-10) {
1918 ta = (rmin2 - rmin1) / dz;
1919 calf = 1. / TMath::Sqrt(1 + ta * ta);
1920 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
1921 saf[1] = (r - rpgon) * calf;
1922 } else {
1923 saf[1] = TGeoShape::Big();
1924 }
1925 ta = (rmax2 - rmax1) / dz;
1926 calf = 1. / TMath::Sqrt(1 + ta * ta);
1927 rpgon = rmax1 + (point[2] - fZ[ipl]) * ta;
1928 saf[2] = (rpgon - r) * calf;
1929 if (in) {
1930 safe = saf[TMath::LocMin(3, saf)];
1932 } else {
1933 for (i = 0; i < 3; i++)
1934 saf[i] = -saf[i];
1935 safe = saf[TMath::LocMax(3, saf)];
1937 }
1938 if (safe < 0)
1939 safe = 0;
1940 return safe;
1941}
1942
1943////////////////////////////////////////////////////////////////////////////////
1944/// computes the closest distance from given point to this shape, according
1945/// to option. The matching point on the shape is stored in spoint.
1946
1948{
1950 Double_t dz;
1951 Int_t ipl, iplane, iphi;
1952 LocatePhi(point, iphi);
1953 safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi1 + fDphi);
1954 if (in) {
1955 //---> point is inside pgon
1956 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1957 if (ipl == (fNz - 1))
1958 return 0; // point on last Z boundary
1959 if (ipl < 0)
1960 return 0; // point on first Z boundary
1961 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1962 if (dz < 1E-8)
1963 return 0;
1964 // Check safety for current segment
1965 safmin = SafetyToSegment(point, ipl, iphi, in, safphi);
1966 if (safmin > 1E10) {
1967 // something went wrong - point is not inside current segment
1968 return TGeoShape::Big();
1969 }
1970 if (safmin < 1E-6)
1971 return TMath::Abs(safmin); // point on radius-changing plane
1972 // check increasing iplanes
1973 iplane = ipl + 1;
1974 saftmp = 0.;
1975 while ((iplane < fNz - 1) && saftmp < 1E10) {
1977 if (saftmp < safmin)
1978 safmin = saftmp;
1979 iplane++;
1980 }
1981 // now decreasing nplanes
1982 iplane = ipl - 1;
1983 saftmp = 0.;
1984 while ((iplane >= 0) && saftmp < 1E10) {
1986 if (saftmp < safmin)
1987 safmin = saftmp;
1988 iplane--;
1989 }
1990 return safmin;
1991 }
1992 //---> point is outside pgon
1993 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1994 if (ipl < 0)
1995 ipl = 0;
1996 else if (ipl == fNz - 1)
1997 ipl = fNz - 2;
1998 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1999 if (dz < 1E-8) {
2000 ipl++;
2001 if (ipl > fNz - 2)
2002 return 0.; // invalid last section
2003 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
2004 }
2005 // Check safety for current segment
2007 if (safmin < 1E-6)
2008 return TMath::Abs(safmin); // point on radius-changing plane
2009 // check increasing iplanes
2010 iplane = ipl + 1;
2011 saftmp = 0.;
2012 while ((iplane < fNz - 1) && saftmp < 1E10) {
2014 if (saftmp < safmin)
2015 safmin = saftmp;
2016 iplane++;
2017 }
2018 // now decreasing nplanes
2019 iplane = ipl - 1;
2020 saftmp = 0.;
2021 while ((iplane >= 0) && saftmp < 1E10) {
2023 if (saftmp < safmin)
2024 safmin = saftmp;
2025 iplane--;
2026 }
2027 return safmin;
2028}
2029
2030////////////////////////////////////////////////////////////////////////////////
2031/// Save a primitive as a C++ statement(s) on output stream "out".
2032
2033void TGeoPgon::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2034{
2036 return;
2037 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2038 out << " phi1 = " << fPhi1 << ";" << std::endl;
2039 out << " dphi = " << fDphi << ";" << std::endl;
2040 out << " nedges = " << fNedges << ";" << std::endl;
2041 out << " nz = " << fNz << ";" << std::endl;
2042 out << " auto " << GetPointerName() << " = new TGeoPgon(\"" << GetName() << "\", phi1, dphi, nedges, nz);"
2043 << std::endl;
2044 for (Int_t i = 0; i < fNz; i++) {
2045 out << " z = " << fZ[i] << ";" << std::endl;
2046 out << " rmin = " << fRmin[i] << ";" << std::endl;
2047 out << " rmax = " << fRmax[i] << ";" << std::endl;
2048 out << " " << GetPointerName() << "->DefineSection(" << i << ", z, rmin, rmax);" << std::endl;
2049 }
2051}
2052
2053////////////////////////////////////////////////////////////////////////////////
2054/// Set PGON dimensions starting from an array.
2055
2057{
2058 fPhi1 = param[0];
2059 fDphi = param[1];
2060 fNedges = (Int_t)param[2];
2061 fNz = (Int_t)param[3];
2062 if (fNz < 2) {
2063 Error("SetDimensions", "Pgon %s: Number of Z sections must be > 2", GetName());
2064 return;
2065 }
2066 if (fRmin)
2067 delete[] fRmin;
2068 if (fRmax)
2069 delete[] fRmax;
2070 if (fZ)
2071 delete[] fZ;
2072 fRmin = new Double_t[fNz];
2073 fRmax = new Double_t[fNz];
2074 fZ = new Double_t[fNz];
2075 memset(fRmin, 0, fNz * sizeof(Double_t));
2076 memset(fRmax, 0, fNz * sizeof(Double_t));
2077 memset(fZ, 0, fNz * sizeof(Double_t));
2078 for (Int_t i = 0; i < fNz; i++)
2079 DefineSection(i, param[4 + 3 * i], param[5 + 3 * i], param[6 + 3 * i]);
2080}
2081
2082////////////////////////////////////////////////////////////////////////////////
2083/// create polygone mesh points
2084
2086{
2087 Double_t phi, dphi;
2088 Int_t n = fNedges + 1;
2089 dphi = fDphi / (n - 1);
2090 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
2091 Int_t i, j;
2092 Int_t indx = 0;
2093
2095
2096 if (points) {
2097 for (i = 0; i < GetNz(); i++) {
2098 if (hasInside)
2099 for (j = 0; j < n; j++) {
2100 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2101 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
2102 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
2103 points[indx++] = fZ[i];
2104 }
2105 for (j = 0; j < n; j++) {
2106 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2107 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
2108 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
2109 points[indx++] = fZ[i];
2110 }
2111 }
2112
2113 if (!hasInside) {
2114 points[indx++] = 0;
2115 points[indx++] = 0;
2116 points[indx++] = fZ[0];
2117
2118 points[indx++] = 0;
2119 points[indx++] = 0;
2120 points[indx++] = fZ[GetNz() - 1];
2121 }
2122 }
2123}
2124
2125////////////////////////////////////////////////////////////////////////////////
2126/// create polygone mesh points
2127
2129{
2130 Double_t phi, dphi;
2131 Int_t n = fNedges + 1;
2132 dphi = fDphi / (n - 1);
2133 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
2134 Int_t i, j;
2135 Int_t indx = 0;
2136
2138
2139 if (points) {
2140 for (i = 0; i < fNz; i++) {
2141 if (hasInside)
2142 for (j = 0; j < n; j++) {
2143 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2144 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
2145 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
2146 points[indx++] = fZ[i];
2147 }
2148 for (j = 0; j < n; j++) {
2149 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2150 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
2151 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
2152 points[indx++] = fZ[i];
2153 }
2154 }
2155
2156 if (!hasInside) {
2157 points[indx++] = 0;
2158 points[indx++] = 0;
2159 points[indx++] = fZ[0];
2160
2161 points[indx++] = 0;
2162 points[indx++] = 0;
2163 points[indx++] = fZ[GetNz() - 1];
2164 }
2165 }
2166}
2167
2168////////////////////////////////////////////////////////////////////////////////
2169/// Returns numbers of vertices, segments and polygons composing the shape mesh.
2170
2172{
2173 nvert = nsegs = npols = 0;
2174
2175 Int_t n = GetNedges() + 1;
2176 Int_t nz = GetNz();
2177
2178 if (nz < 2)
2179 return;
2180
2181 if (HasInsideSurface()) {
2183 nvert = nz * 2 * n;
2184 nsegs = 4 * (nz * n - 1 + (specialCase ? 1 : 0));
2185 npols = 2 * (nz * n - 1 + (specialCase ? 1 : 0));
2186 } else {
2187 nvert = nz * n + 2;
2188 nsegs = nz * (n - 1) + n * 2 + (nz - 1) * n;
2189 npols = 2 * (n - 1) + (nz - 1) * (n - 1);
2190 }
2191}
2192
2193////////////////////////////////////////////////////////////////////////////////
2194/// Return number of vertices of the mesh representation
2195
2197{
2199
2201
2202 return nvert;
2203}
2204
2205////////////////////////////////////////////////////////////////////////////////
2206/// fill size of this 3-D object
2207
2208void TGeoPgon::Sizeof3D() const {}
2209
2210////////////////////////////////////////////////////////////////////////////////
2211/// Fills a static 3D buffer and returns a reference.
2212
2214{
2215 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
2216
2218
2222 if (nbPnts > 0) {
2223 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
2225 }
2226 }
2227 }
2228 // TODO: Push down to TGeoShape?? Would have to do raw sizes set first..
2229 // can rest of TGeoShape be deferred until after this?
2231 SetPoints(buffer.fPnts);
2232 if (!buffer.fLocalFrame) {
2233 TransformPoints(buffer.fPnts, buffer.NbPnts());
2234 }
2235
2236 SetSegsAndPols(buffer);
2238 }
2239
2240 return buffer;
2241}
2242
2243////////////////////////////////////////////////////////////////////////////////
2244/// Check the inside status for each of the points in the array.
2245/// Input: Array of point coordinates + vector size
2246/// Output: Array of Booleans for the inside of each point
2247
2249{
2250 for (Int_t i = 0; i < vecsize; i++)
2251 inside[i] = Contains(&points[3 * i]);
2252}
2253
2254////////////////////////////////////////////////////////////////////////////////
2255/// Compute the normal for an array o points so that norm.dot.dir is positive
2256/// Input: Arrays of point coordinates and directions + vector size
2257/// Output: Array of normal directions
2258
2260{
2261 for (Int_t i = 0; i < vecsize; i++)
2262 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
2263}
2264
2265////////////////////////////////////////////////////////////////////////////////
2266/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2267
2269 Double_t *step) const
2270{
2271 for (Int_t i = 0; i < vecsize; i++)
2272 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2273}
2274
2275////////////////////////////////////////////////////////////////////////////////
2276/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2277
2279 Double_t *step) const
2280{
2281 for (Int_t i = 0; i < vecsize; i++)
2282 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2283}
2284
2285////////////////////////////////////////////////////////////////////////////////
2286/// Compute safe distance from each of the points in the input array.
2287/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
2288/// Output: Safety values
2289
2291{
2292 for (Int_t i = 0; i < vecsize; i++)
2293 safe[i] = Safety(&points[3 * i], inside[i]);
2294}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define s1(x)
Definition RSha256.hxx:91
std::size_t capacity
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:267
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
char name[80]
Definition TGX11.cxx:142
R__EXTERN TGeoManager * gGeoManager
float xmin
float ymin
float xmax
float ymax
Generic 3D primitive description class.
Definition TBuffer3D.h:18
UInt_t NbPnts() const
Definition TBuffer3D.h:89
Bool_t SectionsValid(UInt_t mask) const
Definition TBuffer3D.h:76
void SetSectionsValid(UInt_t mask)
Definition TBuffer3D.h:74
Bool_t fLocalFrame
Definition TBuffer3D.h:99
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:122
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
Double_t fDY
Definition TGeoBBox.h:22
Double_t fDZ
Definition TGeoBBox.h:23
TGeoVolumeMulti * MakeVolumeMulti(const char *name, TGeoMedium *medium)
Make a TGeoVolumeMulti handling a list of volumes.
TObjArray * GetListOfShapes() const
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 GetDphi() const
Definition TGeoPcon.h:77
Double_t * fRmax
Definition TGeoPcon.h:24
Double_t * fRmin
Definition TGeoPcon.h:23
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
void InspectShape() const override
print shape parameters
Definition TGeoPcon.cxx:919
Bool_t HasInsideSurface() const
Returns true when pgon has internal surface It will be only disabled when all Rmin values are 0.
Double_t fPhi1
Definition TGeoPcon.h:21
Double_t fDphi
Definition TGeoPcon.h:22
Int_t GetNz() const
Definition TGeoPcon.h:78
Polygons are defined in the same way as polycones, the difference being just that the segments betwee...
Definition TGeoPgon.h:23
void Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const override
Compute safe distance from each of the points in the input array.
TBuffer3D * MakeBuffer3D() const override
Creates a TBuffer3D describing this shape.
static std::atomic< UInt_t > fgInstanceCount
Definition TGeoPgon.h:69
void SetPoints(Double_t *points) const override
create polygone mesh points
Bool_t Contains(const Double_t *point) const override
test if point is inside this shape check total z range
Definition TGeoPgon.cxx:360
std::mutex fOwnedDataMutex
! Protects cold allocation and cleanup
Definition TGeoPgon.h:61
Bool_t SliceCrossingInZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const
Performs ray propagation between Z segments.
Definition TGeoPgon.cxx:626
std::vector< std::unique_ptr< OwnedThreadData_t > > fOwnedData
! Object-owned per-thread buffers
Definition TGeoPgon.h:60
~TGeoPgon() override
destructor
Definition TGeoPgon.cxx:154
Bool_t SliceCrossing(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const
Check boundary crossing inside phi slices.
Definition TGeoPgon.cxx:939
void Sizeof3D() const override
fill size of this 3-D object
Int_t GetNmeshVertices() const override
Return number of vertices of the mesh representation.
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
Compute normal to closest surface from POINT.
Definition TGeoPgon.cxx:262
void GetBoundingCylinder(Double_t *param) const override
Fill vector param[4] with the bounding cylinder parameters.
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...
Int_t fNedges
Definition TGeoPgon.h:59
Bool_t SliceCrossingZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const
Performs ray propagation between Z segments.
Definition TGeoPgon.cxx:705
void InspectShape() const override
Inspect the PGON parameters.
void LocatePhi(const Double_t *point, Int_t &ipsec) const
Locates index IPSEC of the phi sector containing POINT.
Definition TGeoPgon.cxx:528
TGeoPgon()
dummy ctor
Definition TGeoPgon.cxx:108
TGeoVolume * Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step) override
Divide this polygone shape belonging to volume "voldiv" into ndiv volumes called divname,...
Int_t GetNedges() const
Definition TGeoPgon.h:116
void GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const override
Returns numbers of vertices, segments and polygons composing the shape mesh.
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save a primitive as a C++ statement(s) on output stream "out".
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 ClearThreadData() const override
Release object-owned scratch buffers and invalidate the non-owning TLS slots.
Definition TGeoPgon.cxx:98
Double_t SafetyToSegment(const Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin=TGeoShape::Big()) const
Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
Double_t Capacity() const override
Computes capacity of the shape in [length^3].
Definition TGeoPgon.cxx:162
Double_t Rpg(Double_t z, Int_t ipl, Bool_t inner, Double_t &a, Double_t &b) const
Computes projected pgon radius (inner or outer) corresponding to a given Z value.
void SetDimensions(Double_t *param) override
Set PGON dimensions starting from an array.
void SetSegsAndPolsNoInside(TBuffer3D &buff) const
Fill TBuffer3D structure for segments and polygons, when no inner surface exists.
Bool_t SliceCrossingIn(const Double_t *point, const Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const
Check boundary crossing inside phi slices.
Definition TGeoPgon.cxx:795
void Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const override
Check the inside status for each of the points in the array.
void 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...
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Fills a static 3D buffer and returns a reference.
void InitThreadSlot(ThreadData_t &td) const
(Re)build the per-thread scratch buffers for this shape into the given slot.
Definition TGeoPgon.cxx:82
ThreadData_t & GetThreadData() const
Per-thread non-owning cache of scratch buffers indexed by this shape.
Definition TGeoPgon.h:38
void ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize) override
Compute the normal for an array o points so that norm.dot.dir is positive Input: Arrays of point coor...
void ComputeBBox() override
compute bounding box for a polygone Check if the sections are in increasing Z order
Definition TGeoPgon.cxx:187
Double_t Rproj(Double_t z, const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const
Computes projected distance at a given Z for a given ray inside a given sector and fills coefficients...
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 polygone first find out in which Z section the p...
Definition TGeoPgon.cxx:418
Bool_t IsCrossingSlice(const Double_t *point, const Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const
Check crossing of a given pgon slice, from a starting point inside the slice.
Int_t GetPhiCrossList(const Double_t *point, const Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax=TGeoShape::Big()) const
Returns lists of PGON phi crossings for a ray starting from POINT.
Definition TGeoPgon.cxx:541
void SetSegsAndPols(TBuffer3D &buff) const override
Fill TBuffer3D structure for segments and polygons.
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 polygone.
std::atomic< Int_t > fGeneration
non-reused index of this shape into the per-thread vector
Definition TGeoPgon.h:26
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
compute closest distance from point px,py to each corner
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.
static void NormalPhi(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
Static method to compute normal to phi planes.
static Bool_t IsCrossingSemiplane(const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy)
Compute distance from POINT to semiplane defined by PHI angle along DIR.
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 Bool_t IsCloseToPhi(Double_t epsil, const Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
True if point is closer than epsil to one of the phi planes defined by c1,s1 or c2,...
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
Volume families.
Definition TGeoVolume.h:269
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:45
Int_t IndexOf(const TObject *obj) const override
R__ALWAYS_INLINE 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:226
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:386
TPaveText * pt
return c1
Definition legend1.C:41
const Int_t n
Definition legend1.C:16
return c2
Definition legend2.C:14
Long64_t LocMin(Long64_t n, const T *a)
Returns index of array with the minimum element.
Definition TMath.h:995
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:659
Long64_t LocMax(Long64_t n, const T *a)
Returns index of array with the maximum element.
Definition TMath.h:1105
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:675
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:607
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:613
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
std::unique_ptr< Int_t[]> fIntBuffer
Definition TGeoPgon.cxx:72
OwnedThreadData_t(std::size_t size)
Definition TGeoPgon.cxx:75
std::unique_ptr< Double_t[]> fDblBuffer
Definition TGeoPgon.cxx:73
bumped whenever the per-thread state must be rebuilt
Definition TGeoPgon.h:29
TMarker m
Definition textangle.C:8