00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #include "Riostream.h"
00096
00097 #include "TGeoManager.h"
00098 #include "TGeoVolume.h"
00099 #include "TVirtualGeoPainter.h"
00100 #include "TGeoTube.h"
00101 #include "TVirtualPad.h"
00102 #include "TBuffer3D.h"
00103 #include "TBuffer3DTypes.h"
00104 #include "TMath.h"
00105
00106 ClassImp(TGeoTube)
00107
00108
00109 TGeoTube::TGeoTube()
00110 {
00111
00112 SetShapeBit(TGeoShape::kGeoTube);
00113 fRmin = 0.0;
00114 fRmax = 0.0;
00115 fDz = 0.0;
00116 }
00117
00118
00119
00120 TGeoTube::TGeoTube(Double_t rmin, Double_t rmax, Double_t dz)
00121 :TGeoBBox(0, 0, 0)
00122 {
00123
00124 SetShapeBit(TGeoShape::kGeoTube);
00125 SetTubeDimensions(rmin, rmax, dz);
00126 if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
00127 SetShapeBit(kGeoRunTimeShape);
00128
00129
00130 }
00131 ComputeBBox();
00132 }
00133
00134 TGeoTube::TGeoTube(const char *name, Double_t rmin, Double_t rmax, Double_t dz)
00135 :TGeoBBox(name, 0, 0, 0)
00136 {
00137
00138 SetShapeBit(TGeoShape::kGeoTube);
00139 SetTubeDimensions(rmin, rmax, dz);
00140 if ((fDz<0) || (fRmin<0) || (fRmax<0)) {
00141 SetShapeBit(kGeoRunTimeShape);
00142
00143
00144 }
00145 ComputeBBox();
00146 }
00147
00148
00149 TGeoTube::TGeoTube(Double_t *param)
00150 :TGeoBBox(0, 0, 0)
00151 {
00152
00153
00154
00155
00156 SetShapeBit(TGeoShape::kGeoTube);
00157 SetDimensions(param);
00158 if ((fDz<0) || (fRmin<0) || (fRmax<0)) SetShapeBit(kGeoRunTimeShape);
00159 ComputeBBox();
00160 }
00161
00162
00163 TGeoTube::~TGeoTube()
00164 {
00165
00166 }
00167
00168
00169 Double_t TGeoTube::Capacity() const
00170 {
00171
00172 return TGeoTube::Capacity(fRmin,fRmax, fDz);
00173 }
00174
00175
00176 Double_t TGeoTube::Capacity(Double_t rmin, Double_t rmax, Double_t dz)
00177 {
00178
00179 Double_t capacity = 2.*TMath::Pi()*(rmax*rmax-rmin*rmin)*dz;
00180 return capacity;
00181 }
00182
00183
00184 void TGeoTube::ComputeBBox()
00185 {
00186
00187 fDX = fDY = fRmax;
00188 fDZ = fDz;
00189 }
00190
00191
00192 void TGeoTube::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00193 {
00194
00195 Double_t saf[3];
00196 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00197 Double_t r = TMath::Sqrt(rsq);
00198 saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
00199 saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
00200 saf[2] = TMath::Abs(fRmax-r);
00201 Int_t i = TMath::LocMin(3,saf);
00202 if (i==0) {
00203 norm[0] = norm[1] = 0.;
00204 norm[2] = TMath::Sign(1.,dir[2]);
00205 return;
00206 }
00207 norm[2] = 0;
00208 Double_t phi = TMath::ATan2(point[1], point[0]);
00209 norm[0] = TMath::Cos(phi);
00210 norm[1] = TMath::Sin(phi);
00211 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
00212 norm[0] = -norm[0];
00213 norm[1] = -norm[1];
00214 }
00215 }
00216
00217
00218 void TGeoTube::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
00219 Double_t , Double_t , Double_t )
00220 {
00221
00222 norm[2] = 0;
00223 Double_t phi = TMath::ATan2(point[1], point[0]);
00224 norm[0] = TMath::Cos(phi);
00225 norm[1] = TMath::Sin(phi);
00226 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
00227 norm[0] = -norm[0];
00228 norm[1] = -norm[1];
00229 }
00230 }
00231
00232
00233 Bool_t TGeoTube::Contains(Double_t *point) const
00234 {
00235
00236 if (TMath::Abs(point[2]) > fDz) return kFALSE;
00237 Double_t r2 = point[0]*point[0]+point[1]*point[1];
00238 if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax)) return kFALSE;
00239 return kTRUE;
00240 }
00241
00242
00243 Int_t TGeoTube::DistancetoPrimitive(Int_t px, Int_t py)
00244 {
00245
00246 Int_t n = gGeoManager->GetNsegments();
00247 Int_t numPoints = 4*n;
00248 if (!HasRmin()) numPoints = 2*(n+1);
00249 return ShapeDistancetoPrimitive(numPoints, px, py);
00250 }
00251
00252
00253 Double_t TGeoTube::DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
00254 {
00255
00256
00257
00258
00259 Double_t sz = TGeoShape::Big();
00260 if (dir[2]) {
00261 sz = (TMath::Sign(dz, dir[2])-point[2])/dir[2];
00262 if (sz<=0) return 0.0;
00263 }
00264
00265 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
00266 if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return sz;
00267 Double_t rsq=point[0]*point[0]+point[1]*point[1];
00268 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
00269 Double_t b,d;
00270 Double_t sr = TGeoShape::Big();
00271
00272 if (rmin>0) {
00273
00274 if (rsq <= rmin*rmin+TGeoShape::Tolerance()) {
00275 if (rdotn<0) return 0.0;
00276 } else {
00277 if (rdotn<0) {
00278 DistToTube(rsq,nsq,rdotn,rmin,b,d);
00279 if (d>0) {
00280 sr=-b-d;
00281 if (sr>0) return TMath::Min(sz,sr);
00282 }
00283 }
00284 }
00285 }
00286
00287 if (rsq >= rmax*rmax-TGeoShape::Tolerance()) {
00288 if (rdotn>=0) return 0.0;
00289 }
00290 DistToTube(rsq,nsq,rdotn,rmax,b,d);
00291 if (d>0) {
00292 sr=-b+d;
00293 if (sr>0) return TMath::Min(sz,sr);
00294 }
00295 return 0.;
00296 }
00297
00298
00299 Double_t TGeoTube::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00300 {
00301
00302
00303 if (iact<3 && safe) {
00304 *safe = Safety(point, kTRUE);
00305 if (iact==0) return TGeoShape::Big();
00306 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00307 }
00308
00309 return DistFromInsideS(point, dir, fRmin, fRmax, fDz);
00310 }
00311
00312
00313 Double_t TGeoTube::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
00314 {
00315
00316
00317
00318 Double_t xi,yi,zi;
00319 Double_t rmaxsq = rmax*rmax;
00320 Double_t rminsq = rmin*rmin;
00321 zi = dz - TMath::Abs(point[2]);
00322 Double_t s = TGeoShape::Big();
00323 Bool_t in = kFALSE;
00324 Bool_t inz = (zi<0)?kFALSE:kTRUE;
00325 if (!inz) {
00326 if (point[2]*dir[2]>=0) return TGeoShape::Big();
00327 s = -zi/TMath::Abs(dir[2]);
00328 xi = point[0]+s*dir[0];
00329 yi = point[1]+s*dir[1];
00330 Double_t r2=xi*xi+yi*yi;
00331 if ((rminsq<=r2) && (r2<=rmaxsq)) return s;
00332 }
00333
00334 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00335
00336 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
00337 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
00338 Double_t b,d;
00339 Bool_t inrmax = kFALSE;
00340 Bool_t inrmin = kFALSE;
00341 if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
00342 if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
00343 in = inz & inrmin & inrmax;
00344
00345 if (in) {
00346 Bool_t checkout = kFALSE;
00347 Double_t r = TMath::Sqrt(rsq);
00348 if (zi<rmax-r) {
00349 if ((TGeoShape::IsSameWithinTolerance(rmin,0)) || (zi<r-rmin)) {
00350 if (point[2]*dir[2]<0) return 0.0;
00351 return TGeoShape::Big();
00352 }
00353 }
00354 if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
00355 if (checkout) {
00356 if (rdotn>=0) return TGeoShape::Big();
00357 return 0.0;
00358 }
00359 if (TGeoShape::IsSameWithinTolerance(rmin,0)) return 0.0;
00360 if (rdotn>=0) return 0.0;
00361
00362 if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
00363 DistToTube(rsq, nsq, rdotn, rmin, b, d);
00364 if (d>0) {
00365 s=-b+d;
00366 if (s>0) {
00367 zi=point[2]+s*dir[2];
00368 if (TMath::Abs(zi)<=dz) return s;
00369 }
00370 }
00371 return TGeoShape::Big();
00372 }
00373
00374 if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
00375 if (!inrmax) {
00376 DistToTube(rsq, nsq, rdotn, rmax, b, d);
00377 if (d>0) {
00378 s=-b-d;
00379 if (s>0) {
00380 zi=point[2]+s*dir[2];
00381 if (TMath::Abs(zi)<=dz) return s;
00382 }
00383 }
00384 }
00385
00386 if (rmin>0) {
00387 DistToTube(rsq, nsq, rdotn, rmin, b, d);
00388 if (d>0) {
00389 s=-b+d;
00390 if (s>0) {
00391 zi=point[2]+s*dir[2];
00392 if (TMath::Abs(zi)<=dz) return s;
00393 }
00394 }
00395 }
00396 return TGeoShape::Big();
00397 }
00398
00399
00400 Double_t TGeoTube::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00401 {
00402
00403
00404
00405 if (iact<3 && safe) {
00406 *safe = Safety(point, kFALSE);
00407 if (iact==0) return TGeoShape::Big();
00408 if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
00409 }
00410
00411 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00412 if (sdist>=step) return TGeoShape::Big();
00413
00414 return DistFromOutsideS(point, dir, fRmin, fRmax, fDz);
00415 }
00416
00417
00418 void TGeoTube::DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta)
00419 {
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 Double_t t1 = 1./nsq;
00430 Double_t t3=rsq-(radius*radius);
00431 b = t1*rdotn;
00432 Double_t c =t1*t3;
00433 delta = b*b-c;
00434 if (delta>0) {
00435 delta=TMath::Sqrt(delta);
00436 } else {
00437 delta = -1;
00438 }
00439 }
00440
00441
00442 TGeoVolume *TGeoTube::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
00443 Double_t start, Double_t step)
00444 {
00445
00446
00447
00448
00449
00450
00451 TGeoShape *shape;
00452 TGeoVolume *vol;
00453 TGeoVolumeMulti *vmulti;
00454 TGeoPatternFinder *finder;
00455 TString opt = "";
00456 Int_t id;
00457 Double_t end = start+ndiv*step;
00458 switch (iaxis) {
00459 case 1:
00460 finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
00461 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00462 voldiv->SetFinder(finder);
00463 finder->SetDivIndex(voldiv->GetNdaughters());
00464 for (id=0; id<ndiv; id++) {
00465 shape = new TGeoTube(start+id*step, start+(id+1)*step, fDz);
00466 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00467 vmulti->AddVolume(vol);
00468 opt = "R";
00469 voldiv->AddNodeOffset(vol, id, 0, opt.Data());
00470 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00471 }
00472 return vmulti;
00473 case 2:
00474 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
00475 voldiv->SetFinder(finder);
00476 finder->SetDivIndex(voldiv->GetNdaughters());
00477 shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
00478 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00479 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00480 vmulti->AddVolume(vol);
00481 opt = "Phi";
00482 for (id=0; id<ndiv; id++) {
00483 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
00484 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00485 }
00486 return vmulti;
00487 case 3:
00488 finder = new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
00489 voldiv->SetFinder(finder);
00490 finder->SetDivIndex(voldiv->GetNdaughters());
00491 shape = new TGeoTube(fRmin, fRmax, step/2);
00492 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00493 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00494 vmulti->AddVolume(vol);
00495 opt = "Z";
00496 for (id=0; id<ndiv; id++) {
00497 voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
00498 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00499 }
00500 return vmulti;
00501 default:
00502 Error("Divide", "In shape %s wrong axis type for division", GetName());
00503 return 0;
00504 }
00505 }
00506
00507
00508 const char *TGeoTube::GetAxisName(Int_t iaxis) const
00509 {
00510
00511 switch (iaxis) {
00512 case 1:
00513 return "R";
00514 case 2:
00515 return "PHI";
00516 case 3:
00517 return "Z";
00518 default:
00519 return "UNDEFINED";
00520 }
00521 }
00522
00523
00524 Double_t TGeoTube::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00525 {
00526
00527 xlo = 0;
00528 xhi = 0;
00529 Double_t dx = 0;
00530 switch (iaxis) {
00531 case 1:
00532 xlo = fRmin;
00533 xhi = fRmax;
00534 dx = xhi-xlo;
00535 return dx;
00536 case 2:
00537 xlo = 0;
00538 xhi = 360;
00539 dx = 360;
00540 return dx;
00541 case 3:
00542 xlo = -fDz;
00543 xhi = fDz;
00544 dx = xhi-xlo;
00545 return dx;
00546 }
00547 return dx;
00548 }
00549
00550
00551 void TGeoTube::GetBoundingCylinder(Double_t *param) const
00552 {
00553
00554
00555 param[0] = fRmin;
00556 param[0] *= param[0];
00557 param[1] = fRmax;
00558 param[1] *= param[1];
00559 param[2] = 0.;
00560 param[3] = 360.;
00561 }
00562
00563
00564 TGeoShape *TGeoTube::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
00565 {
00566
00567
00568 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00569 Double_t rmin, rmax, dz;
00570 Double_t xmin,xmax;
00571 rmin = fRmin;
00572 rmax = fRmax;
00573 dz = fDz;
00574 if (fDz<0) {
00575 mother->GetAxisRange(3,xmin,xmax);
00576 if (xmax<0) return 0;
00577 dz=xmax;
00578 }
00579 mother->GetAxisRange(1,xmin,xmax);
00580 if (fRmin<0) {
00581 if (xmin<0) return 0;
00582 rmin = xmin;
00583 }
00584 if (fRmax<0) {
00585 if (xmax<=0) return 0;
00586 rmax = xmax;
00587 }
00588
00589 return (new TGeoTube(GetName(), rmin, rmax, dz));
00590 }
00591
00592
00593 void TGeoTube::InspectShape() const
00594 {
00595
00596 printf("*** Shape %s: TGeoTube ***\n", GetName());
00597 printf(" Rmin = %11.5f\n", fRmin);
00598 printf(" Rmax = %11.5f\n", fRmax);
00599 printf(" dz = %11.5f\n", fDz);
00600 printf(" Bounding box:\n");
00601 TGeoBBox::InspectShape();
00602 }
00603
00604
00605 TBuffer3D *TGeoTube::MakeBuffer3D() const
00606 {
00607
00608
00609
00610 Int_t n = gGeoManager->GetNsegments();
00611 Int_t nbPnts = 4*n;
00612 Int_t nbSegs = 8*n;
00613 Int_t nbPols = 4*n;
00614 if (!HasRmin()) {
00615 nbPnts = 2*(n+1);
00616 nbSegs = 5*n;
00617 nbPols = 3*n;
00618 }
00619 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00620 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
00621 if (buff)
00622 {
00623 SetPoints(buff->fPnts);
00624 SetSegsAndPols(*buff);
00625 }
00626
00627 return buff;
00628 }
00629
00630
00631 void TGeoTube::SetSegsAndPols(TBuffer3D &buffer) const
00632 {
00633
00634 Int_t i, j,indx;
00635 Int_t n = gGeoManager->GetNsegments();
00636 Int_t c = (((buffer.fColor) %8) -1) * 4;
00637 if (c < 0) c = 0;
00638
00639 if (HasRmin()) {
00640
00641
00642
00643
00644
00645 for (i = 0; i < 4; i++) {
00646 for (j = 0; j < n; j++) {
00647 indx = 3*(i*n+j);
00648 buffer.fSegs[indx ] = c;
00649 buffer.fSegs[indx+1] = i*n+j;
00650 buffer.fSegs[indx+2] = i*n+(j+1)%n;
00651 }
00652 }
00653
00654
00655
00656 for (i = 4; i < 6; i++) {
00657 for (j = 0; j < n; j++) {
00658 indx = 3*(i*n+j);
00659 buffer.fSegs[indx ] = c+1;
00660 buffer.fSegs[indx+1] = (i-4)*n+j;
00661 buffer.fSegs[indx+2] = (i-2)*n+j;
00662 }
00663 }
00664
00665
00666
00667 for (i = 6; i < 8; i++) {
00668 for (j = 0; j < n; j++) {
00669 indx = 3*(i*n+j);
00670 buffer.fSegs[indx ] = c;
00671 buffer.fSegs[indx+1] = 2*(i-6)*n+j;
00672 buffer.fSegs[indx+2] = (2*(i-6)+1)*n+j;
00673 }
00674 }
00675
00676 i=0;
00677
00678 for (j = 0; j < n; j++) {
00679 indx = 6*(i*n+j);
00680 buffer.fPols[indx ] = c;
00681 buffer.fPols[indx+1] = 4;
00682 buffer.fPols[indx+2] = j;
00683 buffer.fPols[indx+3] = 4*n+(j+1)%n;
00684 buffer.fPols[indx+4] = 2*n+j;
00685 buffer.fPols[indx+5] = 4*n+j;
00686 }
00687 i=1;
00688
00689 for (j = 0; j < n; j++) {
00690 indx = 6*(i*n+j);
00691 buffer.fPols[indx ] = c+1;
00692 buffer.fPols[indx+1] = 4;
00693 buffer.fPols[indx+2] = n+j;
00694 buffer.fPols[indx+3] = 5*n+j;
00695 buffer.fPols[indx+4] = 3*n+j;
00696 buffer.fPols[indx+5] = 5*n+(j+1)%n;
00697 }
00698 i=2;
00699
00700 for (j = 0; j < n; j++) {
00701 indx = 6*(i*n+j);
00702 buffer.fPols[indx ] = c;
00703 buffer.fPols[indx+1] = 4;
00704 buffer.fPols[indx+2] = j;
00705 buffer.fPols[indx+3] = 6*n+j;
00706 buffer.fPols[indx+4] = n+j;
00707 buffer.fPols[indx+5] = 6*n+(j+1)%n;
00708 }
00709 i=3;
00710
00711 for (j = 0; j < n; j++) {
00712 indx = 6*(i*n+j);
00713 buffer.fPols[indx ] = c;
00714 buffer.fPols[indx+1] = 4;
00715 buffer.fPols[indx+2] = 2*n+j;
00716 buffer.fPols[indx+3] = 7*n+(j+1)%n;
00717 buffer.fPols[indx+4] = 3*n+j;
00718 buffer.fPols[indx+5] = 7*n+j;
00719 }
00720 return;
00721 }
00722
00723
00724
00725
00726 for (i = 0; i < 2; i++) {
00727 for (j = 0; j < n; j++) {
00728 indx = 3*(i*n+j);
00729 buffer.fSegs[indx ] = c;
00730 buffer.fSegs[indx+1] = 2+i*n+j;
00731 buffer.fSegs[indx+2] = 2+i*n+(j+1)%n;
00732 }
00733 }
00734
00735 for (j = 0; j < n; j++) {
00736 indx = 3*(2*n+j);
00737 buffer.fSegs[indx ] = c+1;
00738 buffer.fSegs[indx+1] = 2+j;
00739 buffer.fSegs[indx+2] = 2+n+j;
00740 }
00741
00742
00743
00744 for (i = 3; i < 5; i++) {
00745 for (j = 0; j < n; j++) {
00746 indx = 3*(i*n+j);
00747 buffer.fSegs[indx ] = c;
00748 buffer.fSegs[indx+1] = i-3;
00749 buffer.fSegs[indx+2] = 2+(i-3)*n+j;
00750 }
00751 }
00752
00753
00754 for (j = 0; j < n; j++) {
00755 indx = 6*j;
00756 buffer.fPols[indx ] = c+1;
00757 buffer.fPols[indx+1] = 4;
00758 buffer.fPols[indx+2] = j;
00759 buffer.fPols[indx+3] = 2*n+j;
00760 buffer.fPols[indx+4] = n+j;
00761 buffer.fPols[indx+5] = 2*n+(j+1)%n;
00762 }
00763
00764 for (j = 0; j < n; j++) {
00765 indx = 6*n + 5*j;
00766 buffer.fPols[indx ] = c;
00767 buffer.fPols[indx+1] = 3;
00768 buffer.fPols[indx+2] = j;
00769 buffer.fPols[indx+3] = 3*n+(j+1)%n;
00770 buffer.fPols[indx+4] = 3*n+j;
00771 }
00772
00773 for (j = 0; j < n; j++) {
00774 indx = 6*n + 5*n + 5*j;
00775 buffer.fPols[indx ] = c;
00776 buffer.fPols[indx+1] = 3;
00777 buffer.fPols[indx+2] = n+j;
00778 buffer.fPols[indx+3] = 4*n+j;
00779 buffer.fPols[indx+4] = 4*n+(j+1)%n;
00780 }
00781 }
00782
00783
00784 Double_t TGeoTube::Safety(Double_t *point, Bool_t in) const
00785 {
00786
00787
00788 #ifndef NEVER
00789 Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00790 Double_t safe, safrmin, safrmax;
00791 if (in) {
00792 safe = fDz-TMath::Abs(point[2]);
00793 if (fRmin>1E-10) {
00794 safrmin = r-fRmin;
00795 if (safrmin < safe) safe = safrmin;
00796 }
00797 safrmax = fRmax-r;
00798 if (safrmax < safe) safe = safrmax;
00799 } else {
00800 safe = -fDz+TMath::Abs(point[2]);
00801 if (fRmin>1E-10) {
00802 safrmin = -r+fRmin;
00803 if (safrmin > safe) safe = safrmin;
00804 }
00805 safrmax = -fRmax+r;
00806 if (safrmax > safe) safe = safrmax;
00807 }
00808 return safe;
00809 #else
00810 Double_t saf[3];
00811 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00812 Double_t r = TMath::Sqrt(rsq);
00813 saf[0] = fDz-TMath::Abs(point[2]);
00814 saf[1] = (fRmin>1E-10)?(r-fRmin):TGeoShape::Big();
00815 saf[2] = fRmax-r;
00816 if (in) return saf[TMath::LocMin(3,saf)];
00817 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00818 return saf[TMath::LocMax(3,saf)];
00819 #endif
00820 }
00821
00822
00823 Double_t TGeoTube::SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
00824 {
00825
00826
00827 Double_t saf[3];
00828 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00829 Double_t r = TMath::Sqrt(rsq);
00830 switch (skipz) {
00831 case 1:
00832 saf[0] = dz - point[2];
00833 break;
00834 case 2:
00835 saf[0] = dz + point[2];
00836 break;
00837 case 3:
00838 saf[0] = TGeoShape::Big();
00839 break;
00840 default:
00841 saf[0] = dz-TMath::Abs(point[2]);
00842 }
00843 saf[1] = (rmin>1E-10)?(r-rmin):TGeoShape::Big();
00844 saf[2] = rmax-r;
00845
00846 if (in) return saf[TMath::LocMin(3,saf)];
00847 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00848 return saf[TMath::LocMax(3,saf)];
00849 }
00850
00851
00852 void TGeoTube::SavePrimitive(ostream &out, Option_t * )
00853 {
00854
00855 if (TObject::TestBit(kGeoSavePrimitive)) return;
00856 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
00857 out << " rmin = " << fRmin << ";" << endl;
00858 out << " rmax = " << fRmax << ";" << endl;
00859 out << " dz = " << fDz << ";" << endl;
00860 out << " TGeoShape *" << GetPointerName() << " = new TGeoTube(\"" << GetName() << "\",rmin,rmax,dz);" << endl;
00861 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00862 }
00863
00864
00865 void TGeoTube::SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz)
00866 {
00867
00868 fRmin = rmin;
00869 fRmax = rmax;
00870 fDz = dz;
00871 if (fRmin>0 && fRmax>0 && fRmin>=fRmax)
00872 Error("SetTubeDimensions", "In shape %s wrong rmin=%g rmax=%g", GetName(), rmin,rmax);
00873 }
00874
00875
00876 void TGeoTube::SetDimensions(Double_t *param)
00877 {
00878
00879 Double_t rmin = param[0];
00880 Double_t rmax = param[1];
00881 Double_t dz = param[2];
00882 SetTubeDimensions(rmin, rmax, dz);
00883 }
00884
00885
00886 Bool_t TGeoTube::GetPointsOnSegments(Int_t npoints, Double_t *array) const
00887 {
00888
00889
00890
00891 if (npoints > (npoints/2)*2) {
00892 Error("GetPointsOnSegments","Npoints must be even number");
00893 return kFALSE;
00894 }
00895 Int_t nc = 0;
00896 if (HasRmin()) nc = (Int_t)TMath::Sqrt(0.5*npoints);
00897 else nc = (Int_t)TMath::Sqrt(1.*npoints);
00898 Double_t dphi = TMath::TwoPi()/nc;
00899 Double_t phi = 0;
00900 Int_t ntop = 0;
00901 if (HasRmin()) ntop = npoints/2 - nc*(nc-1);
00902 else ntop = npoints - nc*(nc-1);
00903 Double_t dz = 2*fDz/(nc-1);
00904 Double_t z = 0;
00905 Int_t icrt = 0;
00906 Int_t nphi = nc;
00907
00908 for (Int_t i=0; i<nc; i++) {
00909 if (i == (nc-1)) nphi = ntop;
00910 z = -fDz + i*dz;
00911
00912 for (Int_t j=0; j<nphi; j++) {
00913 phi = j*dphi;
00914 if (HasRmin()) {
00915 array[icrt++] = fRmin * TMath::Cos(phi);
00916 array[icrt++] = fRmin * TMath::Sin(phi);
00917 array[icrt++] = z;
00918 }
00919 array[icrt++] = fRmax * TMath::Cos(phi);
00920 array[icrt++] = fRmax * TMath::Sin(phi);
00921 array[icrt++] = z;
00922 }
00923 }
00924 return kTRUE;
00925 }
00926
00927
00928 void TGeoTube::SetPoints(Double_t *points) const
00929 {
00930
00931 Double_t dz;
00932 Int_t j, n;
00933 n = gGeoManager->GetNsegments();
00934 Double_t dphi = 360./n;
00935 Double_t phi = 0;
00936 dz = fDz;
00937 Int_t indx = 0;
00938 if (points) {
00939 if (HasRmin()) {
00940
00941
00942
00943 for (j = 0; j < n; j++) {
00944 phi = j*dphi*TMath::DegToRad();
00945 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
00946 indx++;
00947 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
00948 indx++;
00949 points[indx+6*n] = dz;
00950 points[indx] =-dz;
00951 indx++;
00952 }
00953
00954
00955 for (j = 0; j < n; j++) {
00956 phi = j*dphi*TMath::DegToRad();
00957 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
00958 indx++;
00959 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
00960 indx++;
00961 points[indx+6*n]= dz;
00962 points[indx] =-dz;
00963 indx++;
00964 }
00965 } else {
00966
00967 points[indx++] = 0.;
00968 points[indx++] = 0.;
00969 points[indx++] = -dz;
00970 points[indx++] = 0.;
00971 points[indx++] = 0.;
00972 points[indx++] = dz;
00973
00974
00975 for (j = 0; j < n; j++) {
00976 phi = j*dphi*TMath::DegToRad();
00977 points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
00978 indx++;
00979 points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
00980 indx++;
00981 points[indx+3*n]= dz;
00982 points[indx] =-dz;
00983 indx++;
00984 }
00985 }
00986 }
00987 }
00988
00989
00990 void TGeoTube::SetPoints(Float_t *points) const
00991 {
00992
00993 Double_t dz;
00994 Int_t j, n;
00995 n = gGeoManager->GetNsegments();
00996 Double_t dphi = 360./n;
00997 Double_t phi = 0;
00998 dz = fDz;
00999 Int_t indx = 0;
01000 if (points) {
01001 if (HasRmin()) {
01002
01003
01004
01005 for (j = 0; j < n; j++) {
01006 phi = j*dphi*TMath::DegToRad();
01007 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
01008 indx++;
01009 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
01010 indx++;
01011 points[indx+6*n] = dz;
01012 points[indx] =-dz;
01013 indx++;
01014 }
01015
01016
01017 for (j = 0; j < n; j++) {
01018 phi = j*dphi*TMath::DegToRad();
01019 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
01020 indx++;
01021 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
01022 indx++;
01023 points[indx+6*n]= dz;
01024 points[indx] =-dz;
01025 indx++;
01026 }
01027 } else {
01028
01029 points[indx++] = 0.;
01030 points[indx++] = 0.;
01031 points[indx++] = -dz;
01032 points[indx++] = 0.;
01033 points[indx++] = 0.;
01034 points[indx++] = dz;
01035
01036
01037 for (j = 0; j < n; j++) {
01038 phi = j*dphi*TMath::DegToRad();
01039 points[indx+3*n] = points[indx] = fRmax * TMath::Cos(phi);
01040 indx++;
01041 points[indx+3*n] = points[indx] = fRmax * TMath::Sin(phi);
01042 indx++;
01043 points[indx+3*n]= dz;
01044 points[indx] =-dz;
01045 indx++;
01046 }
01047 }
01048 }
01049 }
01050
01051
01052 Int_t TGeoTube::GetNmeshVertices() const
01053 {
01054
01055 Int_t n = gGeoManager->GetNsegments();
01056 Int_t numPoints = n*4;
01057 if (!HasRmin()) numPoints = 2*(n+1);
01058 return numPoints;
01059 }
01060
01061
01062 void TGeoTube::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
01063 {
01064
01065 Int_t n = gGeoManager->GetNsegments();
01066 nvert = n*4;
01067 nsegs = n*8;
01068 npols = n*4;
01069 if (!HasRmin()) {
01070 nvert = 2*(n+1);
01071 nsegs = 5*n;
01072 npols = 3*n;
01073 } else {
01074 nvert = n*4;
01075 nsegs = n*8;
01076 npols = n*4;
01077 }
01078 }
01079
01080
01081 void TGeoTube::Sizeof3D() const
01082 {
01083
01084
01085
01086
01087
01088
01089
01090
01091 }
01092
01093
01094 const TBuffer3D & TGeoTube::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
01095 {
01096
01097 static TBuffer3DTube buffer;
01098 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
01099
01100 if (reqSections & TBuffer3D::kShapeSpecific) {
01101 buffer.fRadiusInner = fRmin;
01102 buffer.fRadiusOuter = fRmax;
01103 buffer.fHalfLength = fDz;
01104 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
01105 }
01106 if (reqSections & TBuffer3D::kRawSizes) {
01107 Int_t n = gGeoManager->GetNsegments();
01108 Int_t nbPnts = 4*n;
01109 Int_t nbSegs = 8*n;
01110 Int_t nbPols = 4*n;
01111 if (!HasRmin()) {
01112 nbPnts = 2*(n+1);
01113 nbSegs = 5*n;
01114 nbPols = 3*n;
01115 }
01116 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
01117 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
01118 }
01119 }
01120 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
01121 SetPoints(buffer.fPnts);
01122 if (!buffer.fLocalFrame) {
01123 TransformPoints(buffer.fPnts, buffer.NbPnts());
01124 }
01125 SetSegsAndPols(buffer);
01126 buffer.SetSectionsValid(TBuffer3D::kRaw);
01127 }
01128
01129 return buffer;
01130 }
01131
01132 ClassImp(TGeoTubeSeg)
01133
01134
01135 TGeoTubeSeg::TGeoTubeSeg()
01136 {
01137
01138 SetShapeBit(TGeoShape::kGeoTubeSeg);
01139 fPhi1 = fPhi2 = 0.0;
01140 }
01141
01142
01143 TGeoTubeSeg::TGeoTubeSeg(Double_t rmin, Double_t rmax, Double_t dz,
01144 Double_t phi1, Double_t phi2)
01145 :TGeoTube(rmin, rmax, dz)
01146 {
01147
01148 SetShapeBit(TGeoShape::kGeoTubeSeg);
01149 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
01150 ComputeBBox();
01151 }
01152
01153
01154 TGeoTubeSeg::TGeoTubeSeg(const char *name, Double_t rmin, Double_t rmax, Double_t dz,
01155 Double_t phi1, Double_t phi2)
01156 :TGeoTube(name, rmin, rmax, dz)
01157 {
01158
01159 SetShapeBit(TGeoShape::kGeoTubeSeg);
01160 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
01161 ComputeBBox();
01162 }
01163
01164
01165 TGeoTubeSeg::TGeoTubeSeg(Double_t *param)
01166 :TGeoTube(0, 0, 0)
01167 {
01168
01169
01170
01171
01172
01173
01174 SetShapeBit(TGeoShape::kGeoTubeSeg);
01175 SetDimensions(param);
01176 ComputeBBox();
01177 }
01178
01179
01180 TGeoTubeSeg::~TGeoTubeSeg()
01181 {
01182
01183 }
01184
01185
01186 Double_t TGeoTubeSeg::Capacity() const
01187 {
01188
01189 return TGeoTubeSeg::Capacity(fRmin,fRmax,fDz,fPhi1,fPhi2);
01190 }
01191
01192
01193 Double_t TGeoTubeSeg::Capacity(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2)
01194 {
01195
01196 Double_t capacity = TMath::Abs(phi2-phi1)*TMath::DegToRad()*(rmax*rmax-rmin*rmin)*dz;
01197 return capacity;
01198 }
01199
01200
01201 void TGeoTubeSeg::ComputeBBox()
01202 {
01203
01204 Double_t xc[4];
01205 Double_t yc[4];
01206 xc[0] = fRmax*TMath::Cos(fPhi1*TMath::DegToRad());
01207 yc[0] = fRmax*TMath::Sin(fPhi1*TMath::DegToRad());
01208 xc[1] = fRmax*TMath::Cos(fPhi2*TMath::DegToRad());
01209 yc[1] = fRmax*TMath::Sin(fPhi2*TMath::DegToRad());
01210 xc[2] = fRmin*TMath::Cos(fPhi1*TMath::DegToRad());
01211 yc[2] = fRmin*TMath::Sin(fPhi1*TMath::DegToRad());
01212 xc[3] = fRmin*TMath::Cos(fPhi2*TMath::DegToRad());
01213 yc[3] = fRmin*TMath::Sin(fPhi2*TMath::DegToRad());
01214
01215 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
01216 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
01217 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
01218 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
01219
01220 Double_t dp = fPhi2-fPhi1;
01221 if (dp<0) dp+=360;
01222 Double_t ddp = -fPhi1;
01223 if (ddp<0) ddp+= 360;
01224 if (ddp>360) ddp-=360;
01225 if (ddp<=dp) xmax = fRmax;
01226 ddp = 90-fPhi1;
01227 if (ddp<0) ddp+= 360;
01228 if (ddp>360) ddp-=360;
01229 if (ddp<=dp) ymax = fRmax;
01230 ddp = 180-fPhi1;
01231 if (ddp<0) ddp+= 360;
01232 if (ddp>360) ddp-=360;
01233 if (ddp<=dp) xmin = -fRmax;
01234 ddp = 270-fPhi1;
01235 if (ddp<0) ddp+= 360;
01236 if (ddp>360) ddp-=360;
01237 if (ddp<=dp) ymin = -fRmax;
01238 fOrigin[0] = (xmax+xmin)/2;
01239 fOrigin[1] = (ymax+ymin)/2;
01240 fOrigin[2] = 0;
01241 fDX = (xmax-xmin)/2;
01242 fDY = (ymax-ymin)/2;
01243 fDZ = fDz;
01244 }
01245
01246
01247 void TGeoTubeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
01248 {
01249
01250 Double_t saf[3];
01251 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01252 Double_t r = TMath::Sqrt(rsq);
01253 Double_t c1 = TMath::Cos(fPhi1*TMath::DegToRad());
01254 Double_t s1 = TMath::Sin(fPhi1*TMath::DegToRad());
01255 Double_t c2 = TMath::Cos(fPhi2*TMath::DegToRad());
01256 Double_t s2 = TMath::Sin(fPhi2*TMath::DegToRad());
01257 saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
01258 saf[1] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
01259 saf[2] = TMath::Abs(fRmax-r);
01260 Int_t i = TMath::LocMin(3,saf);
01261 if (((fPhi2-fPhi1)<360.) && TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
01262 TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
01263 return;
01264 }
01265 if (i==0) {
01266 norm[0] = norm[1] = 0.;
01267 norm[2] = TMath::Sign(1.,dir[2]);
01268 return;
01269 }
01270 norm[2] = 0;
01271 Double_t phi = TMath::ATan2(point[1], point[0]);
01272 norm[0] = TMath::Cos(phi);
01273 norm[1] = TMath::Sin(phi);
01274 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
01275 norm[0] = -norm[0];
01276 norm[1] = -norm[1];
01277 }
01278 }
01279
01280
01281 void TGeoTubeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
01282 Double_t rmin, Double_t rmax, Double_t ,
01283 Double_t c1, Double_t s1, Double_t c2, Double_t s2)
01284 {
01285
01286 Double_t saf[2];
01287 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01288 Double_t r = TMath::Sqrt(rsq);
01289 saf[0] = (rmin>1E-10)?TMath::Abs(r-rmin):TGeoShape::Big();
01290 saf[1] = TMath::Abs(rmax-r);
01291 Int_t i = TMath::LocMin(2,saf);
01292 if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
01293 TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
01294 return;
01295 }
01296 norm[2] = 0;
01297 Double_t phi = TMath::ATan2(point[1], point[0]);
01298 norm[0] = TMath::Cos(phi);
01299 norm[1] = TMath::Sin(phi);
01300 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
01301 norm[0] = -norm[0];
01302 norm[1] = -norm[1];
01303 }
01304 }
01305
01306
01307 Bool_t TGeoTubeSeg::Contains(Double_t *point) const
01308 {
01309
01310
01311 if (!TGeoTube::Contains(point)) return kFALSE;
01312 return IsInPhiRange(point, fPhi1, fPhi2);
01313 }
01314
01315
01316 Int_t TGeoTubeSeg::DistancetoPrimitive(Int_t px, Int_t py)
01317 {
01318
01319 Int_t n = gGeoManager->GetNsegments()+1;
01320 const Int_t numPoints = 4*n;
01321 return ShapeDistancetoPrimitive(numPoints, px, py);
01322 }
01323
01324
01325 Double_t TGeoTubeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
01326 Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
01327 {
01328
01329
01330
01331 Double_t stube = TGeoTube::DistFromInsideS(point,dir,rmin,rmax,dz);
01332 if (stube<=0) return 0.0;
01333 Double_t sfmin = TGeoShape::Big();
01334 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01335 Double_t r = TMath::Sqrt(rsq);
01336 Double_t cpsi=point[0]*cm+point[1]*sm;
01337 if (cpsi>r*cdfi+TGeoShape::Tolerance()) {
01338 sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
01339 return TMath::Min(stube,sfmin);
01340 }
01341
01342
01343 Double_t ddotn, xi, yi;
01344 if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
01345 ddotn = s1*dir[0]-c1*dir[1];
01346 if (ddotn>=0) return 0.0;
01347 ddotn = -s2*dir[0]+c2*dir[1];
01348 if (ddotn<=0) return stube;
01349 sfmin = s2*point[0]-c2*point[1];
01350 if (sfmin<=0) return stube;
01351 sfmin /= ddotn;
01352 if (sfmin >= stube) return stube;
01353 xi = point[0]+sfmin*dir[0];
01354 yi = point[1]+sfmin*dir[1];
01355 if (yi*cm-xi*sm<0) return stube;
01356 return sfmin;
01357 }
01358 ddotn = -s2*dir[0]+c2*dir[1];
01359 if (ddotn>=0) return 0.0;
01360 ddotn = s1*dir[0]-c1*dir[1];
01361 if (ddotn<=0) return stube;
01362 sfmin = -s1*point[0]+c1*point[1];
01363 if (sfmin<=0) return stube;
01364 sfmin /= ddotn;
01365 if (sfmin >= stube) return stube;
01366 xi = point[0]+sfmin*dir[0];
01367 yi = point[1]+sfmin*dir[1];
01368 if (yi*cm-xi*sm>0) return stube;
01369 return sfmin;
01370 }
01371
01372
01373 Double_t TGeoTubeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
01374 {
01375
01376
01377 if (iact<3 && safe) {
01378 *safe = SafetyS(point, kTRUE, fRmin, fRmax, fDz, fPhi1, fPhi2);
01379 if (iact==0) return TGeoShape::Big();
01380 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
01381 }
01382 if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromInsideS(point,dir,fRmin,fRmax,fDz);
01383 Double_t phi1 = fPhi1*TMath::DegToRad();
01384 Double_t phi2 = fPhi2*TMath::DegToRad();
01385 Double_t c1 = TMath::Cos(phi1);
01386 Double_t c2 = TMath::Cos(phi2);
01387 Double_t s1 = TMath::Sin(phi1);
01388 Double_t s2 = TMath::Sin(phi2);
01389 Double_t phim = 0.5*(phi1+phi2);
01390 Double_t cm = TMath::Cos(phim);
01391 Double_t sm = TMath::Sin(phim);
01392 Double_t dfi = 0.5*(phi2-phi1);
01393 Double_t cdfi = TMath::Cos(dfi);
01394
01395
01396 return TGeoTubeSeg::DistFromInsideS(point,dir,fRmin,fRmax,fDz,c1,s1,c2,s2,cm,sm,cdfi);
01397 }
01398
01399
01400 Double_t TGeoTubeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax,
01401 Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2,
01402 Double_t cm, Double_t sm, Double_t cdfi)
01403 {
01404
01405
01406 Double_t r2, cpsi;
01407
01408 Double_t xi, yi, zi;
01409 zi = dz - TMath::Abs(point[2]);
01410 Double_t rmaxsq = rmax*rmax;
01411 Double_t rminsq = rmin*rmin;
01412 Double_t s = TGeoShape::Big();
01413 Double_t snxt=TGeoShape::Big();
01414 Bool_t in = kFALSE;
01415 Bool_t inz = (zi<0)?kFALSE:kTRUE;
01416 if (!inz) {
01417 if (point[2]*dir[2]>=0) return TGeoShape::Big();
01418 s = -zi/TMath::Abs(dir[2]);
01419 xi = point[0]+s*dir[0];
01420 yi = point[1]+s*dir[1];
01421 r2=xi*xi+yi*yi;
01422 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01423 cpsi=(xi*cm+yi*sm)/TMath::Sqrt(r2);
01424 if (cpsi>=cdfi) return s;
01425 }
01426 }
01427
01428
01429 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01430 Double_t r = TMath::Sqrt(rsq);
01431 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
01432 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
01433 Double_t b,d;
01434 Bool_t inrmax = kFALSE;
01435 Bool_t inrmin = kFALSE;
01436 Bool_t inphi = kFALSE;
01437 if (rsq<=rmaxsq+TGeoShape::Tolerance()) inrmax = kTRUE;
01438 if (rsq>=rminsq-TGeoShape::Tolerance()) inrmin = kTRUE;
01439 cpsi=point[0]*cm+point[1]*sm;
01440 if (cpsi>r*cdfi-TGeoShape::Tolerance()) inphi = kTRUE;
01441 in = inz & inrmin & inrmax & inphi;
01442
01443 if (in) {
01444 Bool_t checkout = kFALSE;
01445 Double_t safphi = (cpsi-r*cdfi)*TMath::Sqrt(1.-cdfi*cdfi);
01446
01447
01448 if (zi<rmax-r) {
01449 if (TGeoShape::IsSameWithinTolerance(rmin,0) || (zi<r-rmin)) {
01450 if (zi<safphi) {
01451 if (point[2]*dir[2]<0) return 0.0;
01452 return TGeoShape::Big();
01453 }
01454 }
01455 }
01456 if ((rmaxsq-rsq) < (rsq-rminsq)) checkout = kTRUE;
01457
01458 if (checkout && (rmax-r<safphi)) {
01459 if (rdotn>=0) return TGeoShape::Big();
01460 return 0.0;
01461 }
01462 if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
01463
01464 if (TGeoShape::IsSameWithinTolerance(rmin,0) || (safphi<r-rmin)) {
01465
01466
01467 Double_t un;
01468 if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
01469 un = dir[0]*s1-dir[1]*c1;
01470 if (un < 0) return 0.0;
01471 if (cdfi>=0) return TGeoShape::Big();
01472 un = -dir[0]*s2+dir[1]*c2;
01473 if (un<0) {
01474 s = -point[0]*s2+point[1]*c2;
01475 if (s>0) {
01476 s /= (-un);
01477 zi = point[2]+s*dir[2];
01478 if (TMath::Abs(zi)<=dz) {
01479 xi = point[0]+s*dir[0];
01480 yi = point[1]+s*dir[1];
01481 r2=xi*xi+yi*yi;
01482 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01483 if ((yi*cm-xi*sm)>0) return s;
01484 }
01485 }
01486 }
01487 }
01488 } else {
01489 un = -dir[0]*s2+dir[1]*c2;
01490 if (un < 0) return 0.0;
01491 if (cdfi>=0) return TGeoShape::Big();
01492 un = dir[0]*s1-dir[1]*c1;
01493 if (un<0) {
01494 s = point[0]*s1-point[1]*c1;
01495 if (s>0) {
01496 s /= (-un);
01497 zi = point[2]+s*dir[2];
01498 if (TMath::Abs(zi)<=dz) {
01499 xi = point[0]+s*dir[0];
01500 yi = point[1]+s*dir[1];
01501 r2=xi*xi+yi*yi;
01502 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01503 if ((yi*cm-xi*sm)<0) return s;
01504 }
01505 }
01506 }
01507 }
01508 }
01509
01510 if (rdotn>=0) return TGeoShape::Big();
01511 if (cdfi>=0) return TGeoShape::Big();
01512 DistToTube(rsq, nsq, rdotn, rmin, b, d);
01513 if (d>0) {
01514 s=-b+d;
01515 if (s>0) {
01516 zi=point[2]+s*dir[2];
01517 if (TMath::Abs(zi)<=dz) {
01518 xi=point[0]+s*dir[0];
01519 yi=point[1]+s*dir[1];
01520 if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
01521 }
01522 }
01523 }
01524 return TGeoShape::Big();
01525 }
01526
01527 if (rdotn>=0) return 0.0;
01528 DistToTube(rsq, nsq, rdotn, rmin, b, d);
01529 if (d>0) {
01530 s=-b+d;
01531 if (s>0) {
01532 zi=point[2]+s*dir[2];
01533 if (TMath::Abs(zi)<=dz) {
01534
01535 xi=point[0]+s*dir[0];
01536 yi=point[1]+s*dir[1];
01537 r2=xi*xi+yi*yi;
01538 if ((xi*cm+yi*sm) >= rmin*cdfi) return s;
01539
01540 Double_t un=-dir[0]*s1+dir[1]*c1;
01541 if (un > 0) {
01542 s=point[0]*s1-point[1]*c1;
01543 if (s>=0) {
01544 s /= un;
01545 zi=point[2]+s*dir[2];
01546 if (TMath::Abs(zi)<=dz) {
01547 xi=point[0]+s*dir[0];
01548 yi=point[1]+s*dir[1];
01549 r2=xi*xi+yi*yi;
01550 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01551 if ((yi*cm-xi*sm)<=0) {
01552 if (s<snxt) snxt=s;
01553 }
01554 }
01555 }
01556 }
01557 }
01558 un=dir[0]*s2-dir[1]*c2;
01559 if (un > 0) {
01560 s=(point[1]*c2-point[0]*s2)/un;
01561 if (s>=0 && s<snxt) {
01562 zi=point[2]+s*dir[2];
01563 if (TMath::Abs(zi)<=dz) {
01564 xi=point[0]+s*dir[0];
01565 yi=point[1]+s*dir[1];
01566 r2=xi*xi+yi*yi;
01567 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01568 if ((yi*cm-xi*sm)>=0) {
01569 return s;
01570 }
01571 }
01572 }
01573 }
01574 }
01575 return snxt;
01576 }
01577 }
01578 }
01579 return TGeoShape::Big();
01580 }
01581
01582 if (TMath::Abs(nsq)<TGeoShape::Tolerance()) return TGeoShape::Big();
01583 if (rsq>=rmax*rmax) {
01584 if (rdotn>=0) return TGeoShape::Big();
01585 TGeoTube::DistToTube(rsq, nsq, rdotn, rmax, b, d);
01586 if (d>0) {
01587 s=-b-d;
01588 if (s>0) {
01589 zi=point[2]+s*dir[2];
01590 if (TMath::Abs(zi)<=dz) {
01591 xi=point[0]+s*dir[0];
01592 yi=point[1]+s*dir[1];
01593 cpsi = xi*cm+yi*sm;
01594 if (cpsi>=rmax*cdfi) return s;
01595 }
01596 }
01597 }
01598 }
01599
01600 if (rmin>0) {
01601 TGeoTube::DistToTube(rsq, nsq, rdotn, rmin, b, d);
01602 if (d>0) {
01603 s=-b+d;
01604 if (s>0) {
01605 zi=point[2]+s*dir[2];
01606 if (TMath::Abs(zi)<=dz) {
01607 xi=point[0]+s*dir[0];
01608 yi=point[1]+s*dir[1];
01609 cpsi = xi*cm+yi*sm;
01610 if (cpsi>=rmin*cdfi) snxt=s;
01611 }
01612 }
01613 }
01614 }
01615
01616 Double_t un=-dir[0]*s1+dir[1]*c1;
01617 if (un > 0) {
01618 s=point[0]*s1-point[1]*c1;
01619 if (s>=0) {
01620 s /= un;
01621 zi=point[2]+s*dir[2];
01622 if (TMath::Abs(zi)<=dz) {
01623 xi=point[0]+s*dir[0];
01624 yi=point[1]+s*dir[1];
01625 r2=xi*xi+yi*yi;
01626 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01627 if ((yi*cm-xi*sm)<=0) {
01628 if (s<snxt) snxt=s;
01629 }
01630 }
01631 }
01632 }
01633 }
01634 un=dir[0]*s2-dir[1]*c2;
01635 if (un > 0) {
01636 s=point[1]*c2-point[0]*s2;
01637 if (s>=0) {
01638 s /= un;
01639 zi=point[2]+s*dir[2];
01640 if (TMath::Abs(zi)<=dz) {
01641 xi=point[0]+s*dir[0];
01642 yi=point[1]+s*dir[1];
01643 r2=xi*xi+yi*yi;
01644 if ((rminsq<=r2) && (r2<=rmaxsq)) {
01645 if ((yi*cm-xi*sm)>=0) {
01646 if (s<snxt) snxt=s;
01647 }
01648 }
01649 }
01650 }
01651 }
01652 return snxt;
01653 }
01654
01655
01656 Double_t TGeoTubeSeg::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
01657 {
01658
01659
01660 if (iact<3 && safe) {
01661 *safe = SafetyS(point, kFALSE, fRmin, fRmax, fDz, fPhi1, fPhi2);
01662 if (iact==0) return TGeoShape::Big();
01663 if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
01664 }
01665
01666 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
01667 if (sdist>=step) return TGeoShape::Big();
01668 if ((fPhi2-fPhi1)>=360.) return TGeoTube::DistFromOutsideS(point,dir,fRmin,fRmax,fDz);
01669 Double_t phi1 = fPhi1*TMath::DegToRad();
01670 Double_t phi2 = fPhi2*TMath::DegToRad();
01671 Double_t c1 = TMath::Cos(phi1);
01672 Double_t s1 = TMath::Sin(phi1);
01673 Double_t c2 = TMath::Cos(phi2);
01674 Double_t s2 = TMath::Sin(phi2);
01675 Double_t fio = 0.5*(phi1+phi2);
01676 Double_t cm = TMath::Cos(fio);
01677 Double_t sm = TMath::Sin(fio);
01678 Double_t dfi = 0.5*(phi2-phi1);
01679 Double_t cdfi = TMath::Cos(dfi);
01680
01681
01682 return TGeoTubeSeg::DistFromOutsideS(point, dir, fRmin, fRmax, fDz, c1, s1, c2, s2, cm, sm, cdfi);
01683 }
01684
01685
01686 TGeoVolume *TGeoTubeSeg::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
01687 Double_t start, Double_t step)
01688 {
01689
01690
01691
01692
01693
01694
01695 TGeoShape *shape;
01696 TGeoVolume *vol;
01697 TGeoVolumeMulti *vmulti;
01698 TGeoPatternFinder *finder;
01699 TString opt = "";
01700 Double_t dphi;
01701 Int_t id;
01702 Double_t end = start+ndiv*step;
01703 switch (iaxis) {
01704 case 1:
01705 finder = new TGeoPatternCylR(voldiv, ndiv, start, end);
01706 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01707 voldiv->SetFinder(finder);
01708 finder->SetDivIndex(voldiv->GetNdaughters());
01709 for (id=0; id<ndiv; id++) {
01710 shape = new TGeoTubeSeg(start+id*step, start+(id+1)*step, fDz, fPhi1, fPhi2);
01711 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01712 vmulti->AddVolume(vol);
01713 opt = "R";
01714 voldiv->AddNodeOffset(vol, id, 0, opt.Data());
01715 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01716 }
01717 return vmulti;
01718 case 2:
01719 dphi = fPhi2-fPhi1;
01720 if (dphi<0) dphi+=360.;
01721 if (step<=0) {step=dphi/ndiv; start=fPhi1; end=fPhi2;}
01722 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
01723 voldiv->SetFinder(finder);
01724 finder->SetDivIndex(voldiv->GetNdaughters());
01725 shape = new TGeoTubeSeg(fRmin, fRmax, fDz, -step/2, step/2);
01726 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01727 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01728 vmulti->AddVolume(vol);
01729 opt = "Phi";
01730 for (id=0; id<ndiv; id++) {
01731 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
01732 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01733 }
01734 return vmulti;
01735 case 3:
01736 finder = new TGeoPatternZ(voldiv, ndiv, start, end);
01737 voldiv->SetFinder(finder);
01738 finder->SetDivIndex(voldiv->GetNdaughters());
01739 shape = new TGeoTubeSeg(fRmin, fRmax, step/2, fPhi1, fPhi2);
01740 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01741 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01742 vmulti->AddVolume(vol);
01743 opt = "Z";
01744 for (id=0; id<ndiv; id++) {
01745 voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
01746 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01747 }
01748 return vmulti;
01749 default:
01750 Error("Divide", "In shape %s wrong axis type for division", GetName());
01751 return 0;
01752 }
01753 }
01754
01755
01756 Double_t TGeoTubeSeg::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
01757 {
01758
01759 xlo = 0;
01760 xhi = 0;
01761 Double_t dx = 0;
01762 switch (iaxis) {
01763 case 1:
01764 xlo = fRmin;
01765 xhi = fRmax;
01766 dx = xhi-xlo;
01767 return dx;
01768 case 2:
01769 xlo = fPhi1;
01770 xhi = fPhi2;
01771 dx = xhi-xlo;
01772 return dx;
01773 case 3:
01774 xlo = -fDz;
01775 xhi = fDz;
01776 dx = xhi-xlo;
01777 return dx;
01778 }
01779 return dx;
01780 }
01781
01782
01783 void TGeoTubeSeg::GetBoundingCylinder(Double_t *param) const
01784 {
01785
01786
01787 param[0] = fRmin;
01788 param[0] *= param[0];
01789 param[1] = fRmax;
01790 param[1] *= param[1];
01791 param[2] = fPhi1;
01792 param[3] = fPhi2;
01793 }
01794
01795
01796 TGeoShape *TGeoTubeSeg::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
01797 {
01798
01799
01800 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
01801 if (!mother->TestShapeBit(kGeoTube)) {
01802 Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
01803 return 0;
01804 }
01805 Double_t rmin, rmax, dz;
01806 rmin = fRmin;
01807 rmax = fRmax;
01808 dz = fDz;
01809 if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
01810 if (fRmin<0)
01811 rmin = ((TGeoTube*)mother)->GetRmin();
01812 if ((fRmax<0) || (fRmax<=fRmin))
01813 rmax = ((TGeoTube*)mother)->GetRmax();
01814
01815 return (new TGeoTubeSeg(GetName(),rmin, rmax, dz, fPhi1, fPhi2));
01816 }
01817
01818
01819 void TGeoTubeSeg::InspectShape() const
01820 {
01821
01822 printf("*** Shape %s: TGeoTubeSeg ***\n", GetName());
01823 printf(" Rmin = %11.5f\n", fRmin);
01824 printf(" Rmax = %11.5f\n", fRmax);
01825 printf(" dz = %11.5f\n", fDz);
01826 printf(" phi1 = %11.5f\n", fPhi1);
01827 printf(" phi2 = %11.5f\n", fPhi2);
01828 printf(" Bounding box:\n");
01829 TGeoBBox::InspectShape();
01830 }
01831
01832
01833 TBuffer3D *TGeoTubeSeg::MakeBuffer3D() const
01834 {
01835
01836
01837
01838 Int_t n = gGeoManager->GetNsegments()+1;
01839 Int_t nbPnts = 4*n;
01840 Int_t nbSegs = 2*nbPnts;
01841 Int_t nbPols = nbPnts-2;
01842
01843 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
01844 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
01845 if (buff)
01846 {
01847 SetPoints(buff->fPnts);
01848 SetSegsAndPols(*buff);
01849 }
01850
01851 return buff;
01852 }
01853
01854
01855 void TGeoTubeSeg::SetSegsAndPols(TBuffer3D &buff) const
01856 {
01857
01858 Int_t i, j;
01859 Int_t n = gGeoManager->GetNsegments()+1;
01860 Int_t c = GetBasicColor();
01861
01862 memset(buff.fSegs, 0, buff.NbSegs()*3*sizeof(Int_t));
01863 for (i = 0; i < 4; i++) {
01864 for (j = 1; j < n; j++) {
01865 buff.fSegs[(i*n+j-1)*3 ] = c;
01866 buff.fSegs[(i*n+j-1)*3+1] = i*n+j-1;
01867 buff.fSegs[(i*n+j-1)*3+2] = i*n+j;
01868 }
01869 }
01870 for (i = 4; i < 6; i++) {
01871 for (j = 0; j < n; j++) {
01872 buff.fSegs[(i*n+j)*3 ] = c+1;
01873 buff.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
01874 buff.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
01875 }
01876 }
01877 for (i = 6; i < 8; i++) {
01878 for (j = 0; j < n; j++) {
01879 buff.fSegs[(i*n+j)*3 ] = c;
01880 buff.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
01881 buff.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
01882 }
01883 }
01884
01885 Int_t indx = 0;
01886 memset(buff.fPols, 0, buff.NbPols()*6*sizeof(Int_t));
01887 i = 0;
01888 for (j = 0; j < n-1; j++) {
01889 buff.fPols[indx++] = c;
01890 buff.fPols[indx++] = 4;
01891 buff.fPols[indx++] = (4+i)*n+j+1;
01892 buff.fPols[indx++] = (2+i)*n+j;
01893 buff.fPols[indx++] = (4+i)*n+j;
01894 buff.fPols[indx++] = i*n+j;
01895 }
01896 i = 1;
01897 for (j = 0; j < n-1; j++) {
01898 buff.fPols[indx++] = c;
01899 buff.fPols[indx++] = 4;
01900 buff.fPols[indx++] = i*n+j;
01901 buff.fPols[indx++] = (4+i)*n+j;
01902 buff.fPols[indx++] = (2+i)*n+j;
01903 buff.fPols[indx++] = (4+i)*n+j+1;
01904 }
01905 i = 2;
01906 for (j = 0; j < n-1; j++) {
01907 buff.fPols[indx++] = c+i;
01908 buff.fPols[indx++] = 4;
01909 buff.fPols[indx++] = (i-2)*2*n+j;
01910 buff.fPols[indx++] = (4+i)*n+j;
01911 buff.fPols[indx++] = ((i-2)*2+1)*n+j;
01912 buff.fPols[indx++] = (4+i)*n+j+1;
01913 }
01914 i = 3;
01915 for (j = 0; j < n-1; j++) {
01916 buff.fPols[indx++] = c+i;
01917 buff.fPols[indx++] = 4;
01918 buff.fPols[indx++] = (4+i)*n+j+1;
01919 buff.fPols[indx++] = ((i-2)*2+1)*n+j;
01920 buff.fPols[indx++] = (4+i)*n+j;
01921 buff.fPols[indx++] = (i-2)*2*n+j;
01922 }
01923 buff.fPols[indx++] = c+2;
01924 buff.fPols[indx++] = 4;
01925 buff.fPols[indx++] = 6*n;
01926 buff.fPols[indx++] = 4*n;
01927 buff.fPols[indx++] = 7*n;
01928 buff.fPols[indx++] = 5*n;
01929 buff.fPols[indx++] = c+2;
01930 buff.fPols[indx++] = 4;
01931 buff.fPols[indx++] = 6*n-1;
01932 buff.fPols[indx++] = 8*n-1;
01933 buff.fPols[indx++] = 5*n-1;
01934 buff.fPols[indx++] = 7*n-1;
01935 }
01936
01937
01938 Double_t TGeoTubeSeg::Safety(Double_t *point, Bool_t in) const
01939 {
01940
01941
01942 Double_t saf[3];
01943 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01944 Double_t r = TMath::Sqrt(rsq);
01945
01946 Double_t safe = TGeoShape::Big();
01947 if (in) {
01948 saf[0] = fDz-TMath::Abs(point[2]);
01949 saf[1] = r-fRmin;
01950 saf[2] = fRmax-r;
01951 safe = saf[TMath::LocMin(3,saf)];
01952 } else {
01953
01954 saf[0] = TMath::Abs(point[2])-fDz;
01955 saf[1] = fRmin-r;
01956 saf[2] = r-fRmax;
01957 safe = saf[TMath::LocMax(3,saf)];
01958 }
01959 if ((fPhi2-fPhi1)>=360.) return safe;
01960 Double_t safphi = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi2);
01961
01962 if (in) return TMath::Min(safe, safphi);
01963 return TMath::Max(safe, safphi);
01964 }
01965
01966
01967 Double_t TGeoTubeSeg::SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz,
01968 Double_t phi1, Double_t phi2, Int_t skipz)
01969 {
01970
01971 Double_t saf[3];
01972 Double_t rsq = point[0]*point[0]+point[1]*point[1];
01973 Double_t r = TMath::Sqrt(rsq);
01974
01975 switch (skipz) {
01976 case 1:
01977 saf[0] = dz - point[2];
01978 break;
01979 case 2:
01980 saf[0] = dz + point[2];
01981 break;
01982 case 3:
01983 saf[0] = TGeoShape::Big();
01984 break;
01985 default:
01986 saf[0] = dz-TMath::Abs(point[2]);
01987 }
01988 saf[1] = r-rmin;
01989 saf[2] = rmax-r;
01990 Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1,phi2);
01991 Double_t safe = TGeoShape::Big();
01992
01993 if (in) {
01994 safe = saf[TMath::LocMin(3,saf)];
01995 return TMath::Min(safe, safphi);
01996 }
01997
01998 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
01999 safe = saf[TMath::LocMax(3,saf)];
02000 return TMath::Max(safe, safphi);
02001 }
02002
02003
02004 void TGeoTubeSeg::SavePrimitive(ostream &out, Option_t * )
02005 {
02006
02007 if (TObject::TestBit(kGeoSavePrimitive)) return;
02008 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
02009 out << " rmin = " << fRmin << ";" << endl;
02010 out << " rmax = " << fRmax << ";" << endl;
02011 out << " dz = " << fDz << ";" << endl;
02012 out << " phi1 = " << fPhi1 << ";" << endl;
02013 out << " phi2 = " << fPhi2 << ";" << endl;
02014 out << " TGeoShape *" << GetPointerName() << " = new TGeoTubeSeg(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2);" << endl;
02015 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
02016 }
02017
02018
02019 void TGeoTubeSeg::SetTubsDimensions(Double_t rmin, Double_t rmax, Double_t dz,
02020 Double_t phi1, Double_t phi2)
02021 {
02022
02023 fRmin = rmin;
02024 fRmax = rmax;
02025 fDz = dz;
02026 fPhi1 = phi1;
02027 if (fPhi1 < 0) fPhi1+=360.;
02028 fPhi2 = phi2;
02029 while (fPhi2<=fPhi1) fPhi2+=360.;
02030 if (TGeoShape::IsSameWithinTolerance(fPhi1,fPhi2)) Error("SetTubsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
02031 }
02032
02033
02034 void TGeoTubeSeg::SetDimensions(Double_t *param)
02035 {
02036
02037 Double_t rmin = param[0];
02038 Double_t rmax = param[1];
02039 Double_t dz = param[2];
02040 Double_t phi1 = param[3];
02041 Double_t phi2 = param[4];
02042 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
02043 }
02044
02045
02046 Bool_t TGeoTubeSeg::GetPointsOnSegments(Int_t npoints, Double_t *array) const
02047 {
02048
02049
02050
02051 if (npoints > (npoints/2)*2) {
02052 Error("GetPointsOnSegments","Npoints must be even number");
02053 return kFALSE;
02054 }
02055 Int_t nc = (Int_t)TMath::Sqrt(0.5*npoints);
02056 Double_t dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nc-1);
02057 Double_t phi = 0;
02058 Double_t phi1 = fPhi1 * TMath::DegToRad();
02059 Int_t ntop = npoints/2 - nc*(nc-1);
02060 Double_t dz = 2*fDz/(nc-1);
02061 Double_t z = 0;
02062 Int_t icrt = 0;
02063 Int_t nphi = nc;
02064
02065 for (Int_t i=0; i<nc; i++) {
02066 if (i == (nc-1)) {
02067 nphi = ntop;
02068 dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nphi-1);
02069 }
02070 z = -fDz + i*dz;
02071
02072 for (Int_t j=0; j<nphi; j++) {
02073 phi = phi1 + j*dphi;
02074 array[icrt++] = fRmin * TMath::Cos(phi);
02075 array[icrt++] = fRmin * TMath::Sin(phi);
02076 array[icrt++] = z;
02077 array[icrt++] = fRmax * TMath::Cos(phi);
02078 array[icrt++] = fRmax * TMath::Sin(phi);
02079 array[icrt++] = z;
02080 }
02081 }
02082 return kTRUE;
02083 }
02084
02085
02086 void TGeoTubeSeg::SetPoints(Double_t *points) const
02087 {
02088
02089 Double_t dz;
02090 Int_t j, n;
02091 Double_t phi, phi1, phi2, dphi;
02092 phi1 = fPhi1;
02093 phi2 = fPhi2;
02094 if (phi2<phi1) phi2+=360.;
02095 n = gGeoManager->GetNsegments()+1;
02096
02097 dphi = (phi2-phi1)/(n-1);
02098 dz = fDz;
02099
02100 if (points) {
02101 Int_t indx = 0;
02102
02103 for (j = 0; j < n; j++) {
02104 phi = (phi1+j*dphi)*TMath::DegToRad();
02105 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
02106 indx++;
02107 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
02108 indx++;
02109 points[indx+6*n] = dz;
02110 points[indx] =-dz;
02111 indx++;
02112 }
02113 for (j = 0; j < n; j++) {
02114 phi = (phi1+j*dphi)*TMath::DegToRad();
02115 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
02116 indx++;
02117 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
02118 indx++;
02119 points[indx+6*n]= dz;
02120 points[indx] =-dz;
02121 indx++;
02122 }
02123 }
02124 }
02125
02126
02127 void TGeoTubeSeg::SetPoints(Float_t *points) const
02128 {
02129
02130 Double_t dz;
02131 Int_t j, n;
02132 Double_t phi, phi1, phi2, dphi;
02133 phi1 = fPhi1;
02134 phi2 = fPhi2;
02135 if (phi2<phi1) phi2+=360.;
02136 n = gGeoManager->GetNsegments()+1;
02137
02138 dphi = (phi2-phi1)/(n-1);
02139 dz = fDz;
02140
02141 if (points) {
02142 Int_t indx = 0;
02143
02144 for (j = 0; j < n; j++) {
02145 phi = (phi1+j*dphi)*TMath::DegToRad();
02146 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
02147 indx++;
02148 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
02149 indx++;
02150 points[indx+6*n] = dz;
02151 points[indx] =-dz;
02152 indx++;
02153 }
02154 for (j = 0; j < n; j++) {
02155 phi = (phi1+j*dphi)*TMath::DegToRad();
02156 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
02157 indx++;
02158 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
02159 indx++;
02160 points[indx+6*n]= dz;
02161 points[indx] =-dz;
02162 indx++;
02163 }
02164 }
02165 }
02166
02167
02168 void TGeoTubeSeg::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
02169 {
02170
02171 Int_t n = gGeoManager->GetNsegments()+1;
02172 nvert = n*4;
02173 nsegs = n*8;
02174 npols = n*4 - 2;
02175 }
02176
02177
02178 Int_t TGeoTubeSeg::GetNmeshVertices() const
02179 {
02180
02181 Int_t n = gGeoManager->GetNsegments()+1;
02182 Int_t numPoints = n*4;
02183 return numPoints;
02184 }
02185
02186
02187 void TGeoTubeSeg::Sizeof3D() const
02188 {
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199 }
02200
02201
02202 const TBuffer3D & TGeoTubeSeg::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
02203 {
02204
02205 static TBuffer3DTubeSeg buffer;
02206 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
02207
02208 if (reqSections & TBuffer3D::kShapeSpecific) {
02209
02210 buffer.fRadiusInner = fRmin;
02211 buffer.fRadiusOuter = fRmax;
02212 buffer.fHalfLength = fDz;
02213 buffer.fPhiMin = fPhi1;
02214 buffer.fPhiMax = fPhi2;
02215 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
02216 }
02217 if (reqSections & TBuffer3D::kRawSizes) {
02218 Int_t n = gGeoManager->GetNsegments()+1;
02219 Int_t nbPnts = 4*n;
02220 Int_t nbSegs = 2*nbPnts;
02221 Int_t nbPols = nbPnts-2;
02222 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
02223 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
02224 }
02225 }
02226 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
02227 SetPoints(buffer.fPnts);
02228 if (!buffer.fLocalFrame) {
02229 TransformPoints(buffer.fPnts, buffer.NbPnts());
02230 }
02231 SetSegsAndPols(buffer);
02232 buffer.SetSectionsValid(TBuffer3D::kRaw);
02233 }
02234
02235 return buffer;
02236 }
02237
02238 ClassImp(TGeoCtub)
02239
02240 TGeoCtub::TGeoCtub()
02241 {
02242
02243 fNlow[0] = fNlow[1] = fNhigh[0] = fNhigh[1] = 0.;
02244 fNlow[2] = -1;
02245 fNhigh[2] = 1;
02246 }
02247
02248
02249 TGeoCtub::TGeoCtub(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
02250 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
02251 :TGeoTubeSeg(rmin, rmax, dz, phi1, phi2)
02252 {
02253
02254 fNlow[0] = lx;
02255 fNlow[1] = ly;
02256 fNlow[2] = lz;
02257 fNhigh[0] = tx;
02258 fNhigh[1] = ty;
02259 fNhigh[2] = tz;
02260 SetShapeBit(kGeoCtub);
02261 ComputeBBox();
02262 }
02263
02264
02265 TGeoCtub::TGeoCtub(const char *name, Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
02266 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
02267 :TGeoTubeSeg(name, rmin, rmax, dz, phi1, phi2)
02268 {
02269
02270 fNlow[0] = lx;
02271 fNlow[1] = ly;
02272 fNlow[2] = lz;
02273 fNhigh[0] = tx;
02274 fNhigh[1] = ty;
02275 fNhigh[2] = tz;
02276 SetShapeBit(kGeoCtub);
02277 ComputeBBox();
02278 }
02279
02280
02281 TGeoCtub::TGeoCtub(Double_t *params)
02282 :TGeoTubeSeg(0,0,0,0,0)
02283 {
02284
02285 SetCtubDimensions(params[0], params[1], params[2], params[3], params[4], params[5],
02286 params[6], params[7], params[8], params[9], params[10]);
02287 SetShapeBit(kGeoCtub);
02288 }
02289
02290
02291 TGeoCtub::~TGeoCtub()
02292 {
02293
02294 }
02295
02296
02297 Double_t TGeoCtub::Capacity() const
02298 {
02299
02300 Double_t capacity = TGeoTubeSeg::Capacity();
02301 return capacity;
02302 }
02303
02304
02305 void TGeoCtub::ComputeBBox()
02306 {
02307
02308 TGeoTubeSeg::ComputeBBox();
02309 if ((fNlow[2]>-(1E-10)) || (fNhigh[2]<1E-10)) {
02310 Error("ComputeBBox", "In shape %s wrong definition of cut planes", GetName());
02311 return;
02312 }
02313 Double_t xc=0, yc=0;
02314 Double_t zmin=0, zmax=0;
02315 Double_t z1;
02316 Double_t z[8];
02317
02318 Double_t phi_low = TMath::ATan2(fNlow[1], fNlow[0]) *TMath::RadToDeg();
02319 Double_t phi_hi = TMath::ATan2(fNhigh[1], fNhigh[0]) *TMath::RadToDeg();
02320 Bool_t in_range_low = kFALSE;
02321 Bool_t in_range_hi = kFALSE;
02322
02323 Int_t i;
02324 for (i=0; i<2; i++) {
02325 if (phi_low<0) phi_low+=360.;
02326 Double_t dphi = fPhi2 -fPhi1;
02327 if (dphi < 0) dphi+=360.;
02328 Double_t ddp = phi_low-fPhi1;
02329 if (ddp<0) ddp += 360.;
02330 if (ddp <= dphi) {
02331 xc = fRmin*TMath::Cos(phi_low*TMath::DegToRad());
02332 yc = fRmin*TMath::Sin(phi_low*TMath::DegToRad());
02333 z1 = GetZcoord(xc, yc, -fDz);
02334 xc = fRmax*TMath::Cos(phi_low*TMath::DegToRad());
02335 yc = fRmax*TMath::Sin(phi_low*TMath::DegToRad());
02336 z1 = TMath::Min(z1, GetZcoord(xc, yc, -fDz));
02337 if (in_range_low)
02338 zmin = TMath::Min(zmin, z1);
02339 else
02340 zmin = z1;
02341 in_range_low = kTRUE;
02342 }
02343 phi_low += 180;
02344 if (phi_low>360) phi_low-=360.;
02345 }
02346
02347 for (i=0; i<2; i++) {
02348 if (phi_hi<0) phi_hi+=360.;
02349 Double_t dphi = fPhi2 -fPhi1;
02350 if (dphi < 0) dphi+=360.;
02351 Double_t ddp = phi_hi-fPhi1;
02352 if (ddp<0) ddp += 360.;
02353 if (ddp <= dphi) {
02354 xc = fRmin*TMath::Cos(phi_hi*TMath::DegToRad());
02355 yc = fRmin*TMath::Sin(phi_hi*TMath::DegToRad());
02356 z1 = GetZcoord(xc, yc, fDz);
02357 xc = fRmax*TMath::Cos(phi_hi*TMath::DegToRad());
02358 yc = fRmax*TMath::Sin(phi_hi*TMath::DegToRad());
02359 z1 = TMath::Max(z1, GetZcoord(xc, yc, fDz));
02360 if (in_range_hi)
02361 zmax = TMath::Max(zmax, z1);
02362 else
02363 zmax = z1;
02364 in_range_hi = kTRUE;
02365 }
02366 phi_hi += 180;
02367 if (phi_hi>360) phi_hi-=360.;
02368 }
02369
02370
02371 xc = fRmin*TMath::Cos(fPhi1*TMath::DegToRad());
02372 yc = fRmin*TMath::Sin(fPhi1*TMath::DegToRad());
02373 z[0] = GetZcoord(xc, yc, -fDz);
02374 z[4] = GetZcoord(xc, yc, fDz);
02375
02376 xc = fRmin*TMath::Cos(fPhi2*TMath::DegToRad());
02377 yc = fRmin*TMath::Sin(fPhi2*TMath::DegToRad());
02378 z[1] = GetZcoord(xc, yc, -fDz);
02379 z[5] = GetZcoord(xc, yc, fDz);
02380
02381 xc = fRmax*TMath::Cos(fPhi1*TMath::DegToRad());
02382 yc = fRmax*TMath::Sin(fPhi1*TMath::DegToRad());
02383 z[2] = GetZcoord(xc, yc, -fDz);
02384 z[6] = GetZcoord(xc, yc, fDz);
02385
02386 xc = fRmax*TMath::Cos(fPhi2*TMath::DegToRad());
02387 yc = fRmax*TMath::Sin(fPhi2*TMath::DegToRad());
02388 z[3] = GetZcoord(xc, yc, -fDz);
02389 z[7] = GetZcoord(xc, yc, fDz);
02390
02391 z1 = z[TMath::LocMin(4, &z[0])];
02392 if (in_range_low)
02393 zmin = TMath::Min(zmin, z1);
02394 else
02395 zmin = z1;
02396
02397 z1 = z[TMath::LocMax(4, &z[4])+4];
02398 if (in_range_hi)
02399 zmax = TMath::Max(zmax, z1);
02400 else
02401 zmax = z1;
02402
02403 fDZ = 0.5*(zmax-zmin);
02404 fOrigin[2] = 0.5*(zmax+zmin);
02405 }
02406
02407
02408 void TGeoCtub::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
02409 {
02410
02411 Double_t saf[4];
02412 Bool_t isseg = kTRUE;
02413 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
02414 Double_t rsq = point[0]*point[0]+point[1]*point[1];
02415 Double_t r = TMath::Sqrt(rsq);
02416
02417 saf[0] = TMath::Abs(point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2]);
02418 saf[1] = TMath::Abs(point[0]*fNhigh[0] + point[1]*fNhigh[1] - (fDz-point[2])*fNhigh[2]);
02419 saf[2] = (fRmin>1E-10)?TMath::Abs(r-fRmin):TGeoShape::Big();
02420 saf[3] = TMath::Abs(fRmax-r);
02421 Int_t i = TMath::LocMin(4,saf);
02422 if (isseg) {
02423 Double_t c1 = TMath::Cos(fPhi1*TMath::DegToRad());
02424 Double_t s1 = TMath::Sin(fPhi1*TMath::DegToRad());
02425 Double_t c2 = TMath::Cos(fPhi2*TMath::DegToRad());
02426 Double_t s2 = TMath::Sin(fPhi2*TMath::DegToRad());
02427 if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
02428 TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
02429 return;
02430 }
02431 }
02432 if (i==0) {
02433 memcpy(norm, fNlow, 3*sizeof(Double_t));
02434 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
02435 norm[0] = -norm[0];
02436 norm[1] = -norm[1];
02437 norm[2] = -norm[2];
02438 }
02439 return;
02440 }
02441 if (i==1) {
02442 memcpy(norm, fNhigh, 3*sizeof(Double_t));
02443 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
02444 norm[0] = -norm[0];
02445 norm[1] = -norm[1];
02446 norm[2] = -norm[2];
02447 }
02448 return;
02449 }
02450
02451 norm[2] = 0;
02452 Double_t phi = TMath::ATan2(point[1], point[0]);
02453 norm[0] = TMath::Cos(phi);
02454 norm[1] = TMath::Sin(phi);
02455 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
02456 norm[0] = -norm[0];
02457 norm[1] = -norm[1];
02458 }
02459 }
02460
02461
02462 Bool_t TGeoCtub::Contains(Double_t *point) const
02463 {
02464
02465
02466 Double_t zin = point[0]*fNlow[0]+point[1]*fNlow[1]+(point[2]+fDz)*fNlow[2];
02467 if (zin>0) return kFALSE;
02468
02469 zin = point[0]*fNhigh[0]+point[1]*fNhigh[1]+(point[2]-fDz)*fNhigh[2];
02470 if (zin>0) return kFALSE;
02471
02472 Double_t r2 = point[0]*point[0]+point[1]*point[1];
02473 if ((r2<fRmin*fRmin) || (r2>fRmax*fRmax)) return kFALSE;
02474
02475 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
02476 if (phi < 0 ) phi+=360.;
02477 Double_t dphi = fPhi2 -fPhi1;
02478 Double_t ddp = phi-fPhi1;
02479 if (ddp<0) ddp += 360.;
02480
02481 if (ddp > dphi) return kFALSE;
02482 return kTRUE;
02483 }
02484
02485
02486 Double_t TGeoCtub::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
02487 {
02488
02489 xlo = 0;
02490 xhi = 0;
02491 Double_t dx = 0;
02492 switch (iaxis) {
02493 case 1:
02494 xlo = fRmin;
02495 xhi = fRmax;
02496 dx = xhi-xlo;
02497 return dx;
02498 case 2:
02499 xlo = fPhi1;
02500 xhi = fPhi2;
02501 dx = xhi-xlo;
02502 return dx;
02503 }
02504 return dx;
02505 }
02506
02507
02508 Double_t TGeoCtub::GetZcoord(Double_t xc, Double_t yc, Double_t zc) const
02509 {
02510
02511
02512 Double_t newz = 0;
02513 if (zc<0) newz = -fDz-(xc*fNlow[0]+yc*fNlow[1])/fNlow[2];
02514 else newz = fDz-(xc*fNhigh[0]+yc*fNhigh[1])/fNhigh[2];
02515 return newz;
02516 }
02517
02518
02519 Double_t TGeoCtub::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
02520 {
02521
02522 if (iact<3 && safe) {
02523 *safe = Safety(point, kFALSE);
02524 if (iact==0) return TGeoShape::Big();
02525 if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
02526 }
02527
02528 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
02529 if (sdist>=step) return TGeoShape::Big();
02530 Double_t saf[2];
02531 saf[0] = point[0]*fNlow[0] + point[1]*fNlow[1] + (fDz+point[2])*fNlow[2];
02532 saf[1] = point[0]*fNhigh[0] + point[1]*fNhigh[1] + (point[2]-fDz)*fNhigh[2];
02533 Double_t rsq = point[0]*point[0]+point[1]*point[1];
02534 Double_t r = TMath::Sqrt(rsq);
02535 Double_t c1=0,s1=0,c2=0,s2=0;
02536 Double_t fio=0, cfio=0, sfio=0, dfi=0, cdfi=0, cpsi=0;
02537 Double_t phi1 = fPhi1*TMath::DegToRad();
02538 Double_t phi2 = fPhi2*TMath::DegToRad();
02539 Bool_t tub = kFALSE;
02540 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
02541 if (!tub) {
02542 c1 = TMath::Cos(phi1);
02543 c2 = TMath::Cos(phi2);
02544 s1 = TMath::Sin(phi1);
02545 s2 = TMath::Sin(phi2);
02546 fio = 0.5*(phi1+phi2);
02547 cfio = TMath::Cos(fio);
02548 sfio = TMath::Sin(fio);
02549 dfi = 0.5*(phi2-phi1);
02550 cdfi = TMath::Cos(dfi);
02551 }
02552
02553
02554 Double_t r2;
02555 Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
02556
02557 Double_t xi, yi, zi;
02558 Double_t s = TGeoShape::Big();
02559 if (saf[0]>0) {
02560 if (calf<0) {
02561 s = -saf[0]/calf;
02562 xi = point[0]+s*dir[0];
02563 yi = point[1]+s*dir[1];
02564 r2=xi*xi+yi*yi;
02565 if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
02566 if (tub) return s;
02567 cpsi=(xi*cfio+yi*sfio)/TMath::Sqrt(r2);
02568 if (cpsi>=cdfi) return s;
02569 }
02570 }
02571 }
02572 calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
02573 if (saf[1]>0) {
02574 if (calf<0) {
02575 s = -saf[1]/calf;
02576 xi = point[0]+s*dir[0];
02577 yi = point[1]+s*dir[1];
02578 r2=xi*xi+yi*yi;
02579 if (((fRmin*fRmin)<=r2) && (r2<=(fRmax*fRmax))) {
02580 if (tub) return s;
02581 cpsi=(xi*cfio+yi*sfio)/TMath::Sqrt(r2);
02582 if (cpsi>=cdfi) return s;
02583 }
02584 }
02585 }
02586
02587
02588 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
02589 if (TMath::Abs(nsq)<1E-10) return TGeoShape::Big();
02590 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
02591 Double_t b,d;
02592
02593 if (r>fRmax) {
02594 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
02595 if (d>0) {
02596 s=-b-d;
02597 if (s>0) {
02598 xi=point[0]+s*dir[0];
02599 yi=point[1]+s*dir[1];
02600 zi=point[2]+s*dir[2];
02601 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
02602 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
02603 if (tub) return s;
02604 cpsi=(xi*cfio+yi*sfio)/fRmax;
02605 if (cpsi>=cdfi) return s;
02606 }
02607 }
02608 }
02609 }
02610 }
02611
02612 Double_t snxt=TGeoShape::Big();
02613 if (fRmin>0) {
02614 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
02615 if (d>0) {
02616 s=-b+d;
02617 if (s>0) {
02618 xi=point[0]+s*dir[0];
02619 yi=point[1]+s*dir[1];
02620 zi=point[2]+s*dir[2];
02621 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
02622 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
02623 if (tub) return s;
02624 cpsi=(xi*cfio+yi*sfio)/fRmin;
02625 if (cpsi>=cdfi) snxt=s;
02626 }
02627 }
02628 }
02629 }
02630 }
02631
02632 if (tub) return snxt;
02633 Double_t un=dir[0]*s1-dir[1]*c1;
02634 if (!TGeoShape::IsSameWithinTolerance(un,0)) {
02635 s=(point[1]*c1-point[0]*s1)/un;
02636 if (s>=0) {
02637 xi=point[0]+s*dir[0];
02638 yi=point[1]+s*dir[1];
02639 zi=point[2]+s*dir[2];
02640 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
02641 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
02642 r2=xi*xi+yi*yi;
02643 if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
02644 if ((yi*cfio-xi*sfio)<=0) {
02645 if (s<snxt) snxt=s;
02646 }
02647 }
02648 }
02649 }
02650 }
02651 }
02652 un=dir[0]*s2-dir[1]*c2;
02653 if (!TGeoShape::IsSameWithinTolerance(un,0)) {
02654 s=(point[1]*c2-point[0]*s2)/un;
02655 if (s>=0) {
02656 xi=point[0]+s*dir[0];
02657 yi=point[1]+s*dir[1];
02658 zi=point[2]+s*dir[2];
02659 if ((-xi*fNlow[0]-yi*fNlow[1]-(zi+fDz)*fNlow[2])>0) {
02660 if ((-xi*fNhigh[0]-yi*fNhigh[1]+(fDz-zi)*fNhigh[2])>0) {
02661 r2=xi*xi+yi*yi;
02662 if ((fRmin*fRmin<=r2) && (r2<=fRmax*fRmax)) {
02663 if ((yi*cfio-xi*sfio)>=0) {
02664 if (s<snxt) snxt=s;
02665 }
02666 }
02667 }
02668 }
02669 }
02670 }
02671 return snxt;
02672 }
02673
02674
02675 Double_t TGeoCtub::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
02676 {
02677
02678 if (iact<3 && safe) *safe = Safety(point, kTRUE);
02679 if (iact==0) return TGeoShape::Big();
02680 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
02681 Double_t rsq = point[0]*point[0]+point[1]*point[1];
02682 Double_t c1=0,s1=0,c2=0,s2=0,cm=0,sm=0,phim=0;
02683 Double_t phi1 = fPhi1*TMath::DegToRad();
02684 Double_t phi2 = fPhi2*TMath::DegToRad();
02685 Bool_t tub = kFALSE;
02686 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) tub = kTRUE;
02687 if (!tub) {
02688 if (phi2<phi1) phi2+=2.*TMath::Pi();
02689 phim = 0.5*(phi1+phi2);
02690 c1 = TMath::Cos(phi1);
02691 c2 = TMath::Cos(phi2);
02692 s1 = TMath::Sin(phi1);
02693 s2 = TMath::Sin(phi2);
02694 cm = TMath::Cos(phim);
02695 sm = TMath::Sin(phim);
02696 }
02697
02698
02699 Double_t sz = TGeoShape::Big();
02700 Double_t saf[2];
02701 saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
02702 saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
02703 Double_t calf = dir[0]*fNlow[0]+dir[1]*fNlow[1]+dir[2]*fNlow[2];
02704 if (calf>0) sz = saf[0]/calf;
02705
02706 Double_t sz1=TGeoShape::Big();
02707 calf = dir[0]*fNhigh[0]+dir[1]*fNhigh[1]+dir[2]*fNhigh[2];
02708 if (calf>0) {
02709 sz1 = saf[1]/calf;
02710 if (sz1<sz) sz = sz1;
02711 }
02712
02713
02714 Double_t nsq=dir[0]*dir[0]+dir[1]*dir[1];
02715
02716 if (TMath::Abs(nsq)<1E-10) return sz;
02717 Double_t rdotn=point[0]*dir[0]+point[1]*dir[1];
02718 Double_t sr=TGeoShape::Big();
02719 Double_t b, d;
02720 Bool_t skip_outer = kFALSE;
02721
02722 if (fRmin>1E-10) {
02723 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmin, b, d);
02724 if (d>0) {
02725 sr=-b-d;
02726 if (sr>0) skip_outer = kTRUE;
02727 }
02728 }
02729
02730 if (!skip_outer) {
02731 TGeoTube::DistToTube(rsq, nsq, rdotn, fRmax, b, d);
02732 if (d>0) {
02733 sr=-b+d;
02734 if (sr<0) sr=TGeoShape::Big();
02735 } else {
02736 Error("DistFromInside", "In shape %s cannot get outside !", GetName());
02737 }
02738 }
02739
02740 Double_t sfmin = TGeoShape::Big();
02741 if (!tub) sfmin=TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
02742 return TMath::Min(TMath::Min(sz,sr), sfmin);
02743 }
02744
02745
02746 TGeoVolume *TGeoCtub::Divide(TGeoVolume * , const char * , Int_t , Int_t ,
02747 Double_t , Double_t )
02748 {
02749
02750 Warning("Divide", "In shape %s division of a cut tube not implemented", GetName());
02751 return 0;
02752 }
02753
02754
02755 TGeoShape *TGeoCtub::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
02756 {
02757
02758
02759 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
02760 if (!mother->TestShapeBit(kGeoTube)) {
02761 Error("GetMakeRuntimeShape", "Invalid mother for shape %s", GetName());
02762 return 0;
02763 }
02764 Double_t rmin, rmax, dz;
02765 rmin = fRmin;
02766 rmax = fRmax;
02767 dz = fDz;
02768 if (fDz<0) dz=((TGeoTube*)mother)->GetDz();
02769 if (fRmin<0)
02770 rmin = ((TGeoTube*)mother)->GetRmin();
02771 if ((fRmax<0) || (fRmax<=fRmin))
02772 rmax = ((TGeoTube*)mother)->GetRmax();
02773
02774 return (new TGeoCtub(rmin, rmax, dz, fPhi1, fPhi2, fNlow[0], fNlow[1], fNlow[2],
02775 fNhigh[0], fNhigh[1], fNhigh[2]));
02776 }
02777
02778
02779 void TGeoCtub::InspectShape() const
02780 {
02781
02782 printf("*** Shape %s: TGeoCtub ***\n", GetName());
02783 printf(" lx = %11.5f\n", fNlow[0]);
02784 printf(" ly = %11.5f\n", fNlow[1]);
02785 printf(" lz = %11.5f\n", fNlow[2]);
02786 printf(" tx = %11.5f\n", fNhigh[0]);
02787 printf(" ty = %11.5f\n", fNhigh[1]);
02788 printf(" tz = %11.5f\n", fNhigh[2]);
02789 TGeoTubeSeg::InspectShape();
02790 }
02791
02792
02793 Double_t TGeoCtub::Safety(Double_t *point, Bool_t in) const
02794 {
02795
02796
02797 Double_t saf[4];
02798 Double_t rsq = point[0]*point[0]+point[1]*point[1];
02799 Double_t r = TMath::Sqrt(rsq);
02800 Bool_t isseg = kTRUE;
02801 if (TMath::Abs(fPhi2-fPhi1-360.)<1E-8) isseg=kFALSE;
02802
02803 saf[0] = -point[0]*fNlow[0] - point[1]*fNlow[1] - (fDz+point[2])*fNlow[2];
02804 saf[1] = -point[0]*fNhigh[0] - point[1]*fNhigh[1] + (fDz-point[2])*fNhigh[2];
02805 saf[2] = (fRmin<1E-10 && !isseg)?TGeoShape::Big():(r-fRmin);
02806 saf[3] = fRmax-r;
02807 Double_t safphi = TGeoShape::Big();
02808 Double_t safe = TGeoShape::Big();
02809 if (isseg) safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi2);
02810
02811 if (in) {
02812 safe = saf[TMath::LocMin(4,saf)];
02813 return TMath::Min(safe, safphi);
02814 }
02815 for (Int_t i=0; i<4; i++) saf[i]=-saf[i];
02816 safe = saf[TMath::LocMax(4,saf)];
02817 if (isseg) return TMath::Max(safe, safphi);
02818 return safe;
02819 }
02820
02821
02822 void TGeoCtub::SetCtubDimensions(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2,
02823 Double_t lx, Double_t ly, Double_t lz, Double_t tx, Double_t ty, Double_t tz)
02824 {
02825
02826 SetTubsDimensions(rmin, rmax, dz, phi1, phi2);
02827 fNlow[0] = lx;
02828 fNlow[1] = ly;
02829 fNlow[2] = lz;
02830 fNhigh[0] = tx;
02831 fNhigh[1] = ty;
02832 fNhigh[2] = tz;
02833 ComputeBBox();
02834 }
02835
02836
02837 void TGeoCtub::SavePrimitive(ostream &out, Option_t * )
02838 {
02839
02840 if (TObject::TestBit(kGeoSavePrimitive)) return;
02841 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
02842 out << " rmin = " << fRmin << ";" << endl;
02843 out << " rmax = " << fRmax << ";" << endl;
02844 out << " dz = " << fDz << ";" << endl;
02845 out << " phi1 = " << fPhi1 << ";" << endl;
02846 out << " phi2 = " << fPhi2 << ";" << endl;
02847 out << " lx = " << fNlow[0] << ";" << endl;
02848 out << " ly = " << fNlow[1] << ";" << endl;
02849 out << " lz = " << fNlow[2] << ";" << endl;
02850 out << " tx = " << fNhigh[0] << ";" << endl;
02851 out << " ty = " << fNhigh[1] << ";" << endl;
02852 out << " tz = " << fNhigh[2] << ";" << endl;
02853 out << " TGeoShape *" << GetPointerName() << " = new TGeoCtub(\"" << GetName() << "\",rmin,rmax,dz,phi1,phi2,lx,ly,lz,tx,ty,tz);" << endl; TObject::SetBit(TGeoShape::kGeoSavePrimitive);
02854 }
02855
02856
02857 void TGeoCtub::SetDimensions(Double_t *param)
02858 {
02859
02860 SetCtubDimensions(param[0], param[1], param[2], param[3], param[4], param[5],
02861 param[6], param[7], param[8], param[9], param[10]);
02862 ComputeBBox();
02863 }
02864
02865
02866 Bool_t TGeoCtub::GetPointsOnSegments(Int_t , Double_t * ) const
02867 {
02868
02869
02870
02871 return kFALSE;
02872 }
02873
02874
02875 void TGeoCtub::SetPoints(Double_t *points) const
02876 {
02877
02878 Double_t dz;
02879 Int_t j, n;
02880 Double_t phi, phi1, phi2, dphi;
02881 phi1 = fPhi1;
02882 phi2 = fPhi2;
02883 if (phi2<phi1) phi2+=360.;
02884 n = gGeoManager->GetNsegments()+1;
02885
02886 dphi = (phi2-phi1)/(n-1);
02887 dz = fDz;
02888
02889 if (points) {
02890 Int_t indx = 0;
02891
02892 for (j = 0; j < n; j++) {
02893 phi = (phi1+j*dphi)*TMath::DegToRad();
02894 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
02895 indx++;
02896 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
02897 indx++;
02898 points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
02899 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
02900 indx++;
02901 }
02902 for (j = 0; j < n; j++) {
02903 phi = (phi1+j*dphi)*TMath::DegToRad();
02904 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
02905 indx++;
02906 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
02907 indx++;
02908 points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
02909 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
02910 indx++;
02911 }
02912 }
02913 }
02914
02915
02916 void TGeoCtub::SetPoints(Float_t *points) const
02917 {
02918
02919 Double_t dz;
02920 Int_t j, n;
02921 Double_t phi, phi1, phi2, dphi;
02922 phi1 = fPhi1;
02923 phi2 = fPhi2;
02924 if (phi2<phi1) phi2+=360.;
02925 n = gGeoManager->GetNsegments()+1;
02926
02927 dphi = (phi2-phi1)/(n-1);
02928 dz = fDz;
02929
02930 if (points) {
02931 Int_t indx = 0;
02932
02933 for (j = 0; j < n; j++) {
02934 phi = (phi1+j*dphi)*TMath::DegToRad();
02935 points[indx+6*n] = points[indx] = fRmin * TMath::Cos(phi);
02936 indx++;
02937 points[indx+6*n] = points[indx] = fRmin * TMath::Sin(phi);
02938 indx++;
02939 points[indx+6*n] = GetZcoord(points[indx-2], points[indx-1], dz);
02940 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
02941 indx++;
02942 }
02943 for (j = 0; j < n; j++) {
02944 phi = (phi1+j*dphi)*TMath::DegToRad();
02945 points[indx+6*n] = points[indx] = fRmax * TMath::Cos(phi);
02946 indx++;
02947 points[indx+6*n] = points[indx] = fRmax * TMath::Sin(phi);
02948 indx++;
02949 points[indx+6*n]= GetZcoord(points[indx-2], points[indx-1], dz);
02950 points[indx] = GetZcoord(points[indx-2], points[indx-1], -dz);
02951 indx++;
02952 }
02953 }
02954 }
02955
02956
02957 void TGeoCtub::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
02958 {
02959
02960 TGeoTubeSeg::GetMeshNumbers(nvert,nsegs,npols);
02961 }
02962
02963
02964 Int_t TGeoCtub::GetNmeshVertices() const
02965 {
02966
02967 Int_t n = gGeoManager->GetNsegments()+1;
02968 Int_t numPoints = n*4;
02969 return numPoints;
02970 }
02971
02972
02973 const TBuffer3D & TGeoCtub::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
02974 {
02975
02976 static TBuffer3DCutTube buffer;
02977
02978 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
02979
02980 if (reqSections & TBuffer3D::kShapeSpecific) {
02981
02982 buffer.fRadiusInner = fRmin;
02983 buffer.fRadiusOuter = fRmax;
02984 buffer.fHalfLength = fDz;
02985 buffer.fPhiMin = fPhi1;
02986 buffer.fPhiMax = fPhi2;
02987
02988 for (UInt_t i = 0; i < 3; i++ ) {
02989 buffer.fLowPlaneNorm[i] = fNlow[i];
02990 buffer.fHighPlaneNorm[i] = fNhigh[i];
02991 }
02992 buffer.SetSectionsValid(TBuffer3D::kShapeSpecific);
02993 }
02994 if (reqSections & TBuffer3D::kRawSizes) {
02995 Int_t n = gGeoManager->GetNsegments()+1;
02996 Int_t nbPnts = 4*n;
02997 Int_t nbSegs = 2*nbPnts;
02998 Int_t nbPols = nbPnts-2;
02999 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
03000 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
03001 }
03002 }
03003 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
03004 SetPoints(buffer.fPnts);
03005 if (!buffer.fLocalFrame) {
03006 TransformPoints(buffer.fPnts, buffer.NbPnts());
03007 }
03008 SetSegsAndPols(buffer);
03009 buffer.SetSectionsValid(TBuffer3D::kRaw);
03010 }
03011
03012 return buffer;
03013 }