130 SetShapeBit(TGeoShape::kGeoTube);
140 TGeoTube::TGeoTube(Double_t rmin, Double_t rmax, Double_t dz)
143 SetShapeBit(TGeoShape::kGeoTube);
144 SetTubeDimensions(rmin, rmax, dz);
145 if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
146 SetShapeBit(kGeoRunTimeShape);
155 TGeoTube::TGeoTube(
const char *name, Double_t rmin, Double_t rmax, Double_t dz)
156 :TGeoBBox(name, 0, 0, 0)
158 SetShapeBit(TGeoShape::kGeoTube);
159 SetTubeDimensions(rmin, rmax, dz);
160 if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
161 SetShapeBit(kGeoRunTimeShape);
174 TGeoTube::TGeoTube(Double_t *param)
177 SetShapeBit(TGeoShape::kGeoTube);
178 SetDimensions(param);
179 if ((fDz<0) || (fRmin<0) || (fRmax<0)) SetShapeBit(kGeoRunTimeShape);
186 TGeoTube::~TGeoTube()
193 Double_t TGeoTube::Capacity()
const
195 return TGeoTube::Capacity(fRmin,fRmax, fDz);
201 Double_t TGeoTube::Capacity(Double_t rmin, Double_t rmax, Double_t dz)
203 Double_t capacity = 2.*TMath::Pi()*(rmax*rmax-rmin*rmin)*dz;
210 void TGeoTube::ComputeBBox()
219 void TGeoTube::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
222 Double_t rsq = point[0]*point[0]+point[1]*point[1];
223 Double_t r = TMath::Sqrt(rsq);
224 saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
225 saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
226 saf[2] = TMath::Abs(fRmax-r);
227 Int_t i = TMath::LocMin(3,saf);
229 norm[0] = norm[1] = 0.;
230 norm[2] = TMath::Sign(1.,dir[2]);
234 Double_t phi = TMath::ATan2(point[1], point[0]);
235 norm[0] = TMath::Cos(phi);
236 norm[1] = TMath::Sin(phi);
237 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
246 void TGeoTube::ComputeNormalS(
const Double_t *point,
const Double_t *dir, Double_t *norm,
247 Double_t , Double_t , Double_t )
250 Double_t phi = TMath::ATan2(point[1], point[0]);
251 norm[0] = TMath::Cos(phi);
252 norm[1] = TMath::Sin(phi);
253 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
262 Bool_t TGeoTube::Contains(
const Double_t *point)
const
264 if (TMath::Abs(point[2]) > fDz)
return kFALSE;
265 Double_t r2 = point[0]*point[0]+point[1]*point[1];
266 if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax))
return kFALSE;
273 Int_t TGeoTube::DistancetoPrimitive(Int_t px, Int_t py)
275 Int_t n = gGeoManager->GetNsegments();
276 Int_t numPoints = 4*n;
277 if (!HasRmin()) numPoints = 2*(n+1);
278 return ShapeDistancetoPrimitive(numPoints, px, py);
287 Double_t TGeoTube::DistFromInsideS(
const Double_t *point,
const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
289 Double_t sz = TGeoShape::Big();
291 sz = (TMath::Sign(dz, dir[2])-point[2])/dir[2];
292 if (sz<=0)
return 0.0;
295 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
296 if (TMath::Abs(nsq)<TGeoShape::Tolerance())
return sz;
297 Double_t rsq=point[0]*point[0]+point[1]*point[1];
298 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
300 Double_t sr = TGeoShape::Big();
304 if (rsq <= rmin*rmin+TGeoShape::Tolerance()) {
305 if (rdotn<0)
return 0.0;
308 DistToTube(rsq,nsq,rdotn,rmin,b,d);
311 if (sr>0)
return TMath::Min(sz,sr);
317 if (rsq >= rmax*rmax-TGeoShape::Tolerance()) {
318 if (rdotn>=0)
return 0.0;
320 DistToTube(rsq,nsq,rdotn,rmax,b,d);
323 if (sr>0)
return TMath::Min(sz,sr);
332 Double_t TGeoTube::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
334 if (iact<3 && safe) {
335 *safe = Safety(point, kTRUE);
336 if (iact==0)
return TGeoShape::Big();
337 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
340 return DistFromInsideS(point, dir, fRmin, fRmax, fDz);
348 Double_t TGeoTube::DistFromOutsideS(
const Double_t *point,
const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
351 Double_t rmaxsq = rmax*rmax;
352 Double_t rminsq = rmin*rmin;
353 zi = dz - TMath::Abs(point[2]);
354 Double_t s = TGeoShape::Big();
356 Bool_t inz = (zi<0)?kFALSE:kTRUE;
358 if (point[2]*dir[2]>=0)
return TGeoShape::Big();
359 s = -zi/TMath::Abs(dir[2]);
360 xi = point[0]+s*dir[0];
361 yi = point[1]+s*dir[1];
362 Double_t r2=xi*xi+yi*yi;
363 if ((rminsq<=r2) && (r2<=rmaxsq))
return s;
366 Double_t rsq = point[0]*point[0]+point[1]*point[1];
368 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
369 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
371 Bool_t inrmax = kFALSE;
372 Bool_t inrmin = kFALSE;
373 if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
374 if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
375 in = inz & inrmin & inrmax;
378 Bool_t checkout = kFALSE;
379 Double_t r = TMath::Sqrt(rsq);
381 if ((TGeoShape::IsSameWithinTolerance(rmin,0)) || (zi<r-rmin)) {
382 if (point[2]*dir[2]<0)
return 0.0;
383 return TGeoShape::Big();
386 if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
388 if (rdotn>=0)
return TGeoShape::Big();
391 if (TGeoShape::IsSameWithinTolerance(rmin,0))
return 0.0;
392 if (rdotn>=0)
return 0.0;
394 if (TMath::Abs(nsq)<TGeoShape::Tolerance())
return TGeoShape::Big();
395 DistToTube(rsq, nsq, rdotn, rmin, b, d);
399 zi=point[2]+s*dir[2];
400 if (TMath::Abs(zi)<=dz)
return s;
403 return TGeoShape::Big();
406 if (TMath::Abs(nsq)<TGeoShape::Tolerance())
return TGeoShape::Big();
408 DistToTube(rsq, nsq, rdotn, rmax, b, d);
412 zi=point[2]+s*dir[2];
413 if (TMath::Abs(zi)<=dz)
return s;
419 DistToTube(rsq, nsq, rdotn, rmin, b, d);
423 zi=point[2]+s*dir[2];
424 if (TMath::Abs(zi)<=dz)
return s;
428 return TGeoShape::Big();
436 Double_t TGeoTube::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
438 if (iact<3 && safe) {
439 *safe = Safety(point, kFALSE);
440 if (iact==0)
return TGeoShape::Big();
441 if ((iact==1) && (step<=*safe))
return TGeoShape::Big();
444 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
445 if (sdist>=step)
return TGeoShape::Big();
447 return DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
460 void TGeoTube::DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta)
462 Double_t t1 = 1./nsq;
463 Double_t t3=rsq-(radius*radius);
468 delta=TMath::Sqrt(delta);
482 TGeoVolume *TGeoTube::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv,
483 Double_t start, Double_t step)
487 TGeoVolumeMulti *vmulti;
488 TGeoPatternFinder *finder;
491 Double_t end = start+ndiv*step;
494 finder =
new TGeoPatternCylR(voldiv, ndiv, start, end);
495 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
496 voldiv->SetFinder(finder);
497 finder->SetDivIndex(voldiv->GetNdaughters());
498 for (
id=0;
id<ndiv;
id++) {
499 shape =
new TGeoTube(start+
id*step, start+(
id+1)*step, fDz);
500 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
501 vmulti->AddVolume(vol);
503 voldiv->AddNodeOffset(vol,
id, 0, opt.Data());
504 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
508 finder =
new TGeoPatternCylPhi(voldiv, ndiv, start, end);
509 voldiv->SetFinder(finder);
510 finder->SetDivIndex(voldiv->GetNdaughters());
511 shape =
new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
512 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
513 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
514 vmulti->AddVolume(vol);
516 for (
id=0;
id<ndiv;
id++) {
517 voldiv->AddNodeOffset(vol,
id, start+
id*step+step/2, opt.Data());
518 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
522 finder =
new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
523 voldiv->SetFinder(finder);
524 finder->SetDivIndex(voldiv->GetNdaughters());
525 shape =
new TGeoTube(fRmin, fRmax, step/2);
526 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
527 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
528 vmulti->AddVolume(vol);
530 for (
id=0;
id<ndiv;
id++) {
531 voldiv->AddNodeOffset(vol,
id, start+step/2+
id*step, opt.Data());
532 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
536 Error(
"Divide",
"In shape %s wrong axis type for division", GetName());
544 const char *TGeoTube::GetAxisName(Int_t iaxis)
const
561 Double_t TGeoTube::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
590 void TGeoTube::GetBoundingCylinder(Double_t *param)
const
593 param[0] *= param[0];
595 param[1] *= param[1];
604 TGeoShape *TGeoTube::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
606 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
607 Double_t rmin, rmax, dz;
613 mother->GetAxisRange(3,xmin,xmax);
614 if (xmax<0)
return 0;
617 mother->GetAxisRange(1,xmin,xmax);
619 if (xmin<0)
return 0;
623 if (xmax<=0)
return 0;
627 return (
new TGeoTube(GetName(), rmin, rmax, dz));
633 void TGeoTube::InspectShape()
const
635 printf(
"*** Shape %s: TGeoTube ***\n", GetName());
636 printf(
" Rmin = %11.5f\n", fRmin);
637 printf(
" Rmax = %11.5f\n", fRmax);
638 printf(
" dz = %11.5f\n", fDz);
639 printf(
" Bounding box:\n");
640 TGeoBBox::InspectShape();
647 TBuffer3D *TGeoTube::MakeBuffer3D()
const
649 Int_t n = gGeoManager->GetNsegments();
658 TBuffer3D* buff =
new TBuffer3D(TBuffer3DTypes::kGeneric,
659 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
662 SetPoints(buff->fPnts);
663 SetSegsAndPols(*buff);
672 void TGeoTube::SetSegsAndPols(TBuffer3D &buffer)
const
675 Int_t n = gGeoManager->GetNsegments();
676 Int_t c = (((buffer.fColor) %8) -1) * 4;
685 for (i = 0; i < 4; i++) {
686 for (j = 0; j < n; j++) {
688 buffer.fSegs[indx ] = c;
689 buffer.fSegs[indx+1] = i*n+j;
690 buffer.fSegs[indx+2] = i*n+(j+1)%n;
696 for (i = 4; i < 6; i++) {
697 for (j = 0; j < n; j++) {
699 buffer.fSegs[indx ] = c+1;
700 buffer.fSegs[indx+1] = (i-4)*n+j;
701 buffer.fSegs[indx+2] = (i-2)*n+j;
707 for (i = 6; i < 8; i++) {
708 for (j = 0; j < n; j++) {
710 buffer.fSegs[indx ] = c;
711 buffer.fSegs[indx+1] = 2*(i-6)*n+j;
712 buffer.fSegs[indx+2] = (2*(i-6)+1)*n+j;
718 for (j = 0; j < n; j++) {
720 buffer.fPols[indx ] = c;
721 buffer.fPols[indx+1] = 4;
722 buffer.fPols[indx+2] = j;
723 buffer.fPols[indx+3] = 4*n+(j+1)%n;
724 buffer.fPols[indx+4] = 2*n+j;
725 buffer.fPols[indx+5] = 4*n+j;
729 for (j = 0; j < n; j++) {
731 buffer.fPols[indx ] = c+1;
732 buffer.fPols[indx+1] = 4;
733 buffer.fPols[indx+2] = n+j;
734 buffer.fPols[indx+3] = 5*n+j;
735 buffer.fPols[indx+4] = 3*n+j;
736 buffer.fPols[indx+5] = 5*n+(j+1)%n;
740 for (j = 0; j < n; j++) {
742 buffer.fPols[indx ] = c;
743 buffer.fPols[indx+1] = 4;
744 buffer.fPols[indx+2] = j;
745 buffer.fPols[indx+3] = 6*n+j;
746 buffer.fPols[indx+4] = n+j;
747 buffer.fPols[indx+5] = 6*n+(j+1)%n;
751 for (j = 0; j < n; j++) {
753 buffer.fPols[indx ] = c;
754 buffer.fPols[indx+1] = 4;
755 buffer.fPols[indx+2] = 2*n+j;
756 buffer.fPols[indx+3] = 7*n+(j+1)%n;
757 buffer.fPols[indx+4] = 3*n+j;
758 buffer.fPols[indx+5] = 7*n+j;
766 for (i = 0; i < 2; i++) {
767 for (j = 0; j < n; j++) {
769 buffer.fSegs[indx ] = c;
770 buffer.fSegs[indx+1] = 2+i*n+j;
771 buffer.fSegs[indx+2] = 2+i*n+(j+1)%n;
775 for (j = 0; j < n; j++) {
777 buffer.fSegs[indx ] = c+1;
778 buffer.fSegs[indx+1] = 2+j;
779 buffer.fSegs[indx+2] = 2+n+j;
784 for (i = 3; i < 5; i++) {
785 for (j = 0; j < n; j++) {
787 buffer.fSegs[indx ] = c;
788 buffer.fSegs[indx+1] = i-3;
789 buffer.fSegs[indx+2] = 2+(i-3)*n+j;
794 for (j = 0; j < n; j++) {
796 buffer.fPols[indx ] = c+1;
797 buffer.fPols[indx+1] = 4;
798 buffer.fPols[indx+2] = j;
799 buffer.fPols[indx+3] = 2*n+j;
800 buffer.fPols[indx+4] = n+j;
801 buffer.fPols[indx+5] = 2*n+(j+1)%n;
804 for (j = 0; j < n; j++) {
806 buffer.fPols[indx ] = c;
807 buffer.fPols[indx+1] = 3;
808 buffer.fPols[indx+2] = j;
809 buffer.fPols[indx+3] = 3*n+(j+1)%n;
810 buffer.fPols[indx+4] = 3*n+j;
813 for (j = 0; j < n; j++) {
814 indx = 6*n + 5*n + 5*j;
815 buffer.fPols[indx ] = c;
816 buffer.fPols[indx+1] = 3;
817 buffer.fPols[indx+2] = n+j;
818 buffer.fPols[indx+3] = 4*n+j;
819 buffer.fPols[indx+4] = 4*n+(j+1)%n;
827 Double_t TGeoTube::Safety(
const Double_t *point, Bool_t in)
const
830 Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
831 Double_t safe, safrmin, safrmax;
833 safe = fDz-TMath::Abs(point[2]);
836 if (safrmin < safe) safe = safrmin;
839 if (safrmax < safe) safe = safrmax;
841 safe = -fDz+TMath::Abs(point[2]);
844 if (safrmin > safe) safe = safrmin;
847 if (safrmax > safe) safe = safrmax;
852 Double_t rsq = point[0]*point[0]+point[1]*point[1];
853 Double_t r = TMath::Sqrt(rsq);
854 saf[0] = fDz-TMath::Abs(point[2]);
855 saf[1] = (fRmin>1E-10)?(r-fRmin):TGeoShape::Big();
857 if (in)
return saf[TMath::LocMin(3,saf)];
858 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
859 return saf[TMath::LocMax(3,saf)];
867 Double_t TGeoTube::SafetyS(
const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
870 Double_t rsq = point[0]*point[0]+point[1]*point[1];
871 Double_t r = TMath::Sqrt(rsq);
874 saf[0] = dz - point[2];
877 saf[0] = dz + point[2];
880 saf[0] = TGeoShape::Big();
883 saf[0] = dz-TMath::Abs(point[2]);
885 saf[1] = (rmin>1E-10)?(r-rmin):TGeoShape::Big();
888 if (in)
return saf[TMath::LocMin(3,saf)];
889 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
890 return saf[TMath::LocMax(3,saf)];
896 void TGeoTube::SavePrimitive(std::ostream &out, Option_t * )
898 if (TObject::TestBit(kGeoSavePrimitive))
return;
899 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
900 out <<
" rmin = " << fRmin <<
";" << std::endl;
901 out <<
" rmax = " << fRmax <<
";" << std::endl;
902 out <<
" dz = " << fDz <<
";" << std::endl;
903 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoTube(\"" << GetName() <<
"\",rmin,rmax,dz);" << std::endl;
904 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
910 void TGeoTube::SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz)
915 if (fRmin>0 && fRmax>0 && fRmin>=fRmax)
916 Error(
"SetTubeDimensions",
"In shape %s wrong rmin=%g rmax=%g", GetName(), rmin,rmax);
922 void TGeoTube::SetDimensions(Double_t *param)
924 Double_t rmin = param[0];
925 Double_t rmax = param[1];
926 Double_t dz = param[2];
927 SetTubeDimensions(rmin, rmax, dz);
935 Bool_t TGeoTube::GetPointsOnSegments(Int_t npoints, Double_t *array)
const
937 if (npoints > (npoints/2)*2) {
938 Error(
"GetPointsOnSegments",
"Npoints must be even number");
942 if (HasRmin()) nc = (Int_t)TMath::Sqrt(0.5*npoints);
943 else nc = (Int_t)TMath::Sqrt(1.*npoints);
944 Double_t dphi = TMath::TwoPi()/nc;
947 if (HasRmin()) ntop = npoints/2 - nc*(nc-1);
948 else ntop = npoints - nc*(nc-1);
949 Double_t dz = 2*fDz/(nc-1);
954 for (Int_t i=0; i<nc; i++) {
955 if (i == (nc-1)) nphi = ntop;
958 for (Int_t j=0; j<nphi; j++) {
961 array[icrt++] = fRmin * TMath::Cos(phi);
962 array[icrt++] = fRmin * TMath::Sin(phi);
965 array[icrt++] = fRmax * TMath::Cos(phi);
966 array[icrt++] = fRmax * TMath::Sin(phi);
976 void TGeoTube::SetPoints(Double_t *points)
const
980 n = gGeoManager->GetNsegments();
981 Double_t dphi = 360./n;
990 for (j = 0; j < n; j++) {
991 phi = j*dphi*TMath::DegToRad();
992 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
994 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
996 points[indx+6*n] = dz;
1002 for (j = 0; j < n; j++) {
1003 phi = j*dphi*TMath::DegToRad();
1004 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
1006 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
1008 points[indx+6*n]= dz;
1014 points[indx++] = 0.;
1015 points[indx++] = 0.;
1016 points[indx++] = -dz;
1017 points[indx++] = 0.;
1018 points[indx++] = 0.;
1019 points[indx++] = dz;
1022 for (j = 0; j < n; j++) {
1023 phi = j*dphi*TMath::DegToRad();
1024 points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1026 points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1028 points[indx+3*n]= dz;
1039 void TGeoTube::SetPoints(Float_t *points)
const
1043 n = gGeoManager->GetNsegments();
1044 Double_t dphi = 360./n;
1053 for (j = 0; j < n; j++) {
1054 phi = j*dphi*TMath::DegToRad();
1055 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
1057 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
1059 points[indx+6*n] = dz;
1065 for (j = 0; j < n; j++) {
1066 phi = j*dphi*TMath::DegToRad();
1067 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
1069 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
1071 points[indx+6*n]= dz;
1077 points[indx++] = 0.;
1078 points[indx++] = 0.;
1079 points[indx++] = -dz;
1080 points[indx++] = 0.;
1081 points[indx++] = 0.;
1082 points[indx++] = dz;
1085 for (j = 0; j < n; j++) {
1086 phi = j*dphi*TMath::DegToRad();
1087 points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
1089 points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
1091 points[indx+3*n]= dz;
1102 Int_t TGeoTube::GetNmeshVertices()
const
1104 Int_t n = gGeoManager->GetNsegments();
1105 Int_t numPoints = n*4;
1106 if (!HasRmin()) numPoints = 2*(n+1);
1113 void TGeoTube::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
1115 Int_t n = gGeoManager->GetNsegments();
1133 void TGeoTube::Sizeof3D()
const
1140 const TBuffer3D & TGeoTube::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
1142 static TBuffer3DTube buffer;
1143 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1145 if (reqSections & TBuffer3D::kShapeSpecific) {
1146 buffer.fRadiusInner = fRmin;
1147 buffer.fRadiusOuter = fRmax;
1148 buffer.fHalfLength = fDz;
1149 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
1151 if (reqSections & TBuffer3D::kRawSizes) {
1152 Int_t n = gGeoManager->GetNsegments();
1161 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
1162 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1165 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1166 SetPoints(buffer.fPnts);
1167 if (!buffer.fLocalFrame) {
1168 TransformPoints(buffer.fPnts, buffer.NbPnts());
1170 SetSegsAndPols(buffer);
1171 buffer.SetSectionsValid(TBuffer3D::kRaw);
1182 void TGeoTube::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
1184 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
1192 void TGeoTube::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
1194 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
1200 void TGeoTube::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1202 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
1208 void TGeoTube::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1210 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
1218 void TGeoTube::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
1220 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
1223 ClassImp(TGeoTubeSeg);
1228 TGeoTubeSeg::TGeoTubeSeg()
1230 fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1232 SetShapeBit(TGeoShape::kGeoTubeSeg);
1239 TGeoTubeSeg::TGeoTubeSeg(Double_t rmin, Double_t rmax, Double_t dz,
1240 Double_t phiStart, Double_t phiEnd)
1241 :TGeoTube(rmin, rmax, dz),
1242 fPhi1(0.), fPhi2(0.), fS1(0.), fC1(0.), fS2(0.), fC2(0.), fSm(0.), fCm(0.), fCdfi(0.)
1244 SetShapeBit(TGeoShape::kGeoTubeSeg);
1245 SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1253 TGeoTubeSeg::TGeoTubeSeg(
const char *name, Double_t rmin, Double_t rmax, Double_t dz,
1254 Double_t phiStart, Double_t phiEnd)
1255 :TGeoTube(name, rmin, rmax, dz)
1257 SetShapeBit(TGeoShape::kGeoTubeSeg);
1258 SetTubsDimensions(rmin, rmax, dz, phiStart, phiEnd);
1270 TGeoTubeSeg::TGeoTubeSeg(Double_t *param)
1273 SetShapeBit(TGeoShape::kGeoTubeSeg);
1274 SetDimensions(param);
1281 TGeoTubeSeg::~TGeoTubeSeg()
1288 void TGeoTubeSeg::AfterStreamer()
1296 void TGeoTubeSeg::InitTrigonometry()
1298 Double_t phi1 = fPhi1*TMath::DegToRad();
1299 Double_t phi2 = fPhi2*TMath::DegToRad();
1300 fC1 = TMath::Cos(phi1);
1301 fS1 = TMath::Sin(phi1);
1302 fC2 = TMath::Cos(phi2);
1303 fS2 = TMath::Sin(phi2);
1304 Double_t fio = 0.5*(phi1+phi2);
1305 fCm = TMath::Cos(fio);
1306 fSm = TMath::Sin(fio);
1307 Double_t dfi = 0.5*(phi2-phi1);
1308 fCdfi = TMath::Cos(dfi);
1314 Double_t TGeoTubeSeg::Capacity()
const
1316 return TGeoTubeSeg::Capacity(fRmin,fRmax,fDz,fPhi1,fPhi2);
1322 Double_t TGeoTubeSeg::Capacity(Double_t rmin, Double_t rmax, Double_t dz, Double_t phiStart, Double_t phiEnd)
1324 Double_t capacity = TMath::Abs(phiEnd-phiStart)*TMath::DegToRad()*(rmax*rmax-rmin*rmin)*dz;
1331 void TGeoTubeSeg::ComputeBBox()
1344 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
1345 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
1346 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
1347 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
1349 Double_t dp = fPhi2-fPhi1;
1351 Double_t ddp = -fPhi1;
1352 if (ddp<0) ddp+= 360;
1353 if (ddp>360) ddp-=360;
1354 if (ddp<=dp) xmax = fRmax;
1356 if (ddp<0) ddp+= 360;
1357 if (ddp>360) ddp-=360;
1358 if (ddp<=dp) ymax = fRmax;
1360 if (ddp<0) ddp+= 360;
1361 if (ddp>360) ddp-=360;
1362 if (ddp<=dp) xmin = -fRmax;
1364 if (ddp<0) ddp+= 360;
1365 if (ddp>360) ddp-=360;
1366 if (ddp<=dp) ymin = -fRmax;
1367 fOrigin[0] = (xmax+xmin)/2;
1368 fOrigin[1] = (ymax+ymin)/2;
1370 fDX = (xmax-xmin)/2;
1371 fDY = (ymax-ymin)/2;
1378 void TGeoTubeSeg::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
1381 Double_t rsq = point[0]*point[0]+point[1]*point[1];
1382 Double_t r = TMath::Sqrt(rsq);
1383 saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
1384 saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
1385 saf[2] = TMath::Abs(fRmax-r);
1386 Int_t i = TMath::LocMin(3,saf);
1387 if (((fPhi2-fPhi1)<360.) && TGeoShape::IsCloseToPhi(saf[i], point,fC1,fS1,fC2,fS2)) {
1388 TGeoShape::NormalPhi(point,dir,norm,fC1,fS1,fC2,fS2);
1392 norm[0] = norm[1] = 0.;
1393 norm[2] = TMath::Sign(1.,dir[2]);
1397 Double_t phi = TMath::ATan2(point[1], point[0]);
1398 norm[0] = TMath::Cos(phi);
1399 norm[1] = TMath::Sin(phi);
1400 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1409 void TGeoTubeSeg::ComputeNormalS(
const Double_t *point,
const Double_t *dir, Double_t *norm,
1410 Double_t rmin, Double_t rmax, Double_t ,
1411 Double_t c1, Double_t s1, Double_t c2, Double_t s2)
1414 Double_t rsq = point[0]*point[0]+point[1]*point[1];
1415 Double_t r = TMath::Sqrt(rsq);
1416 saf[0] = (rmin>1E-10)?TMath::Abs(r-rmin):TGeoShape::Big();
1417 saf[1] = TMath::Abs(rmax-r);
1418 Int_t i = TMath::LocMin(2,saf);
1419 if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
1420 TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
1424 Double_t phi = TMath::ATan2(point[1], point[0]);
1425 norm[0] = TMath::Cos(phi);
1426 norm[1] = TMath::Sin(phi);
1427 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
1437 Bool_t TGeoTubeSeg::Contains(
const Double_t *point)
const
1439 if (!TGeoTube::Contains(point))
return kFALSE;
1440 return IsInPhiRange(point, fPhi1, fPhi2);
1446 Int_t TGeoTubeSeg::DistancetoPrimitive(Int_t px, Int_t py)
1448 Int_t n = gGeoManager->GetNsegments()+1;
1449 const Int_t numPoints = 4*n;
1450 return ShapeDistancetoPrimitive(numPoints, px, py);
1458 Double_t TGeoTubeSeg::DistFromInsideS(
const Double_t *point,
const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
1459 Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
1461 Double_t stube = TGeoTube::DistFromInsideS(point,dir,rmin,rmax,dz);
1462 if (stube<=0)
return 0.0;
1463 Double_t sfmin = TGeoShape::Big();
1464 Double_t rsq = point[0]*point[0]+point[1]*point[1];
1465 Double_t r = TMath::Sqrt(rsq);
1466 Double_t cpsi=point[0]*cm+point[1]*sm;
1467 if (cpsi>r*cdfi+TGeoShape::Tolerance()) {
1468 sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
1469 return TMath::Min(stube,sfmin);
1473 Double_t ddotn, xi, yi;
1474 if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
1475 ddotn = s1*dir[0]-c1*dir[1];
1476 if (ddotn>=0)
return 0.0;
1477 ddotn = -s2*dir[0]+c2*dir[1];
1478 if (ddotn<=0)
return stube;
1479 sfmin = s2*point[0]-c2*point[1];
1480 if (sfmin<=0)
return stube;
1482 if (sfmin >= stube)
return stube;
1483 xi = point[0]+sfmin*dir[0];
1484 yi = point[1]+sfmin*dir[1];
1485 if (yi*cm-xi*sm<0)
return stube;
1488 ddotn = -s2*dir[0]+c2*dir[1];
1489 if (ddotn>=0)
return 0.0;
1490 ddotn = s1*dir[0]-c1*dir[1];
1491 if (ddotn<=0)
return stube;
1492 sfmin = -s1*point[0]+c1*point[1];
1493 if (sfmin<=0)
return stube;
1495 if (sfmin >= stube)
return stube;
1496 xi = point[0]+sfmin*dir[0];
1497 yi = point[1]+sfmin*dir[1];
1498 if (yi*cm-xi*sm>0)
return stube;
1506 Double_t TGeoTubeSeg::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
1508 if (iact<3 && safe) {
1509 *safe = SafetyS(point, kTRUE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1510 if (iact==0)
return TGeoShape::Big();
1511 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
1513 if ((fPhi2-fPhi1)>=360.)
return TGeoTube::DistFromInsideS(point,dir,fRmin,fRmax,fDz);
1516 return TGeoTubeSeg::DistFromInsideS(point,dir,fRmin,fRmax,fDz,fC1,fS1,fC2,fS2,fCm,fSm,fCdfi);
1523 Double_t TGeoTubeSeg::DistFromOutsideS(
const Double_t *point,
const Double_t *dir, Double_t rmin, Double_t rmax,
1524 Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2,
1525 Double_t cm, Double_t sm, Double_t cdfi)
1529 Double_t xi, yi, zi;
1530 zi = dz - TMath::Abs(point[2]);
1531 Double_t rmaxsq = rmax*rmax;
1532 Double_t rminsq = rmin*rmin;
1533 Double_t s = TGeoShape::Big();
1534 Double_t snxt=TGeoShape::Big();
1536 Bool_t inz = (zi<0)?kFALSE:kTRUE;
1538 if (point[2]*dir[2]>=0)
return TGeoShape::Big();
1539 s = -zi/TMath::Abs(dir[2]);
1540 xi = point[0]+s*dir[0];
1541 yi = point[1]+s*dir[1];
1543 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1544 cpsi=(xi*cm+yi*sm)/TMath::Sqrt(r2);
1545 if (cpsi>=cdfi)
return s;
1550 Double_t rsq = point[0]*point[0]+point[1]*point[1];
1551 Double_t r = TMath::Sqrt(rsq);
1552 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
1553 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
1555 Bool_t inrmax = kFALSE;
1556 Bool_t inrmin = kFALSE;
1557 Bool_t inphi = kFALSE;
1558 if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
1559 if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
1560 cpsi=point[0]*cm+point[1]*sm;
1561 if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
1562 in = inz & inrmin & inrmax & inphi;
1565 Bool_t checkout = kFALSE;
1566 Double_t safphi = (cpsi-r*cdfi)*TMath::Sqrt(1.-cdfi*cdfi);
1570 if (TGeoShape::IsSameWithinTolerance(rmin,0) || (zi<r-rmin)) {
1572 if (point[2]*dir[2]<0)
return 0.0;
1573 return TGeoShape::Big();
1577 if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
1579 if (checkout && (rmax-r<safphi)) {
1580 if (rdotn>=0)
return TGeoShape::Big();
1583 if (TMath::Abs(nsq)<TGeoShape::Tolerance())
return TGeoShape::Big();
1585 if (TGeoShape::IsSameWithinTolerance(rmin,0) || (safphi<r-rmin)) {
1589 if (point[0]*c1 + point[1]*s1 > point[0]*c2 + point[1]*s2) {
1590 un = dir[0]*s1-dir[1]*c1;
1591 if (un < 0)
return 0.0;
1592 if (cdfi>=0)
return TGeoShape::Big();
1593 un = -dir[0]*s2+dir[1]*c2;
1595 s = -point[0]*s2+point[1]*c2;
1598 zi = point[2]+s*dir[2];
1599 if (TMath::Abs(zi)<=dz) {
1600 xi = point[0]+s*dir[0];
1601 yi = point[1]+s*dir[1];
1603 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1604 if ((yi*cm-xi*sm)>0)
return s;
1610 un = -dir[0]*s2+dir[1]*c2;
1611 if (un < 0)
return 0.0;
1612 if (cdfi>=0)
return TGeoShape::Big();
1613 un = dir[0]*s1-dir[1]*c1;
1615 s = point[0]*s1-point[1]*c1;
1618 zi = point[2]+s*dir[2];
1619 if (TMath::Abs(zi)<=dz) {
1620 xi = point[0]+s*dir[0];
1621 yi = point[1]+s*dir[1];
1623 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1624 if ((yi*cm-xi*sm)<0)
return s;
1631 if (rdotn>=0)
return TGeoShape::Big();
1632 if (cdfi>=0)
return TGeoShape::Big();
1633 DistToTube(rsq, nsq, rdotn, rmin, b, d);
1637 zi=point[2]+s*dir[2];
1638 if (TMath::Abs(zi)<=dz) {
1639 xi=point[0]+s*dir[0];
1640 yi=point[1]+s*dir[1];
1641 if ((xi*cm+yi*sm) >= rmin*cdfi)
return s;
1645 return TGeoShape::Big();
1648 if (rdotn>=0)
return 0.0;
1649 DistToTube(rsq, nsq, rdotn, rmin, b, d);
1653 zi=point[2]+s*dir[2];
1654 if (TMath::Abs(zi)<=dz) {
1656 xi=point[0]+s*dir[0];
1657 yi=point[1]+s*dir[1];
1659 if ((xi*cm+yi*sm) >= rmin*cdfi)
return s;
1661 Double_t un=-dir[0]*s1+dir[1]*c1;
1663 s=point[0]*s1-point[1]*c1;
1666 zi=point[2]+s*dir[2];
1667 if (TMath::Abs(zi)<=dz) {
1668 xi=point[0]+s*dir[0];
1669 yi=point[1]+s*dir[1];
1671 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1672 if ((yi*cm-xi*sm)<=0) {
1679 un=dir[0]*s2-dir[1]*c2;
1681 s=(point[1]*c2-point[0]*s2)/un;
1682 if (s>=0 && s<snxt) {
1683 zi=point[2]+s*dir[2];
1684 if (TMath::Abs(zi)<=dz) {
1685 xi=point[0]+s*dir[0];
1686 yi=point[1]+s*dir[1];
1688 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1689 if ((yi*cm-xi*sm)>=0) {
1700 return TGeoShape::Big();
1703 if (TMath::Abs(nsq)<TGeoShape::Tolerance())
return TGeoShape::Big();
1704 if (rsq>=rmax*rmax) {
1705 if (rdotn>=0)
return TGeoShape::Big();
1706 TGeoTube::DistToTube(rsq, nsq, rdotn, rmax, b, d);
1710 zi=point[2]+s*dir[2];
1711 if (TMath::Abs(zi)<=dz) {
1712 xi=point[0]+s*dir[0];
1713 yi=point[1]+s*dir[1];
1715 if (cpsi>=rmax*cdfi)
return s;
1722 TGeoTube::DistToTube(rsq, nsq, rdotn, rmin, b, d);
1726 zi=point[2]+s*dir[2];
1727 if (TMath::Abs(zi)<=dz) {
1728 xi=point[0]+s*dir[0];
1729 yi=point[1]+s*dir[1];
1731 if (cpsi>=rmin*cdfi) snxt=s;
1737 Double_t un=-dir[0]*s1+dir[1]*c1;
1739 s=point[0]*s1-point[1]*c1;
1742 zi=point[2]+s*dir[2];
1743 if (TMath::Abs(zi)<=dz) {
1744 xi=point[0]+s*dir[0];
1745 yi=point[1]+s*dir[1];
1747 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1748 if ((yi*cm-xi*sm)<=0) {
1755 un=dir[0]*s2-dir[1]*c2;
1757 s=point[1]*c2-point[0]*s2;
1760 zi=point[2]+s*dir[2];
1761 if (TMath::Abs(zi)<=dz) {
1762 xi=point[0]+s*dir[0];
1763 yi=point[1]+s*dir[1];
1765 if ((rminsq<=r2) && (r2<=rmaxsq)) {
1766 if ((yi*cm-xi*sm)>=0) {
1780 Double_t TGeoTubeSeg::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
1782 if (iact<3 && safe) {
1783 *safe = SafetyS(point, kFALSE, fRmin, fRmax, fDz, fPhi1, fPhi2);
1784 if (iact==0)
return TGeoShape::Big();
1785 if ((iact==1) && (step<=*safe))
return TGeoShape::Big();
1788 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
1789 if (sdist>=step)
return TGeoShape::Big();
1790 if ((fPhi2-fPhi1)>=360.)
return TGeoTube::DistFromOutsideS(point,dir,fRmin,fRmax,fDz);
1793 return TGeoTubeSeg::DistFromOutsideS(point, dir, fRmin, fRmax, fDz, fC1, fS1, fC2, fS2, fCm, fSm, fCdfi);
1804 TGeoVolume *TGeoTubeSeg::Divide(TGeoVolume *voldiv,
const char *divname, Int_t iaxis, Int_t ndiv,
1805 Double_t start, Double_t step)
1809 TGeoVolumeMulti *vmulti;
1810 TGeoPatternFinder *finder;
1814 Double_t end = start+ndiv*step;
1817 finder =
new TGeoPatternCylR(voldiv, ndiv, start, end);
1818 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1819 voldiv->SetFinder(finder);
1820 finder->SetDivIndex(voldiv->GetNdaughters());
1821 for (
id=0;
id<ndiv;
id++) {
1822 shape =
new TGeoTubeSeg(start+
id*step, start+(
id+1)*step, fDz, fPhi1, fPhi2);
1823 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
1824 vmulti->AddVolume(vol);
1826 voldiv->AddNodeOffset(vol,
id, 0, opt.Data());
1827 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1832 if (dphi<0) dphi+=360.;
1833 if (step<=0) {step=dphi/ndiv; start=fPhi1; end=fPhi2;}
1834 finder =
new TGeoPatternCylPhi(voldiv, ndiv, start, end);
1835 voldiv->SetFinder(finder);
1836 finder->SetDivIndex(voldiv->GetNdaughters());
1837 shape =
new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
1838 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
1839 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1840 vmulti->AddVolume(vol);
1842 for (
id=0;
id<ndiv;
id++) {
1843 voldiv->AddNodeOffset(vol,
id, start+
id*step+step/2, opt.Data());
1844 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1848 finder =
new TGeoPatternZ(voldiv, ndiv, start, end);
1849 voldiv->SetFinder(finder);
1850 finder->SetDivIndex(voldiv->GetNdaughters());
1851 shape =
new TGeoTubeSeg(fRmin, fRmax, step/2, fPhi1, fPhi2);
1852 vol =
new TGeoVolume(divname, shape, voldiv->GetMedium());
1853 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
1854 vmulti->AddVolume(vol);
1856 for (
id=0;
id<ndiv;
id++) {
1857 voldiv->AddNodeOffset(vol,
id, start+step/2+
id*step, opt.Data());
1858 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
1862 Error(
"Divide",
"In shape %s wrong axis type for division", GetName());
1870 Double_t TGeoTubeSeg::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
1899 void TGeoTubeSeg::GetBoundingCylinder(Double_t *param)
const
1902 param[0] *= param[0];
1904 param[1] *= param[1];
1913 TGeoShape *TGeoTubeSeg::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
1915 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
1916 if (!mother->TestShapeBit(kGeoTube)) {
1917 Error(
"GetMakeRuntimeShape",
"Invalid mother for shape %s", GetName());
1920 Double_t rmin, rmax, dz;
1924 if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
1926 rmin = ((TGeoTube*)mother)->GetRmin();
1927 if ((fRmax<0) || (fRmax<=fRmin))
1928 rmax = ((TGeoTube*)mother)->GetRmax();
1930 return (
new TGeoTubeSeg(GetName(),rmin, rmax, dz, fPhi1, fPhi2));
1936 void TGeoTubeSeg::InspectShape()
const
1938 printf(
"*** Shape %s: TGeoTubeSeg ***\n", GetName());
1939 printf(
" Rmin = %11.5f\n", fRmin);
1940 printf(
" Rmax = %11.5f\n", fRmax);
1941 printf(
" dz = %11.5f\n", fDz);
1942 printf(
" phi1 = %11.5f\n", fPhi1);
1943 printf(
" phi2 = %11.5f\n", fPhi2);
1944 printf(
" Bounding box:\n");
1945 TGeoBBox::InspectShape();
1952 TBuffer3D *TGeoTubeSeg::MakeBuffer3D()
const
1954 Int_t n = gGeoManager->GetNsegments()+1;
1956 Int_t nbSegs = 2*nbPnts;
1957 Int_t nbPols = nbPnts-2;
1959 TBuffer3D* buff =
new TBuffer3D(TBuffer3DTypes::kGeneric,
1960 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
1963 SetPoints(buff->fPnts);
1964 SetSegsAndPols(*buff);
1973 void TGeoTubeSeg::SetSegsAndPols(TBuffer3D &buff)
const
1976 Int_t n = gGeoManager->GetNsegments()+1;
1977 Int_t c = GetBasicColor();
1979 memset(buff.fSegs, 0, buff.NbSegs()*3*
sizeof(Int_t));
1980 for (i = 0; i < 4; i++) {
1981 for (j = 1; j < n; j++) {
1982 buff.fSegs[(i*n+j-1)*3 ] = c;
1983 buff.fSegs[(i*n+j-1)*3+1] = i*n+j-1;
1984 buff.fSegs[(i*n+j-1)*3+2] = i*n+j;
1987 for (i = 4; i < 6; i++) {
1988 for (j = 0; j < n; j++) {
1989 buff.fSegs[(i*n+j)*3 ] = c+1;
1990 buff.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
1991 buff.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
1994 for (i = 6; i < 8; i++) {
1995 for (j = 0; j < n; j++) {
1996 buff.fSegs[(i*n+j)*3 ] = c;
1997 buff.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
1998 buff.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
2003 memset(buff.fPols, 0, buff.NbPols()*6*
sizeof(Int_t));
2005 for (j = 0; j < n-1; j++) {
2006 buff.fPols[indx++] = c;
2007 buff.fPols[indx++] = 4;
2008 buff.fPols[indx++] = (4+i)*n+j+1;
2009 buff.fPols[indx++] = (2+i)*n+j;
2010 buff.fPols[indx++] = (4+i)*n+j;
2011 buff.fPols[indx++] = i*n+j;
2014 for (j = 0; j < n-1; j++) {
2015 buff.fPols[indx++] = c;
2016 buff.fPols[indx++] = 4;
2017 buff.fPols[indx++] = i*n+j;
2018 buff.fPols[indx++] = (4+i)*n+j;
2019 buff.fPols[indx++] = (2+i)*n+j;
2020 buff.fPols[indx++] = (4+i)*n+j+1;
2023 for (j = 0; j < n-1; j++) {
2024 buff.fPols[indx++] = c+i;
2025 buff.fPols[indx++] = 4;
2026 buff.fPols[indx++] = (i-2)*2*n+j;
2027 buff.fPols[indx++] = (4+i)*n+j;
2028 buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2029 buff.fPols[indx++] = (4+i)*n+j+1;
2032 for (j = 0; j < n-1; j++) {
2033 buff.fPols[indx++] = c+i;
2034 buff.fPols[indx++] = 4;
2035 buff.fPols[indx++] = (4+i)*n+j+1;
2036 buff.fPols[indx++] = ((i-2)*2+1)*n+j;
2037 buff.fPols[indx++] = (4+i)*n+j;
2038 buff.fPols[indx++] = (i-2)*2*n+j;
2040 buff.fPols[indx++] = c+2;
2041 buff.fPols[indx++] = 4;
2042 buff.fPols[indx++] = 6*n;
2043 buff.fPols[indx++] = 4*n;
2044 buff.fPols[indx++] = 7*n;
2045 buff.fPols[indx++] = 5*n;
2046 buff.fPols[indx++] = c+2;
2047 buff.fPols[indx++] = 4;
2048 buff.fPols[indx++] = 6*n-1;
2049 buff.fPols[indx++] = 8*n-1;
2050 buff.fPols[indx++] = 5*n-1;
2051 buff.fPols[indx++] = 7*n-1;
2058 Double_t TGeoTubeSeg::Safety(
const Double_t *point, Bool_t in)
const
2060 Double_t safe = TGeoShape::Big();
2062 Double_t rsq = point[0]*point[0]+point[1]*point[1];
2063 Double_t r = TMath::Sqrt(rsq);
2065 saf[0] = fDz-TMath::Abs(point[2]);
2068 safe = saf[TMath::LocMin(3,saf)];
2069 if ((fPhi2-fPhi1)>=360.)
return safe;
2070 Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2071 return TMath::Min(safe, safphi);
2074 Bool_t inphi = kFALSE;
2075 Double_t cpsi=point[0]*fCm+point[1]*fSm;
2076 saf[0] = TMath::Abs(point[2])-fDz;
2077 if (cpsi>r*fCdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2081 safe = saf[TMath::LocMax(3,saf)];
2082 safe = TMath::Max(0., safe);
2088 Double_t rproj = TMath::Max(point[0]*fC1+point[1]*fS1, point[0]*fC2+point[1]*fS2);
2089 saf[1] = fRmin-rproj;
2090 saf[2] = rproj-fRmax;
2091 safe = TMath::Max(saf[1], saf[2]);
2092 if ((fPhi2-fPhi1)>=360.)
return TMath::Max(safe,saf[0]);
2095 safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2096 return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2098 Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
2099 return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2105 Double_t TGeoTubeSeg::SafetyS(
const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz,
2106 Double_t phi1d, Double_t phi2d, Int_t skipz)
2108 Double_t safe = TGeoShape::Big();
2110 Double_t rsq = point[0]*point[0]+point[1]*point[1];
2111 Double_t r = TMath::Sqrt(rsq);
2115 saf[0] = dz - point[2];
2118 saf[0] = dz + point[2];
2121 saf[0] = TGeoShape::Big();
2124 saf[0] = dz-TMath::Abs(point[2]);
2130 safe = saf[TMath::LocMin(3,saf)];
2131 if ((phi2d-phi1d)>=360.)
return safe;
2132 Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2133 return TMath::Min(safe, safphi);
2137 Bool_t inphi = kFALSE;
2138 Double_t phi1 = phi1d*TMath::DegToRad();
2139 Double_t phi2 = phi2d*TMath::DegToRad();
2141 Double_t fio = 0.5*(phi1+phi2);
2142 Double_t cm = TMath::Cos(fio);
2143 Double_t sm = TMath::Sin(fio);
2144 Double_t cpsi=point[0]*cm+point[1]*sm;
2145 Double_t dfi = 0.5*(phi2-phi1);
2146 Double_t cdfi = TMath::Cos(dfi);
2147 if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
2151 safe = saf[TMath::LocMax(3,saf)];
2152 safe = TMath::Max(0., safe);
2158 Double_t c1 = TMath::Cos(phi1);
2159 Double_t s1 = TMath::Sin(phi1);
2160 Double_t c2 = TMath::Cos(phi2);
2161 Double_t s2 = TMath::Sin(phi2);
2163 Double_t rproj = TMath::Max(point[0]*c1+point[1]*s1, point[0]*c2+point[1]*s2);
2164 saf[1] = rmin-rproj;
2165 saf[2] = rproj-rmax;
2166 safe = TMath::Max(saf[1], saf[2]);
2167 if ((phi2d-phi1d)>=360.)
return TMath::Max(safe,saf[0]);
2170 safe = TMath::Sqrt(rsq-rproj*rproj+safe*safe);
2171 return (saf[0]<0) ? safe : TMath::Sqrt(safe*safe+saf[0]*saf[0]);
2173 Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1d,phi2d);
2174 return (saf[0]<0) ? safphi : TMath::Sqrt(saf[0]*saf[0]+safphi*safphi);
2180 void TGeoTubeSeg::SavePrimitive(std::ostream &out, Option_t * )
2182 if (TObject::TestBit(kGeoSavePrimitive))
return;
2183 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
2184 out <<
" rmin = " << fRmin <<
";" << std::endl;
2185 out <<
" rmax = " << fRmax <<
";" << std::endl;
2186 out <<
" dz = " << fDz <<
";" << std::endl;
2187 out <<
" phi1 = " << fPhi1 <<
";" << std::endl;
2188 out <<
" phi2 = " << fPhi2 <<
";" << std::endl;
2189 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoTubeSeg(\"" << GetName() <<
"\",rmin,rmax,dz,phi1,phi2);" << std::endl;
2190 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
2197 void TGeoTubeSeg::SetTubsDimensions(Double_t rmin, Double_t rmax, Double_t dz,
2198 Double_t phiStart, Double_t phiEnd)
2204 if (fPhi1 < 0) fPhi1 += 360.;
2206 while (fPhi2<=fPhi1) fPhi2+=360.;
2207 if (TGeoShape::IsSameWithinTolerance(fPhi1,fPhi2)) Fatal(
"SetTubsDimensions",
"In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
2214 void TGeoTubeSeg::SetDimensions(Double_t *param)
2216 Double_t rmin = param[0];
2217 Double_t rmax = param[1];
2218 Double_t dz = param[2];
2219 Double_t phi1 = param[3];
2220 Double_t phi2 = param[4];
2221 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
2229 Bool_t TGeoTubeSeg::GetPointsOnSegments(Int_t npoints, Double_t *array)
const
2231 if (npoints > (npoints/2)*2) {
2232 Error(
"GetPointsOnSegments",
"Npoints must be even number");
2235 Int_t nc = (Int_t)TMath::Sqrt(0.5*npoints);
2236 Double_t dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nc-1);
2238 Double_t phi1 = fPhi1 * TMath::DegToRad();
2239 Int_t ntop = npoints/2 - nc*(nc-1);
2240 Double_t dz = 2*fDz/(nc-1);
2245 for (Int_t i=0; i<nc; i++) {
2248 dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nphi-1);
2252 for (Int_t j=0; j<nphi; j++) {
2253 phi = phi1 + j*dphi;
2254 array[icrt++] = fRmin * TMath::Cos(phi);
2255 array[icrt++] = fRmin * TMath::Sin(phi);
2257 array[icrt++] = fRmax * TMath::Cos(phi);
2258 array[icrt++] = fRmax * TMath::Sin(phi);
2268 void TGeoTubeSeg::SetPoints(Double_t *points)
const
2272 Double_t phi, phi1, phi2, dphi;
2275 if (phi2<phi1) phi2+=360.;
2276 n = gGeoManager->GetNsegments()+1;
2278 dphi = (phi2-phi1)/(n-1);
2284 for (j = 0; j < n; j++) {
2285 phi = (phi1+j*dphi)*TMath::DegToRad();
2286 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2288 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2290 points[indx+6*n] = dz;
2294 for (j = 0; j < n; j++) {
2295 phi = (phi1+j*dphi)*TMath::DegToRad();
2296 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2298 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2300 points[indx+6*n]= dz;
2310 void TGeoTubeSeg::SetPoints(Float_t *points)
const
2314 Double_t phi, phi1, phi2, dphi;
2317 if (phi2<phi1) phi2+=360.;
2318 n = gGeoManager->GetNsegments()+1;
2320 dphi = (phi2-phi1)/(n-1);
2326 for (j = 0; j < n; j++) {
2327 phi = (phi1+j*dphi)*TMath::DegToRad();
2328 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
2330 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
2332 points[indx+6*n] = dz;
2336 for (j = 0; j < n; j++) {
2337 phi = (phi1+j*dphi)*TMath::DegToRad();
2338 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
2340 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
2342 points[indx+6*n]= dz;
2352 void TGeoTubeSeg::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
2354 Int_t n = gGeoManager->GetNsegments()+1;
2363 Int_t TGeoTubeSeg::GetNmeshVertices()
const
2365 Int_t n = gGeoManager->GetNsegments()+1;
2366 Int_t numPoints = n*4;
2373 void TGeoTubeSeg::Sizeof3D()
const
2380 const TBuffer3D & TGeoTubeSeg::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
2382 static TBuffer3DTubeSeg buffer;
2383 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
2385 if (reqSections & TBuffer3D::kShapeSpecific) {
2387 buffer.fRadiusInner = fRmin;
2388 buffer.fRadiusOuter = fRmax;
2389 buffer.fHalfLength = fDz;
2390 buffer.fPhiMin = fPhi1;
2391 buffer.fPhiMax = fPhi2;
2392 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
2394 if (reqSections & TBuffer3D::kRawSizes) {
2395 Int_t n = gGeoManager->GetNsegments()+1;
2397 Int_t nbSegs = 2*nbPnts;
2398 Int_t nbPols = nbPnts-2;
2399 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
2400 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
2403 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
2404 SetPoints(buffer.fPnts);
2405 if (!buffer.fLocalFrame) {
2406 TransformPoints(buffer.fPnts, buffer.NbPnts());
2408 SetSegsAndPols(buffer);
2409 buffer.SetSectionsValid(TBuffer3D::kRaw);
2420 void TGeoTubeSeg::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
2422 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
2430 void TGeoTubeSeg::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
2432 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
2438 void TGeoTubeSeg::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
2440 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
2446 void TGeoTubeSeg::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
2448 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
2456 void TGeoTubeSeg::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
2458 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
2463 TGeoCtub::TGeoCtub()
2466 fNlow[0] = fNlow[1] = fNhigh[0] = fNhigh[1] = 0.;
2474 TGeoCtub::TGeoCtub(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
2475 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
2476 :TGeoTubeSeg(rmin, rmax, dz, phi1, phi2)
2484 SetShapeBit(kGeoCtub);
2491 TGeoCtub::TGeoCtub(
const char *name, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
2492 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
2493 :TGeoTubeSeg(name, rmin, rmax, dz, phi1, phi2)
2501 SetShapeBit(kGeoCtub);
2508 TGeoCtub::TGeoCtub(Double_t *params)
2509 :TGeoTubeSeg(0,0,0,0,0)
2511 SetCtubDimensions(params[0], params[1], params[2], params[3], params[4], params[5],
2512 params[6], params[7], params[8], params[9], params[10]);
2513 SetShapeBit(kGeoCtub);
2519 TGeoCtub::~TGeoCtub()
2526 Double_t TGeoCtub::Capacity()
const
2528 Double_t capacity = TGeoTubeSeg::Capacity();
2535 void TGeoCtub::ComputeBBox()
2537 TGeoTubeSeg::ComputeBBox();
2538 if ((fNlow[2]>-(1E-10)) || (fNhigh[2]<1E-10)) {
2539 Error(
"ComputeBBox",
"In shape %s wrong definition of cut planes", GetName());
2542 Double_t xc=0, yc=0;
2543 Double_t zmin=0, zmax=0;
2547 Double_t phi_low = TMath::ATan2(fNlow[1], fNlow[0]) *TMath::RadToDeg();
2548 Double_t phi_hi = TMath::ATan2(fNhigh[1], fNhigh[0]) *TMath::RadToDeg();
2549 Bool_t in_range_low = kFALSE;
2550 Bool_t in_range_hi = kFALSE;
2553 for (i=0; i<2; i++) {
2554 if (phi_low<0) phi_low+=360.;
2555 Double_t dphi = fPhi2 -fPhi1;
2556 if (dphi < 0) dphi+=360.;
2557 Double_t ddp = phi_low-fPhi1;
2558 if (ddp<0) ddp += 360.;
2560 xc = fRmin*TMath::Cos(phi_low*TMath::DegToRad());
2561 yc = fRmin*TMath::Sin(phi_low*TMath::DegToRad());
2562 z1 = GetZcoord(xc, yc, -fDz);
2563 xc = fRmax*TMath::Cos(phi_low*TMath::DegToRad());
2564 yc = fRmax*TMath::Sin(phi_low*TMath::DegToRad());
2565 z1 = TMath::Min(z1, GetZcoord(xc, yc, -fDz));
2567 zmin = TMath::Min(zmin, z1);
2570 in_range_low = kTRUE;
2573 if (phi_low>360) phi_low-=360.;
2576 for (i=0; i<2; i++) {
2577 if (phi_hi<0) phi_hi+=360.;
2578 Double_t dphi = fPhi2 -fPhi1;
2579 if (dphi < 0) dphi+=360.;
2580 Double_t ddp = phi_hi-fPhi1;
2581 if (ddp<0) ddp += 360.;
2583 xc = fRmin*TMath::Cos(phi_hi*TMath::DegToRad());
2584 yc = fRmin*TMath::Sin(phi_hi*TMath::DegToRad());
2585 z1 = GetZcoord(xc, yc, fDz);
2586 xc = fRmax*TMath::Cos(phi_hi*TMath::DegToRad());
2587 yc = fRmax*TMath::Sin(phi_hi*TMath::DegToRad());
2588 z1 = TMath::Max(z1, GetZcoord(xc, yc, fDz));
2590 zmax = TMath::Max(zmax, z1);
2593 in_range_hi = kTRUE;
2596 if (phi_hi>360) phi_hi-=360.;
2602 z[0] = GetZcoord(xc, yc, -fDz);
2603 z[4] = GetZcoord(xc, yc, fDz);
2607 z[1] = GetZcoord(xc, yc, -fDz);
2608 z[5] = GetZcoord(xc, yc, fDz);
2612 z[2] = GetZcoord(xc, yc, -fDz);
2613 z[6] = GetZcoord(xc, yc, fDz);
2617 z[3] = GetZcoord(xc, yc, -fDz);
2618 z[7] = GetZcoord(xc, yc, fDz);
2620 z1 = z[TMath::LocMin(4, &z[0])];
2622 zmin = TMath::Min(zmin, z1);
2626 z1 = z[TMath::LocMax(4, &z[4])+4];
2628 zmax = TMath::Max(zmax, z1);
2632 fDZ = 0.5*(zmax-zmin);
2633 fOrigin[2] = 0.5*(zmax+zmin);
2639 void TGeoCtub::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
2642 Bool_t isseg = kTRUE;
2643 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
2644 Double_t rsq = point[0]*point[0]+point[1]*point[1];
2645 Double_t r = TMath::Sqrt(rsq);
2647 saf[0] = TMath::Abs(point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2]);
2648 saf[1] = TMath::Abs(point[0]*fNhigh[0] + point[1]*fNhigh[1] - (fDz-point[2])*fNhigh[2]);
2649 saf[2] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
2650 saf[3] = TMath::Abs(fRmax-r);
2651 Int_t i = TMath::LocMin(4,saf);
2653 if (TGeoShape::IsCloseToPhi(saf[i], point,fC1,fS1,fC2,fS2)) {
2654 TGeoShape::NormalPhi(point,dir,norm,fC1,fS1,fC2,fS2);
2659 memcpy(norm, fNlow, 3*
sizeof(Double_t));
2660 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
2668 memcpy(norm, fNhigh, 3*
sizeof(Double_t));
2669 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
2678 Double_t phi = TMath::ATan2(point[1], point[0]);
2679 norm[0] = TMath::Cos(phi);
2680 norm[1] = TMath::Sin(phi);
2681 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
2691 Bool_t TGeoCtub::Contains(
const Double_t *point)
const
2693 Double_t zin = point[0]*fNlow[0]+point[1]*fNlow[1]+(point[2]+fDz)*fNlow[2];
2694 if (zin>0)
return kFALSE;
2696 zin = point[0]*fNhigh[0]+point[1]*fNhigh[1]+(point[2]-fDz)*fNhigh[2];
2697 if (zin>0)
return kFALSE;
2699 Double_t r2 = point[0]*point[0]+point[1]*point[1];
2700 if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax))
return kFALSE;
2702 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
2703 if (phi < 0 ) phi+=360.;
2704 Double_t dphi = fPhi2 -fPhi1;
2705 Double_t ddp = phi-fPhi1;
2706 if (ddp<0) ddp += 360.;
2708 if (ddp > dphi)
return kFALSE;
2715 Double_t TGeoCtub::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi)
const
2739 Double_t TGeoCtub::GetZcoord(Double_t xc, Double_t yc, Double_t zc)
const
2742 if (zc<0) newz = -fDz-(xc*fNlow[0]+yc*fNlow[1])/fNlow[2];
2743 else newz = fDz-(xc*fNhigh[0]+yc*fNhigh[1])/fNhigh[2];
2750 Double_t TGeoCtub::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
2752 if (iact<3 && safe) {
2753 *safe = Safety(point, kFALSE);
2754 if (iact==0)
return TGeoShape::Big();
2755 if ((iact==1) && (step<=*safe))
return TGeoShape::Big();
2758 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
2759 if (sdist>=step)
return TGeoShape::Big();
2761 saf[0] = point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2];
2762 saf[1] = point[0]*fNhigh[0] + point[1]*fNhigh[1] + (point[2]-fDz)*fNhigh[2];
2763 Double_t rsq = point[0]*point[0]+point[1]*point[1];
2764 Double_t r = TMath::Sqrt(rsq);
2766 Bool_t tub = kFALSE;
2767 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
2771 Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
2773 Double_t xi, yi, zi;
2774 Double_t s = TGeoShape::Big();
2778 xi = point[0]+s*dir[0];
2779 yi = point[1]+s*dir[1];
2781 if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
2783 cpsi=(xi*fCm+yi*fSm)/TMath::Sqrt(r2);
2784 if (cpsi>=fCdfi)
return s;
2788 calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
2792 xi = point[0]+s*dir[0];
2793 yi = point[1]+s*dir[1];
2795 if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
2797 cpsi=(xi*fCm+yi*fSm)/TMath::Sqrt(r2);
2798 if (cpsi>=fCdfi)
return s;
2804 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
2805 if (TMath::Abs(nsq)<1E-10)
return TGeoShape::Big();
2806 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
2809 if (r>fRmax && rdotn<0) {
2810 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
2814 xi=point[0]+s*dir[0];
2815 yi=point[1]+s*dir[1];
2816 zi=point[2]+s*dir[2];
2817 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2818 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2820 cpsi=(xi*fCm+yi*fSm)/fRmax;
2821 if (cpsi>=fCdfi)
return s;
2828 Double_t snxt=TGeoShape::Big();
2830 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
2834 xi=point[0]+s*dir[0];
2835 yi=point[1]+s*dir[1];
2836 zi=point[2]+s*dir[2];
2837 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2838 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2840 cpsi=(xi*fCm+yi*fSm)/fRmin;
2841 if (cpsi>=fCdfi) snxt=s;
2848 if (tub)
return snxt;
2849 Double_t un=dir[0]*fS1-dir[1]*fC1;
2850 if (un<-TGeoShape::Tolerance()) {
2851 s=(point[1]*fC1-point[0]*fS1)/un;
2853 xi=point[0]+s*dir[0];
2854 yi=point[1]+s*dir[1];
2855 zi=point[2]+s*dir[2];
2856 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2857 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2859 if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
2860 if ((yi*fCm-xi*fSm)<=0) {
2868 un=dir[0]*fS2-dir[1]*fC2;
2869 if (un>TGeoShape::Tolerance()) {
2870 s=(point[1]*fC2-point[0]*fS2)/un;
2872 xi=point[0]+s*dir[0];
2873 yi=point[1]+s*dir[1];
2874 zi=point[2]+s*dir[2];
2875 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
2876 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
2878 if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
2879 if ((yi*fCm-xi*fSm)>=0) {
2893 Double_t TGeoCtub::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
2895 if (iact<3 && safe) *safe = Safety(point, kTRUE);
2896 if (iact==0)
return TGeoShape::Big();
2897 if ((iact==1) && (*safe>step))
return TGeoShape::Big();
2898 Double_t rsq = point[0]*point[0]+point[1]*point[1];
2899 Bool_t tub = kFALSE;
2900 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
2903 Double_t sz = TGeoShape::Big();
2905 saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
2906 saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
2907 Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
2908 if (calf>0) sz = saf[0]/calf;
2910 Double_t sz1=TGeoShape::Big();
2911 calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
2914 if (sz1<sz) sz = sz1;
2918 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
2920 if (TMath::Abs(nsq)<1E-10)
return sz;
2921 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
2922 Double_t sr=TGeoShape::Big();
2924 Bool_t skip_outer = kFALSE;
2927 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
2930 if (sr>0) skip_outer = kTRUE;
2935 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
2938 if (sr<0) sr=TGeoShape::Big();
2944 Double_t sfmin = TGeoShape::Big();
2945 if (!tub) sfmin=TGeoShape::DistToPhiMin(point, dir, fS1, fC1, fS2, fC2, fSm, fCm);
2946 return TMath::Min(TMath::Min(sz,sr), sfmin);
2952 TGeoVolume *TGeoCtub::Divide(TGeoVolume * ,
const char * , Int_t , Int_t ,
2953 Double_t , Double_t )
2955 Warning(
"Divide",
"In shape %s division of a cut tube not implemented", GetName());
2963 TGeoShape *TGeoCtub::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * )
const
2965 if (!TestShapeBit(kGeoRunTimeShape))
return 0;
2966 if (!mother->TestShapeBit(kGeoTube)) {
2967 Error(
"GetMakeRuntimeShape",
"Invalid mother for shape %s", GetName());
2970 Double_t rmin, rmax, dz;
2974 if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
2976 rmin = ((TGeoTube*)mother)->GetRmin();
2977 if ((fRmax<0) || (fRmax<=fRmin))
2978 rmax = ((TGeoTube*)mother)->GetRmax();
2980 return (
new TGeoCtub(rmin, rmax, dz, fPhi1, fPhi2, fNlow[0], fNlow[1], fNlow[2],
2981 fNhigh[0], fNhigh[1], fNhigh[2]));
2987 void TGeoCtub::InspectShape()
const
2989 printf(
"*** Shape %s: TGeoCtub ***\n", GetName());
2990 printf(
" lx = %11.5f\n", fNlow[0]);
2991 printf(
" ly = %11.5f\n", fNlow[1]);
2992 printf(
" lz = %11.5f\n", fNlow[2]);
2993 printf(
" tx = %11.5f\n", fNhigh[0]);
2994 printf(
" ty = %11.5f\n", fNhigh[1]);
2995 printf(
" tz = %11.5f\n", fNhigh[2]);
2996 TGeoTubeSeg::InspectShape();
3003 Double_t TGeoCtub::Safety(
const Double_t *point, Bool_t in)
const
3006 Double_t rsq = point[0]*point[0]+point[1]*point[1];
3007 Double_t r = TMath::Sqrt(rsq);
3008 Bool_t isseg = kTRUE;
3009 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
3011 saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
3012 saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
3013 saf[2] = (fRmin<1E-10 && !isseg)?TGeoShape::Big():(r-fRmin);
3015 Double_t safphi = TGeoShape::Big();
3016 Double_t safe = TGeoShape::Big();
3017 if (isseg) safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi2);
3020 safe = saf[TMath::LocMin(4,saf)];
3021 return TMath::Min(safe, safphi);
3023 for (Int_t i=0; i<4; i++) saf[i]=-saf[i];
3024 safe = saf[TMath::LocMax(4,saf)];
3025 if (isseg)
return TMath::Max(safe, safphi);
3032 void TGeoCtub::SetCtubDimensions(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
3033 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
3035 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
3048 void TGeoCtub::SavePrimitive(std::ostream &out, Option_t * )
3050 if (TObject::TestBit(kGeoSavePrimitive))
return;
3051 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
3052 out <<
" rmin = " << fRmin <<
";" << std::endl;
3053 out <<
" rmax = " << fRmax <<
";" << std::endl;
3054 out <<
" dz = " << fDz <<
";" << std::endl;
3055 out <<
" phi1 = " << fPhi1 <<
";" << std::endl;
3056 out <<
" phi2 = " << fPhi2 <<
";" << std::endl;
3057 out <<
" lx = " << fNlow[0] <<
";" << std::endl;
3058 out <<
" ly = " << fNlow[1] <<
";" << std::endl;
3059 out <<
" lz = " << fNlow[2] <<
";" << std::endl;
3060 out <<
" tx = " << fNhigh[0] <<
";" << std::endl;
3061 out <<
" ty = " << fNhigh[1] <<
";" << std::endl;
3062 out <<
" tz = " << fNhigh[2] <<
";" << std::endl;
3063 out <<
" TGeoShape *" << GetPointerName() <<
" = new TGeoCtub(\"" << GetName() <<
"\",rmin,rmax,dz,phi1,phi2,lx,ly,lz,tx,ty,tz);" << std::endl; TObject::SetBit(TGeoShape::kGeoSavePrimitive);
3069 void TGeoCtub::SetDimensions(Double_t *param)
3071 SetCtubDimensions(param[0], param[1], param[2], param[3], param[4], param[5],
3072 param[6], param[7], param[8], param[9], param[10]);
3081 Bool_t TGeoCtub::GetPointsOnSegments(Int_t , Double_t * )
const
3089 void TGeoCtub::SetPoints(Double_t *points)
const
3093 Double_t phi, phi1, phi2, dphi;
3096 if (phi2<phi1) phi2+=360.;
3097 n = gGeoManager->GetNsegments()+1;
3099 dphi = (phi2-phi1)/(n-1);
3105 for (j = 0; j < n; j++) {
3106 phi = (phi1+j*dphi)*TMath::DegToRad();
3107 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
3109 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
3111 points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
3112 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3115 for (j = 0; j < n; j++) {
3116 phi = (phi1+j*dphi)*TMath::DegToRad();
3117 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
3119 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
3121 points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
3122 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3131 void TGeoCtub::SetPoints(Float_t *points)
const
3135 Double_t phi, phi1, phi2, dphi;
3138 if (phi2<phi1) phi2+=360.;
3139 n = gGeoManager->GetNsegments()+1;
3141 dphi = (phi2-phi1)/(n-1);
3147 for (j = 0; j < n; j++) {
3148 phi = (phi1+j*dphi)*TMath::DegToRad();
3149 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
3151 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
3153 points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
3154 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3157 for (j = 0; j < n; j++) {
3158 phi = (phi1+j*dphi)*TMath::DegToRad();
3159 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
3161 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
3163 points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
3164 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
3173 void TGeoCtub::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
3175 TGeoTubeSeg::GetMeshNumbers(nvert,nsegs,npols);
3181 Int_t TGeoCtub::GetNmeshVertices()
const
3183 Int_t n = gGeoManager->GetNsegments()+1;
3184 Int_t numPoints = n*4;
3191 const TBuffer3D & TGeoCtub::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
3193 static TBuffer3DCutTube buffer;
3195 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
3197 if (reqSections & TBuffer3D::kShapeSpecific) {
3199 buffer.fRadiusInner = fRmin;
3200 buffer.fRadiusOuter = fRmax;
3201 buffer.fHalfLength = fDz;
3202 buffer.fPhiMin = fPhi1;
3203 buffer.fPhiMax = fPhi2;
3205 for (UInt_t i = 0; i < 3; i++ ) {
3206 buffer.fLowPlaneNorm[i] = fNlow[i];
3207 buffer.fHighPlaneNorm[i] = fNhigh[i];
3209 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
3211 if (reqSections & TBuffer3D::kRawSizes) {
3212 Int_t n = gGeoManager->GetNsegments()+1;
3214 Int_t nbSegs = 2*nbPnts;
3215 Int_t nbPols = nbPnts-2;
3216 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
3217 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
3220 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
3221 SetPoints(buffer.fPnts);
3222 if (!buffer.fLocalFrame) {
3223 TransformPoints(buffer.fPnts, buffer.NbPnts());
3225 SetSegsAndPols(buffer);
3226 buffer.SetSectionsValid(TBuffer3D::kRaw);
3237 void TGeoCtub::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
3239 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
3247 void TGeoCtub::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
3249 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
3255 void TGeoCtub::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
3257 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
3263 void TGeoCtub::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
3265 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
3273 void TGeoCtub::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
3275 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);