00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "Riostream.h"
00014
00015 #include "TGeoManager.h"
00016 #include "TGeoVolume.h"
00017 #include "TVirtualGeoPainter.h"
00018 #include "TGeoHype.h"
00019 #include "TVirtualPad.h"
00020 #include "TBuffer3D.h"
00021 #include "TBuffer3DTypes.h"
00022 #include "TMath.h"
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 ClassImp(TGeoHype)
00056
00057
00058 TGeoHype::TGeoHype()
00059 {
00060
00061 SetShapeBit(TGeoShape::kGeoHype);
00062 fStIn = 0.;
00063 fStOut = 0.;
00064 fTin = 0.;
00065 fTinsq = 0.;
00066 fTout = 0.;
00067 fToutsq = 0.;
00068 }
00069
00070
00071
00072 TGeoHype::TGeoHype(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
00073 :TGeoTube(rin, rout, dz)
00074 {
00075
00076 SetShapeBit(TGeoShape::kGeoHype);
00077 SetHypeDimensions(rin, stin, rout, stout, dz);
00078
00079 if (fDz<0) SetShapeBit(kGeoRunTimeShape);
00080 ComputeBBox();
00081 }
00082
00083 TGeoHype::TGeoHype(const char *name,Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
00084 :TGeoTube(name, rin, rout, dz)
00085 {
00086
00087 SetShapeBit(TGeoShape::kGeoHype);
00088 SetHypeDimensions(rin, stin, rout, stout, dz);
00089
00090 if (fDz<0) SetShapeBit(kGeoRunTimeShape);
00091 ComputeBBox();
00092 }
00093
00094
00095 TGeoHype::TGeoHype(Double_t *param)
00096 :TGeoTube(param[1],param[3],param[0])
00097 {
00098
00099
00100
00101
00102
00103
00104 SetShapeBit(TGeoShape::kGeoHype);
00105 SetDimensions(param);
00106
00107 if (fDz<0) SetShapeBit(kGeoRunTimeShape);
00108 ComputeBBox();
00109 }
00110
00111
00112 TGeoHype::~TGeoHype()
00113 {
00114
00115 }
00116
00117
00118 Double_t TGeoHype::Capacity() const
00119 {
00120
00121 Double_t capacity = 2.*TMath::Pi()*fDz*(fRmax*fRmax-fRmin*fRmin) +
00122 (2.*TMath::Pi()/3.)*fDz*fDz*fDz*(fToutsq-fTinsq);
00123 return capacity;
00124 }
00125
00126
00127 void TGeoHype::ComputeBBox()
00128 {
00129
00130 if (fRmin<0.) {
00131 Warning("ComputeBBox", "Shape %s has invalid rmin=%g ! SET TO 0.", GetName(),fRmin);
00132 fRmin = 0.;
00133 }
00134 if ((fRmin>fRmax) || (fRmin*fRmin+fTinsq*fDz*fDz > fRmax*fRmax+fToutsq*fDz*fDz)) {
00135 SetShapeBit(kGeoInvalidShape);
00136 Error("ComputeBBox", "Shape %s hyperbolic surfaces are malformed: rin=%g, stin=%g, rout=%g, stout=%g",
00137 GetName(), fRmin, fStIn, fRmax, fStOut);
00138 return;
00139 }
00140
00141 fDX = fDY = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
00142 fDZ = fDz;
00143 }
00144
00145
00146 void TGeoHype::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00147 {
00148
00149 Double_t saf[3];
00150 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00151 Double_t r = TMath::Sqrt(rsq);
00152 Double_t rin = (HasInner())?(TMath::Sqrt(RadiusHypeSq(point[2],kTRUE))):0.;
00153 Double_t rout = TMath::Sqrt(RadiusHypeSq(point[2],kFALSE));
00154 saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
00155 saf[1] = (HasInner())?TMath::Abs(rin-r):TGeoShape::Big();
00156 saf[2] = TMath::Abs(rout-r);
00157 Int_t i = TMath::LocMin(3,saf);
00158 if (i==0 || r<1.E-10) {
00159 norm[0] = norm[1] = 0.;
00160 norm[2] = TMath::Sign(1.,dir[2]);
00161 return;
00162 }
00163 Double_t t = (i==1)?fTinsq:fToutsq;;
00164 t *= -point[2]/r;
00165 Double_t ct = TMath::Sqrt(1./(1.+t*t));
00166 Double_t st = t * ct;
00167 Double_t phi = TMath::ATan2(point[1], point[0]);
00168 Double_t cphi = TMath::Cos(phi);
00169 Double_t sphi = TMath::Sin(phi);
00170
00171 norm[0] = ct*cphi;
00172 norm[1] = ct*sphi;
00173 norm[2] = st;
00174 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
00175 norm[0] = -norm[0];
00176 norm[1] = -norm[1];
00177 norm[2] = -norm[2];
00178 }
00179 }
00180
00181
00182 Bool_t TGeoHype::Contains(Double_t *point) const
00183 {
00184
00185 if (TMath::Abs(point[2]) > fDz) return kFALSE;
00186 Double_t r2 = point[0]*point[0]+point[1]*point[1];
00187 Double_t routsq = RadiusHypeSq(point[2], kFALSE);
00188 if (r2>routsq) return kFALSE;
00189 if (!HasInner()) return kTRUE;
00190 Double_t rinsq = RadiusHypeSq(point[2], kTRUE);
00191 if (r2<rinsq) return kFALSE;
00192 return kTRUE;
00193 }
00194
00195
00196 Int_t TGeoHype::DistancetoPrimitive(Int_t px, Int_t py)
00197 {
00198
00199 Int_t numPoints = GetNmeshVertices();
00200 return ShapeDistancetoPrimitive(numPoints, px, py);
00201 }
00202
00203
00204 Double_t TGeoHype::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00205 {
00206
00207 if (iact<3 && safe) {
00208 *safe = Safety(point, kTRUE);
00209 if (iact==0) return TGeoShape::Big();
00210 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00211 }
00212
00213
00214 Double_t sz = TGeoShape::Big();
00215 if (dir[2]>0) {
00216 sz = (fDz-point[2])/dir[2];
00217 if (sz<=0.) return 0.;
00218 } else {
00219 if (dir[2]<0) {
00220 sz = -(fDz+point[2])/dir[2];
00221 if (sz<=0.) return 0.;
00222 }
00223 }
00224
00225
00226
00227 Double_t srin = TGeoShape::Big();
00228 Double_t srout = TGeoShape::Big();
00229 Double_t sr;
00230
00231 Double_t s[2];
00232 Int_t npos;
00233 npos = DistToHype(point, dir, s, kTRUE);
00234 if (npos) srin = s[0];
00235 npos = DistToHype(point, dir, s, kFALSE);
00236 if (npos) srout = s[0];
00237 sr = TMath::Min(srin, srout);
00238 return TMath::Min(sz,sr);
00239 }
00240
00241
00242
00243 Double_t TGeoHype::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00244 {
00245
00246 if (iact<3 && safe) {
00247 *safe = Safety(point, kFALSE);
00248 if (iact==0) return TGeoShape::Big();
00249 if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
00250 }
00251
00252 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00253 if (sdist>=step) return TGeoShape::Big();
00254
00255
00256 Double_t xi, yi, zi;
00257 Double_t sz = TGeoShape::Big();
00258 if (TMath::Abs(point[2])>=fDz) {
00259
00260 if ((point[2]*dir[2]) < 0) {
00261
00262 sz = (TMath::Abs(point[2])-fDz)/TMath::Abs(dir[2]);
00263
00264 xi = point[0]+sz*dir[0];
00265 yi = point[1]+sz*dir[1];
00266 Double_t r2 = xi*xi + yi*yi;
00267 Double_t rmin2 = RadiusHypeSq(fDz, kTRUE);
00268 if (r2 >= rmin2) {
00269 Double_t rmax2 = RadiusHypeSq(fDz, kFALSE);
00270 if (r2 <= rmax2) return sz;
00271 }
00272 }
00273 }
00274
00275 Double_t sin = TGeoShape::Big();
00276 Double_t sout = TGeoShape::Big();
00277 Double_t s[2];
00278 Int_t npos;
00279 npos = DistToHype(point, dir, s, kTRUE);
00280 if (npos) {
00281 zi = point[2] + s[0]*dir[2];
00282 if (TMath::Abs(zi) <= fDz) sin = s[0];
00283 else if (npos==2) {
00284 zi = point[2] + s[1]*dir[2];
00285 if (TMath::Abs(zi) <= fDz) sin = s[1];
00286 }
00287 }
00288 npos = DistToHype(point, dir, s, kFALSE);
00289 if (npos) {
00290 zi = point[2] + s[0]*dir[2];
00291 if (TMath::Abs(zi) <= fDz) sout = s[0];
00292 else if (npos==2) {
00293 zi = point[2] + s[1]*dir[2];
00294 if (TMath::Abs(zi) <= fDz) sout = s[1];
00295 }
00296 }
00297 return TMath::Min(sin, sout);
00298 }
00299
00300
00301 Int_t TGeoHype::DistToHype(Double_t *point, Double_t *dir, Double_t *s, Bool_t inner) const
00302 {
00303
00304
00305 Double_t r0, t0, snext;
00306 if (inner) {
00307 if (!HasInner()) return 0;
00308 r0 = fRmin;
00309 t0 = fTinsq;
00310 } else {
00311 r0 = fRmax;
00312 t0 = fToutsq;
00313 }
00314 Double_t a = dir[0]*dir[0] + dir[1]*dir[1] - t0*dir[2]*dir[2];
00315 Double_t b = t0*point[2]*dir[2] - point[0]*dir[0] - point[1]*dir[1];
00316 Double_t c = point[0]*point[0] + point[1]*point[1] - t0*point[2]*point[2] - r0*r0;
00317
00318 if (TMath::Abs(a) < TGeoShape::Tolerance()) {
00319 if (TMath::Abs(b) < TGeoShape::Tolerance()) return 0;
00320 snext = 0.5*c/b;
00321 if (snext < 0.) return 0;
00322 s[0] = snext;
00323 return 1;
00324 }
00325
00326 Double_t delta = b*b - a*c;
00327 Double_t ainv = 1./a;
00328 Int_t npos = 0;
00329 if (delta < 0.) return 0;
00330 delta = TMath::Sqrt(delta);
00331 Double_t sone = TMath::Sign(1.,ainv);
00332 snext = (b - sone*delta)*ainv;
00333 if (snext >= 0.) s[npos++] = snext;
00334 snext = (b + sone*delta)*ainv;
00335 if (snext >= 0.) s[npos++] = snext;
00336 return npos;
00337 }
00338
00339
00340 TGeoVolume *TGeoHype::Divide(TGeoVolume * , const char *divname, Int_t , Int_t ,
00341 Double_t , Double_t )
00342 {
00343
00344 Error("Divide", "Hyperboloids cannot be divided. Division volume %s not created", divname);
00345 return 0;
00346 }
00347
00348
00349 Double_t TGeoHype::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00350 {
00351
00352 xlo = 0;
00353 xhi = 0;
00354 Double_t dx = 0;
00355 switch (iaxis) {
00356 case 1:
00357 xlo = fRmin;
00358 xhi = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
00359 dx = xhi-xlo;
00360 return dx;
00361 case 2:
00362 xlo = 0;
00363 xhi = 360;
00364 dx = 360;
00365 return dx;
00366 case 3:
00367 xlo = -fDz;
00368 xhi = fDz;
00369 dx = xhi-xlo;
00370 return dx;
00371 }
00372 return dx;
00373 }
00374
00375
00376 void TGeoHype::GetBoundingCylinder(Double_t *param) const
00377 {
00378
00379
00380 param[0] = fRmin;
00381 param[0] *= param[0];
00382 param[1] = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
00383 param[1] *= param[1];
00384 param[2] = 0.;
00385 param[3] = 360.;
00386 }
00387
00388
00389 TGeoShape *TGeoHype::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
00390 {
00391
00392
00393 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00394 Double_t rmin, rmax, dz;
00395 Double_t zmin,zmax;
00396 rmin = fRmin;
00397 rmax = fRmax;
00398 dz = fDz;
00399 if (fDz<0) {
00400 mother->GetAxisRange(3,zmin,zmax);
00401 if (zmax<0) return 0;
00402 dz=zmax;
00403 } else {
00404 Error("GetMakeRuntimeShape", "Shape %s does not have negative Z range", GetName());
00405 return 0;
00406 }
00407 TGeoShape *hype = new TGeoHype(GetName(), dz, fRmax, fStOut, fRmin, fStIn);
00408 return hype;
00409 }
00410
00411
00412 void TGeoHype::InspectShape() const
00413 {
00414
00415 printf("*** Shape %s: TGeoHype ***\n", GetName());
00416 printf(" Rin = %11.5f\n", fRmin);
00417 printf(" sin = %11.5f\n", fStIn);
00418 printf(" Rout = %11.5f\n", fRmax);
00419 printf(" sout = %11.5f\n", fStOut);
00420 printf(" dz = %11.5f\n", fDz);
00421
00422 printf(" Bounding box:\n");
00423 TGeoBBox::InspectShape();
00424 }
00425
00426
00427 TBuffer3D *TGeoHype::MakeBuffer3D() const
00428 {
00429
00430
00431
00432 Int_t n = gGeoManager->GetNsegments();
00433 Bool_t hasRmin = HasInner();
00434 Int_t nbPnts = (hasRmin)?(2*n*n):(n*n+2);
00435 Int_t nbSegs = (hasRmin)?(4*n*n):(n*(2*n+1));
00436 Int_t nbPols = (hasRmin)?(2*n*n):(n*(n+1));
00437
00438 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00439 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
00440 if (buff)
00441 {
00442 SetPoints(buff->fPnts);
00443 SetSegsAndPols(*buff);
00444 }
00445
00446 return buff;
00447 }
00448
00449
00450 void TGeoHype::SetSegsAndPols(TBuffer3D &buff) const
00451 {
00452
00453 Int_t c = GetBasicColor();
00454 Int_t i, j, n;
00455 n = gGeoManager->GetNsegments();
00456 Bool_t hasRmin = HasInner();
00457 Int_t irin = 0;
00458 Int_t irout = (hasRmin)?(n*n):2;
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 Int_t isin = 0;
00491 Int_t isgenin = (hasRmin)?(isin+n*n):0;
00492 Int_t isout = (hasRmin)?(isgenin+n*(n-1)):0;
00493 Int_t isgenout = isout+n*n;
00494 Int_t islo = isgenout+n*(n-1);
00495 Int_t ishi = islo + n;
00496
00497 Int_t npt = 0;
00498
00499 if (hasRmin) {
00500 for (i=0; i<n; i++) {
00501 for (j=0; j<n; j++) {
00502 npt = 3*(isin+n*i+j);
00503 buff.fSegs[npt] = c;
00504 buff.fSegs[npt+1] = irin+n*i+j;
00505 buff.fSegs[npt+2] = irin+n*i+((j+1)%n);
00506 }
00507 }
00508
00509 for (i=0; i<n-1; i++) {
00510 for (j=0; j<n; j++) {
00511 npt = 3*(isgenin+n*i+j);
00512 buff.fSegs[npt] = c;
00513 buff.fSegs[npt+1] = irin+n*i+j;
00514 buff.fSegs[npt+2] = irin+n*(i+1)+j;
00515 }
00516 }
00517 }
00518
00519 for (i=0; i<n; i++) {
00520 for (j=0; j<n; j++) {
00521 npt = 3*(isout + n*i+j);
00522 buff.fSegs[npt] = c;
00523 buff.fSegs[npt+1] = irout+n*i+j;
00524 buff.fSegs[npt+2] = irout+n*i+((j+1)%n);
00525 }
00526 }
00527
00528 for (i=0; i<n-1; i++) {
00529 for (j=0; j<n; j++) {
00530 npt = 3*(isgenout+n*i+j);
00531 buff.fSegs[npt] = c;
00532 buff.fSegs[npt+1] = irout+n*i+j;
00533 buff.fSegs[npt+2] = irout+n*(i+1)+j;
00534 }
00535 }
00536
00537 for (j=0; j<n; j++) {
00538 npt = 3*(islo+j);
00539 buff.fSegs[npt] = c;
00540 buff.fSegs[npt+1] = irin;
00541 if (hasRmin) buff.fSegs[npt+1] += j;
00542 buff.fSegs[npt+2] = irout + j;
00543 }
00544
00545 for (j=0; j<n; j++) {
00546 npt = 3*(ishi+j);
00547 buff.fSegs[npt] = c;
00548 buff.fSegs[npt+1] = irin+1;
00549 if (hasRmin) buff.fSegs[npt+1] += n*(n-1)+j-1;
00550 buff.fSegs[npt+2] = irout + n*(n-1)+j;
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 Int_t ipin = 0;
00576 Int_t ipout = (hasRmin)?(ipin+n*(n-1)):0;
00577 Int_t iplo = ipout+n*(n-1);
00578 Int_t ipup = iplo+n;
00579
00580 if (hasRmin) {
00581 for (i=0; i<n-1; i++) {
00582 for (j=0; j<n; j++) {
00583 npt = 6*(ipin+n*i+j);
00584 buff.fPols[npt] = c;
00585 buff.fPols[npt+1] = 4;
00586 buff.fPols[npt+2] = isin+n*i+j;
00587 buff.fPols[npt+3] = isgenin+i*n+((j+1)%n);
00588 buff.fPols[npt+4] = isin+n*(i+1)+j;
00589 buff.fPols[npt+5] = isgenin+i*n+j;
00590 }
00591 }
00592 }
00593
00594 for (i=0; i<n-1; i++) {
00595 for (j=0; j<n; j++) {
00596 npt = 6*(ipout+n*i+j);
00597 buff.fPols[npt] = c;
00598 buff.fPols[npt+1] = 4;
00599 buff.fPols[npt+2] = isout+n*i+j;
00600 buff.fPols[npt+3] = isgenout+i*n+j;
00601 buff.fPols[npt+4] = isout+n*(i+1)+j;
00602 buff.fPols[npt+5] = isgenout+i*n+((j+1)%n);
00603 }
00604 }
00605
00606 if (hasRmin) {
00607 for (j=0; j<n; j++) {
00608 npt = 6*(iplo+j);
00609 buff.fPols[npt] = c+1;
00610 buff.fPols[npt+1] = 4;
00611 buff.fPols[npt+2] = isin+j;
00612 buff.fPols[npt+3] = islo+j;
00613 buff.fPols[npt+4] = isout+j;
00614 buff.fPols[npt+5] = islo+((j+1)%n);
00615 }
00616 for (j=0; j<n; j++) {
00617 npt = 6*(ipup+j);
00618 buff.fPols[npt] = c+2;
00619 buff.fPols[npt+1] = 4;
00620 buff.fPols[npt+2] = isin+n*(n-1)+j;
00621 buff.fPols[npt+3] = ishi+((j+1)%n);
00622 buff.fPols[npt+4] = isout+n*(n-1)+j;
00623 buff.fPols[npt+5] = ishi+j;
00624 }
00625 } else {
00626 for (j=0; j<n; j++) {
00627 npt = 6*iplo+5*j;
00628 buff.fPols[npt] = c+1;
00629 buff.fPols[npt+1] = 3;
00630 buff.fPols[npt+2] = isout+j;
00631 buff.fPols[npt+3] = islo+((j+1)%n);
00632 buff.fPols[npt+4] = islo+j;
00633 }
00634 for (j=0; j<n; j++) {
00635 npt = 6*iplo+5*(n+j);
00636 buff.fPols[npt] = c+2;
00637 buff.fPols[npt+1] = 3;
00638 buff.fPols[npt+2] = isout+n*(n-1)+j;
00639 buff.fPols[npt+3] = ishi+j;
00640 buff.fPols[npt+4] = ishi+((j+1)%n);
00641 }
00642 }
00643 }
00644
00645
00646 Double_t TGeoHype::RadiusHypeSq(Double_t z, Bool_t inner) const
00647 {
00648
00649 Double_t r0, tsq;
00650 if (inner) {
00651 r0 = fRmin;
00652 tsq = fTinsq;
00653 } else {
00654 r0 = fRmax;
00655 tsq = fToutsq;
00656 }
00657 return (r0*r0+tsq*z*z);
00658 }
00659
00660
00661 Double_t TGeoHype::ZHypeSq(Double_t r, Bool_t inner) const
00662 {
00663
00664 Double_t r0, tsq;
00665 if (inner) {
00666 r0 = fRmin;
00667 tsq = fTinsq;
00668 } else {
00669 r0 = fRmax;
00670 tsq = fToutsq;
00671 }
00672 if (TMath::Abs(tsq) < TGeoShape::Tolerance()) return TGeoShape::Big();
00673 return ((r*r-r0*r0)/tsq);
00674 }
00675
00676
00677 Double_t TGeoHype::Safety(Double_t *point, Bool_t in) const
00678 {
00679
00680
00681 Double_t safe, safrmin, safrmax;
00682 if (in) {
00683 safe = fDz-TMath::Abs(point[2]);
00684 safrmin = SafetyToHype(point, kTRUE, in);
00685 if (safrmin < safe) safe = safrmin;
00686 safrmax = SafetyToHype(point, kFALSE,in);
00687 if (safrmax < safe) safe = safrmax;
00688 } else {
00689 safe = -fDz+TMath::Abs(point[2]);
00690 safrmin = SafetyToHype(point, kTRUE, in);
00691 if (safrmin > safe) safe = safrmin;
00692 safrmax = SafetyToHype(point, kFALSE,in);
00693 if (safrmax > safe) safe = safrmax;
00694 }
00695 return safe;
00696 }
00697
00698
00699 Double_t TGeoHype::SafetyToHype(Double_t *point, Bool_t inner, Bool_t in) const
00700 {
00701
00702
00703 Double_t r, rsq, rhsq, rh, dr, tsq, saf;
00704 if (inner && !HasInner()) return (in)?TGeoShape::Big():-TGeoShape::Big();
00705 rsq = point[0]*point[0]+point[1]*point[1];
00706 r = TMath::Sqrt(rsq);
00707 rhsq = RadiusHypeSq(point[2], inner);
00708 rh = TMath::Sqrt(rhsq);
00709 dr = r - rh;
00710 if (inner) {
00711 if (!in && dr>0) return -TGeoShape::Big();
00712 if (TMath::Abs(fStIn) < TGeoShape::Tolerance()) return TMath::Abs(dr);
00713 if (fRmin<TGeoShape::Tolerance()) return TMath::Abs(dr/TMath::Sqrt(1.+ fTinsq));
00714 tsq = fTinsq;
00715 } else {
00716 if (!in && dr<0) return -TGeoShape::Big();
00717 if (TMath::Abs(fStOut) < TGeoShape::Tolerance()) return TMath::Abs(dr);
00718 tsq = fToutsq;
00719 }
00720 if (TMath::Abs(dr)<TGeoShape::Tolerance()) return 0.;
00721
00722 Double_t m;
00723 if (dr<0) {
00724 m = rh/(tsq*TMath::Abs(point[2]));
00725 saf = -m*dr/TMath::Sqrt(1.+m*m);
00726 return saf;
00727 }
00728
00729 m = (TMath::Sqrt(ZHypeSq(r,inner)) - TMath::Abs(point[2]))/dr;
00730 saf = m*dr/TMath::Sqrt(1.+m*m);
00731 return saf;
00732 }
00733
00734
00735 void TGeoHype::SavePrimitive(ostream &out, Option_t * )
00736 {
00737
00738 if (TObject::TestBit(kGeoSavePrimitive)) return;
00739 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
00740 out << " rin = " << fRmin << ";" << endl;
00741 out << " stin = " << fStIn << ";" << endl;
00742 out << " rout = " << fRmax << ";" << endl;
00743 out << " stout = " << fStOut << ";" << endl;
00744 out << " dz = " << fDz << ";" << endl;
00745 out << " TGeoShape *" << GetPointerName() << " = new TGeoHype(\"" << GetName() << "\",rin,stin,rout,stout,dz);" << endl;
00746 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00747 }
00748
00749
00750 void TGeoHype::SetHypeDimensions(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
00751 {
00752
00753 fRmin = rin;
00754 fRmax = rout;
00755 fDz = dz;
00756 fStIn = stin;
00757 fStOut = stout;
00758 fTin = TMath::Tan(fStIn*TMath::DegToRad());
00759 fTinsq = fTin*fTin;
00760 fTout = TMath::Tan(fStOut*TMath::DegToRad());
00761 fToutsq = fTout*fTout;
00762 if ((fRmin==0) && (fStIn==0)) SetShapeBit(kGeoRSeg, kTRUE);
00763 else SetShapeBit(kGeoRSeg, kFALSE);
00764 }
00765
00766
00767 void TGeoHype::SetDimensions(Double_t *param)
00768 {
00769
00770
00771
00772
00773
00774
00775 Double_t dz = param[0];
00776 Double_t rin = param[1];
00777 Double_t stin = param[2];
00778 Double_t rout = param[3];
00779 Double_t stout = param[4];
00780 SetHypeDimensions(rin, stin, rout, stout, dz);
00781 }
00782
00783
00784 void TGeoHype::SetPoints(Double_t *points) const
00785 {
00786
00787 Double_t z,dz,r;
00788 Int_t i,j, n;
00789 if (!points) return;
00790 n = gGeoManager->GetNsegments();
00791 Double_t dphi = 360./n;
00792 Double_t phi = 0;
00793 dz = 2.*fDz/(n-1);
00794
00795 Int_t indx = 0;
00796
00797 if (HasInner()) {
00798
00799 for (i=0; i<n; i++) {
00800 z = -fDz+i*dz;
00801 r = TMath::Sqrt(RadiusHypeSq(z, kTRUE));
00802 for (j=0; j<n; j++) {
00803 phi = j*dphi*TMath::DegToRad();
00804 points[indx++] = r * TMath::Cos(phi);
00805 points[indx++] = r * TMath::Sin(phi);
00806 points[indx++] = z;
00807 }
00808 }
00809 } else {
00810 points[indx++] = 0.;
00811 points[indx++] = 0.;
00812 points[indx++] = -fDz;
00813 points[indx++] = 0.;
00814 points[indx++] = 0.;
00815 points[indx++] = fDz;
00816 }
00817
00818 for (i=0; i<n; i++) {
00819 z = -fDz + i*dz;
00820 r = TMath::Sqrt(RadiusHypeSq(z, kFALSE));
00821 for (j=0; j<n; j++) {
00822 phi = j*dphi*TMath::DegToRad();
00823 points[indx++] = r * TMath::Cos(phi);
00824 points[indx++] = r * TMath::Sin(phi);
00825 points[indx++] = z;
00826 }
00827 }
00828 }
00829
00830
00831 void TGeoHype::SetPoints(Float_t *points) const
00832 {
00833
00834 Double_t z,dz,r;
00835 Int_t i,j, n;
00836 if (!points) return;
00837 n = gGeoManager->GetNsegments();
00838 Double_t dphi = 360./n;
00839 Double_t phi = 0;
00840 dz = 2.*fDz/(n-1);
00841
00842 Int_t indx = 0;
00843
00844 if (HasInner()) {
00845
00846 for (i=0; i<n; i++) {
00847 z = -fDz+i*dz;
00848 r = TMath::Sqrt(RadiusHypeSq(z, kTRUE));
00849 for (j=0; j<n; j++) {
00850 phi = j*dphi*TMath::DegToRad();
00851 points[indx++] = r * TMath::Cos(phi);
00852 points[indx++] = r * TMath::Sin(phi);
00853 points[indx++] = z;
00854 }
00855 }
00856 } else {
00857 points[indx++] = 0.;
00858 points[indx++] = 0.;
00859 points[indx++] = -fDz;
00860 points[indx++] = 0.;
00861 points[indx++] = 0.;
00862 points[indx++] = fDz;
00863 }
00864
00865 for (i=0; i<n; i++) {
00866 z = -fDz + i*dz;
00867 r = TMath::Sqrt(RadiusHypeSq(z, kFALSE));
00868 for (j=0; j<n; j++) {
00869 phi = j*dphi*TMath::DegToRad();
00870 points[indx++] = r * TMath::Cos(phi);
00871 points[indx++] = r * TMath::Sin(phi);
00872 points[indx++] = z;
00873 }
00874 }
00875 }
00876
00877
00878 void TGeoHype::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00879 {
00880
00881 Int_t n = gGeoManager->GetNsegments();
00882 Bool_t hasRmin = HasInner();
00883 nvert = (hasRmin)?(2*n*n):(n*n+2);
00884 nsegs = (hasRmin)?(4*n*n):(n*(2*n+1));
00885 npols = (hasRmin)?(2*n*n):(n*(n+1));
00886 }
00887
00888
00889 Int_t TGeoHype::GetNmeshVertices() const
00890 {
00891
00892 Int_t n = gGeoManager->GetNsegments();
00893 Int_t numPoints = (HasRmin())?(2*n*n):(n*n+2);
00894 return numPoints;
00895 }
00896
00897
00898 void TGeoHype::Sizeof3D() const
00899 {
00900
00901
00902
00903
00904
00905
00906
00907
00908 }
00909
00910
00911 const TBuffer3D & TGeoHype::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
00912 {
00913
00914 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
00915
00916 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
00917
00918 if (reqSections & TBuffer3D::kRawSizes) {
00919 Int_t n = gGeoManager->GetNsegments();
00920 Bool_t hasRmin = HasInner();
00921 Int_t nbPnts = (hasRmin)?(2*n*n):(n*n+2);
00922 Int_t nbSegs = (hasRmin)?(4*n*n):(n*(2*n+1));
00923 Int_t nbPols = (hasRmin)?(2*n*n):(n*(n+1));
00924 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
00925 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
00926 }
00927 }
00928 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
00929 SetPoints(buffer.fPnts);
00930 if (!buffer.fLocalFrame) {
00931 TransformPoints(buffer.fPnts, buffer.NbPnts());
00932 }
00933
00934 SetSegsAndPols(buffer);
00935 buffer.SetSectionsValid(TBuffer3D::kRaw);
00936 }
00937
00938 return buffer;
00939 }