85 SetShapeBit(TGeoShape::kGeoPcon);
91 TGeoPcon::TGeoPcon(Double_t phi, Double_t dphi, Int_t nz)
108 SetShapeBit(TGeoShape::kGeoPcon);
109 while (fPhi1<0) fPhi1+=360.;
110 fRmin =
new Double_t [nz];
111 fRmax =
new Double_t [nz];
112 fZ =
new Double_t [nz];
113 memset(fRmin, 0, nz*
sizeof(Double_t));
114 memset(fRmax, 0, nz*
sizeof(Double_t));
115 memset(fZ, 0, nz*
sizeof(Double_t));
116 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) fFullPhi = kTRUE;
117 Double_t phi1 = fPhi1;
118 Double_t phi2 = phi1+fDphi;
119 Double_t phim = 0.5*(phi1+phi2);
120 fC1 = TMath::Cos(phi1*TMath::DegToRad());
121 fS1 = TMath::Sin(phi1*TMath::DegToRad());
122 fC2 = TMath::Cos(phi2*TMath::DegToRad());
123 fS2 = TMath::Sin(phi2*TMath::DegToRad());
124 fCm = TMath::Cos(phim*TMath::DegToRad());
125 fSm = TMath::Sin(phim*TMath::DegToRad());
126 fCdphi = TMath::Cos(0.5*fDphi*TMath::DegToRad());
132 TGeoPcon::TGeoPcon(
const char *name, Double_t phi, Double_t dphi, Int_t nz)
133 :TGeoBBox(name, 0, 0, 0),
149 SetShapeBit(TGeoShape::kGeoPcon);
150 while (fPhi1<0) fPhi1+=360.;
151 fRmin =
new Double_t [nz];
152 fRmax =
new Double_t [nz];
153 fZ =
new Double_t [nz];
154 memset(fRmin, 0, nz*
sizeof(Double_t));
155 memset(fRmax, 0, nz*
sizeof(Double_t));
156 memset(fZ, 0, nz*
sizeof(Double_t));
157 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) fFullPhi = kTRUE;
158 Double_t phi1 = fPhi1;
159 Double_t phi2 = phi1+fDphi;
160 Double_t phim = 0.5*(phi1+phi2);
161 fC1 = TMath::Cos(phi1*TMath::DegToRad());
162 fS1 = TMath::Sin(phi1*TMath::DegToRad());
163 fC2 = TMath::Cos(phi2*TMath::DegToRad());
164 fS2 = TMath::Sin(phi2*TMath::DegToRad());
165 fCm = TMath::Cos(phim*TMath::DegToRad());
166 fSm = TMath::Sin(phim*TMath::DegToRad());
167 fCdphi = TMath::Cos(0.5*fDphi*TMath::DegToRad());
180 TGeoPcon::TGeoPcon(Double_t *param)
197 SetShapeBit(TGeoShape::kGeoPcon);
198 SetDimensions(param);
205 TGeoPcon::TGeoPcon(
const TGeoPcon& pc) :
227 TGeoPcon& TGeoPcon::operator=(
const TGeoPcon& pc)
230 TGeoBBox::operator=(pc);
252 TGeoPcon::~TGeoPcon()
254 if (fRmin) {
delete[] fRmin; fRmin = 0;}
255 if (fRmax) {
delete[] fRmax; fRmax = 0;}
256 if (fZ) {
delete[] fZ; fZ = 0;}
262 Double_t TGeoPcon::Capacity()
const
265 Double_t rmin1, rmax1, rmin2, rmax2, phi1, phi2, dz;
266 Double_t capacity = 0.;
268 phi2 = fPhi1 + fDphi;
269 for (ipl=0; ipl<fNz-1; ipl++) {
270 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
271 if (dz < TGeoShape::Tolerance())
continue;
274 rmin2 = fRmin[ipl+1];
275 rmax2 = fRmax[ipl+1];
276 capacity += TGeoConeSeg::Capacity(dz,rmin1,rmax1,rmin2,rmax2,phi1,phi2);
285 void TGeoPcon::ComputeBBox()
287 for (Int_t isec=0; isec<fNz-1; isec++) {
288 if (TMath::Abs(fZ[isec]-fZ[isec+1]) < TGeoShape::Tolerance()) {
290 if (IsSameWithinTolerance(fRmin[isec], fRmin[isec+1]) &&
291 IsSameWithinTolerance(fRmax[isec], fRmax[isec+1])) {
293 Error(
"ComputeBBox",
"Duplicated section %d/%d for shape %s", isec, isec+1, GetName());
296 if (fZ[isec]>fZ[isec+1]) {
298 Fatal(
"ComputeBBox",
"Wrong section order");
302 if (TMath::Abs(fZ[1]-fZ[0]) < TGeoShape::Tolerance() ||
303 TMath::Abs(fZ[fNz-1]-fZ[fNz-2]) < TGeoShape::Tolerance()) {
305 Fatal(
"ComputeBBox",
"Shape %s at index %d: Not allowed first two or last two sections at same Z",
306 GetName(), gGeoManager->GetListOfShapes()->IndexOf(
this));
308 Double_t zmin = TMath::Min(fZ[0], fZ[fNz-1]);
309 Double_t zmax = TMath::Max(fZ[0], fZ[fNz-1]);
312 rmin = fRmin[TMath::LocMin(fNz, fRmin)];
313 rmax = fRmax[TMath::LocMax(fNz, fRmax)];
326 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
327 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
328 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
329 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
331 Double_t ddp = -fPhi1;
332 if (ddp<0) ddp+= 360;
333 if (ddp<=fDphi) xmax = rmax;
335 if (ddp<0) ddp+= 360;
336 if (ddp<=fDphi) ymax = rmax;
338 if (ddp<0) ddp+= 360;
339 if (ddp<=fDphi) xmin = -rmax;
341 if (ddp<0) ddp+= 360;
342 if (ddp<=fDphi) ymin = -rmax;
343 fOrigin[0] = (xmax+xmin)/2;
344 fOrigin[1] = (ymax+ymin)/2;
345 fOrigin[2] = (zmax+zmin)/2;
349 SetShapeBit(kGeoClosedShape);
355 void TGeoPcon::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
357 memset(norm,0,3*
sizeof(Double_t));
360 Double_t dz, rmin1, rmax1, rmin2, rmax2;
362 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
363 if (ipl==(fNz-1) || ipl<0) {
365 norm[2] = TMath::Sign(1., dir[2]);
368 Int_t iplclose = ipl;
369 if ((fZ[ipl+1]-point[2])<(point[2]-fZ[ipl])) iplclose++;
370 dz = TMath::Abs(fZ[iplclose]-point[2]);
372 if (iplclose==0 || iplclose==(fNz-1)) {
373 norm[2] = TMath::Sign(1., dir[2]);
376 if (iplclose==ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1])) {
377 r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
378 if (r<TMath::Max(fRmin[ipl],fRmin[ipl-1]) || r>TMath::Min(fRmax[ipl],fRmax[ipl-1])) {
379 norm[2] = TMath::Sign(1., dir[2]);
383 if (TGeoShape::IsSameWithinTolerance(fZ[iplclose],fZ[iplclose+1])) {
384 r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
385 if (r<TMath::Max(fRmin[iplclose],fRmin[iplclose+1]) || r>TMath::Min(fRmax[iplclose],fRmax[iplclose+1])) {
386 norm[2] = TMath::Sign(1., dir[2]);
392 memcpy(ptnew, point, 3*
sizeof(Double_t));
393 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
394 if (TGeoShape::IsSameWithinTolerance(dz,0.)) {
395 norm[2] = TMath::Sign(1., dir[2]);
398 ptnew[2] -= 0.5*(fZ[ipl]+fZ[ipl+1]);
401 rmin2 = fRmin[ipl+1];
402 rmax2 = fRmax[ipl+1];
403 is_tube = (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2))?kTRUE:kFALSE;
405 if (is_tube) TGeoTubeSeg::ComputeNormalS(ptnew,dir,norm,rmin1,rmax1,dz,fC1,fS1,fC2,fS2);
406 else TGeoConeSeg::ComputeNormalS(ptnew,dir,norm,dz,rmin1,rmax1,rmin2,rmax2,fC1,fS1,fC2,fS2);
408 if (is_tube) TGeoTube::ComputeNormalS(ptnew,dir,norm,rmin1,rmax1,dz);
409 else TGeoCone::ComputeNormalS(ptnew,dir,norm,dz,rmin1,rmax1,rmin2,rmax2);
417 Bool_t TGeoPcon::Contains(
const Double_t *point)
const
419 if ((point[2]<fZ[0]) || (point[2]>fZ[fNz-1]))
return kFALSE;
421 Double_t r2 = point[0]*point[0]+point[1]*point[1];
425 Int_t izt = (fNz-1)/2;
426 while ((izh-izl)>1) {
427 if (point[2] > fZ[izt]) izl = izt;
435 if (TGeoShape::IsSameWithinTolerance(fZ[izl],fZ[izh]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[izl])) {
436 rmin = TMath::Min(fRmin[izl], fRmin[izh]);
437 rmax = TMath::Max(fRmax[izl], fRmax[izh]);
439 Double_t dz = fZ[izh] - fZ[izl];
440 Double_t dz1 = point[2] - fZ[izl];
441 rmin = (fRmin[izl]*(dz-dz1)+fRmin[izh]*dz1)/dz;
442 rmax = (fRmax[izl]*(dz-dz1)+fRmax[izh]*dz1)/dz;
444 if ((r2<rmin*rmin) || (r2>rmax*rmax))
return kFALSE;
446 if (TGeoShape::IsSameWithinTolerance(fDphi,360))
return kTRUE;
447 if (r2<1E-10)
return kTRUE;
448 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
449 if (phi < 0) phi+=360.0;
450 Double_t ddp = phi-fPhi1;
451 if (ddp<0) ddp+=360.;
452 if (ddp<=fDphi)
return kTRUE;
459 Int_t TGeoPcon::DistancetoPrimitive(Int_t px, Int_t py)
461 Int_t n = gGeoManager->GetNsegments()+1;
462 const Int_t numPoints = 2*n*fNz;
463 return ShapeDistancetoPrimitive(numPoints, px, py);
469 Double_t TGeoPcon::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
471 if (iact<3 && safe) {
472 *safe = Safety(point, kTRUE);
473 if (iact==0)
return TGeoShape::Big();
474 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
476 Double_t snxt = TGeoShape::Big();
477 Double_t sstep = 1E-6;
478 Double_t point_new[3];
480 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]+TMath::Sign(1.E-10,dir[2]));
482 if (ipl==(fNz-1)) ipl--;
483 Double_t dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
484 Bool_t special_case = kFALSE;
487 if (TGeoShape::IsSameWithinTolerance(dir[2], 0)) {
488 special_case = kTRUE;
491 point_new[0] = point[0]+sstep*dir[0];
492 point_new[1] = point[1]+sstep*dir[1];
493 point_new[2] = point[2]+sstep*dir[2];
494 if (!Contains(point_new))
return 0.;
495 return (DistFromInside(point_new,dir,iact,step,safe)+sstep);
499 Bool_t intub = kTRUE;
500 if (!TGeoShape::IsSameWithinTolerance(fRmin[ipl],fRmin[ipl+1])) intub=kFALSE;
501 else if (!TGeoShape::IsSameWithinTolerance(fRmax[ipl],fRmax[ipl+1])) intub=kFALSE;
503 memcpy(point_new, point, 2*
sizeof(Double_t));
505 point_new[2] = point[2]-0.5*(fZ[ipl]+fZ[ipl+1]);
508 if (!fFullPhi) snxt = TGeoTubeSeg::DistFromInsideS(point_new, dir,
509 TMath::Min(fRmin[ipl],fRmin[ipl+1]), TMath::Max(fRmax[ipl],fRmax[ipl+1]),
510 dz, fC1,fS1,fC2,fS2,fCm,fSm,fCdphi);
511 else snxt = TGeoTube::DistFromInsideS(point_new, dir,
512 TMath::Min(fRmin[ipl],fRmin[ipl+1]), TMath::Max(fRmax[ipl],fRmax[ipl+1]),dz);
516 if (!fFullPhi) snxt=TGeoTubeSeg::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl],dz, fC1,fS1,fC2,fS2,fCm,fSm,fCdphi);
517 else snxt=TGeoTube::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl],dz);
519 if (!fFullPhi) snxt=TGeoConeSeg::DistFromInsideS(point_new,dir,dz,fRmin[ipl],fRmax[ipl],fRmin[ipl+1],fRmax[ipl+1],fC1,fS1,fC2,fS2,fCm,fSm,fCdphi);
520 else snxt=TGeoCone::DistFromInsideS(point_new,dir,dz,fRmin[ipl],fRmax[ipl],fRmin[ipl+1], fRmax[ipl+1]);
523 for (Int_t i=0; i<3; i++) point_new[i]=point[i]+(snxt+1E-6)*dir[i];
524 if (!Contains(&point_new[0]))
return snxt;
526 snxt += DistFromInside(&point_new[0], dir, 3) + 1E-6;
533 Double_t TGeoPcon::DistToSegZ(
const Double_t *point,
const Double_t *dir, Int_t &iz)
const
535 Double_t zmin=fZ[iz];
536 Double_t zmax=fZ[iz+1];
537 if (TGeoShape::IsSameWithinTolerance(zmin,zmax)) {
538 if (TGeoShape::IsSameWithinTolerance(dir[2],0))
return TGeoShape::Big();
539 Int_t istep=(dir[2]>0)?1:-1;
541 if (iz<0 || iz>(fNz-2))
return TGeoShape::Big();
542 return DistToSegZ(point,dir,iz);
544 Double_t dz=0.5*(zmax-zmin);
546 memcpy(&local[0], point, 3*
sizeof(Double_t));
547 local[2]=point[2]-0.5*(zmin+zmax);
549 Double_t rmin1=fRmin[iz];
550 Double_t rmax1=fRmax[iz];
551 Double_t rmin2=fRmin[iz+1];
552 Double_t rmax2=fRmax[iz+1];
554 if (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2)) {
555 if (fFullPhi) snxt=TGeoTube::DistFromOutsideS(local, dir, rmin1, rmax1, dz);
556 else snxt=TGeoTubeSeg::DistFromOutsideS(local,dir,rmin1,rmax1,dz,fC1,fS1,fC2,fS2,fCm,fSm,fCdphi);
558 if (fFullPhi) snxt=TGeoCone::DistFromOutsideS(local,dir,dz,rmin1, rmax1,rmin2,rmax2);
559 else snxt=TGeoConeSeg::DistFromOutsideS(local,dir,dz,rmin1,rmax1,rmin2,rmax2,fC1,fS1,fC2,fS2,fCm,fSm,fCdphi);
561 if (snxt<1E20)
return snxt;
563 if (TGeoShape::IsSameWithinTolerance(dir[2],0))
return TGeoShape::Big();
564 Int_t istep=(dir[2]>0)?1:-1;
566 if (iz<0 || iz>(fNz-2))
return TGeoShape::Big();
567 return DistToSegZ(point,dir,iz);
573 Double_t TGeoPcon::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
575 if ((iact<3) && safe) {
576 *safe = Safety(point, kFALSE);
577 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
578 if (iact==0)
return TGeoShape::Big();
581 if ((point[2]<fZ[0]) && (dir[2]<=0))
return TGeoShape::Big();
582 if ((point[2]>fZ[fNz-1]) && (dir[2]>=0))
return TGeoShape::Big();
584 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
585 if (sdist>=step)
return TGeoShape::Big();
587 Double_t r2 = point[0]*point[0]+point[1]*point[1];
589 radmax=fRmax[TMath::LocMax(fNz, fRmax)];
590 if (r2>(radmax*radmax)) {
591 Double_t rpr=-point[0]*dir[0]-point[1]*dir[1];
592 Double_t nxy=dir[0]*dir[0]+dir[1]*dir[1];
593 if (rpr<TMath::Sqrt((r2-radmax*radmax)*nxy))
return TGeoShape::Big();
597 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
601 }
else if (ifirst>=(fNz-1)) ifirst=fNz-2;
605 phi=TMath::ATan2(point[1], point[0]);
606 if (phi<0) phi+=2.*TMath::Pi();
610 return DistToSegZ(point,dir,ifirst);
618 void TGeoPcon::DefineSection(Int_t snum, Double_t z, Double_t rmin, Double_t rmax)
620 if ((snum<0) || (snum>=fNz))
return;
625 Warning(
"DefineSection",
"Shape %s: invalid rmin=%g rmax=%g", GetName(), rmin, rmax);
628 if (fZ[0] > fZ[snum]) {
637 fRmin[iz] = fRmin[izi];
640 fRmax[iz] = fRmax[izi];
653 Int_t TGeoPcon::GetNsegments()
const
655 return gGeoManager->GetNsegments();
666 TGeoVolume *TGeoPcon::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv,
667 Double_t start, Double_t step)
671 TGeoVolumeMulti *vmulti;
672 TGeoPatternFinder *finder;
674 Double_t zmin = start;
675 Double_t zmax = start+ndiv*step;
680 Error(
"Divide",
"Shape %s: cannot divide a pcon on radius", GetName());
683 finder =
new TGeoPatternCylPhi(voldiv, ndiv, start, start+ndiv*step);
684 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
685 voldiv->SetFinder(finder);
686 finder->SetDivIndex(voldiv->GetNdaughters());
687 shape =
new TGeoPcon(-step/2, step, fNz);
688 for (is=0; is<fNz; is++)
689 ((TGeoPcon*)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
690 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
691 vmulti->AddVolume(vol);
693 for (
id=0;
id<ndiv;
id++) {
694 voldiv->AddNodeOffset(vol,
id, start+
id*step+step/2, opt.Data());
695 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
700 for (ipl=0; ipl<fNz-1; ipl++) {
701 if (start<fZ[ipl])
continue;
703 if ((start+ndiv*step)>fZ[ipl+1])
continue;
711 Error(
"Divide",
"Shape %s: cannot divide pcon on Z if divided region is not between 2 planes", GetName());
714 finder =
new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
715 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
716 voldiv->SetFinder(finder);
717 finder->SetDivIndex(voldiv->GetNdaughters());
719 for (
id=0;
id<ndiv;
id++) {
720 Double_t z1 = start+
id*step;
721 Double_t z2 = start+(
id+1)*step;
722 Double_t rmin1 = (fRmin[isect]*(zmax-z1)-fRmin[isect+1]*(zmin-z1))/(zmax-zmin);
723 Double_t rmax1 = (fRmax[isect]*(zmax-z1)-fRmax[isect+1]*(zmin-z1))/(zmax-zmin);
724 Double_t rmin2 = (fRmin[isect]*(zmax-z2)-fRmin[isect+1]*(zmin-z2))/(zmax-zmin);
725 Double_t rmax2 = (fRmax[isect]*(zmax-z2)-fRmax[isect+1]*(zmin-z2))/(zmax-zmin);
726 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(fRmin[isect],fRmin[isect+1]) && TGeoShape::IsSameWithinTolerance(fRmax[isect],fRmax[isect+1]))?kTRUE:kFALSE;
727 Bool_t is_seg = (fDphi<360)?kTRUE:kFALSE;
729 if (is_tube) shape=
new TGeoTubeSeg(fRmin[isect],fRmax[isect],step/2, fPhi1, fPhi1+fDphi);
730 else shape=
new TGeoConeSeg(step/2, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi1+fDphi);
732 if (is_tube) shape=
new TGeoTube(fRmin[isect],fRmax[isect],step/2);
733 else shape =
new TGeoCone(step/2,rmin1,rmax1,rmin2,rmax2);
735 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
736 vmulti->AddVolume(vol);
737 voldiv->AddNodeOffset(vol,
id, start+
id*step+step/2, opt.Data());
738 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
742 Error(
"Divide",
"Shape %s: Wrong axis %d for division",GetName(), iaxis);
750 const char *TGeoPcon::GetAxisName(Int_t iaxis)
const
767 Double_t TGeoPcon::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
791 void TGeoPcon::GetBoundingCylinder(Double_t *param)
const
795 for (Int_t i=1; i<fNz; i++) {
796 if (fRmin[i] < param[0]) param[0] = fRmin[i];
797 if (fRmax[i] > param[1]) param[1] = fRmax[i];
799 param[0] *= param[0];
800 param[1] *= param[1];
801 if (TGeoShape::IsSameWithinTolerance(fDphi,360.)) {
806 param[2] = (fPhi1<0)?(fPhi1+360.):fPhi1;
807 param[3] = param[2]+fDphi;
813 Double_t TGeoPcon::GetRmin(Int_t ipl)
const
815 if (ipl<0 || ipl>(fNz-1)) {
816 Error(
"GetRmin",
"ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
825 Double_t TGeoPcon::GetRmax(Int_t ipl)
const
827 if (ipl<0 || ipl>(fNz-1)) {
828 Error(
"GetRmax",
"ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
837 Double_t TGeoPcon::GetZ(Int_t ipl)
const
839 if (ipl<0 || ipl>(fNz-1)) {
840 Error(
"GetZ",
"ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
849 void TGeoPcon::InspectShape()
const
851 printf(
"*** Shape %s: TGeoPcon ***\n", GetName());
852 printf(
" Nz = %i\n", fNz);
853 printf(
" phi1 = %11.5f\n", fPhi1);
854 printf(
" dphi = %11.5f\n", fDphi);
855 for (Int_t ipl=0; ipl<fNz; ipl++)
856 printf(
" plane %i: z=%11.5f Rmin=%11.5f Rmax=%11.5f\n", ipl, fZ[ipl], fRmin[ipl], fRmax[ipl]);
857 printf(
" Bounding box:\n");
858 TGeoBBox::InspectShape();
865 TBuffer3D *TGeoPcon::MakeBuffer3D()
const
867 const Int_t n = gGeoManager->GetNsegments()+1;
869 if (nz < 2)
return 0;
870 Int_t nbPnts = nz*2*n;
871 if (nbPnts <= 0)
return 0;
872 Double_t dphi = GetDphi();
874 Bool_t specialCase = kFALSE;
875 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
877 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
878 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
879 TBuffer3D* buff =
new TBuffer3D(TBuffer3DTypes::kGeneric,
880 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
883 SetPoints(buff->fPnts);
884 SetSegsAndPols(*buff);
893 void TGeoPcon::SetSegsAndPols(TBuffer3D &buff)
const
896 const Int_t n = gGeoManager->GetNsegments()+1;
899 Int_t nbPnts = nz*2*n;
900 if (nbPnts <= 0)
return;
901 Double_t dphi = GetDphi();
903 Bool_t specialCase = kFALSE;
904 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
905 Int_t c = GetBasicColor();
907 Int_t indx, indx2, k;
912 for (i = 0; i < nz*2; i++) {
914 for (j = 1; j < n; j++) {
915 buff.fSegs[indx++] = c;
916 buff.fSegs[indx++] = indx2+j-1;
917 buff.fSegs[indx++] = indx2+j;
920 buff.fSegs[indx++] = c;
921 buff.fSegs[indx++] = indx2+j-1;
922 buff.fSegs[indx++] = indx2;
927 for (i = 0; i < 2; i++) {
928 indx2 = i*(nz-1)*2*n;
929 for (j = 0; j < n; j++) {
930 buff.fSegs[indx++] = c;
931 buff.fSegs[indx++] = indx2+j;
932 buff.fSegs[indx++] = indx2+n+j;
937 for (i = 0; i < (nz-1); i++) {
940 for (j = 0; j < n; j++) {
941 buff.fSegs[indx++] = c+2;
942 buff.fSegs[indx++] = indx2+j;
943 buff.fSegs[indx++] = indx2+n*2+j;
947 for (j = 0; j < n; j++) {
948 buff.fSegs[indx++] = c+3;
949 buff.fSegs[indx++] = indx2+j;
950 buff.fSegs[indx++] = indx2+n*2+j;
957 for (i = 1; i < (nz-1); i++) {
958 for (j = 0; j < 2; j++) {
959 buff.fSegs[indx++] = c;
960 buff.fSegs[indx++] = 2*i * n + j*(n-1);
961 buff.fSegs[indx++] = (2*i+1) * n + j*(n-1);
966 Int_t m = n - 1 + (specialCase == kTRUE);
971 for (j = 0; j < n-1; j++) {
972 buff.fPols[indx++] = c+3;
973 buff.fPols[indx++] = 4;
974 buff.fPols[indx++] = 2*nz*m+j;
975 buff.fPols[indx++] = m+j;
976 buff.fPols[indx++] = 2*nz*m+j+1;
977 buff.fPols[indx++] = j;
979 for (j = 0; j < n-1; j++) {
980 buff.fPols[indx++] = c+3;
981 buff.fPols[indx++] = 4;
982 buff.fPols[indx++] = 2*nz*m+n+j;
983 buff.fPols[indx++] = (nz*2-2)*m+j;
984 buff.fPols[indx++] = 2*nz*m+n+j+1;
985 buff.fPols[indx++] = (nz*2-2)*m+m+j;
988 buff.fPols[indx++] = c+3;
989 buff.fPols[indx++] = 4;
990 buff.fPols[indx++] = 2*nz*m+j;
991 buff.fPols[indx++] = m+j;
992 buff.fPols[indx++] = 2*nz*m;
993 buff.fPols[indx++] = j;
995 buff.fPols[indx++] = c+3;
996 buff.fPols[indx++] = 4;
997 buff.fPols[indx++] = 2*nz*m+n+j;
998 buff.fPols[indx++] = (nz*2-2)*m+m+j;
999 buff.fPols[indx++] = 2*nz*m+n;
1000 buff.fPols[indx++] = (nz*2-2)*m+j;
1004 for (k = 0; k < (nz-1); k++) {
1005 for (j = 0; j < n-1; j++) {
1006 buff.fPols[indx++] = c;
1007 buff.fPols[indx++] = 4;
1008 buff.fPols[indx++] = 2*k*m+j;
1009 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j+1;
1010 buff.fPols[indx++] = (2*k+2)*m+j;
1011 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j;
1013 for (j = 0; j < n-1; j++) {
1014 buff.fPols[indx++] = c+1;
1015 buff.fPols[indx++] = 4;
1016 buff.fPols[indx++] = (2*k+1)*m+j;
1017 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j;
1018 buff.fPols[indx++] = (2*k+3)*m+j;
1019 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j+1;
1022 buff.fPols[indx++] = c;
1023 buff.fPols[indx++] = 4;
1024 buff.fPols[indx++] = 2*k*m+j;
1025 buff.fPols[indx++] = nz*2*m+(2*k+2)*n;
1026 buff.fPols[indx++] = (2*k+2)*m+j;
1027 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j;
1029 buff.fPols[indx++] = c+1;
1030 buff.fPols[indx++] = 4;
1031 buff.fPols[indx++] = (2*k+1)*m+j;
1032 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j;
1033 buff.fPols[indx++] = (2*k+3)*m+j;
1034 buff.fPols[indx++] = nz*2*m+(2*k+3)*n;
1042 for (k = 0; k < (nz-1); k++) {
1043 buff.fPols[indx++] = c+2;
1044 buff.fPols[indx++] = 4;
1045 buff.fPols[indx++] = k==0 ? indx2 : indx2+2*nz*n+2*(k-1);
1046 buff.fPols[indx++] = indx2+2*(k+1)*n;
1047 buff.fPols[indx++] = indx2+2*nz*n+2*k;
1048 buff.fPols[indx++] = indx2+(2*k+3)*n;
1050 buff.fPols[indx++] = c+2;
1051 buff.fPols[indx++] = 4;
1052 buff.fPols[indx++] = k==0 ? indx2+n-1 : indx2+2*nz*n+2*(k-1)+1;
1053 buff.fPols[indx++] = indx2+(2*k+3)*n+n-1;
1054 buff.fPols[indx++] = indx2+2*nz*n+2*k+1;
1055 buff.fPols[indx++] = indx2+2*(k+1)*n+n-1;
1057 buff.fPols[indx-8] = indx2+n;
1058 buff.fPols[indx-2] = indx2+2*n-1;
1065 Double_t TGeoPcon::SafetyToSegment(
const Double_t *point, Int_t ipl, Bool_t in, Double_t safmin)
const
1067 Double_t safe = TGeoShape::Big();
1068 if (ipl<0 || ipl>fNz-2)
return (safmin+1.);
1070 Double_t dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
1071 if (dz<1E-9)
return 1E9;
1073 memcpy(ptnew, point, 3*
sizeof(Double_t));
1074 ptnew[2] -= 0.5*(fZ[ipl]+fZ[ipl+1]);
1075 safe = TMath::Abs(ptnew[2])-dz;
1076 if (safe>safmin)
return TGeoShape::Big();
1077 Double_t rmin1 = fRmin[ipl];
1078 Double_t rmax1 = fRmax[ipl];
1079 Double_t rmin2 = fRmin[ipl+1];
1080 Double_t rmax2 = fRmax[ipl+1];
1081 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2))?kTRUE:kFALSE;
1083 if (is_tube) safe = TGeoTubeSeg::SafetyS(ptnew,in,rmin1,rmax1, dz,fPhi1,fPhi1+fDphi,0);
1084 else safe = TGeoConeSeg::SafetyS(ptnew,in,dz,rmin1,rmax1,rmin2,rmax2,fPhi1,fPhi1+fDphi,0);
1086 if (is_tube) safe = TGeoTube::SafetyS(ptnew,in,rmin1,rmax1,dz,0);
1087 else safe = TGeoCone::SafetyS(ptnew,in,dz,rmin1,rmax1,rmin2,rmax2,0);
1098 Double_t TGeoPcon::Safety(
const Double_t *point, Bool_t in)
const
1100 Double_t safmin, saftmp;
1106 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1107 if (ipl==(fNz-1))
return 0;
1108 if (ipl<0)
return 0;
1109 if (ipl>0 && TGeoShape::IsSameWithinTolerance(fZ[ipl-1],fZ[ipl]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[ipl-1])) ipl--;
1110 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
1113 safmin = TMath::Min(point[2]-fZ[ipl-1],fZ[ipl+2]-point[2]);
1114 saftmp = TGeoShape::Big();
1115 if (fDphi<360) saftmp = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi1+fDphi);
1116 if (saftmp<safmin) safmin = saftmp;
1117 Double_t radius = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
1118 if (fRmin[ipl]>0) safmin = TMath::Min(safmin, radius-fRmin[ipl]);
1119 if (fRmin[ipl+1]>0) safmin = TMath::Min(safmin, radius-fRmin[ipl+1]);
1120 safmin = TMath::Min(safmin, fRmax[ipl]-radius);
1121 safmin = TMath::Min(safmin, fRmax[ipl+1]-radius);
1122 if (safmin<0) safmin = 0;
1126 safmin = SafetyToSegment(point, ipl);
1131 if (safmin<1E-6)
return TMath::Abs(safmin);
1153 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
1155 else if (ipl==fNz-1) ipl=fNz-2;
1156 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
1157 if (dz<1E-8 && (ipl+2<fNz)) {
1159 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
1162 safmin = SafetyToSegment(point, ipl, kFALSE);
1163 if (safmin<1E-6)
return TMath::Abs(safmin);
1168 while ((iplane<fNz-1) && saftmp<1E10) {
1169 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
1170 if (saftmp<safmin) safmin=saftmp;
1176 while ((iplane>=0) && saftmp<1E10) {
1177 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
1178 if (saftmp<safmin) safmin=saftmp;
1187 void TGeoPcon::SavePrimitive(std::ostream &out, Option_t * )
1189 if (TObject::TestBit(kGeoSavePrimitive))
return;
1190 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
1191 out <<
" phi1 = " << fPhi1 <<
";" << std::endl;
1192 out <<
" dphi = " << fDphi <<
";" << std::endl;
1193 out <<
" nz = " << fNz <<
";" << std::endl;
1194 out <<
" TGeoPcon *pcon = new TGeoPcon(\"" << GetName() <<
"\",phi1,dphi,nz);" << std::endl;
1195 for (Int_t i=0; i<fNz; i++) {
1196 out <<
" z = " << fZ[i] <<
";" << std::endl;
1197 out <<
" rmin = " << fRmin[i] <<
";" << std::endl;
1198 out <<
" rmax = " << fRmax[i] <<
";" << std::endl;
1199 out <<
" pcon->DefineSection(" << i <<
", z,rmin,rmax);" << std::endl;
1201 out <<
" TGeoShape *" << GetPointerName() <<
" = pcon;" << std::endl;
1202 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
1208 void TGeoPcon::SetDimensions(Double_t *param)
1211 while (fPhi1<0) fPhi1 += 360.;
1213 fNz = (Int_t)param[2];
1215 Error(
"SetDimensions",
"Pcon %s: Number of Z sections must be > 2", GetName());
1218 if (fRmin)
delete [] fRmin;
1219 if (fRmax)
delete [] fRmax;
1220 if (fZ)
delete [] fZ;
1221 fRmin =
new Double_t [fNz];
1222 fRmax =
new Double_t [fNz];
1223 fZ =
new Double_t [fNz];
1224 memset(fRmin, 0, fNz*
sizeof(Double_t));
1225 memset(fRmax, 0, fNz*
sizeof(Double_t));
1226 memset(fZ, 0, fNz*
sizeof(Double_t));
1227 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) fFullPhi = kTRUE;
1228 Double_t phi1 = fPhi1;
1229 Double_t phi2 = phi1+fDphi;
1230 Double_t phim = 0.5*(phi1+phi2);
1231 fC1 = TMath::Cos(phi1*TMath::DegToRad());
1232 fS1 = TMath::Sin(phi1*TMath::DegToRad());
1233 fC2 = TMath::Cos(phi2*TMath::DegToRad());
1234 fS2 = TMath::Sin(phi2*TMath::DegToRad());
1235 fCm = TMath::Cos(phim*TMath::DegToRad());
1236 fSm = TMath::Sin(phim*TMath::DegToRad());
1237 fCdphi = TMath::Cos(0.5*fDphi*TMath::DegToRad());
1239 for (Int_t i=0; i<fNz; i++)
1240 DefineSection(i, param[3+3*i], param[4+3*i], param[5+3*i]);
1246 void TGeoPcon::SetPoints(Double_t *points)
const
1249 Int_t n = gGeoManager->GetNsegments() + 1;
1255 for (i = 0; i < fNz; i++) {
1256 for (j = 0; j < n; j++) {
1257 phi = (fPhi1+j*dphi)*TMath::DegToRad();
1258 points[indx++] = fRmin[i] * TMath::Cos(phi);
1259 points[indx++] = fRmin[i] * TMath::Sin(phi);
1260 points[indx++] = fZ[i];
1262 for (j = 0; j < n; j++) {
1263 phi = (fPhi1+j*dphi)*TMath::DegToRad();
1264 points[indx++] = fRmax[i] * TMath::Cos(phi);
1265 points[indx++] = fRmax[i] * TMath::Sin(phi);
1266 points[indx++] = fZ[i];
1275 void TGeoPcon::SetPoints(Float_t *points)
const
1278 Int_t n = gGeoManager->GetNsegments() + 1;
1284 for (i = 0; i < fNz; i++) {
1285 for (j = 0; j < n; j++) {
1286 phi = (fPhi1+j*dphi)*TMath::DegToRad();
1287 points[indx++] = fRmin[i] * TMath::Cos(phi);
1288 points[indx++] = fRmin[i] * TMath::Sin(phi);
1289 points[indx++] = fZ[i];
1291 for (j = 0; j < n; j++) {
1292 phi = (fPhi1+j*dphi)*TMath::DegToRad();
1293 points[indx++] = fRmax[i] * TMath::Cos(phi);
1294 points[indx++] = fRmax[i] * TMath::Sin(phi);
1295 points[indx++] = fZ[i];
1303 Int_t TGeoPcon::GetNmeshVertices()
const
1305 Int_t n = gGeoManager->GetNsegments()+1;
1306 Int_t numPoints = fNz*2*n;
1313 void TGeoPcon::Sizeof3D()
const
1320 void TGeoPcon::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
1322 Int_t n = gGeoManager->GetNsegments()+1;
1325 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(),360);
1326 nsegs = 4*(nz*n-1+(specialCase == kTRUE));
1327 npols = 2*(nz*n-1+(specialCase == kTRUE));
1333 const TBuffer3D & TGeoPcon::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
1335 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1337 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1339 if (reqSections & TBuffer3D::kRawSizes) {
1340 const Int_t n = gGeoManager->GetNsegments()+1;
1342 Int_t nbPnts = nz*2*n;
1343 if (nz >= 2 && nbPnts > 0) {
1344 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(),360);
1345 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
1346 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
1347 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
1348 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1354 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1355 SetPoints(buffer.fPnts);
1356 if (!buffer.fLocalFrame) {
1357 TransformPoints(buffer.fPnts, buffer.NbPnts());
1360 SetSegsAndPols(buffer);
1361 buffer.SetSectionsValid(TBuffer3D::kRaw);
1370 void TGeoPcon::Streamer(TBuffer &R__b)
1372 if (R__b.IsReading()) {
1373 R__b.ReadClassBuffer(TGeoPcon::Class(),
this);
1374 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) fFullPhi = kTRUE;
1375 Double_t phi1 = fPhi1;
1376 Double_t phi2 = phi1+fDphi;
1377 Double_t phim = 0.5*(phi1+phi2);
1378 fC1 = TMath::Cos(phi1*TMath::DegToRad());
1379 fS1 = TMath::Sin(phi1*TMath::DegToRad());
1380 fC2 = TMath::Cos(phi2*TMath::DegToRad());
1381 fS2 = TMath::Sin(phi2*TMath::DegToRad());
1382 fCm = TMath::Cos(phim*TMath::DegToRad());
1383 fSm = TMath::Sin(phim*TMath::DegToRad());
1384 fCdphi = TMath::Cos(0.5*fDphi*TMath::DegToRad());
1386 R__b.WriteClassBuffer(TGeoPcon::Class(),
this);
1395 void TGeoPcon::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
1397 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
1405 void TGeoPcon::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
1407 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
1413 void TGeoPcon::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1415 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
1421 void TGeoPcon::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1423 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
1431 void TGeoPcon::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
1433 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);