68 TGeoPgon::ThreadData_t::ThreadData_t()
69 : fIntBuffer(0), fDblBuffer(0)
76 TGeoPgon::ThreadData_t::~ThreadData_t()
84 TGeoPgon::ThreadData_t &TGeoPgon::GetThreadData()
const
86 Int_t tid = TGeoManager::ThreadId();
87 return *fThreadData[tid];
92 void TGeoPgon::ClearThreadData()
const
94 std::lock_guard<std::mutex> guard(fMutex);
95 std::vector<ThreadData_t *>::iterator i = fThreadData.begin();
96 while (i != fThreadData.end()) {
107 void TGeoPgon::CreateThreadData(Int_t nthreads)
109 if (fThreadSize) ClearThreadData();
110 std::lock_guard<std::mutex> guard(fMutex);
111 fThreadData.resize(nthreads);
112 fThreadSize = nthreads;
113 for (Int_t tid = 0; tid < nthreads; tid++) {
114 if (fThreadData[tid] == 0) {
115 fThreadData[tid] =
new ThreadData_t;
116 fThreadData[tid]->fIntBuffer =
new Int_t[fNedges + 10];
117 fThreadData[tid]->fDblBuffer =
new Double_t[fNedges + 10];
127 SetShapeBit(TGeoShape::kGeoPgon);
135 TGeoPgon::TGeoPgon(Double_t phi, Double_t dphi, Int_t nedges, Int_t nz) : TGeoPcon(phi, dphi, nz)
137 SetShapeBit(TGeoShape::kGeoPgon);
146 TGeoPgon::TGeoPgon(
const char *name, Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
147 : TGeoPcon(name, phi, dphi, nz)
149 SetShapeBit(TGeoShape::kGeoPgon);
166 TGeoPgon::TGeoPgon(Double_t *param) : TGeoPcon()
168 SetShapeBit(TGeoShape::kGeoPgon);
169 SetDimensions(param);
178 TGeoPgon::~TGeoPgon()
186 Double_t TGeoPgon::Capacity()
const
189 Double_t rmin1, rmax1, rmin2, rmax2, dphi, dz;
190 Double_t capacity = 0.;
191 dphi = fDphi / fNedges;
192 Double_t tphi2 = TMath::Tan(0.5 * dphi * TMath::DegToRad());
193 for (ipl = 0; ipl < fNz - 1; ipl++) {
194 dz = fZ[ipl + 1] - fZ[ipl];
195 if (dz < TGeoShape::Tolerance())
continue;
198 rmin2 = fRmin[ipl + 1];
199 rmax2 = fRmax[ipl + 1];
200 capacity += fNedges * (tphi2 / 3.) * dz *
201 (rmax1 * rmax1 + rmax1 * rmax2 + rmax2 * rmax2 - rmin1 * rmin1 - rmin1 * rmin2 - rmin2 * rmin2);
210 void TGeoPgon::ComputeBBox()
212 for (Int_t isec = 0; isec < fNz - 1; isec++) {
213 if (fZ[isec] > fZ[isec + 1]) {
215 Fatal(
"ComputeBBox",
"Wrong section order");
219 if (TMath::Abs(fZ[1] - fZ[0]) < TGeoShape::Tolerance() ||
220 TMath::Abs(fZ[fNz - 1] - fZ[fNz - 2]) < TGeoShape::Tolerance()) {
222 Fatal(
"ComputeBBox",
"Shape %s at index %d: Not allowed first two or last two sections at same Z", GetName(),
223 gGeoManager->GetListOfShapes()->IndexOf(
this));
225 Double_t zmin = TMath::Min(fZ[0], fZ[fNz - 1]);
226 Double_t zmax = TMath::Max(fZ[0], fZ[fNz - 1]);
229 Double_t divphi = fDphi / fNedges;
231 rmin = fRmin[TMath::LocMin(fNz, fRmin)];
232 rmax = fRmax[TMath::LocMax(fNz, fRmax)];
233 rmax = rmax / TMath::Cos(0.5 * divphi * TMath::DegToRad());
234 Double_t phi1 = fPhi1;
235 Double_t phi2 = phi1 + fDphi;
239 xc[0] = rmax * TMath::Cos(phi1 * TMath::DegToRad());
240 yc[0] = rmax * TMath::Sin(phi1 * TMath::DegToRad());
241 xc[1] = rmax * TMath::Cos(phi2 * TMath::DegToRad());
242 yc[1] = rmax * TMath::Sin(phi2 * TMath::DegToRad());
243 xc[2] = rmin * TMath::Cos(phi1 * TMath::DegToRad());
244 yc[2] = rmin * TMath::Sin(phi1 * TMath::DegToRad());
245 xc[3] = rmin * TMath::Cos(phi2 * TMath::DegToRad());
246 yc[3] = rmin * TMath::Sin(phi2 * TMath::DegToRad());
248 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
249 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
250 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
251 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
253 Double_t ddp = -phi1;
254 if (ddp < 0) ddp += 360;
255 if (ddp <= fDphi) xmax = rmax;
257 if (ddp < 0) ddp += 360;
258 if (ddp <= fDphi) ymax = rmax;
260 if (ddp < 0) ddp += 360;
261 if (ddp <= fDphi) xmin = -rmax;
263 if (ddp < 0) ddp += 360;
264 if (ddp <= fDphi) ymin = -rmax;
265 fOrigin[0] = 0.5 * (xmax + xmin);
266 fOrigin[1] = 0.5 * (ymax + ymin);
267 fOrigin[2] = 0.5 * (zmax + zmin);
268 fDX = 0.5 * (xmax - xmin);
269 fDY = 0.5 * (ymax - ymin);
270 fDZ = 0.5 * (zmax - zmin);
271 SetShapeBit(kGeoClosedShape);
277 void TGeoPgon::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
279 memset(norm, 0, 3 *
sizeof(Double_t));
280 Double_t phi1 = 0, phi2 = 0, c1 = 0, s1 = 0, c2 = 0, s2 = 0;
281 Double_t dz, rmin1, rmin2;
282 Bool_t is_seg = (fDphi < 360) ? kTRUE : kFALSE;
285 if (phi1 < 0) phi1 += 360;
287 phi1 *= TMath::DegToRad();
288 phi2 *= TMath::DegToRad();
289 c1 = TMath::Cos(phi1);
290 s1 = TMath::Sin(phi1);
291 c2 = TMath::Cos(phi2);
292 s2 = TMath::Sin(phi2);
293 if (TGeoShape::IsCloseToPhi(1E-5, point, c1, s1, c2, s2)) {
294 TGeoShape::NormalPhi(point, dir, norm, c1, s1, c2, s2);
299 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
300 if (ipl == (fNz - 1) || ipl < 0) {
302 norm[2] = TMath::Sign(1., dir[2]);
305 Int_t iplclose = ipl;
306 if ((fZ[ipl + 1] - point[2]) < (point[2] - fZ[ipl])) iplclose++;
307 dz = TMath::Abs(fZ[iplclose] - point[2]);
309 Double_t divphi = fDphi / fNedges;
310 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
311 while (phi < fPhi1) phi += 360.;
312 Double_t ddp = phi - fPhi1;
313 Int_t ipsec = Int_t(ddp / divphi);
314 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
316 Double_t r, rsum, rpgon, ta, calf;
317 r = TMath::Abs(point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0));
319 if (iplclose == 0 || iplclose == (fNz - 1)) {
320 norm[2] = TMath::Sign(1., dir[2]);
323 if (iplclose == ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
324 if (r < TMath::Max(fRmin[ipl], fRmin[ipl - 1]) || r > TMath::Min(fRmax[ipl], fRmax[ipl - 1])) {
325 norm[2] = TMath::Sign(1., dir[2]);
329 if (TGeoShape::IsSameWithinTolerance(fZ[iplclose], fZ[iplclose + 1])) {
330 if (r < TMath::Max(fRmin[iplclose], fRmin[iplclose + 1]) ||
331 r > TMath::Min(fRmax[iplclose], fRmax[iplclose + 1])) {
332 norm[2] = TMath::Sign(1., dir[2]);
339 dz = fZ[ipl + 1] - fZ[ipl];
341 rmin2 = fRmin[ipl + 1];
342 rsum = rmin1 + rmin2;
343 Double_t safe = TGeoShape::Big();
345 ta = (rmin2 - rmin1) / dz;
346 calf = 1. / TMath::Sqrt(1 + ta * ta);
347 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
348 safe = TMath::Abs(r - rpgon);
349 norm[0] = calf * TMath::Cos(ph0);
350 norm[1] = calf * TMath::Sin(ph0);
351 norm[2] = -calf * ta;
353 ta = (fRmax[ipl + 1] - fRmax[ipl]) / dz;
354 calf = 1. / TMath::Sqrt(1 + ta * ta);
355 rpgon = fRmax[ipl] + (point[2] - fZ[ipl]) * ta;
356 if (safe > TMath::Abs(rpgon - r)) {
357 norm[0] = calf * TMath::Cos(ph0);
358 norm[1] = calf * TMath::Sin(ph0);
359 norm[2] = -calf * ta;
361 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
372 Bool_t TGeoPgon::Contains(
const Double_t *point)
const
374 if (point[2] < fZ[0])
return kFALSE;
375 if (point[2] > fZ[fNz - 1])
return kFALSE;
376 Double_t divphi = fDphi / fNedges;
378 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
379 while (phi < fPhi1) phi += 360.0;
380 Double_t ddp = phi - fPhi1;
381 if (ddp > fDphi)
return kFALSE;
383 Int_t ipsec = TMath::Min(Int_t(ddp / divphi), fNedges - 1);
384 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
386 Double_t r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
388 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
390 if (r < fRmin[iz])
return kFALSE;
391 if (r > fRmax[iz])
return kFALSE;
394 Double_t dz = fZ[iz + 1] - fZ[iz];
398 rmin = TMath::Min(fRmin[iz], fRmin[iz + 1]);
399 rmax = TMath::Max(fRmax[iz], fRmax[iz + 1]);
400 if (r < rmin)
return kFALSE;
401 if (r > rmax)
return kFALSE;
405 Double_t dzrat = (point[2] - fZ[iz]) / dz;
406 rmin = fRmin[iz] + dzrat * (fRmin[iz + 1] - fRmin[iz]);
408 if (r < rmin)
return kFALSE;
409 rmax = fRmax[iz] + dzrat * (fRmax[iz + 1] - fRmax[iz]);
410 if (r > rmax)
return kFALSE;
419 Double_t TGeoPgon::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step,
420 Double_t *safe)
const
422 if (iact < 3 && safe) {
423 *safe = Safety(point, kTRUE);
424 if (iact == 0)
return TGeoShape::Big();
425 if (iact == 1 && step < *safe)
return TGeoShape::Big();
429 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
430 if (ipl == fNz - 1) {
431 if (dir[2] >= 0)
return 0.;
436 if (dir[2] <= 0)
return 0.;
439 Double_t stepmax = step;
440 if (!fThreadSize) ((TGeoPgon *)
this)->CreateThreadData(1);
441 ThreadData_t &td = GetThreadData();
442 Double_t *sph = td.fDblBuffer;
443 Int_t *iph = td.fIntBuffer;
445 LocatePhi(point, ipsec);
448 Double_t phi1 = fPhi1 * TMath::DegToRad();
449 Double_t phi2 = (fPhi1 + fDphi) * TMath::DegToRad();
450 if ((point[0] * dir[1] - point[1] * dir[0]) > 0) {
452 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) <
453 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
462 if ((point[0] * TMath::Cos(phi1) + point[1] * TMath::Sin(phi1)) >
463 (point[0] * TMath::Cos(phi2) + point[1] * TMath::Sin(phi2))) {
473 if (TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
476 if (fNz > 3 && ipl >= 0 && ipl < fNz - 3 && TGeoShape::IsSameWithinTolerance(fZ[ipl + 1], fZ[ipl + 2]) &&
477 TMath::Abs(point[2] - fZ[ipl + 1]) < 1.E-8) {
480 if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1]) &&
481 TMath::Abs(point[2] - fZ[ipl]) < 1.E-8)
487 Double_t divphi = fDphi / fNedges;
488 Double_t phi = (fPhi1 + (ipsec + 0.5) * divphi) * TMath::DegToRad();
489 Double_t cphi = TMath::Cos(phi);
490 Double_t sphi = TMath::Sin(phi);
491 Double_t rproj = point[0] * cphi + point[1] * sphi;
494 if (rproj > fRmin[ipln] && rproj < fRmin[ipln + 1])
return 0.0;
495 if (rproj < fRmax[ipln] && rproj > fRmax[ipln + 1])
return 0.0;
498 if (rproj < fRmin[ipln] && rproj > fRmin[ipln + 1])
return 0.0;
499 if (rproj > fRmax[ipln] && rproj < fRmax[ipln + 1])
return 0.0;
504 icrossed = GetPhiCrossList(point, dir, ipsec, sph, iph, stepmax);
506 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
507 if (SliceCrossingInZ(point, dir, icrossed, iph, sph, snext, stepmax))
return snext;
508 if (snext > TGeoShape::Tolerance())
return TGeoShape::Big();
511 if (SliceCrossingIn(point, dir, ipl, icrossed, iph, sph, snext, stepmax))
return snext;
512 if (snext > TGeoShape::Tolerance())
return TGeoShape::Big();
519 void TGeoPgon::LocatePhi(
const Double_t *point, Int_t &ipsec)
const
521 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
522 while (phi < fPhi1) phi += 360.;
523 ipsec = Int_t(fNedges * (phi - fPhi1) / fDphi);
524 if (ipsec > fNedges - 1) ipsec = -1;
530 Int_t TGeoPgon::GetPhiCrossList(
const Double_t *point,
const Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi,
531 Double_t stepmax)
const
533 Double_t rxy, phi, cph, sph;
535 if ((1. - TMath::Abs(dir[2])) < 1E-8) {
541 Bool_t shootorig = (TMath::Abs(point[0] * dir[1] - point[1] * dir[0]) < 1E-8) ? kTRUE : kFALSE;
542 Double_t divphi = fDphi / fNedges;
544 Double_t rdotn = point[0] * dir[0] + point[1] * dir[1];
550 sphi[0] = TMath::Sqrt((point[0] * point[0] + point[1] * point[1]) / (1. - dir[2] * dir[2]));
552 if (sphi[0] > stepmax) {
556 phi = TMath::ATan2(dir[1], dir[0]) * TMath::RadToDeg();
557 while (phi < fPhi1) phi += 360.;
558 istart = Int_t((phi - fPhi1) / divphi);
559 if (istart > fNedges - 1) istart = -1;
564 Int_t incsec = Int_t(TMath::Sign(1., point[0] * dir[1] - point[1] * dir[0]));
567 ist = (incsec > 0) ? 0 : fNedges;
569 ist = (incsec > 0) ? (istart + 1) : istart;
570 Bool_t crossing = kTRUE;
571 Bool_t gapdone = kFALSE;
572 divphi *= TMath::DegToRad();
573 Double_t phi1 = fPhi1 * TMath::DegToRad();
575 if (istart < 0) gapdone = kTRUE;
576 phi = phi1 + ist * divphi;
577 cph = TMath::Cos(phi);
578 sph = TMath::Sin(phi);
579 crossing = IsCrossingSemiplane(point, dir, cph, sph, sphi[icrossed], rxy);
580 if (!crossing) sphi[icrossed] = stepmax;
581 iphi[icrossed++] = istart;
583 if (sphi[icrossed - 1] > stepmax) {
584 sphi[icrossed - 1] = stepmax;
588 istart = (incsec > 0) ? 0 : (fNedges - 1);
591 if (istart > fNedges - 1)
592 istart = (fDphi < 360.) ? (-1) : 0;
593 else if (istart < 0 && TGeoShape::IsSameWithinTolerance(fDphi, 360))
594 istart = fNedges - 1;
597 if (gapdone)
return icrossed;
598 ist = (incsec > 0) ? 0 : fNedges;
600 ist = (incsec > 0) ? (istart + 1) : istart;
610 Bool_t TGeoPgon::SliceCrossingInZ(
const Double_t *point,
const Double_t *dir, Int_t nphi, Int_t *iphi,
611 Double_t *stepphi, Double_t &snext, Double_t stepmax)
const
614 if (!nphi)
return kFALSE;
619 if (iphi[0] < 0 && nphi == 1)
return kFALSE;
621 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
622 if (ipl < 0 || ipl == fNz - 1)
return kFALSE;
623 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
624 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
625 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
626 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
627 }
else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
628 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
629 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
635 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
636 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
639 Double_t divphi = TMath::DegToRad() * fDphi / fNedges;
640 Double_t rproj, ndot, dist;
641 Double_t phi1 = fPhi1 * TMath::DegToRad();
642 Double_t cosph, sinph;
643 Double_t snextphi = 0.;
646 memcpy(pt, point, 3 *
sizeof(Double_t));
647 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
648 if (step > stepmax) {
652 if (iphi[iphcrt] < 0) {
657 snextphi = stepphi[iphcrt];
658 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
659 cosph = TMath::Cos(phi);
660 sinph = TMath::Sin(phi);
661 rproj = pt[0] * cosph + pt[1] * sinph;
662 dist = TGeoShape::Big();
663 ndot = dir[0] * cosph + dir[1] * sinph;
664 if (!TGeoShape::IsSameWithinTolerance(ndot, 0)) {
665 dist = (ndot > 0) ? ((rmax - rproj) / ndot) : ((rmin - rproj) / ndot);
666 if (dist < 0) dist = 0.;
668 if (dist < (snextphi - step)) {
670 if (snext < stepmax)
return kTRUE;
674 for (i = 0; i < 3; i++) pt[i] = point[i] + step * dir[i];
683 Bool_t TGeoPgon::SliceCrossingZ(
const Double_t *point,
const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi,
684 Double_t &snext, Double_t stepmax)
const
686 if (!nphi)
return kFALSE;
691 if (iphi[0] < 0 && nphi == 1)
return kFALSE;
693 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
694 if (ipl < 0 || ipl == fNz - 1)
return kFALSE;
695 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
696 if (ipl < fNz - 2 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) {
697 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
698 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
699 }
else if (ipl > 1 && TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl - 1])) {
700 rmin = TMath::Min(fRmin[ipl], fRmin[ipl + 1]);
701 rmax = TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
707 rmin = Rpg(point[2], ipl, kTRUE, apg, bpg);
708 rmax = Rpg(point[2], ipl, kFALSE, apg, bpg);
711 Double_t divphi = TMath::DegToRad() * fDphi / fNedges;
712 Double_t rproj, ndot, dist;
713 Double_t phi1 = fPhi1 * TMath::DegToRad();
714 Double_t cosph, sinph;
715 Double_t snextphi = 0.;
718 memcpy(pt, point, 3 *
sizeof(Double_t));
719 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
720 if (step > stepmax)
return kFALSE;
721 snextphi = stepphi[iphcrt];
722 if (iphi[iphcrt] < 0) {
723 if (iphcrt == nphi - 1)
return kFALSE;
724 if (snextphi > stepmax)
return kFALSE;
725 for (i = 0; i < 3; i++) pt[i] = point[i] + snextphi * dir[i];
726 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
727 cosph = TMath::Cos(phi);
728 sinph = TMath::Sin(phi);
729 rproj = pt[0] * cosph + pt[1] * sinph;
730 if (rproj < rmin || rproj > rmax) {
738 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
739 cosph = TMath::Cos(phi);
740 sinph = TMath::Sin(phi);
741 rproj = pt[0] * cosph + pt[1] * sinph;
742 dist = TGeoShape::Big();
743 ndot = dir[0] * cosph + dir[1] * sinph;
745 dist = (ndot > 0) ? ((rmin - rproj) / ndot) : TGeoShape::Big();
747 dist = (ndot < 0) ? ((rmax - rproj) / ndot) : TGeoShape::Big();
751 if (snext < stepmax)
return kTRUE;
754 for (i = 0; i < 3; i++) pt[i] = point[i] + step * dir[i];
764 Bool_t TGeoPgon::SliceCrossingIn(
const Double_t *point,
const Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi,
765 Double_t *stepphi, Double_t &snext, Double_t stepmax)
const
768 if (!nphi)
return kFALSE;
773 if (stepphi[0] > TGeoShape::Tolerance())
return kFALSE;
776 if (nphi > 1 && iphi[1] < 0 && stepphi[0] < TGeoShape::Tolerance()) {
781 Double_t snextphi = 0.;
783 Int_t incseg = (dir[2] > 0) ? 1 : -1;
785 Int_t iplstart = ipl;
787 Double_t apr = TGeoShape::Big(), bpr = 0, db = 0;
788 Double_t rpg = 0, rnew = 0, znew = 0;
789 Double_t rpgin = 0, rpgout = 0, apgin = 0, apgout = 0, bpgin = 0, bpgout = 0;
790 Double_t divphi = TMath::DegToRad() * fDphi / fNedges;
791 Double_t phi1 = fPhi1 * TMath::DegToRad();
792 Double_t phi = 0, dz = 0;
793 Double_t cosph = 0, sinph = 0;
794 Double_t distz = 0, distr = 0, din = 0, dout = 0;
795 Double_t invdir = 1. / dir[2];
796 memcpy(pt, point, 3 *
sizeof(Double_t));
797 for (iphcrt = iphstart; iphcrt < nphi; iphcrt++) {
799 if (step > stepmax) {
803 if (iphi[iphcrt] < 0) {
807 snextphi = stepphi[iphcrt];
808 phi = phi1 + (iphi[iphcrt] + 0.5) * divphi;
809 cosph = TMath::Cos(phi);
810 sinph = TMath::Sin(phi);
811 Double_t rproj = Rproj(pt[2], pt, dir, cosph, sinph, apr, bpr);
813 while (ipl >= 0 && ipl < fNz - 1) {
814 din = dout = TGeoShape::Big();
816 distz = (fZ[ipl + ((1 + incseg) >> 1)] - pt[2]) * invdir;
818 dz = fZ[ipl + 1] - fZ[ipl];
819 if (dz < TGeoShape::Tolerance()) {
820 rnew = apr + bpr * fZ[ipl];
821 rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
822 if (rpg <= 0) din = distz;
823 rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
824 if (rpg <= 0) dout = distz;
825 distr = TMath::Min(din, dout);
827 rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
829 if (TMath::Abs(db) > TGeoShape::Tolerance()) {
830 znew = (apr - apgin) / db;
831 din = (znew - pt[2]) * invdir;
833 rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
835 if (TMath::Abs(db) > TGeoShape::Tolerance()) {
836 znew = (apr - apgout) / db;
837 dout = (znew - pt[2]) * invdir;
840 Double_t dinp = (din > TMath::Abs(snext - TGeoShape::Tolerance())) ? din : TGeoShape::Big();
841 Double_t doutp = (dout > TMath::Abs(snext - TGeoShape::Tolerance())) ? dout : TGeoShape::Big();
842 distr = TMath::Min(dinp, doutp);
843 if (iphcrt == iphstart && ipl == iplstart) {
844 if (rproj < rpgin + 1.E-8) {
845 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
847 snext = (din < 0) ? step : (step + din);
851 din = -TGeoShape::Big();
853 distr = TMath::Max(din, dout);
854 if (distr < TGeoShape::Tolerance()) distr = TGeoShape::Big();
855 }
else if (rproj > rpgout - 1.E-8) {
856 Double_t ndotd = dir[0] * cosph + dir[1] * sinph + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
858 snext = (dout < 0) ? step : (step + dout);
862 dout = -TGeoShape::Big();
864 distr = TMath::Max(din, dout);
865 if (distr < TGeoShape::Tolerance()) distr = TGeoShape::Big();
869 if (distr < snext - TGeoShape::Tolerance()) distr = TGeoShape::Big();
870 if (snextphi < step + TMath::Min(distz, distr)) {
871 for (i = 0; i < 3; i++) pt[i] = point[i] + snextphi * dir[i];
876 if (distr <= distz + TGeoShape::Tolerance()) {
879 return (step > stepmax) ? kFALSE : kTRUE;
883 if ((ipl + incseg < 0) || (ipl + incseg > fNz - 2)) {
887 return (step > stepmax) ? kFALSE : kTRUE;
892 snext = TGeoShape::Big();
900 Bool_t TGeoPgon::SliceCrossing(
const Double_t *point,
const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi,
901 Double_t &snext, Double_t stepmax)
const
903 if (!nphi)
return kFALSE;
906 if (iphi[0] < 0 && nphi == 1)
return kFALSE;
908 Double_t snextphi = 0.;
911 Int_t incseg = (dir[2] > 0) ? 1 : -1;
912 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
915 if (incseg < 0)
return kFALSE;
917 if (ipl == fNz - 1) {
919 if (incseg > 0)
return kFALSE;
921 if (TMath::Abs(point[2] - fZ[ipl]) < TGeoShape::Tolerance()) {
923 if ((ipl + incseg) < 0 || (ipl + incseg) > fNz - 1)
return kFALSE;
924 if (TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + incseg])) ipl += incseg;
927 if (TGeoShape::IsSameWithinTolerance(fZ[ipl], fZ[ipl + 1])) ipl--;
937 Double_t divphi = TMath::DegToRad() * fDphi / fNedges;
938 Double_t phi1 = fPhi1 * TMath::DegToRad();
940 Double_t cosph, sinph;
942 memcpy(pt, point, 3 *
sizeof(Double_t));
943 for (iphcrt = 0; iphcrt < nphi; iphcrt++) {
945 if (step > stepmax)
return kFALSE;
947 snextphi = stepphi[iphcrt];
948 if (iphi[iphcrt] < 0) {
949 if (iphcrt == nphi - 1)
return kFALSE;
950 if (snextphi > stepmax)
return kFALSE;
951 for (i = 0; i < 3; i++) pt[i] = point[i] + snextphi * dir[i];
955 while (pt[2] > fZ[ipl + 1]) {
957 if (ipl > fNz - 2)
return kFALSE;
960 while (pt[2] < fZ[ipl]) {
962 if (ipl < 0)
return kFALSE;
966 rpgin = Rpg(pt[2], ipl, kTRUE, apg, bpg);
967 rpgout = Rpg(pt[2], ipl, kFALSE, apg, bpg);
968 phi = phi1 + (iphi[iphcrt + 1] + 0.5) * divphi;
969 cosph = TMath::Cos(phi);
970 sinph = TMath::Sin(phi);
972 rproj = pt[0] * cosph + pt[1] * sinph;
973 if (rproj < rpgin || rproj > rpgout) {
980 if (IsCrossingSlice(point, dir, iphi[iphcrt], step, ipl, snext, TMath::Min(snextphi, stepmax)))
return kTRUE;
989 Bool_t TGeoPgon::IsCrossingSlice(
const Double_t *point,
const Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl,
990 Double_t &snext, Double_t stepmax)
const
992 if (ipl < 0 || ipl > fNz - 2)
return kFALSE;
993 if (sstart > stepmax)
return kFALSE;
995 memcpy(pt, point, 3 *
sizeof(Double_t));
997 for (Int_t i = 0; i < 3; i++) pt[i] += sstart * dir[i];
1000 Int_t incseg = (dir[2] > 0) ? 1 : -1;
1001 Double_t invdir = 1. / dir[2];
1002 Double_t divphi = TMath::DegToRad() * fDphi / fNedges;
1003 Double_t phi = fPhi1 * TMath::DegToRad() + (iphi + 0.5) * divphi;
1004 Double_t cphi = TMath::Cos(phi);
1005 Double_t sphi = TMath::Sin(phi);
1006 Double_t apr = TGeoShape::Big();
1008 Rproj(pt[2], point, dir, cphi, sphi, apr, bpr);
1011 Int_t icrtseg = ipl;
1012 Int_t isegstart = ipl;
1013 Int_t iseglast = (incseg > 0) ? (fNz - 1) : -1;
1014 Double_t din, dout, rdot, rnew, rpg, apg, bpg, db, znew;
1016 for (ipl = isegstart; ipl != iseglast; ipl += incseg) {
1017 step = (fZ[ipl + 1 - ((1 + incseg) >> 1)] - pt[2]) * invdir;
1019 if (step > stepmax) {
1025 din = dout = TGeoShape::Big();
1026 dz = fZ[ipl + 1] - fZ[ipl];
1029 if (TGeoShape::IsSameWithinTolerance(dz, 0))
1030 rdot = dir[2] * TMath::Sign(1., fRmin[ipl] - fRmin[ipl + 1]);
1032 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) / dz;
1036 if (TGeoShape::IsSameWithinTolerance(dz, 0)) {
1037 rnew = apr + bpr * fZ[ipl];
1038 rpg = (rnew - fRmin[ipl]) * (rnew - fRmin[ipl + 1]);
1039 if (rpg <= 0) din = (fZ[ipl] - pt[2]) * invdir;
1041 rpg = Rpg(pt[2], ipl, kTRUE, apg, bpg);
1043 if (!TGeoShape::IsSameWithinTolerance(db, 0)) {
1044 znew = (apr - apg) / db;
1045 if (znew > fZ[ipl] && znew < fZ[ipl + 1]) {
1046 din = (znew - pt[2]) * invdir;
1047 if (din < 0) din = TGeoShape::Big();
1054 if (TGeoShape::IsSameWithinTolerance(dz, 0))
1055 rdot = dir[2] * TMath::Sign(1., fRmax[ipl] - fRmax[ipl + 1]);
1057 rdot = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) / dz;
1061 if (TGeoShape::IsSameWithinTolerance(dz, 0)) {
1062 rnew = apr + bpr * fZ[ipl];
1063 rpg = (rnew - fRmax[ipl]) * (rnew - fRmax[ipl + 1]);
1064 if (rpg <= 0) dout = (fZ[ipl] - pt[2]) * invdir;
1066 rpg = Rpg(pt[2], ipl, kFALSE, apg, bpg);
1068 if (!TGeoShape::IsSameWithinTolerance(db, 0)) {
1069 znew = (apr - apg) / db;
1070 if (znew > fZ[ipl] && znew < fZ[ipl + 1]) dout = (znew - pt[2]) * invdir;
1071 if (dout < 0) dout = TGeoShape::Big();
1076 step = TMath::Min(din, dout);
1079 if (step > stepmax) {
1083 snext = sstart + step;
1094 Double_t TGeoPgon::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step,
1095 Double_t *safe)
const
1097 if (iact < 3 && safe) {
1098 *safe = Safety(point, kFALSE);
1099 if (iact == 0)
return TGeoShape::Big();
1100 if (iact == 1 && step < *safe)
return TGeoShape::Big();
1103 Double_t sdist = TGeoBBox::DistFromOutside(point, dir, fDX, fDY, fDZ, fOrigin, step);
1104 if (sdist >= step)
return TGeoShape::Big();
1106 if (dir[2] <= 0 && TMath::Abs(point[2] - fZ[0]) < TGeoShape::Tolerance())
return TGeoShape::Big();
1107 if (dir[2] >= 0 && TMath::Abs(point[2] - fZ[fNz - 1]) < TGeoShape::Tolerance())
return TGeoShape::Big();
1110 memcpy(pt, point, 3 *
sizeof(Double_t));
1114 ipl = TMath::BinarySearch(fNz, fZ, pt[2]);
1116 Double_t divphi = fDphi / fNedges;
1118 Double_t snext = 0.;
1119 Double_t stepmax = step;
1120 Double_t rpr, snewcross;
1121 Double_t r2 = pt[0] * pt[0] + pt[1] * pt[1];
1122 Double_t radmax = fRmax[TMath::LocMax(fNz, fRmax)];
1123 radmax = radmax / TMath::Cos(0.5 * divphi * TMath::DegToRad());
1125 if (r2 > (radmax * radmax) || pt[2] < fZ[0] || pt[2] > fZ[fNz - 1]) {
1126 pt[2] -= 0.5 * (fZ[0] + fZ[fNz - 1]);
1127 snext = TGeoTube::DistFromOutsideS(pt, dir, 0., radmax, 0.5 * (fZ[fNz - 1] - fZ[0]));
1128 if (snext > 1E10)
return TGeoShape::Big();
1129 if (snext > stepmax)
return TGeoShape::Big();
1132 for (i = 0; i < 3; i++) pt[i] += snext * dir[i];
1133 Bool_t checkz = (ipl < 0 && TMath::Abs(pt[2] - fZ[0]) < 1E-8) ? kTRUE : kFALSE;
1134 if (!checkz) checkz = (ipl == fNz - 1 && TMath::Abs(pt[2] - fZ[fNz - 1]) < 1E-8) ? kTRUE : kFALSE;
1136 Double_t rmin, rmax;
1141 rmin = fRmin[fNz - 1];
1142 rmax = fRmax[fNz - 1];
1144 Double_t phi = TMath::ATan2(pt[1], pt[0]) * TMath::RadToDeg();
1145 while (phi < fPhi1) phi += 360.0;
1146 Double_t ddp = phi - fPhi1;
1148 ipsec = Int_t(ddp / divphi);
1149 Double_t ph0 = (fPhi1 + divphi * (ipsec + 0.5)) * TMath::DegToRad();
1150 rpr = pt[0] * TMath::Cos(ph0) + pt[1] * TMath::Sin(ph0);
1151 if (rpr >= rmin && rpr <= rmax)
return snext;
1155 if (!fThreadSize) ((TGeoPgon *)
this)->CreateThreadData(1);
1156 ThreadData_t &td = GetThreadData();
1157 Double_t *sph = td.fDblBuffer;
1158 Int_t *iph = td.fIntBuffer;
1162 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1163 LocatePhi(pt, ipsec);
1164 icrossed = GetPhiCrossList(pt, dir, ipsec, sph, iph, stepmax);
1165 if (SliceCrossingZ(pt, dir, icrossed, iph, sph, snewcross, stepmax))
return (snext + snewcross);
1166 return TGeoShape::Big();
1169 divphi *= TMath::DegToRad();
1170 Bool_t inphi = kTRUE;
1171 Double_t ph = TMath::ATan2(pt[1], pt[0]) * TMath::RadToDeg();
1172 while (ph < fPhi1) ph += 360.;
1173 ipsec = Int_t(fNedges * (ph - fPhi1) / fDphi);
1174 if (ipsec > fNedges - 1) ipsec = -1;
1175 Double_t phim = fPhi1 + 0.5 * fDphi;
1176 Double_t ddp = TMath::Abs(ph - phim);
1177 if (fDphi < 360.0) {
1178 inphi = (ddp < 0.5 * fDphi + TGeoShape::Tolerance()) ? kTRUE : kFALSE;
1180 ipl = TMath::BinarySearch(fNz, fZ, pt[2]);
1181 if (ipl < 0) ipl = 0;
1182 if (ipl == fNz - 1) ipl--;
1184 if (pt[2] > fZ[fNz - 1] + TGeoShape::Tolerance()) inz = kFALSE;
1185 if (pt[2] < fZ[0] - TGeoShape::Tolerance()) inz = kFALSE;
1186 Bool_t onphi = kFALSE;
1188 Bool_t done = kFALSE;
1189 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1190 Double_t phi = fPhi1 * TMath::DegToRad() + (ipsec + 0.5) * divphi;
1191 Double_t cphi = TMath::Cos(phi);
1192 Double_t sphi = TMath::Sin(phi);
1193 Double_t rproj = pt[0] * cphi + pt[1] * sphi;
1194 if (TGeoShape::IsSameWithinTolerance(dz, 0)) {
1195 if (rproj < fRmin[ipl] && rproj > fRmin[ipl + 1] && dir[2] > 0)
return 0.0;
1196 if (rproj > fRmin[ipl] && rproj < fRmin[ipl + 1] && dir[2] < 0)
return 0.0;
1197 if (rproj > fRmax[ipl] && rproj < fRmax[ipl + 1] && dir[2] > 0)
return 0.0;
1198 if (rproj < fRmax[ipl] && rproj > fRmax[ipl + 1] && dir[2] < 0)
return 0.0;
1202 Double_t apgout, bpgout;
1203 Double_t rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
1204 if (rproj < rpgout + 1.E-8) {
1205 Double_t apgin, bpgin;
1206 Double_t rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
1207 if (rproj > rpgin - 1.E-8) {
1208 Double_t safrmin = rproj - rpgin;
1209 Double_t safrmax = rpgout - rproj;
1210 Double_t safz = TMath::Min(pt[2] - fZ[ipl], fZ[ipl + 1] - pt[2]);
1211 Double_t safphi = TGeoShape::Big();
1213 safphi = rproj * TMath::Sin((ddp - 0.5 * fDphi) * TMath::DegToRad());
1214 safphi = TMath::Abs(safphi);
1218 Double_t dzinv = 1. / dz;
1219 if (safrmin < safz && safrmin < safrmax && safrmin < safphi) {
1221 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmin[ipl] - fRmin[ipl + 1]) * dzinv;
1223 if (ndotd > 0)
return snext;
1226 if (!done && safrmax < safz && safrmax < safphi) {
1227 Double_t ndotd = dir[0] * cphi + dir[1] * sphi + dir[2] * (fRmax[ipl] - fRmax[ipl + 1]) * dzinv;
1229 if (ndotd < 0)
return snext;
1232 if (!done && safz < safphi) {
1235 if (TMath::Abs(pt[2] - fZ[ipl]) > TMath::Abs(fZ[ipl + 1] - pt[2])) iplc++;
1236 if (iplc == 0 || iplc == fNz - 1) {
1237 if (pt[2] * dir[2] < 0)
return snext;
1238 return TGeoShape::Big();
1240 if (TGeoShape::IsSameWithinTolerance(fZ[iplc], fZ[iplc + 1])) {
1242 if (rproj < fRmin[iplc] && rproj > fRmin[iplc + 1])
return snext;
1243 if (rproj > fRmax[iplc] && rproj < fRmax[iplc + 1])
return snext;
1245 if (rproj > fRmin[iplc] && rproj < fRmin[iplc + 1])
return snext;
1246 if (rproj < fRmax[iplc] && rproj > fRmax[iplc + 1])
return snext;
1248 }
else if (TGeoShape::IsSameWithinTolerance(fZ[iplc], fZ[iplc - 1])) {
1250 if (rproj < fRmin[iplc - 1] && rproj > fRmin[iplc])
return snext;
1251 if (rproj > fRmax[iplc - 1] && rproj < fRmax[iplc])
return snext;
1253 if (rproj > fRmin[iplc - 1] && rproj < fRmin[iplc])
return snext;
1254 if (rproj < fRmax[iplc - 1] && rproj > fRmax[iplc])
return snext;
1267 icrossed = GetPhiCrossList(pt, dir, ipsec, sph, iph, stepmax);
1269 if (!icrossed)
return snext;
1270 if (iph[0] < 0 && sph[0] < TGeoShape::Tolerance())
return (snext + sph[0]);
1271 if (iph[0] >= 0 && sph[0] > 1.E-8)
return snext;
1274 if (SliceCrossing(pt, dir, icrossed, iph, sph, snewcross, stepmax)) {
1278 return TGeoShape::Big();
1284 Int_t TGeoPgon::DistancetoPrimitive(Int_t px, Int_t py)
1286 Int_t n = fNedges + 1;
1287 const Int_t numPoints = 2 * n * fNz;
1288 return ShapeDistancetoPrimitive(numPoints, px, py);
1299 TGeoVolume *TGeoPgon::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv, Double_t start,
1306 TGeoVolumeMulti *vmulti;
1307 TGeoPatternFinder *finder;
1309 Int_t nedges = fNedges;
1310 Double_t zmin = start;
1311 Double_t zmax = start + ndiv * step;
1316 Error(
"Divide",
"makes no sense dividing a pgon on radius");
1319 if (fNedges % ndiv) {
1320 Error(
"Divide",
"ndiv should divide number of pgon edges");
1323 nedges = fNedges / ndiv;
1324 finder =
new TGeoPatternCylPhi(voldiv, ndiv, start, start + ndiv * step);
1325 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1326 voldiv->SetFinder(finder);
1327 finder->SetDivIndex(voldiv->GetNdaughters());
1328 shape =
new TGeoPgon(-step / 2, step, nedges, fNz);
1329 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
1330 vmulti->AddVolume(vol);
1331 for (is = 0; is < fNz; is++) ((TGeoPgon *)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
1333 for (
id = 0;
id < ndiv;
id++) {
1334 voldiv->AddNodeOffset(vol,
id, start +
id * step + step / 2, opt.Data());
1335 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1340 for (ipl = 0; ipl < fNz - 1; ipl++) {
1341 if (start < fZ[ipl])
1344 if ((start + ndiv * step) > fZ[ipl + 1])
continue;
1348 zmax = fZ[isect + 1];
1352 Error(
"Divide",
"cannot divide pcon on Z if divided region is not between 2 consecutive planes");
1355 finder =
new TGeoPatternZ(voldiv, ndiv, start, start + ndiv * step);
1356 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1357 voldiv->SetFinder(finder);
1358 finder->SetDivIndex(voldiv->GetNdaughters());
1360 for (
id = 0;
id < ndiv;
id++) {
1361 Double_t z1 = start +
id * step;
1362 Double_t z2 = start + (
id + 1) * step;
1363 Double_t rmin1 = (fRmin[isect] * (zmax - z1) - fRmin[isect + 1] * (zmin - z1)) / (zmax - zmin);
1364 Double_t rmax1 = (fRmax[isect] * (zmax - z1) - fRmax[isect + 1] * (zmin - z1)) / (zmax - zmin);
1365 Double_t rmin2 = (fRmin[isect] * (zmax - z2) - fRmin[isect + 1] * (zmin - z2)) / (zmax - zmin);
1366 Double_t rmax2 = (fRmax[isect] * (zmax - z2) - fRmax[isect + 1] * (zmin - z2)) / (zmax - zmin);
1367 shape =
new TGeoPgon(fPhi1, fDphi, nedges, 2);
1368 ((TGeoPgon *)shape)->DefineSection(0, -step / 2, rmin1, rmax1);
1369 ((TGeoPgon *)shape)->DefineSection(1, step / 2, rmin2, rmax2);
1370 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
1371 vmulti->AddVolume(vol);
1372 voldiv->AddNodeOffset(vol,
id, start +
id * step + step / 2, opt.Data());
1373 ((TGeoNodeOffset *)voldiv->GetNodes()->At(voldiv->GetNdaughters() - 1))->SetFinder(finder);
1376 default: Error(
"Divide",
"Wrong axis type for division");
return 0;
1384 void TGeoPgon::GetBoundingCylinder(Double_t *param)
const
1386 param[0] = fRmin[0];
1387 param[1] = fRmax[0];
1388 for (Int_t i = 1; i < fNz; i++) {
1389 if (fRmin[i] < param[0]) param[0] = fRmin[i];
1390 if (fRmax[i] > param[1]) param[1] = fRmax[i];
1392 Double_t divphi = fDphi / fNedges;
1393 param[1] /= TMath::Cos(0.5 * divphi * TMath::DegToRad());
1394 param[0] *= param[0];
1395 param[1] *= param[1];
1396 if (TGeoShape::IsSameWithinTolerance(fDphi, 360)) {
1401 param[2] = (fPhi1 < 0) ? (fPhi1 + 360.) : fPhi1;
1402 param[3] = param[2] + fDphi;
1408 void TGeoPgon::InspectShape()
const
1410 printf(
"*** Shape %s: TGeoPgon ***\n", GetName());
1411 printf(
" Nedges = %i\n", fNedges);
1412 TGeoPcon::InspectShape();
1419 TBuffer3D *TGeoPgon::MakeBuffer3D()
const
1421 const Int_t n = GetNsegments() + 1;
1423 if (nz < 2)
return 0;
1424 Int_t nbPnts = nz * 2 * n;
1425 if (nbPnts <= 0)
return 0;
1426 Double_t dphi = GetDphi();
1427 Bool_t specialCase = kFALSE;
1428 if (TGeoShape::IsSameWithinTolerance(dphi, 360)) specialCase = kTRUE;
1429 Int_t nbSegs = 4 * (nz * n - 1 + (specialCase == kTRUE));
1430 Int_t nbPols = 2 * (nz * n - 1 + (specialCase == kTRUE));
1433 new TBuffer3D(TBuffer3DTypes::kGeneric, nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols);
1435 SetPoints(buff->fPnts);
1436 SetSegsAndPols(*buff);
1445 void TGeoPgon::SetSegsAndPols(TBuffer3D &buff)
const
1448 const Int_t n = GetNsegments() + 1;
1451 Int_t nbPnts = nz * 2 * n;
1452 if (nbPnts <= 0)
return;
1453 Double_t dphi = GetDphi();
1454 Bool_t specialCase = kFALSE;
1455 if (TGeoShape::IsSameWithinTolerance(dphi, 360)) specialCase = kTRUE;
1456 Int_t c = GetBasicColor();
1458 Int_t indx, indx2, k;
1463 for (i = 0; i < nz * 2; i++) {
1465 for (j = 1; j < n; j++) {
1466 buff.fSegs[indx++] = c;
1467 buff.fSegs[indx++] = indx2 + j - 1;
1468 buff.fSegs[indx++] = indx2 + j;
1471 buff.fSegs[indx++] = c;
1472 buff.fSegs[indx++] = indx2 + j - 1;
1473 buff.fSegs[indx++] = indx2;
1478 for (i = 0; i < 2; i++) {
1479 indx2 = i * (nz - 1) * 2 * n;
1480 for (j = 0; j < n; j++) {
1481 buff.fSegs[indx++] = c;
1482 buff.fSegs[indx++] = indx2 + j;
1483 buff.fSegs[indx++] = indx2 + n + j;
1488 for (i = 0; i < (nz - 1); i++) {
1491 for (j = 0; j < n; j++) {
1492 buff.fSegs[indx++] = c + 2;
1493 buff.fSegs[indx++] = indx2 + j;
1494 buff.fSegs[indx++] = indx2 + n * 2 + j;
1497 indx2 = i * n * 2 + n;
1498 for (j = 0; j < n; j++) {
1499 buff.fSegs[indx++] = c + 3;
1500 buff.fSegs[indx++] = indx2 + j;
1501 buff.fSegs[indx++] = indx2 + n * 2 + j;
1508 for (i = 1; i < (nz - 1); i++) {
1509 for (j = 0; j < 2; j++) {
1510 buff.fSegs[indx++] = c;
1511 buff.fSegs[indx++] = 2 * i * n + j * (n - 1);
1512 buff.fSegs[indx++] = (2 * i + 1) * n + j * (n - 1);
1517 Int_t m = n - 1 + (specialCase == kTRUE);
1523 for (j = 0; j < n - 1; j++) {
1524 buff.fPols[indx++] = c + 3;
1525 buff.fPols[indx++] = 4;
1526 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1527 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1528 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1529 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1532 buff.fPols[indx++] = c + 3;
1533 buff.fPols[indx++] = 4;
1534 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1535 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1536 buff.fPols[indx++] = 2 * nz * m + i * n;
1537 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1540 for (j = 0; j < n - 1; j++) {
1541 buff.fPols[indx++] = c + 3;
1542 buff.fPols[indx++] = 4;
1543 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1544 buff.fPols[indx++] = 2 * nz * m + i * n + j + 1;
1545 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1546 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1549 buff.fPols[indx++] = c + 3;
1550 buff.fPols[indx++] = 4;
1551 buff.fPols[indx++] = i * (nz * 2 - 2) * m + j;
1552 buff.fPols[indx++] = 2 * nz * m + i * n;
1553 buff.fPols[indx++] = i * (nz * 2 - 2) * m + m + j;
1554 buff.fPols[indx++] = 2 * nz * m + i * n + j;
1558 for (k = 0; k < (nz - 1); k++) {
1560 for (j = 0; j < n - 1; j++) {
1561 buff.fPols[indx++] = c + i;
1562 buff.fPols[indx++] = 4;
1563 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1564 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1565 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1566 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1569 buff.fPols[indx++] = c + i;
1570 buff.fPols[indx++] = 4;
1571 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1572 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1573 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1574 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1577 for (j = 0; j < n - 1; j++) {
1578 buff.fPols[indx++] = c + i;
1579 buff.fPols[indx++] = 4;
1580 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1581 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1582 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1583 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j + 1;
1586 buff.fPols[indx++] = c + i;
1587 buff.fPols[indx++] = 4;
1588 buff.fPols[indx++] = (2 * k + i * 1) * m + j;
1589 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n + j;
1590 buff.fPols[indx++] = (2 * k + i * 1 + 2) * m + j;
1591 buff.fPols[indx++] = nz * 2 * m + (2 * k + i * 1 + 2) * n;
1598 indx2 = nz * 2 * (n - 1);
1599 for (k = 0; k < (nz - 1); k++) {
1600 buff.fPols[indx++] = c + 2;
1601 buff.fPols[indx++] = 4;
1602 buff.fPols[indx++] = k == 0 ? indx2 : indx2 + 2 * nz * n + 2 * (k - 1);
1603 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n;
1604 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k;
1605 buff.fPols[indx++] = indx2 + (2 * k + 3) * n;
1607 buff.fPols[indx++] = c + 2;
1608 buff.fPols[indx++] = 4;
1609 buff.fPols[indx++] = k == 0 ? indx2 + n - 1 : indx2 + 2 * nz * n + 2 * (k - 1) + 1;
1610 buff.fPols[indx++] = indx2 + (2 * k + 3) * n + n - 1;
1611 buff.fPols[indx++] = indx2 + 2 * nz * n + 2 * k + 1;
1612 buff.fPols[indx++] = indx2 + 2 * (k + 1) * n + n - 1;
1614 buff.fPols[indx - 8] = indx2 + n;
1615 buff.fPols[indx - 2] = indx2 + 2 * n - 1;
1626 Double_t TGeoPgon::Rpg(Double_t z, Int_t ipl, Bool_t inner, Double_t &a, Double_t &b)
const
1629 if (ipl < 0 || ipl > fNz - 2) {
1630 Fatal(
"Rpg",
"Plane index parameter ipl=%i out of range\n", ipl);
1633 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1634 if (dz < TGeoShape::Tolerance()) {
1636 rpg = (inner) ? TMath::Min(fRmin[ipl], fRmin[ipl + 1]) : TMath::Max(fRmax[ipl], fRmax[ipl + 1]);
1641 Double_t r1 = 0, r2 = 0;
1644 r2 = fRmin[ipl + 1];
1647 r2 = fRmax[ipl + 1];
1649 Double_t dzinv = 1. / dz;
1650 a = (r1 * fZ[ipl + 1] - r2 * fZ[ipl]) * dzinv;
1651 b = (r2 - r1) * dzinv;
1660 Double_t TGeoPgon::Rproj(Double_t z,
const Double_t *point,
const Double_t *dir, Double_t cphi, Double_t sphi,
1661 Double_t &a, Double_t &b)
const
1663 if (TMath::Abs(dir[2]) < TGeoShape::Tolerance()) {
1664 a = b = TGeoShape::Big();
1665 return TGeoShape::Big();
1667 Double_t invdirz = 1. / dir[2];
1668 a = ((point[0] * dir[2] - point[2] * dir[0]) * cphi + (point[1] * dir[2] - point[2] * dir[1]) * sphi) * invdirz;
1669 b = (dir[0] * cphi + dir[1] * sphi) * invdirz;
1676 Double_t TGeoPgon::SafetyToSegment(
const Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi,
1677 Double_t safmin)
const
1682 Double_t r, rpgon, ta, calf;
1683 if (ipl < 0 || ipl > fNz - 2)
return (safmin + 1.);
1685 Double_t dz = fZ[ipl + 1] - fZ[ipl];
1686 if (dz < 1E-9)
return 1E9;
1687 Double_t znew = point[2] - 0.5 * (fZ[ipl] + fZ[ipl + 1]);
1688 saf[0] = 0.5 * dz - TMath::Abs(znew);
1689 if (-saf[0] > safmin)
return TGeoShape::Big();
1690 Double_t rmin1 = fRmin[ipl];
1691 Double_t rmax1 = fRmax[ipl];
1692 Double_t rmin2 = fRmin[ipl + 1];
1693 Double_t rmax2 = fRmax[ipl + 1];
1694 Double_t divphi = fDphi / fNedges;
1696 Double_t f = 1. / TMath::Cos(0.5 * divphi * TMath::DegToRad());
1699 r = TMath::Sqrt(point[0] * point[0] + point[1] * point[1]);
1700 Double_t ro1 = 0.5 * (rmin1 + rmin2);
1701 Double_t tg1 = (rmin2 - rmin1) / dz;
1702 Double_t cr1 = 1. / TMath::Sqrt(1. + tg1 * tg1);
1703 Double_t ro2 = 0.5 * (rmax1 + rmax2);
1704 Double_t tg2 = (rmax2 - rmax1) / dz;
1705 Double_t cr2 = 1. / TMath::Sqrt(1. + tg2 * tg2);
1706 Double_t rin = tg1 * znew + ro1;
1707 Double_t rout = tg2 * znew + ro2;
1708 saf[1] = (ro1 > 0) ? ((r - rin) * cr1) : TGeoShape::Big();
1709 saf[2] = (rout - r) * cr2;
1710 for (i = 0; i < 3; i++) saf[i] = -saf[i];
1711 safe = saf[TMath::LocMax(3, saf)];
1712 safe = TMath::Max(safe, safphi);
1713 if (safe < 0) safe = 0;
1716 Double_t ph0 = (fPhi1 + divphi * (iphi + 0.5)) * TMath::DegToRad();
1717 r = point[0] * TMath::Cos(ph0) + point[1] * TMath::Sin(ph0);
1718 if (rmin1 + rmin2 > 1E-10) {
1719 ta = (rmin2 - rmin1) / dz;
1720 calf = 1. / TMath::Sqrt(1 + ta * ta);
1721 rpgon = rmin1 + (point[2] - fZ[ipl]) * ta;
1722 saf[1] = (r - rpgon) * calf;
1724 saf[1] = TGeoShape::Big();
1726 ta = (rmax2 - rmax1) / dz;
1727 calf = 1. / TMath::Sqrt(1 + ta * ta);
1728 rpgon = rmax1 + (point[2] - fZ[ipl]) * ta;
1729 saf[2] = (rpgon - r) * calf;
1731 safe = saf[TMath::LocMin(3, saf)];
1732 safe = TMath::Min(safe, safphi);
1734 for (i = 0; i < 3; i++) saf[i] = -saf[i];
1735 safe = saf[TMath::LocMax(3, saf)];
1736 safe = TMath::Max(safe, safphi);
1738 if (safe < 0) safe = 0;
1746 Double_t TGeoPgon::Safety(
const Double_t *point, Bool_t in)
const
1748 Double_t safmin, saftmp, safphi;
1750 Int_t ipl, iplane, iphi;
1751 LocatePhi(point, iphi);
1752 safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi1 + fDphi);
1755 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1756 if (ipl == (fNz - 1))
return 0;
1757 if (ipl < 0)
return 0;
1758 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1759 if (dz < 1E-8)
return 0;
1761 safmin = SafetyToSegment(point, ipl, iphi, in, safphi);
1762 if (safmin > 1E10) {
1764 return TGeoShape::Big();
1766 if (safmin < 1E-6)
return TMath::Abs(safmin);
1770 while ((iplane < fNz - 1) && saftmp < 1E10) {
1771 saftmp = TMath::Abs(SafetyToSegment(point, iplane, iphi, kFALSE, safphi, safmin));
1772 if (saftmp < safmin) safmin = saftmp;
1778 while ((iplane >= 0) && saftmp < 1E10) {
1779 saftmp = TMath::Abs(SafetyToSegment(point, iplane, iphi, kFALSE, safphi, safmin));
1780 if (saftmp < safmin) safmin = saftmp;
1786 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1789 else if (ipl == fNz - 1)
1791 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1794 if (ipl > fNz - 2)
return 0.;
1795 dz = 0.5 * (fZ[ipl + 1] - fZ[ipl]);
1798 safmin = SafetyToSegment(point, ipl, iphi, kFALSE, safphi);
1799 if (safmin < 1E-6)
return TMath::Abs(safmin);
1804 while ((iplane < fNz - 1) && saftmp < 1E10) {
1805 saftmp = TMath::Abs(SafetyToSegment(point, iplane, iphi, kFALSE, safphi, safmin));
1806 if (saftmp < safmin) safmin = saftmp;
1812 while ((iplane >= 0) && saftmp < 1E10) {
1813 saftmp = TMath::Abs(SafetyToSegment(point, iplane, iphi, kFALSE, safphi, safmin));
1814 if (saftmp < safmin) safmin = saftmp;
1823 void TGeoPgon::SavePrimitive(std::ostream &out, Option_t * )
1825 if (TObject::TestBit(kGeoSavePrimitive))
return;
1826 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
1827 out <<
" phi1 = " << fPhi1 <<
";" << std::endl;
1828 out <<
" dphi = " << fDphi <<
";" << std::endl;
1829 out <<
" nedges = " << fNedges <<
";" << std::endl;
1830 out <<
" nz = " << fNz <<
";" << std::endl;
1831 out <<
" TGeoPgon *pgon = new TGeoPgon(\"" << GetName() <<
"\",phi1,dphi,nedges,nz);" << std::endl;
1832 for (Int_t i = 0; i < fNz; i++) {
1833 out <<
" z = " << fZ[i] <<
";" << std::endl;
1834 out <<
" rmin = " << fRmin[i] <<
";" << std::endl;
1835 out <<
" rmax = " << fRmax[i] <<
";" << std::endl;
1836 out <<
" pgon->DefineSection(" << i <<
", z,rmin,rmax);" << std::endl;
1838 out <<
" TGeoShape *" << GetPointerName() <<
" = pgon;" << std::endl;
1839 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
1845 void TGeoPgon::SetDimensions(Double_t *param)
1849 fNedges = (Int_t)param[2];
1850 fNz = (Int_t)param[3];
1852 Error(
"SetDimensions",
"Pgon %s: Number of Z sections must be > 2", GetName());
1855 if (fRmin)
delete[] fRmin;
1856 if (fRmax)
delete[] fRmax;
1857 if (fZ)
delete[] fZ;
1858 fRmin =
new Double_t[fNz];
1859 fRmax =
new Double_t[fNz];
1860 fZ =
new Double_t[fNz];
1861 memset(fRmin, 0, fNz *
sizeof(Double_t));
1862 memset(fRmax, 0, fNz *
sizeof(Double_t));
1863 memset(fZ, 0, fNz *
sizeof(Double_t));
1864 for (Int_t i = 0; i < fNz; i++) DefineSection(i, param[4 + 3 * i], param[5 + 3 * i], param[6 + 3 * i]);
1870 void TGeoPgon::SetPoints(Double_t *points)
const
1873 Int_t n = fNedges + 1;
1874 dphi = fDphi / (n - 1);
1875 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
1880 for (i = 0; i < fNz; i++) {
1881 for (j = 0; j < n; j++) {
1882 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1883 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
1884 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
1885 points[indx++] = fZ[i];
1887 for (j = 0; j < n; j++) {
1888 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1889 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
1890 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
1891 points[indx++] = fZ[i];
1900 void TGeoPgon::SetPoints(Float_t *points)
const
1903 Int_t n = fNedges + 1;
1904 dphi = fDphi / (n - 1);
1905 Double_t factor = 1. / TMath::Cos(TMath::DegToRad() * dphi / 2);
1910 for (i = 0; i < fNz; i++) {
1911 for (j = 0; j < n; j++) {
1912 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1913 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
1914 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
1915 points[indx++] = fZ[i];
1917 for (j = 0; j < n; j++) {
1918 phi = (fPhi1 + j * dphi) * TMath::DegToRad();
1919 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
1920 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
1921 points[indx++] = fZ[i];
1930 void TGeoPgon::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
1932 Int_t n = fNedges + 1;
1935 Bool_t specialCase = (TGeoShape::IsSameWithinTolerance(GetDphi(), 360));
1936 nsegs = 4 * (nz * n - 1 + (specialCase == kTRUE));
1937 npols = 2 * (nz * n - 1 + (specialCase == kTRUE));
1943 Int_t TGeoPgon::GetNmeshVertices()
const
1945 Int_t n = fNedges + 1;
1946 Int_t numPoints = fNz * 2 * n;
1953 void TGeoPgon::Sizeof3D()
const
1960 const TBuffer3D &TGeoPgon::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
1962 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1964 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1966 if (reqSections & TBuffer3D::kRawSizes) {
1967 const Int_t n = GetNsegments() + 1;
1969 Int_t nbPnts = nz * 2 * n;
1970 if (nz >= 2 && nbPnts > 0) {
1971 Bool_t specialCase = (TGeoShape::IsSameWithinTolerance(GetDphi(), 360));
1972 Int_t nbSegs = 4 * (nz * n - 1 + (specialCase == kTRUE));
1973 Int_t nbPols = 2 * (nz * n - 1 + (specialCase == kTRUE));
1974 if (buffer.SetRawSizes(nbPnts, 3 * nbPnts, nbSegs, 3 * nbSegs, nbPols, 6 * nbPols)) {
1975 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1981 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1982 SetPoints(buffer.fPnts);
1983 if (!buffer.fLocalFrame) {
1984 TransformPoints(buffer.fPnts, buffer.NbPnts());
1987 SetSegsAndPols(buffer);
1988 buffer.SetSectionsValid(TBuffer3D::kRaw);
1999 void TGeoPgon::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
2001 for (Int_t i = 0; i < vecsize; i++) inside[i] = Contains(&points[3 * i]);
2009 void TGeoPgon::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
2011 for (Int_t i = 0; i < vecsize; i++) ComputeNormal(&points[3 * i], &dirs[3 * i], &norms[3 * i]);
2017 void TGeoPgon::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize,
2018 Double_t *step)
const
2020 for (Int_t i = 0; i < vecsize; i++) dists[i] = DistFromInside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2026 void TGeoPgon::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize,
2027 Double_t *step)
const
2029 for (Int_t i = 0; i < vecsize; i++) dists[i] = DistFromOutside(&points[3 * i], &dirs[3 * i], 3, step[i]);
2037 void TGeoPgon::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
2039 for (Int_t i = 0; i < vecsize; i++) safe[i] = Safety(&points[3 * i], inside[i]);