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 } // Phi done
280
281 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
282 if (point[2] >= fZ[fNz - 1] || ipl < 0) {
283 // point outside Z range
284 norm[2] = TMath::Sign(1., dir[2]);
285 return;
286 }
288 if ((fZ[ipl + 1] - point[2]) < (point[2] - fZ[ipl]))
289 iplclose++;
290 dz = TMath::Abs(fZ[iplclose] - point[2]);
291
293 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
294 while (phi < fPhi1)
295 phi += 360.;
296 Double_t ddp = phi - fPhi1;
298 // A point on or just outside a phi cut belongs to the nearest end sector.
299 if (ipsec >= fNedges)
300 ipsec = (ddp - fDphi < 360. - ddp) ? fNedges - 1 : 0;
301 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
302 // compute projected distance
304 r = TMath::Abs(point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0));
306 if (iplclose == 0 || iplclose == (fNz - 1)) {
307 safz = dz;
308 } else if (iplclose == ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
309 if (r < TMath::Max(fRmin[ipl], fRmin[ipl - 1]) || r > TMath::Min(fRmax[ipl], fRmax[ipl - 1]))
310 safz = dz;
313 safz = dz;
314 } //-> Z done
315
316 // At a repeated z plane, use a section with nonzero height for the radial faces.
317 while (ipl < fNz - 2 && fZ[ipl] == fZ[ipl + 1])
318 ++ipl;
319 dz = fZ[ipl + 1] - fZ[ipl];
320 rmin1 = fRmin[ipl];
321 rmin2 = fRmin[ipl + 1];
322 rsum = rmin1 + rmin2;
324 if (rsum > 1E-10) {
325 ta = (rmin2 - rmin1) / dz;
326 calf = 1. / TMath::Sqrt(1 + ta * ta);
327 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
328 safe = TMath::Abs(r - rpgon) * calf;
329 norm[0] = calf * TMath::Cos(ph0);
330 norm[1] = calf * TMath::Sin(ph0);
331 norm[2] = -calf * ta;
332 }
333 ta = (fRmax[ipl + 1] - fRmax[ipl]) / dz;
334 calf = 1. / TMath::Sqrt(1 + ta * ta);
335 rpgon = fRmax[ipl] + (point[2] - fZ[ipl]) * ta;
337 if (safe > safr) {
338 safe = safr;
339 norm[0] = calf * TMath::Cos(ph0);
340 norm[1] = calf * TMath::Sin(ph0);
341 norm[2] = -calf * ta;
342 }
343 // Compare face distances instead of letting a fixed tolerance select a nearby face.
344 if (safz < safe) {
345 safe = safz;
346 norm[0] = norm[1] = 0.;
347 norm[2] = 1.;
348 }
349 if (is_seg && TGeoShape::IsCloseToPhi(safe, point, c1, s1, c2, s2)) {
350 TGeoShape::NormalPhi(point, dir, norm, c1, s1, c2, s2);
351 return;
352 }
353 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
354 norm[0] = -norm[0];
355 norm[1] = -norm[1];
356 norm[2] = -norm[2];
357 }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// test if point is inside this shape
362/// check total z range
363
365{
366 if (point[2] < fZ[0])
367 return kFALSE;
368 if (point[2] > fZ[fNz - 1])
369 return kFALSE;
371 // now check phi
372 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
373 while (phi < fPhi1)
374 phi += 360.0;
375 Double_t ddp = phi - fPhi1;
376 if (ddp > fDphi)
377 return kFALSE;
378 // now find phi division
380 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
381 // now check projected distance
382 Double_t r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
383 // find in which Z section the point is in
384 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
385 if (iz == fNz - 1) {
386 if (r < fRmin[iz])
387 return kFALSE;
388 if (r > fRmax[iz])
389 return kFALSE;
390 return kTRUE;
391 }
392 Double_t dz = fZ[iz + 1] - fZ[iz];
394 if (dz < 1E-8) {
395 // we are at a radius-changing plane
396 rmin = TMath::Min(fRmin[iz], fRmin[iz + 1]);
397 rmax = TMath::Max(fRmax[iz], fRmax[iz + 1]);
398 if (r < rmin)
399 return kFALSE;
400 if (r > rmax)
401 return kFALSE;
402 return kTRUE;
403 }
404 // now compute rmin and rmax and test the value of r
405 Double_t dzrat = (point[2] - fZ[iz]) / dz;
406 rmin = fRmin[iz] + dzrat * (fRmin[iz + 1] - fRmin[iz]);
407 // is the point inside the 'hole' at the center of the volume ?
408 if (r < rmin)
409 return kFALSE;
410 rmax = fRmax[iz] + dzrat * (fRmax[iz + 1] - fRmax[iz]);
411 if (r > rmax)
412 return kFALSE;
413
414 return kTRUE;
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// compute distance from inside point to surface of the polygone
419/// first find out in which Z section the point is in
420
423{
424 if (iact < 3 && safe) {
425 *safe = Safety(point, kTRUE);
426 if (iact == 0)
427 return TGeoShape::Big();
428 if (iact == 1 && step < *safe)
429 return TGeoShape::Big();
430 }
431 // find current Z section
432 Int_t ipl, ipsec;
433 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
434 if (ipl == fNz - 1) {
435 if (dir[2] >= 0)
436 return 0.;
437 ipl--;
438 }
439 if (ipl < 0) {
440 // point out
441 if (dir[2] <= 0)
442 return 0.;
443 ipl++;
444 }
445 Double_t stepmax = step;
447 Double_t *sph = td.fDblBuffer;
448 Int_t *iph = td.fIntBuffer;
449 // locate current phi sector [0,fNedges-1]; -1 for dead region
450 LocatePhi(point, ipsec);
451 if (ipsec < 0) {
452 // Point on a phi boundary - entering or exiting ?
455 if ((point[0] * dir[1] - point[1] * dir[0]) > 0) {
456 // phi1 next crossing
457 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) <
458 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
459 // close to phimax
460 return 0.0;
461 } else {
462 // close to phi1 - ignore it
463 ipsec = 0;
464 }
465 } else {
466 // phimax next crossing
467 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) >
468 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
469 // close to phi1
470 return 0.0;
471 } else {
472 // close to phimax - ignore it
473 ipsec = fNedges - 1;
474 }
475 }
476 }
477 Int_t ipln = -1;
479 ipln = ipl;
480 } else {
481 if (fNz > 3 && ipl >= 0 && ipl < fNz - 3 && TGeoShape::IsSameWithinTolerance(fZ[ipl + 1], fZ[ipl + 2]) &&
482 TMath::Abs(point[2] - fZ[ipl + 1]) < 1.E-8) {
483 ipln = ipl + 1;
484 } else {
485 if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1]) &&
486 TMath::Abs(point[2] - fZ[ipl]) < 1.E-8)
487 ipln = ipl - 1;
488 }
489 }
490 if (ipln > 0) {
491 // point between segments
493 Double_t phi = (fPhi1 + (ipsec + 0.5) * divphi) * TMath::DegToRad();
494 Double_t cphi = TMath::Cos(phi);
495 Double_t sphi = TMath::Sin(phi);
496 Double_t rproj = point[0] * cphi + point[1] * sphi;
497 if (dir[2] > 0) {
498 ipl = ipln + 1;
499 if (rproj > fRmin[ipln] && rproj < fRmin[ipln + 1])
500 return 0.0;
501 if (rproj < fRmax[ipln] && rproj > fRmax[ipln + 1])
502 return 0.0;
503 } else {
504 ipl = ipln - 1;
505 if (rproj < fRmin[ipln] && rproj > fRmin[ipln + 1])
506 return 0.0;
507 if (rproj > fRmax[ipln] && rproj < fRmax[ipln + 1])
508 return 0.0;
509 }
510 }
511
513 icrossed = GetPhiCrossList(point, dir, ipsec, sph, iph, stepmax);
515 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
516 if (SliceCrossingInZ(point, dir, icrossed, iph, sph, snext, stepmax))
517 return snext;
519 return TGeoShape::Big();
520 return 0.;
521 }
522 if (SliceCrossingIn(point, dir, ipl, icrossed, iph, sph, snext, stepmax))
523 return snext;
525 return TGeoShape::Big();
526 return 0.;
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// Locates index IPSEC of the phi sector containing POINT.
531
532void TGeoPgon::LocatePhi(const Double_t *point, Int_t &ipsec) const
533{
534 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
535 while (phi < fPhi1)
536 phi += 360.;
537 ipsec = Int_t(fNedges * (phi - fPhi1) / fDphi); // [0, fNedges-1]
538 if (ipsec > fNedges - 1)
539 ipsec = -1; // in gap
540}
541
542////////////////////////////////////////////////////////////////////////////////
543/// Returns lists of PGON phi crossings for a ray starting from POINT.
544
546 Double_t stepmax) const
547{
548 Double_t rxy, phi, cph, sph;
549 Int_t icrossed = 0;
550 if ((1. - TMath::Abs(dir[2])) < 1E-8) {
551 // ray is going parallel with Z
552 iphi[0] = istart;
553 sphi[0] = stepmax;
554 return 1;
555 }
556 Bool_t shootorig = (TMath::Abs(point[0] * dir[1] - point[1] * dir[0]) < 1E-8) ? kTRUE : kFALSE;
558 if (shootorig) {
559 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
560 if (rdotn > 0) {
561 sphi[0] = stepmax;
562 iphi[0] = istart;
563 return 1;
564 }
565 sphi[0] = TMath::Sqrt((point[0] * point[0] + point[1] * point[1]) / (1. - dir[2] * dir[2]));
566 iphi[0] = istart;
567 if (sphi[0] > stepmax) {
568 sphi[0] = stepmax;
569 return 1;
570 }
571 phi = TMath::ATan2(dir[1], dir[0]) * TMath::RadToDeg();
572 while (phi < fPhi1)
573 phi += 360.;
574 istart = Int_t((phi - fPhi1) / divphi);
575 if (istart > fNedges - 1)
576 istart = -1;
577 iphi[1] = istart;
578 sphi[1] = stepmax;
579 return 2;
580 }
581 Int_t incsec = Int_t(TMath::Sign(1., point[0] * dir[1] - point[1] * dir[0]));
582 Int_t ist;
583 if (istart < 0)
584 ist = (incsec > 0) ? 0 : fNedges;
585 else
586 ist = (incsec > 0) ? (istart + 1) : istart;
591 while (crossing) {
592 if (istart < 0)
593 gapdone = kTRUE;
594 phi = phi1 + ist * divphi;
595 cph = TMath::Cos(phi);
596 sph = TMath::Sin(phi);
598 if (!crossing)
600 iphi[icrossed++] = istart;
601 if (crossing) {
602 if (sphi[icrossed - 1] > stepmax) {
603 sphi[icrossed - 1] = stepmax;
604 return icrossed;
605 }
606 if (istart < 0) {
607 istart = (incsec > 0) ? 0 : (fNedges - 1);
608 } else {
609 istart += incsec;
610 if (istart > fNedges - 1)
611 istart = (fDphi < 360.) ? (-1) : 0;
612 else if (istart < 0 && TGeoShape::IsSameWithinTolerance(fDphi, 360))
613 istart = fNedges - 1;
614 }
615 if (istart < 0) {
616 if (gapdone)
617 return icrossed;
618 ist = (incsec > 0) ? 0 : fNedges;
619 } else {
620 ist = (incsec > 0) ? (istart + 1) : istart;
621 }
622 }
623 }
624 return icrossed;
625}
626
627////////////////////////////////////////////////////////////////////////////////
628/// Performs ray propagation between Z segments.
629
632{
633 snext = 0.;
634 if (!nphi)
635 return kFALSE;
636 Int_t i;
639 Double_t pt[3];
640 if (iphi[0] < 0 && nphi == 1)
641 return kFALSE;
642 // Get current Z segment
643 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
644 if (ipl < 0 || ipl == fNz - 1)
645 return kFALSE;
646 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
647 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
648 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
649 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
650 } else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
651 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
652 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
653 } else {
654 rmin = fRmin[ipl];
655 rmax = fRmax[ipl];
656 }
657 } else {
658 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
659 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
660 }
663 Double_t rproj, ndot, dist;
666 Double_t snextphi = 0.;
667 Double_t step = 0;
668 Double_t phi;
669 memcpy(pt, point, 3 * sizeof(Double_t));
670 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
671 if (step > stepmax) {
672 snext = step;
673 return kFALSE;
674 }
675 if (iphi[iphcrt] < 0) {
676 snext = step;
677 return kTRUE;
678 }
679 // check crossing
681 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
682 cosph = TMath::Cos(phi);
683 sinph = TMath::Sin(phi);
684 rproj = pt[0] * cosph + pt[1] * sinph;
685 dist = TGeoShape::Big();
686 ndot = dir[0] * cosph + dir[1] * sinph;
688 dist = (ndot > 0) ? ((rmax - rproj) / ndot) : ((rmin - rproj) / ndot);
689 if (dist < 0)
690 dist = 0.;
691 }
692 if (dist < (snextphi - step)) {
693 snext = step + dist;
694 if (snext < stepmax)
695 return kTRUE;
696 return kFALSE;
697 }
698 step = snextphi;
699 for (i = 0; i < 3; i++)
700 pt[i] = point[i] + step * dir[i];
701 }
702 snext = step;
703 return kFALSE;
704}
705
706////////////////////////////////////////////////////////////////////////////////
707/// Performs ray propagation between Z segments.
708
711{
712 if (!nphi)
713 return kFALSE;
714 Int_t i;
717 Double_t pt[3];
718 if (iphi[0] < 0 && nphi == 1)
719 return kFALSE;
720 // Get current Z segment
721 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
722 if (ipl < 0 || ipl == fNz - 1)
723 return kFALSE;
724 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
725 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
726 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
727 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
728 } else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
729 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
730 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
731 } else {
732 rmin = fRmin[ipl];
733 rmax = fRmax[ipl];
734 }
735 } else {
736 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
737 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
738 }
741 Double_t rproj, ndot, dist;
744 Double_t snextphi = 0.;
745 Double_t step = 0;
746 Double_t phi;
747 memcpy(pt, point, 3 * sizeof(Double_t));
748 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
749 if (step > stepmax)
750 return kFALSE;
752 if (iphi[iphcrt] < 0) {
753 if (iphcrt == nphi - 1)
754 return kFALSE;
755 if (snextphi > stepmax)
756 return kFALSE;
757 for (i = 0; i < 3; i++)
758 pt[i] = point[i] + snextphi * dir[i];
759 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
760 cosph = TMath::Cos(phi);
761 sinph = TMath::Sin(phi);
762 rproj = pt[0] * cosph + pt[1] * sinph;
764 step = snextphi;
765 continue;
766 }
767 snext = snextphi;
768 return kTRUE;
769 }
770 // check crossing
771 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
772 cosph = TMath::Cos(phi);
773 sinph = TMath::Sin(phi);
774 rproj = pt[0] * cosph + pt[1] * sinph;
775 dist = TGeoShape::Big();
776 ndot = dir[0] * cosph + dir[1] * sinph;
777 if (rproj < rmin) {
778 dist = (ndot > 0) ? ((rmin - rproj) / ndot) : TGeoShape::Big();
779 } else {
780 dist = (ndot < 0) ? ((rmax - rproj) / ndot) : TGeoShape::Big();
781 }
782 if (dist < 1E10) {
783 snext = step + dist;
784 if (snext < stepmax)
785 return kTRUE;
786 }
787 step = snextphi;
788 for (i = 0; i < 3; i++)
789 pt[i] = point[i] + step * dir[i];
790 }
791 return kFALSE;
792}
793
794////////////////////////////////////////////////////////////////////////////////
795/// Check boundary crossing inside phi slices. Return distance snext to first crossing
796/// if smaller than stepmax.
797/// Protection in case point is in phi gap or close to phi boundaries and exiting
798
801{
802 snext = 0.;
803 if (!nphi)
804 return kFALSE;
805 Int_t i;
806 Int_t iphstart = 0;
807 Double_t pt[3];
808 if (iphi[0] < 0) {
809 if (stepphi[0] > TGeoShape::Tolerance())
810 return kFALSE;
811 iphstart = 1;
812 }
813 if (nphi > 1 && iphi[1] < 0 && stepphi[0] < TGeoShape::Tolerance()) {
814 snext = stepphi[0];
815 return kTRUE;
816 }
817 // Get current Z segment
818 Double_t snextphi = 0.;
819 Double_t step = 0;
820 Int_t incseg = (dir[2] > 0) ? 1 : -1; // dir[2] is never 0 here
821 // Compute the projected radius from starting point
823 Int_t iphcrt = 0;
824 Double_t apr = TGeoShape::Big(), bpr = 0, db = 0;
825 Double_t rpg = 0, rnew = 0, znew = 0;
826 Double_t rpgin = 0, rpgout = 0, apgin = 0, apgout = 0, bpgin = 0, bpgout = 0;
829 Double_t phi = 0, dz = 0;
830 Double_t cosph = 0, sinph = 0;
831 Double_t distz = 0, distr = 0, din = 0, dout = 0;
832 Double_t invdir = 1. / dir[2];
833 memcpy(pt, point, 3 * sizeof(Double_t));
834 for (iphcrt = iphstart; iphcrt < nphi; iphcrt++) {
835 // check if step to current checked slice is too big
836 if (step > stepmax) {
837 snext = step;
838 return kFALSE;
839 }
840 if (iphi[iphcrt] < 0) {
841 snext = snextphi;
842 return kTRUE;
843 }
845 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
846 cosph = TMath::Cos(phi);
847 sinph = TMath::Sin(phi);
848 Double_t rproj = Rproj(pt[2], pt, dir, cosph, sinph, apr, bpr);
849 // compute distance to next Z plane
850 while (ipl >= 0 && ipl < fNz - 1) {
851 din = dout = TGeoShape::Big();
852 // dist to last boundary of current segment according dir
853 distz = (fZ[ipl + ((1 + incseg) >> 1)] - pt[2]) * invdir;
854 // length of current segment
855 dz = fZ[ipl + 1] - fZ[ipl];
856 if (dz < TGeoShape::Tolerance()) {
857 rnew = apr + bpr * fZ[ipl];
858 rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
859 if (rpg <= 0)
860 din = distz;
861 rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
862 if (rpg <= 0)
863 dout = distz;
865 } else {
866 rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
867 db = bpgin - bpr;
869 znew = (apr - apgin) / db;
870 din = (znew - pt[2]) * invdir;
871 }
872 rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
873 db = bpgout - bpr;
875 znew = (apr - apgout) / db;
876 dout = (znew - pt[2]) * invdir;
877 }
878 // protection for the first segment
882 if (iphcrt == iphstart && ipl == iplstart) {
883 if (rproj < rpgin + 1.E-8) {
884 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
885 if (ndotd < 0) {
886 snext = (din < 0) ? step : (step + din);
887 return kTRUE;
888 } else {
889 // Ignore din
890 din = -TGeoShape::Big();
891 }
895 } else if (rproj > rpgout - 1.E-8) {
896 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
897 if (ndotd > 0) {
898 snext = (dout < 0) ? step : (step + dout);
899 return kTRUE;
900 } else {
901 // Ignore dout
902 dout = -TGeoShape::Big();
903 }
907 }
908 }
909 }
912 if (snextphi < step + TMath::Min(distz, distr)) {
913 for (i = 0; i < 3; i++)
914 pt[i] = point[i] + snextphi * dir[i];
915 step = snextphi;
916 snext = 0.0;
917 break;
918 }
919 if (distr <= distz + TGeoShape::Tolerance()) {
920 step += distr;
921 snext = step;
922 return (step > stepmax) ? kFALSE : kTRUE;
923 }
924 // we have crossed a Z boundary
925 snext = distz;
926 if ((ipl + incseg < 0) || (ipl + incseg > fNz - 2)) {
927 // it was the last boundary
928 step += distz;
929 snext = step;
930 return (step > stepmax) ? kFALSE : kTRUE;
931 }
932 ipl += incseg;
933 } // end loop Z
934 } // end loop phi
936 return kFALSE;
937}
938
939////////////////////////////////////////////////////////////////////////////////
940/// Check boundary crossing inside phi slices. Return distance snext to first crossing
941/// if smaller than stepmax.
942
945{
946 if (!nphi)
947 return kFALSE;
948 Int_t i;
949 Double_t pt[3];
950 if (iphi[0] < 0 && nphi == 1)
951 return kFALSE;
952
953 Double_t snextphi = 0.;
954 Double_t step = 0;
955 // Get current Z segment
956 Int_t incseg = (dir[2] > 0) ? 1 : -1; // dir[2] is never 0 here
957 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
958 if (ipl < 0) {
959 ipl = 0; // this should never happen
960 if (incseg < 0)
961 return kFALSE;
962 } else {
963 if (ipl == fNz - 1) {
964 ipl = fNz - 2; // nor this
965 if (incseg > 0)
966 return kFALSE;
967 } else {
968 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
969 // we are at the sector edge, but never inside the pgon
970 if ((ipl + incseg) < 0 || (ipl + incseg) > fNz - 1)
971 return kFALSE;
973 ipl += incseg;
974 // move to next clean segment if downwards
975 if (incseg < 0) {
977 ipl--;
978 }
979 }
980 }
981 }
982 // Compute the projected radius from starting point
989 Double_t phi;
992 memcpy(pt, point, 3 * sizeof(Double_t));
993 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
994 // check if step to current checked slice is too big
995 if (step > stepmax)
996 return kFALSE;
997 // jump over the dead sector
999 if (iphi[iphcrt] < 0) {
1000 if (iphcrt == nphi - 1)
1001 return kFALSE;
1002 if (snextphi > stepmax)
1003 return kFALSE;
1004 for (i = 0; i < 3; i++)
1005 pt[i] = point[i] + snextphi * dir[i];
1006 // we have a new z, so check again iz
1007 if (incseg > 0) {
1008 // loop z planes
1009 while (pt[2] > fZ[ipl + 1]) {
1010 ipl++;
1011 if (ipl > fNz - 2)
1012 return kFALSE;
1013 }
1014 } else {
1015 while (pt[2] < fZ[ipl]) {
1016 ipl--;
1017 if (ipl < 0)
1018 return kFALSE;
1019 }
1020 }
1021 // check if we have a crossing when entering new sector
1022 rpgin = Rpg(pt[2], ipl, kTRUE, apg, bpg);
1023 rpgout = Rpg(pt[2], ipl, kFALSE, apg, bpg);
1024 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
1025 cosph = TMath::Cos(phi);
1026 sinph = TMath::Sin(phi);
1027
1028 rproj = pt[0] * cosph + pt[1] * sinph;
1030 step = snextphi;
1031 continue;
1032 }
1033 snext = snextphi;
1034 return kTRUE;
1035 }
1036 if (IsCrossingSlice(point, dir, iphi[iphcrt], step, ipl, snext, TMath::Min(snextphi, stepmax)))
1037 return kTRUE;
1038 step = snextphi;
1039 }
1040 return kFALSE;
1041}
1042
1043////////////////////////////////////////////////////////////////////////////////
1044/// Check crossing of a given pgon slice, from a starting point inside the slice
1045
1048{
1049 if (ipl < 0 || ipl > fNz - 2)
1050 return kFALSE;
1051 if (sstart > stepmax)
1052 return kFALSE;
1053 Double_t pt[3];
1054 memcpy(pt, point, 3 * sizeof(Double_t));
1055 if (sstart > 0)
1056 for (Int_t i = 0; i < 3; i++)
1057 pt[i] += sstart * dir[i];
1058 stepmax -= sstart;
1059 Double_t step;
1060 Int_t incseg = (dir[2] > 0) ? 1 : -1;
1061 Double_t invdir = 1. / dir[2];
1063 Double_t phi = fPhi1 * TMath::DegToRad() + (iphi + 0.5) * divphi;
1064 Double_t cphi = TMath::Cos(phi);
1065 Double_t sphi = TMath::Sin(phi);
1067 Double_t bpr = 0.;
1068 Rproj(pt[2], point, dir, cphi, sphi, apr, bpr);
1069 Double_t dz;
1070 // loop segments
1071 Int_t icrtseg = ipl;
1073 Int_t iseglast = (incseg > 0) ? (fNz - 1) : -1;
1075
1076 for (ipl = isegstart; ipl != iseglast; ipl += incseg) {
1077 step = (fZ[ipl + 1 - ((1 + incseg) >> 1)] - pt[2]) * invdir;
1078 if (step > 0) {
1079 if (step > stepmax) {
1080 ipl = icrtseg;
1081 return kFALSE;
1082 }
1083 icrtseg = ipl;
1084 }
1085 din = dout = TGeoShape::Big();
1086 dz = fZ[ipl + 1] - fZ[ipl];
1087
1088 // rdot = (rproj-fRmin[ipl])*dz - (pt[2]-fZ[ipl])*(fRmin[ipl+1]-fRmin[ipl]);
1090 rdot = dir[2] * TMath::Sign(1., fRmin[ipl] - fRmin[ipl + 1]);
1091 else
1092 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
1093 if (rdot > 0) {
1094 // inner surface visible ->check crossing
1095 // printf(" inner visible\n");
1097 rnew = apr + bpr * fZ[ipl];
1098 Double_t rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
1099 if (rpg <= 0)
1100 din = (fZ[ipl] - pt[2]) * invdir;
1101 } else {
1102 Rpg(pt[2], ipl, kTRUE, apg, bpg);
1103 db = bpg - bpr;
1105 znew = (apr - apg) / db;
1106 if (znew > fZ[ipl] && znew < fZ[ipl + 1]) {
1107 din = (znew - pt[2]) * invdir;
1108 if (din < 0)
1109 din = TGeoShape::Big();
1110 }
1111 }
1112 }
1113 }
1114 // printf(" din=%f\n", din);
1115 // rdot = (rproj-fRmax[ipl])*dz - (pt[2]-fZ[ipl])*(fRmax[ipl+1]-fRmax[ipl]);
1117 rdot = dir[2] * TMath::Sign(1., fRmax[ipl] - fRmax[ipl + 1]);
1118 else
1119 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
1120 if (rdot < 0) {
1121 // printf(" outer visible\n");
1122 // outer surface visible ->check crossing
1124 rnew = apr + bpr * fZ[ipl];
1125 Double_t rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
1126 if (rpg <= 0)
1127 dout = (fZ[ipl] - pt[2]) * invdir;
1128 } else {
1129 Rpg(pt[2], ipl, kFALSE, apg, bpg);
1130 db = bpg - bpr;
1132 znew = (apr - apg) / db;
1133 if (znew > fZ[ipl] && znew < fZ[ipl + 1])
1134 dout = (znew - pt[2]) * invdir;
1135 if (dout < 0)
1136 dout = TGeoShape::Big();
1137 }
1138 }
1139 }
1140 // printf(" dout=%f\n", dout);
1141 step = TMath::Min(din, dout);
1142 if (step < 1E10) {
1143 // there is a crossing within this segment
1144 if (step > stepmax) {
1145 ipl = icrtseg;
1146 return kFALSE;
1147 }
1148 snext = sstart + step;
1149 return kTRUE;
1150 }
1151 }
1152 ipl = icrtseg;
1153 return kFALSE;
1154}
1155
1156////////////////////////////////////////////////////////////////////////////////
1157/// Compute distance from outside point to surface of the polygone
1158
1161{
1162 if (iact < 3 && safe) {
1163 *safe = Safety(point, kFALSE);
1164 if (iact == 0)
1165 return TGeoShape::Big(); // just safety computed
1166 if (iact == 1 && step < *safe)
1167 return TGeoShape::Big(); // safety mode
1168 }
1169 // Check if the bounding box is crossed within the requested distance
1170 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
1171 if (sdist >= step)
1172 return TGeoShape::Big();
1173 // Protection for points on last Z sections
1174 if (dir[2] <= 0 && TMath::Abs(point[2] - fZ[0]) < TGeoShape::Tolerance())
1175 return TGeoShape::Big();
1176 if (dir[2] >= 0 && TMath::Abs(point[2] - fZ[fNz - 1]) < TGeoShape::Tolerance())
1177 return TGeoShape::Big();
1178 // copy the current point
1179 Double_t pt[3];
1180 memcpy(pt, point, 3 * sizeof(Double_t));
1181 // find current Z section
1182 Int_t ipl;
1183 Int_t i, ipsec;
1185
1187 // check if ray may intersect outer cylinder
1188 Double_t snext = 0.;
1189 Double_t stepmax = step;
1191 Double_t r2 = pt[0] * pt[0] + pt[1] * pt[1];
1194 radmax += 1E-8;
1195 if (r2 > (radmax * radmax) || pt[2] < fZ[0] || pt[2] > fZ[fNz - 1]) {
1196 pt[2] -= 0.5 * (fZ[0] + fZ[fNz - 1]);
1197 snext = TGeoTube::DistFromOutsideS(pt, dir, 0., radmax, 0.5 * (fZ[fNz - 1] - fZ[0]));
1198 if (snext > 1E10)
1199 return TGeoShape::Big();
1200 if (snext > stepmax)
1201 return TGeoShape::Big();
1202 stepmax -= snext;
1203 pt[2] = point[2];
1204 for (i = 0; i < 3; i++)
1205 pt[i] += snext * dir[i];
1206 Bool_t checkz = (ipl < 0 && TMath::Abs(pt[2] - fZ[0]) < 1E-8) ? kTRUE : kFALSE;
1207 if (!checkz)
1208 checkz = (ipl == fNz - 1 && TMath::Abs(pt[2] - fZ[fNz - 1]) < 1E-8) ? kTRUE : kFALSE;
1209 if (checkz) {
1211 if (ipl < 0) {
1212 rmin = fRmin[0];
1213 rmax = fRmax[0];
1214 } else {
1215 rmin = fRmin[fNz - 1];
1216 rmax = fRmax[fNz - 1];
1217 }
1218 Double_t phi = TMath::ATan2(pt[1], pt[0]) * TMath::RadToDeg();
1219 while (phi < fPhi1)
1220 phi += 360.0;
1221 Double_t ddp = phi - fPhi1;
1222 if (ddp <= fDphi) {
1223 ipsec = Int_t(ddp / divphi);
1224 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
1225 rpr = pt[0] * TMath::Cos(ph0) + pt[1] * TMath::Sin(ph0);
1226 if (rpr >= rmin && rpr <= rmax)
1227 return snext;
1228 }
1229 }
1230 }
1232 Double_t *sph = td.fDblBuffer;
1233 Int_t *iph = td.fIntBuffer;
1235 // locate current phi sector [0,fNedges-1]; -1 for dead region
1236 // if ray is perpendicular to Z, solve this particular case
1237 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1238 LocatePhi(pt, ipsec);
1241 return (snext + snewcross);
1242 return TGeoShape::Big();
1243 }
1244 // Locate phi and get the phi crossing list
1246 Bool_t inphi = kTRUE;
1248 while (ph < fPhi1)
1249 ph += 360.;
1250 ipsec = Int_t(fNedges * (ph - fPhi1) / fDphi); // [0, fNedges-1]
1251 if (ipsec > fNedges - 1)
1252 ipsec = -1; // in gap
1253 Double_t phim = fPhi1 + 0.5 * fDphi;
1255 if (fDphi < 360.0) {
1256 inphi = (ddp < 0.5 * fDphi + TGeoShape::Tolerance()) ? kTRUE : kFALSE;
1257 }
1259 if (ipl < 0)
1260 ipl = 0;
1261 if (ipl == fNz - 1)
1262 ipl--;
1263 Bool_t inz = kTRUE;
1264 if (pt[2] > fZ[fNz - 1] + TGeoShape::Tolerance())
1265 inz = kFALSE;
1266 if (pt[2] < fZ[0] - TGeoShape::Tolerance())
1267 inz = kFALSE;
1269 if (inphi && inz) {
1270 Bool_t done = kFALSE;
1271 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1272 Double_t phi = fPhi1 * TMath::DegToRad() + (ipsec + 0.5) * divphi;
1273 Double_t cphi = TMath::Cos(phi);
1274 Double_t sphi = TMath::Sin(phi);
1275 Double_t rproj = pt[0] * cphi + pt[1] * sphi;
1277 if (rproj < fRmin[ipl] && rproj > fRmin[ipl + 1] && dir[2] > 0)
1278 return 0.0;
1279 if (rproj > fRmin[ipl] && rproj < fRmin[ipl + 1] && dir[2] < 0)
1280 return 0.0;
1281 if (rproj > fRmax[ipl] && rproj < fRmax[ipl + 1] && dir[2] > 0)
1282 return 0.0;
1283 if (rproj < fRmax[ipl] && rproj > fRmax[ipl + 1] && dir[2] < 0)
1284 return 0.0;
1285 done = kTRUE;
1286 }
1287 if (!done) {
1290 if (rproj < rpgout + 1.E-8) {
1292 Double_t rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
1293 if (rproj > rpgin - 1.E-8) {
1296 Double_t safz = TMath::Min(pt[2] - fZ[ipl], fZ[ipl + 1] - pt[2]);
1298 if (fDphi < 360) {
1299 safphi = rproj * TMath::Sin((ddp - 0.5 * fDphi) * TMath::DegToRad());
1301 }
1302 // printf("inside pgon: safrmin=%f, safrmax=%f, safphi=%f,
1303 // safz=%f\n",safrmin,safrmax,safphi,safz);
1304 Double_t dzinv = 1. / dz;
1305 if (safrmin < safz && safrmin < safrmax && safrmin < safphi) {
1306 // on inner boundary
1307 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) * dzinv;
1308 // printf(" - inner ndotd=%f (>0 ->0)\n",ndotd);
1309 if (ndotd > 0)
1310 return snext;
1311 done = kTRUE;
1312 }
1313 if (!done && safrmax < safz && safrmax < safphi) {
1314 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) * dzinv;
1315 // printf(" - outer ndotd=%f (<0 ->0)\n",ndotd);
1316 if (ndotd < 0)
1317 return snext;
1318 done = kTRUE;
1319 }
1320 if (!done && safz < safphi) {
1321 done = kTRUE;
1322 Int_t iplc = ipl;
1323 if (TMath::Abs(pt[2] - fZ[ipl]) > TMath::Abs(fZ[ipl + 1] - pt[2]))
1324 iplc++;
1325 if (iplc == 0 || iplc == fNz - 1) {
1326 if (pt[2] * dir[2] < 0)
1327 return snext;
1328 return TGeoShape::Big();
1329 } else {
1331 if (dir[2] > 0) {
1332 if (rproj < fRmin[iplc] && rproj > fRmin[iplc + 1])
1333 return snext;
1334 if (rproj > fRmax[iplc] && rproj < fRmax[iplc + 1])
1335 return snext;
1336 } else {
1337 if (rproj > fRmin[iplc] && rproj < fRmin[iplc + 1])
1338 return snext;
1339 if (rproj < fRmax[iplc] && rproj > fRmax[iplc + 1])
1340 return snext;
1341 }
1342 } else if (TGeoShape::IsSameWithinTolerance(fZ[iplc], fZ[iplc - 1])) {
1343 if (dir[2] > 0) {
1344 if (rproj < fRmin[iplc - 1] && rproj > fRmin[iplc])
1345 return snext;
1346 if (rproj > fRmax[iplc - 1] && rproj < fRmax[iplc])
1347 return snext;
1348 } else {
1349 if (rproj > fRmin[iplc - 1] && rproj < fRmin[iplc])
1350 return snext;
1351 if (rproj < fRmax[iplc - 1] && rproj > fRmax[iplc])
1352 return snext;
1353 }
1354 }
1355 }
1356 }
1357 if (!done) {
1358 // point on phi boundary
1359 onphi = kTRUE;
1360 }
1361 }
1362 }
1363 }
1364 }
1366 if (onphi) {
1367 if (!icrossed)
1368 return snext;
1369 if (iph[0] < 0 && sph[0] < TGeoShape::Tolerance())
1370 return (snext + sph[0]);
1371 if (iph[0] >= 0 && sph[0] > 1.E-8)
1372 return snext;
1373 }
1374 // Fire-up slice crossing algorithm
1375 if (SliceCrossing(pt, dir, icrossed, iph, sph, snewcross, stepmax)) {
1376 snext += snewcross;
1377 return snext;
1378 }
1379 return TGeoShape::Big();
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// compute closest distance from point px,py to each corner
1384
1386{
1387 Int_t n = fNedges + 1;
1388 const Int_t numPoints = 2 * n * fNz;
1389 return ShapeDistancetoPrimitive(numPoints, px, py);
1390}
1391
1392////////////////////////////////////////////////////////////////////////////////
1393/// Divide this polygone shape belonging to volume "voldiv" into ndiv volumes
1394/// called divname, from start position with the given step. Returns pointer
1395/// to created division cell volume in case of Z divisions. Phi divisions are
1396/// allowed only if nedges%ndiv=0 and create polygone "segments" with nedges/ndiv edges.
1397/// Z divisions can be performed if the divided range is in between two consecutive Z planes.
1398/// In case a wrong division axis is supplied, returns pointer to volume that was divided.
1399
1400TGeoVolume *
1402{
1403 // printf("Dividing %s : nz=%d nedges=%d phi1=%g dphi=%g (ndiv=%d iaxis=%d start=%g step=%g)\n",
1404 // voldiv->GetName(), fNz, fNedges, fPhi1, fDphi, ndiv, iaxis, start, step);
1405 TGeoShape *shape; //--- shape to be created
1406 TGeoVolume *vol; //--- division volume to be created
1407 TGeoVolumeMulti *vmulti; //--- generic divided volume
1408 TGeoPatternFinder *finder; //--- finder to be attached
1409 TString opt = ""; //--- option to be attached
1411 Double_t zmin = start;
1412 Double_t zmax = start + ndiv * step;
1413 Int_t isect = -1;
1414 Int_t is, id, ipl;
1415 switch (iaxis) {
1416 case 1: //--- R division
1417 Error("Divide", "makes no sense dividing a pgon on radius");
1418 return nullptr;
1419 case 2: //--- Phi division
1420 if (fNedges % ndiv) {
1421 Error("Divide", "ndiv should divide number of pgon edges");
1422 return nullptr;
1423 }
1424 nedges = fNedges / ndiv;
1425 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, start + ndiv * step);
1427 voldiv->SetFinder(finder);
1428 finder->SetDivIndex(voldiv->GetNdaughters());
1429 shape = new TGeoPgon(-step / 2, step, nedges, fNz);
1430 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1431 vmulti->AddVolume(vol);
1432 for (is = 0; is < fNz; is++)
1433 ((TGeoPgon *)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
1434 opt = "Phi";
1435 for (id = 0; id < ndiv; id++) {
1436 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
1437 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1438 }
1439 return vmulti;
1440 case 3: // --- Z division
1441 // find start plane
1442 for (ipl = 0; ipl < fNz - 1; ipl++) {
1443 if (start < fZ[ipl])
1444 continue;
1445 else {
1446 if ((start + ndiv * step) > fZ[ipl + 1])
1447 continue;
1448 }
1449 isect = ipl;
1450 zmin = fZ[isect];
1451 zmax = fZ[isect + 1];
1452 break;
1453 }
1454 if (isect < 0) {
1455 Error("Divide", "cannot divide pcon on Z if divided region is not between 2 consecutive planes");
1456 return nullptr;
1457 }
1458 finder = new TGeoPatternZ(voldiv, ndiv, start, start + ndiv * step);
1460 voldiv->SetFinder(finder);
1461 finder->SetDivIndex(voldiv->GetNdaughters());
1462 opt = "Z";
1463 for (id = 0; id < ndiv; id++) {
1464 Double_t z1 = start + id * step;
1465 Double_t z2 = start + (id + 1) * step;
1466 Double_t rmin1 = (fRmin[isect] * (zmax - z1) - fRmin[isect + 1] * (zmin - z1)) / (zmax - zmin);
1467 Double_t rmax1 = (fRmax[isect] * (zmax - z1) - fRmax[isect + 1] * (zmin - z1)) / (zmax - zmin);
1468 Double_t rmin2 = (fRmin[isect] * (zmax - z2) - fRmin[isect + 1] * (zmin - z2)) / (zmax - zmin);
1469 Double_t rmax2 = (fRmax[isect] * (zmax - z2) - fRmax[isect + 1] * (zmin - z2)) / (zmax - zmin);
1470 shape = new TGeoPgon(fPhi1, fDphi, nedges, 2);
1471 ((TGeoPgon *)shape)->DefineSection(0, -step / 2, rmin1, rmax1);
1472 ((TGeoPgon *)shape)->DefineSection(1, step / 2, rmin2, rmax2);
1473 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
1474 vmulti->AddVolume(vol);
1475 voldiv->AddNodeOffset(vol, id, start + id * step + step / 2, opt.Data());
1476 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1477 }
1478 return vmulti;
1479 default: Error("Divide", "Wrong axis type for division"); return nullptr;
1480 }
1481}
1482
1483////////////////////////////////////////////////////////////////////////////////
1484/// Fill vector param[4] with the bounding cylinder parameters. The order
1485/// is the following : Rmin, Rmax, Phi1, Phi2
1486
1488{
1489 param[0] = fRmin[0]; // Rmin
1490 param[1] = fRmax[0]; // Rmax
1491 for (Int_t i = 1; i < fNz; i++) {
1492 if (fRmin[i] < param[0])
1493 param[0] = fRmin[i];
1494 if (fRmax[i] > param[1])
1495 param[1] = fRmax[i];
1496 }
1498 param[1] /= TMath::Cos(0.5 * divphi * TMath::DegToRad());
1499 param[0] *= param[0];
1500 param[1] *= param[1];
1502 param[2] = 0.;
1503 param[3] = 360.;
1504 return;
1505 }
1506 param[2] = (fPhi1 < 0) ? (fPhi1 + 360.) : fPhi1; // Phi1
1507 param[3] = param[2] + fDphi; // Phi2
1508}
1509
1510////////////////////////////////////////////////////////////////////////////////
1511/// Inspect the PGON parameters.
1512
1514{
1515 printf("*** Shape %s: TGeoPgon ***\n", GetName());
1516 printf(" Nedges = %i\n", fNedges);
1518}
1519
1520////////////////////////////////////////////////////////////////////////////////
1521/// Creates a TBuffer3D describing *this* shape.
1522/// Coordinates are in local reference frame.
1523
1525{
1528
1529 if (nbPnts <= 0)
1530 return nullptr;
1531
1532 TBuffer3D *buff =
1534 if (buff) {
1535 SetPoints(buff->fPnts);
1537 }
1538
1539 return buff;
1540}
1541
1542////////////////////////////////////////////////////////////////////////////////
1543/// Fill TBuffer3D structure for segments and polygons.
1544
1546{
1547 if (!HasInsideSurface()) {
1549 return;
1550 }
1551
1552 Int_t i, j;
1553 const Int_t n = GetNedges() + 1;
1554 Int_t nz = GetNz();
1555 if (nz < 2)
1556 return;
1557 Int_t nbPnts = nz * 2 * n;
1558 if (nbPnts <= 0)
1559 return;
1560 Double_t dphi = GetDphi();
1562
1563 Int_t c = GetBasicColor();
1564
1565 Int_t indx = 0, indx2, k;
1566
1567 // inside & outside circles, number of segments: 2*nz*(n-1)
1568 // special case number of segments: 2*nz*n
1569 for (i = 0; i < nz * 2; i++) {
1570 indx2 = i * n;
1571 for (j = 1; j < n; j++) {
1572 buff.fSegs[indx++] = c;
1573 buff.fSegs[indx++] = indx2 + j - 1;
1574 buff.fSegs[indx++] = indx2 + j;
1575 }
1576 if (specialCase) {
1577 buff.fSegs[indx++] = c;
1578 buff.fSegs[indx++] = indx2 + j - 1;
1579 buff.fSegs[indx++] = indx2;
1580 }
1581 }
1582
1583 // bottom & top lines, number of segments: 2*n
1584 for (i = 0; i < 2; i++) {
1585 indx2 = i * (nz - 1) * 2 * n;
1586 for (j = 0; j < n; j++) {
1587 buff.fSegs[indx++] = c;
1588 buff.fSegs[indx++] = indx2 + j;
1589 buff.fSegs[indx++] = indx2 + n + j;
1590 }
1591 }
1592
1593 // inside & outside cylinders, number of segments: 2*(nz-1)*n
1594 for (i = 0; i < (nz - 1); i++) {
1595 // inside cylinder
1596 indx2 = i * n * 2;
1597 for (j = 0; j < n; j++) {
1598 buff.fSegs[indx++] = c + 2;
1599 buff.fSegs[indx++] = indx2 + j;
1600 buff.fSegs[indx++] = indx2 + n * 2 + j;
1601 }
1602 // outside cylinder
1603 indx2 = i * n * 2 + n;
1604 for (j = 0; j < n; j++) {
1605 buff.fSegs[indx++] = c + 3;
1606 buff.fSegs[indx++] = indx2 + j;
1607 buff.fSegs[indx++] = indx2 + n * 2 + j;
1608 }
1609 }
1610
1611 // left & right sections, number of segments: 2*(nz-2)
1612 // special case number of segments: 0
1613 if (!specialCase) {
1614 for (i = 1; i < (nz - 1); i++) {
1615 for (j = 0; j < 2; j++) {
1616 buff.fSegs[indx++] = c;
1617 buff.fSegs[indx++] = 2 * i * n + j * (n - 1);
1618 buff.fSegs[indx++] = (2 * i + 1) * n + j * (n - 1);
1619 }
1620 }
1621 }
1622
1623 Int_t m = n - 1 + (specialCase ? 1 : 0);
1624 indx = 0;
1625
1626 // bottom & top, number of polygons: 2*(n-1)
1627 // special case number of polygons: 2*n
1628 i = 0;
1629 for (j = 0; j < n - 1; j++) {
1630 buff.fPols[indx++] = c + 3;
1631 buff.fPols[indx++] = 4;
1632 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1633 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1634 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1635 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1636 }
1637 if (specialCase) {
1638 buff.fPols[indx++] = c + 3;
1639 buff.fPols[indx++] = 4;
1640 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1641 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1642 buff.fPols[indx++] = 2 * nz * m + i * n;
1643 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1644 }
1645 i = 1;
1646 for (j = 0; j < n - 1; j++) {
1647 buff.fPols[indx++] = c + 3;
1648 buff.fPols[indx++] = 4;
1649 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1650 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1651 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1652 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1653 }
1654 if (specialCase) {
1655 buff.fPols[indx++] = c + 3;
1656 buff.fPols[indx++] = 4;
1657 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1658 buff.fPols[indx++] = 2 * nz * m + i * n;
1659 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1660 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1661 }
1662
1663 // inside & outside, number of polygons: (nz-1)*2*(n-1)
1664 for (k = 0; k < (nz - 1); k++) {
1665 i = 0;
1666 for (j = 0; j < n - 1; j++) {
1667 buff.fPols[indx++] = c + i;
1668 buff.fPols[indx++] = 4;
1669 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1670 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1671 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1672 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1673 }
1674 if (specialCase) {
1675 buff.fPols[indx++] = c + i;
1676 buff.fPols[indx++] = 4;
1677 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1678 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1679 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1680 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1681 }
1682 i = 1;
1683 for (j = 0; j < n - 1; j++) {
1684 buff.fPols[indx++] = c + i;
1685 buff.fPols[indx++] = 4;
1686 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1687 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1688 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1689 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1690 }
1691 if (specialCase) {
1692 buff.fPols[indx++] = c + i;
1693 buff.fPols[indx++] = 4;
1694 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1695 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1696 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1697 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1698 }
1699 }
1700
1701 // left & right sections, number of polygons: 2*(nz-1)
1702 // special case number of polygons: 0
1703 if (!specialCase) {
1704 indx2 = nz * 2 * (n - 1);
1705 for (k = 0; k < (nz - 1); k++) {
1706 buff.fPols[indx++] = c + 2;
1707 buff.fPols[indx++] = 4;
1708 buff.fPols[indx++] = k == 0 ? indx2 : indx2 + 2 * nz * n + 2 * (k - 1);
1709 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n;
1710 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k;
1711 buff.fPols[indx++] = indx2 + (2 * k + 3) * n;
1712
1713 buff.fPols[indx++] = c + 2;
1714 buff.fPols[indx++] = 4;
1715 buff.fPols[indx++] = k == 0 ? indx2 + n - 1 : indx2 + 2 * nz * n + 2 * (k - 1) + 1; // a
1716 buff.fPols[indx++] = indx2 + (2 * k + 3) * n + n - 1; // d
1717 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k + 1; // c
1718 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n + n - 1; // b
1719 }
1720 buff.fPols[indx - 8] = indx2 + n;
1721 buff.fPols[indx - 2] = indx2 + 2 * n - 1;
1722 }
1723}
1724
1725////////////////////////////////////////////////////////////////////////////////
1726/// Fill TBuffer3D structure for segments and polygons, when no inner surface exists
1727
1729{
1730 const Int_t n = GetNedges() + 1;
1731 const Int_t nz = GetNz();
1732 const Int_t nbPnts = nz * n + 2;
1733
1734 if ((nz < 2) || (nbPnts <= 0) || (n < 2))
1735 return;
1736
1737 Int_t c = GetBasicColor();
1738
1739 Int_t indx = 0, indx1 = 0, indx2 = 0, i, j;
1740
1741 // outside circles, number of segments: nz*n
1742 for (i = 0; i < nz; i++) {
1743 indx2 = i * n;
1744 for (j = 1; j < n; j++) {
1745 buff.fSegs[indx++] = c;
1746 buff.fSegs[indx++] = indx2 + j - 1;
1747 buff.fSegs[indx++] = indx2 + j % (n - 1);
1748 }
1749 }
1750
1751 indx2 = 0;
1752 // bottom lines
1753 for (j = 0; j < n; j++) {
1754 buff.fSegs[indx++] = c;
1755 buff.fSegs[indx++] = indx2 + j % (n - 1);
1756 buff.fSegs[indx++] = nbPnts - 2;
1757 }
1758
1759 indx2 = (nz - 1) * n;
1760 // top lines
1761 for (j = 0; j < n; j++) {
1762 buff.fSegs[indx++] = c;
1763 buff.fSegs[indx++] = indx2 + j % (n - 1);
1764 buff.fSegs[indx++] = nbPnts - 1;
1765 }
1766
1767 // outside cylinders, number of segments: (nz-1)*n
1768 for (i = 0; i < (nz - 1); i++) {
1769 // outside cylinder
1770 indx2 = i * n;
1771 for (j = 0; j < n; j++) {
1772 buff.fSegs[indx++] = c;
1773 buff.fSegs[indx++] = indx2 + j % (n - 1);
1774 buff.fSegs[indx++] = indx2 + n + j % (n - 1);
1775 }
1776 }
1777
1778 indx = 0;
1779
1780 // bottom cap
1781 indx1 = 0; // start of first z layer
1782 indx2 = nz * (n - 1);
1783 for (j = 0; j < n - 1; j++) {
1784 buff.fPols[indx++] = c;
1785 buff.fPols[indx++] = 3;
1786 buff.fPols[indx++] = indx1 + j;
1787 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1788 buff.fPols[indx++] = indx2 + j;
1789 }
1790
1791 // top cap
1792 indx1 = (nz - 1) * (n - 1); // start last z layer
1793 indx2 = nz * (n - 1) + n;
1794 for (j = 0; j < n - 1; j++) {
1795 buff.fPols[indx++] = c;
1796 buff.fPols[indx++] = 3;
1797 buff.fPols[indx++] = indx1 + j; // last z layer
1798 buff.fPols[indx++] = indx2 + j;
1799 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1800 }
1801
1802 // outside, number of polygons: (nz-1)*(n-1)
1803 for (Int_t k = 0; k < (nz - 1); k++) {
1804 indx1 = k * (n - 1);
1805 indx2 = nz * (n - 1) + n * 2 + k * n;
1806 for (j = 0; j < n - 1; j++) {
1807 buff.fPols[indx++] = c;
1808 buff.fPols[indx++] = 4;
1809 buff.fPols[indx++] = indx1 + j;
1810 buff.fPols[indx++] = indx2 + j;
1811 buff.fPols[indx++] = indx1 + j + (n - 1);
1812 buff.fPols[indx++] = indx2 + (j + 1) % (n - 1);
1813 }
1814 }
1815}
1816
1817////////////////////////////////////////////////////////////////////////////////
1818/// Computes projected pgon radius (inner or outer) corresponding to a given Z
1819/// value. Fills corresponding coefficients of:
1820/// `Rpg(z) = a + b*z`
1821///
1822/// Note: ipl must be in range [0,fNz-2]
1823
1825{
1826 Double_t rpg;
1827 if (ipl < 0 || ipl > fNz - 2) {
1828 Fatal("Rpg", "Plane index parameter ipl=%i out of range\n", ipl);
1829 return 0;
1830 }
1831 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1832 if (dz < TGeoShape::Tolerance()) {
1833 // radius-changing region
1834 rpg = (inner) ? TMath::Min(fRmin[ipl], fRmin[ipl + 1]) : TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
1835 a = rpg;
1836 b = 0.;
1837 return rpg;
1838 }
1839 Double_t r1 = 0, r2 = 0;
1840 if (inner) {
1841 r1 = fRmin[ipl];
1842 r2 = fRmin[ipl + 1];
1843 } else {
1844 r1 = fRmax[ipl];
1845 r2 = fRmax[ipl + 1];
1846 }
1847 Double_t dzinv = 1. / dz;
1848 a = (r1 * fZ[ipl + 1] - r2 * fZ[ipl]) * dzinv;
1849 b = (r2 - r1) * dzinv;
1850 return (a + b * z);
1851}
1852
1853////////////////////////////////////////////////////////////////////////////////
1854/// Computes projected distance at a given Z for a given ray inside a given sector
1855/// and fills coefficients:
1856/// `Rproj = a + b*z`
1857
1859 Double_t &a, Double_t &b) const
1860{
1861 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1862 a = b = TGeoShape::Big();
1863 return TGeoShape::Big();
1864 }
1865 Double_t invdirz = 1. / dir[2];
1866 a = ((point[0] * dir[2] - point[2] * dir[0]) * cphi + (point[1] * dir[2] - point[2] * dir[1]) * sphi) * invdirz;
1867 b = (dir[0] * cphi + dir[1] * sphi) * invdirz;
1868 return (a + b * z);
1869}
1870
1871////////////////////////////////////////////////////////////////////////////////
1872/// Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
1873
1875 Double_t safmin) const
1876{
1877 Double_t saf[3];
1878 Double_t safe;
1879 Int_t i;
1880 Double_t r, rpgon, ta, calf;
1881 if (ipl < 0 || ipl > fNz - 2)
1882 return (safmin + 1.); // error in input plane
1883 // Get info about segment.
1884 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1885 if (dz < 1E-9)
1886 return 1E9; // skip radius-changing segment
1887 Double_t znew = point[2] - 0.5 * (fZ[ipl] + fZ[ipl + 1]);
1888 saf[0] = 0.5 * dz - TMath::Abs(znew);
1889 if (-saf[0] > safmin)
1890 return TGeoShape::Big(); // means: stop checking further segments
1893 Double_t rmin2 = fRmin[ipl + 1];
1894 Double_t rmax2 = fRmax[ipl + 1];
1896 if (iphi < 0) {
1897 Double_t f = 1. / TMath::Cos(0.5 * divphi * TMath::DegToRad());
1898 rmax1 *= f;
1899 rmax2 *= f;
1900 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1901 Double_t ro1 = 0.5 * (rmin1 + rmin2);
1902 Double_t tg1 = (rmin2 - rmin1) / dz;
1903 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
1904 Double_t ro2 = 0.5 * (rmax1 + rmax2);
1905 Double_t tg2 = (rmax2 - rmax1) / dz;
1906 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
1907 Double_t rin = tg1 * znew + ro1;
1908 Double_t rout = tg2 * znew + ro2;
1909 saf[1] = (ro1 > 0) ? ((r - rin) * cr1) : TGeoShape::Big();
1910 saf[2] = (rout - r) * cr2;
1911 for (i = 0; i < 3; i++)
1912 saf[i] = -saf[i];
1913 safe = saf[TMath::LocMax(3, saf)];
1915 if (safe < 0)
1916 safe = 0;
1917 return safe;
1918 }
1919 Double_t ph0 = (fPhi1 + divphi * (iphi + 0.5)) * TMath::DegToRad();
1920 r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
1921 if (rmin1 + rmin2 > 1E-10) {
1922 ta = (rmin2 - rmin1) / dz;
1923 calf = 1. / TMath::Sqrt(1 + ta * ta);
1924 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
1925 saf[1] = (r - rpgon) * calf;
1926 } else {
1927 saf[1] = TGeoShape::Big();
1928 }
1929 ta = (rmax2 - rmax1) / dz;
1930 calf = 1. / TMath::Sqrt(1 + ta * ta);
1931 rpgon = rmax1 + (point[2] - fZ[ipl]) * ta;
1932 saf[2] = (rpgon - r) * calf;
1933 if (in) {
1934 safe = saf[TMath::LocMin(3, saf)];
1936 } else {
1937 for (i = 0; i < 3; i++)
1938 saf[i] = -saf[i];
1939 safe = saf[TMath::LocMax(3, saf)];
1941 }
1942 if (safe < 0)
1943 safe = 0;
1944 return safe;
1945}
1946
1947////////////////////////////////////////////////////////////////////////////////
1948/// computes the closest distance from given point to this shape, according
1949/// to option. The matching point on the shape is stored in spoint.
1950
1952{
1954 Double_t dz;
1955 Int_t ipl, iplane, iphi;
1956 LocatePhi(point, iphi);
1957 safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi1 + fDphi);
1958 if (in) {
1959 //---> point is inside pgon
1960 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1961 if (ipl == (fNz - 1))
1962 return 0; // point on last Z boundary
1963 if (ipl < 0)
1964 return 0; // point on first Z boundary
1965 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1966 if (dz < 1E-8)
1967 return 0;
1968 // Check safety for current segment
1969 safmin = SafetyToSegment(point, ipl, iphi, in, safphi);
1970 if (safmin > 1E10) {
1971 // something went wrong - point is not inside current segment
1972 return TGeoShape::Big();
1973 }
1974 if (safmin < 1E-6)
1975 return TMath::Abs(safmin); // point on radius-changing plane
1976 // check increasing iplanes
1977 iplane = ipl + 1;
1978 saftmp = 0.;
1979 while ((iplane < fNz - 1) && saftmp < 1E10) {
1981 if (saftmp < safmin)
1982 safmin = saftmp;
1983 iplane++;
1984 }
1985 // now decreasing nplanes
1986 iplane = ipl - 1;
1987 saftmp = 0.;
1988 while ((iplane >= 0) && saftmp < 1E10) {
1990 if (saftmp < safmin)
1991 safmin = saftmp;
1992 iplane--;
1993 }
1994 return safmin;
1995 }
1996 //---> point is outside pgon
1997 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1998 if (ipl < 0)
1999 ipl = 0;
2000 else if (ipl == fNz - 1)
2001 ipl = fNz - 2;
2002 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
2003 if (dz < 1E-8) {
2004 ipl++;
2005 if (ipl > fNz - 2)
2006 return 0.; // invalid last section
2007 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
2008 }
2009 // Check safety for current segment
2011 if (safmin < 1E-6)
2012 return TMath::Abs(safmin); // point on radius-changing plane
2013 // check increasing iplanes
2014 iplane = ipl + 1;
2015 saftmp = 0.;
2016 while ((iplane < fNz - 1) && saftmp < 1E10) {
2018 if (saftmp < safmin)
2019 safmin = saftmp;
2020 iplane++;
2021 }
2022 // now decreasing nplanes
2023 iplane = ipl - 1;
2024 saftmp = 0.;
2025 while ((iplane >= 0) && saftmp < 1E10) {
2027 if (saftmp < safmin)
2028 safmin = saftmp;
2029 iplane--;
2030 }
2031 return safmin;
2032}
2033
2034////////////////////////////////////////////////////////////////////////////////
2035/// Save a primitive as a C++ statement(s) on output stream "out".
2036
2037void TGeoPgon::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
2038{
2040 return;
2041 out << " // Shape: " << GetName() << " type: " << ClassName() << std::endl;
2042 out << " phi1 = " << fPhi1 << ";" << std::endl;
2043 out << " dphi = " << fDphi << ";" << std::endl;
2044 out << " nedges = " << fNedges << ";" << std::endl;
2045 out << " nz = " << fNz << ";" << std::endl;
2046 out << " auto " << GetPointerName() << " = new TGeoPgon(\"" << GetName() << "\", phi1, dphi, nedges, nz);"
2047 << std::endl;
2048 for (Int_t i = 0; i < fNz; i++) {
2049 out << " z = " << fZ[i] << ";" << std::endl;
2050 out << " rmin = " << fRmin[i] << ";" << std::endl;
2051 out << " rmax = " << fRmax[i] << ";" << std::endl;
2052 out << " " << GetPointerName() << "->DefineSection(" << i << ", z, rmin, rmax);" << std::endl;
2053 }
2055}
2056
2057////////////////////////////////////////////////////////////////////////////////
2058/// Set PGON dimensions starting from an array.
2059
2061{
2062 fPhi1 = param[0];
2063 fDphi = param[1];
2064 fNedges = (Int_t)param[2];
2065 fNz = (Int_t)param[3];
2066 if (fNz < 2) {
2067 Error("SetDimensions", "Pgon %s: Number of Z sections must be > 2", GetName());
2068 return;
2069 }
2070 if (fRmin)
2071 delete[] fRmin;
2072 if (fRmax)
2073 delete[] fRmax;
2074 if (fZ)
2075 delete[] fZ;
2076 fRmin = new Double_t[fNz];
2077 fRmax = new Double_t[fNz];
2078 fZ = new Double_t[fNz];
2079 memset(fRmin, 0, fNz * sizeof(Double_t));
2080 memset(fRmax, 0, fNz * sizeof(Double_t));
2081 memset(fZ, 0, fNz * sizeof(Double_t));
2082 for (Int_t i = 0; i < fNz; i++)
2083 DefineSection(i, param[4 + 3 * i], param[5 + 3 * i], param[6 + 3 * i]);
2084}
2085
2086////////////////////////////////////////////////////////////////////////////////
2087/// create polygone mesh points
2088
2090{
2091 Double_t phi, dphi;
2092 Int_t n = fNedges + 1;
2093 dphi = fDphi / (n - 1);
2094 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
2095 Int_t i, j;
2096 Int_t indx = 0;
2097
2099
2100 if (points) {
2101 for (i = 0; i < GetNz(); i++) {
2102 if (hasInside)
2103 for (j = 0; j < n; j++) {
2104 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2105 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
2106 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
2107 points[indx++] = fZ[i];
2108 }
2109 for (j = 0; j < n; j++) {
2110 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2111 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
2112 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
2113 points[indx++] = fZ[i];
2114 }
2115 }
2116
2117 if (!hasInside) {
2118 points[indx++] = 0;
2119 points[indx++] = 0;
2120 points[indx++] = fZ[0];
2121
2122 points[indx++] = 0;
2123 points[indx++] = 0;
2124 points[indx++] = fZ[GetNz() - 1];
2125 }
2126 }
2127}
2128
2129////////////////////////////////////////////////////////////////////////////////
2130/// create polygone mesh points
2131
2133{
2134 Double_t phi, dphi;
2135 Int_t n = fNedges + 1;
2136 dphi = fDphi / (n - 1);
2137 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
2138 Int_t i, j;
2139 Int_t indx = 0;
2140
2142
2143 if (points) {
2144 for (i = 0; i < fNz; i++) {
2145 if (hasInside)
2146 for (j = 0; j < n; j++) {
2147 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2148 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
2149 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
2150 points[indx++] = fZ[i];
2151 }
2152 for (j = 0; j < n; j++) {
2153 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
2154 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
2155 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
2156 points[indx++] = fZ[i];
2157 }
2158 }
2159
2160 if (!hasInside) {
2161 points[indx++] = 0;
2162 points[indx++] = 0;
2163 points[indx++] = fZ[0];
2164
2165 points[indx++] = 0;
2166 points[indx++] = 0;
2167 points[indx++] = fZ[GetNz() - 1];
2168 }
2169 }
2170}
2171
2172////////////////////////////////////////////////////////////////////////////////
2173/// Returns numbers of vertices, segments and polygons composing the shape mesh.
2174
2176{
2177 nvert = nsegs = npols = 0;
2178
2179 Int_t n = GetNedges() + 1;
2180 Int_t nz = GetNz();
2181
2182 if (nz < 2)
2183 return;
2184
2185 if (HasInsideSurface()) {
2187 nvert = nz * 2 * n;
2188 nsegs = 4 * (nz * n - 1 + (specialCase ? 1 : 0));
2189 npols = 2 * (nz * n - 1 + (specialCase ? 1 : 0));
2190 } else {
2191 nvert = nz * n + 2;
2192 nsegs = nz * (n - 1) + n * 2 + (nz - 1) * n;
2193 npols = 2 * (n - 1) + (nz - 1) * (n - 1);
2194 }
2195}
2196
2197////////////////////////////////////////////////////////////////////////////////
2198/// Return number of vertices of the mesh representation
2199
2201{
2203
2205
2206 return nvert;
2207}
2208
2209////////////////////////////////////////////////////////////////////////////////
2210/// fill size of this 3-D object
2211
2212void TGeoPgon::Sizeof3D() const {}
2213
2214////////////////////////////////////////////////////////////////////////////////
2215/// Fills a static 3D buffer and returns a reference.
2216
2218{
2219 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
2220
2222
2226 if (nbPnts > 0) {
2227 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
2229 }
2230 }
2231 }
2232 // TODO: Push down to TGeoShape?? Would have to do raw sizes set first..
2233 // can rest of TGeoShape be deferred until after this?
2235 SetPoints(buffer.fPnts);
2236 if (!buffer.fLocalFrame) {
2237 TransformPoints(buffer.fPnts, buffer.NbPnts());
2238 }
2239
2240 SetSegsAndPols(buffer);
2242 }
2243
2244 return buffer;
2245}
2246
2247////////////////////////////////////////////////////////////////////////////////
2248/// Check the inside status for each of the points in the array.
2249/// Input: Array of point coordinates + vector size
2250/// Output: Array of Booleans for the inside of each point
2251
2253{
2254 for (Int_t i = 0; i < vecsize; i++)
2255 inside[i] = Contains(&points[3 * i]);
2256}
2257
2258////////////////////////////////////////////////////////////////////////////////
2259/// Compute the normal for an array o points so that norm.dot.dir is positive
2260/// Input: Arrays of point coordinates and directions + vector size
2261/// Output: Array of normal directions
2262
2264{
2265 for (Int_t i = 0; i < vecsize; i++)
2266 ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
2267}
2268
2269////////////////////////////////////////////////////////////////////////////////
2270/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2271
2273 Double_t *step) const
2274{
2275 for (Int_t i = 0; i < vecsize; i++)
2276 dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2277}
2278
2279////////////////////////////////////////////////////////////////////////////////
2280/// Compute distance from array of input points having directions specified by dirs. Store output in dists
2281
2283 Double_t *step) const
2284{
2285 for (Int_t i = 0; i < vecsize; i++)
2286 dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2287}
2288
2289////////////////////////////////////////////////////////////////////////////////
2290/// Compute safe distance from each of the points in the input array.
2291/// Input: Array of point coordinates, array of statuses for these points, size of the arrays
2292/// Output: Safety values
2293
2295{
2296 for (Int_t i = 0; i < vecsize; i++)
2297 safe[i] = Safety(&points[3 * i], inside[i]);
2298}
#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:364
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:630
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:943
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:709
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:532
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:799
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:422
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:545
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:137
const char * Data() const
Definition TString.h:385
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