00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Riostream.h"
00025
00026 #include "TGeoManager.h"
00027 #include "TGeoVolume.h"
00028 #include "TGeoEltu.h"
00029 #include "TBuffer3D.h"
00030 #include "TBuffer3DTypes.h"
00031 #include "TMath.h"
00032
00033 ClassImp(TGeoEltu)
00034
00035
00036 TGeoEltu::TGeoEltu()
00037 {
00038
00039 SetShapeBit(TGeoShape::kGeoEltu);
00040 }
00041
00042
00043 TGeoEltu::TGeoEltu(Double_t a, Double_t b, Double_t dz)
00044 :TGeoTube()
00045 {
00046
00047 SetShapeBit(TGeoShape::kGeoEltu);
00048 SetEltuDimensions(a, b, dz);
00049 ComputeBBox();
00050 }
00051
00052
00053 TGeoEltu::TGeoEltu(const char *name, Double_t a, Double_t b, Double_t dz)
00054 :TGeoTube(name,0.,b,dz)
00055 {
00056
00057 SetName(name);
00058 SetShapeBit(TGeoShape::kGeoEltu);
00059 SetEltuDimensions(a, b, dz);
00060 ComputeBBox();
00061 }
00062
00063
00064 TGeoEltu::TGeoEltu(Double_t *param)
00065 {
00066
00067
00068
00069
00070 SetShapeBit(TGeoShape::kGeoEltu);
00071 SetDimensions(param);
00072 ComputeBBox();
00073 }
00074
00075
00076 TGeoEltu::~TGeoEltu()
00077 {
00078
00079 }
00080
00081
00082 Double_t TGeoEltu::Capacity() const
00083 {
00084
00085 Double_t capacity = 2.*TMath::Pi()*fDz*fRmin*fRmax;
00086 return capacity;
00087 }
00088
00089
00090 void TGeoEltu::ComputeBBox()
00091 {
00092
00093 fDX = fRmin;
00094 fDY = fRmax;
00095 fDZ = fDz;
00096 }
00097
00098
00099 void TGeoEltu::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00100 {
00101
00102 Double_t a = fRmin;
00103 Double_t b = fRmax;
00104 Double_t eps = TMath::Sqrt(point[0]*point[0]/(a*a)+point[1]*point[1]/(b*b))-1.;
00105 if (eps<1E-4 && TMath::Abs(fDz-TMath::Abs(point[2]))<1E-5) {
00106 norm[0] = norm[1] = 0;
00107 norm[2] = TMath::Sign(1.,dir[2]);
00108 return;
00109 }
00110 norm[2] = 0.;
00111 Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00112 Double_t st = point[1]/r;
00113 Double_t ct = point[0]/r;
00114 Double_t rr = TMath::Sqrt(b*b*ct*ct+a*a*st*st);
00115 norm[0] = b*ct/rr;
00116 norm[1] = a*st/rr;
00117 if (norm[0]*dir[0]+norm[1]*dir[1]<0) {
00118 norm[0] = -norm[0];
00119 norm[1] = -norm[1];
00120 }
00121 }
00122
00123
00124 Bool_t TGeoEltu::Contains(Double_t *point) const
00125 {
00126
00127 if (TMath::Abs(point[2]) > fDz) return kFALSE;
00128 Double_t r2 = (point[0]*point[0])/(fRmin*fRmin)+(point[1]*point[1])/(fRmax*fRmax);
00129 if (r2>1.) return kFALSE;
00130 return kTRUE;
00131 }
00132
00133
00134 Int_t TGeoEltu::DistancetoPrimitive(Int_t px, Int_t py)
00135 {
00136
00137 Int_t n = gGeoManager->GetNsegments();
00138 const Int_t numPoints=4*n;
00139 return ShapeDistancetoPrimitive(numPoints, px, py);
00140 }
00141
00142
00143 Double_t TGeoEltu::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00144 {
00145
00146 Double_t a2=fRmin*fRmin;
00147 Double_t b2=fRmax*fRmax;
00148 Double_t safz1=fDz-point[2];
00149 Double_t safz2=fDz+point[2];
00150
00151 if (iact<3 && safe) {
00152 Double_t x0=TMath::Abs(point[0]);
00153 Double_t y0=TMath::Abs(point[1]);
00154 Double_t x1=x0;
00155 Double_t y1=TMath::Sqrt((fRmin-x0)*(fRmin+x0))*fRmax/fRmin;
00156 Double_t y2=y0;
00157 Double_t x2=TMath::Sqrt((fRmax-y0)*(fRmax+y0))*fRmin/fRmax;
00158 Double_t d1=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
00159 Double_t d2=(x2-x0)*(x2-x0)+(y2-y0)*(y2-y0);
00160 Double_t x3,y3;
00161
00162 Double_t safr=TGeoShape::Big();
00163 Double_t safz = TMath::Min(safz1,safz2);
00164 for (Int_t i=0; i<8; i++) {
00165 if (fRmax<fRmin) {
00166 x3=0.5*(x1+x2);
00167 y3=TMath::Sqrt((fRmin-x3)*(fRmin+x3))*fRmax/fRmin;;
00168 } else {
00169 y3=0.5*(y1+y2);
00170 x3=TMath::Sqrt((fRmax-y3)*(fRmax+y3))*fRmin/fRmax;
00171 }
00172 if (d1<d2) {
00173 x2=x3;
00174 y2=y3;
00175 d2=(x2-x0)*(x2-x0)+(y2-y0)*(y2-y0);
00176 } else {
00177 x1=x3;
00178 y1=y3;
00179 d1=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0);
00180 }
00181 }
00182 safr=TMath::Sqrt(d1)-1.0E-3;
00183 *safe = TMath::Min(safz, safr);
00184 if (iact==0) return TGeoShape::Big();
00185 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00186 }
00187
00188
00189 Double_t snxt = TGeoShape::Big();
00190 if (dir[2]>0) {
00191 snxt=safz1/dir[2];
00192 } else {
00193 if (dir[2]<0) snxt=-safz2/dir[2];
00194 }
00195
00196 Double_t sz = snxt;
00197 Double_t xz=point[0]+dir[0]*sz;
00198 Double_t yz=point[1]+dir[1]*sz;
00199 if ((xz*xz/a2+yz*yz/b2)<=1) return snxt;
00200 Double_t u=dir[0]*dir[0]*b2+dir[1]*dir[1]*a2;
00201 Double_t v=point[0]*dir[0]*b2+point[1]*dir[1]*a2;
00202 Double_t w=point[0]*point[0]*b2+point[1]*point[1]*a2-a2*b2;
00203 Double_t d=v*v-u*w;
00204 if (d<0) return snxt;
00205 if (TGeoShape::IsSameWithinTolerance(u,0)) return snxt;
00206 Double_t sd=TMath::Sqrt(d);
00207 Double_t tau1=(-v+sd)/u;
00208 Double_t tau2=(-v+sd)/u;
00209
00210 if (tau1<0) {
00211 if (tau2<0) return snxt;
00212 } else {
00213 snxt=tau1;
00214 if ((tau2>0) && (tau2<tau1)) return tau2;
00215 }
00216 return snxt;
00217 }
00218
00219
00220 Double_t TGeoEltu::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00221 {
00222
00223 Double_t snxt=TGeoShape::Big();
00224 Double_t safz=TMath::Abs(point[2])-fDz;
00225 Double_t a2=fRmin*fRmin;
00226 Double_t b2=fRmax*fRmax;
00227 if (iact<3 && safe) {
00228 Double_t x0=TMath::Abs(point[0]);
00229 Double_t y0=TMath::Abs(point[1]);
00230 *safe=0.;
00231 if ((x0*x0/a2+y0*y0/b2)>=1) {
00232 Double_t phi1=0;
00233 Double_t phi2=0.5*TMath::Pi();
00234 Double_t phi3;
00235 Double_t x3,y3,d;
00236 for (Int_t i=0; i<10; i++) {
00237 phi3=(phi1+phi2)*0.5;
00238 x3=fRmin*TMath::Cos(phi3);
00239 y3=fRmax*TMath::Sin(phi3);
00240 d=y3*a2*(x0-x3)-x3*b2*(y0-y3);
00241 if (d<0) phi1=phi3;
00242 else phi2=phi3;
00243 }
00244 *safe=TMath::Sqrt((x0-x3)*(x0-x3)+(y0-y3)*(y0-y3));
00245 }
00246 if (safz>0) {
00247 *safe=TMath::Sqrt((*safe)*(*safe)+safz*safz);
00248 }
00249 if (iact==0) return TGeoShape::Big();
00250 if ((iact==1) && (step<*safe)) return TGeoShape::Big();
00251 }
00252
00253 if ((safz>0) && (point[2]*dir[2]>=0)) return TGeoShape::Big();
00254
00255 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00256 if (sdist>=step) return TGeoShape::Big();
00257 Double_t zi;
00258 if (!TGeoShape::IsSameWithinTolerance(dir[2],0)) {
00259 Double_t u=dir[0]*dir[0]*b2+dir[1]*dir[1]*a2;
00260 if (TGeoShape::IsSameWithinTolerance(u,0)) return TGeoShape::Big();
00261 Double_t v=point[0]*dir[0]*b2+point[1]*dir[1]*a2;
00262 Double_t w=point[0]*point[0]*b2+point[1]*point[1]*a2-a2*b2;
00263 Double_t d=v*v-u*w;
00264 if (d<0) return TGeoShape::Big();
00265 Double_t dsq=TMath::Sqrt(d);
00266 Double_t tau[2];
00267 tau[0]=(-v+dsq)/u;
00268 tau[1]=(-v-dsq)/u;
00269 for (Int_t j=0; j<2; j++) {
00270 if (tau[j]>=0) {
00271 zi=point[2]+tau[j]*dir[2];
00272 if ((TMath::Abs(zi)-fDz)<0)
00273 snxt=TMath::Min(snxt,tau[j]);
00274 }
00275 }
00276 }
00277
00278 zi=TGeoShape::Big();
00279 if (safz>0) {
00280 if (TGeoShape::IsSameWithinTolerance(dir[2],0)) return TGeoShape::Big();
00281 if (point[2]>0) zi=fDz;
00282 if (point[2]<0) zi=-fDz;
00283 Double_t tauz=(zi-point[2])/dir[2];
00284 Double_t xz=point[0]+dir[0]*tauz;
00285 Double_t yz=point[1]+dir[1]*tauz;
00286 if ((xz*xz/a2+yz*yz/b2)<=1) snxt=tauz;
00287 }
00288 return snxt;
00289 }
00290
00291
00292 TGeoVolume *TGeoEltu::Divide(TGeoVolume * , const char * , Int_t , Int_t ,
00293 Double_t , Double_t )
00294 {
00295
00296 Error("Divide", "Elliptical tubes divisions not implemenetd");
00297 return 0;
00298 }
00299
00300
00301 void TGeoEltu::GetBoundingCylinder(Double_t *param) const
00302 {
00303
00304
00305 param[0] = 0.;
00306 param[1] = TMath::Max(fRmin, fRmax);
00307 param[1] *= param[1];
00308 param[2] = 0.;
00309 param[3] = 360.;
00310 }
00311
00312
00313 TGeoShape *TGeoEltu::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
00314 {
00315
00316
00317 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00318 if (!mother->TestShapeBit(kGeoEltu)) {
00319 Error("GetMakeRuntimeShape", "invalid mother");
00320 return 0;
00321 }
00322 Double_t a, b, dz;
00323 a = fRmin;
00324 b = fRmax;
00325 dz = fDz;
00326 if (fDz<0) dz=((TGeoEltu*)mother)->GetDz();
00327 if (fRmin<0)
00328 a = ((TGeoEltu*)mother)->GetA();
00329 if (fRmax<0)
00330 a = ((TGeoEltu*)mother)->GetB();
00331
00332 return (new TGeoEltu(a, b, dz));
00333 }
00334
00335
00336 void TGeoEltu::InspectShape() const
00337 {
00338
00339 printf("*** Shape %s: TGeoEltu ***\n", GetName());
00340 printf(" A = %11.5f\n", fRmin);
00341 printf(" B = %11.5f\n", fRmax);
00342 printf(" dz = %11.5f\n", fDz);
00343 printf(" Bounding box:\n");
00344 TGeoBBox::InspectShape();
00345 }
00346
00347
00348 Double_t TGeoEltu::Safety(Double_t *point, Bool_t ) const
00349 {
00350
00351
00352 Double_t x0 = TMath::Abs(point[0]);
00353 Double_t y0 = TMath::Abs(point[1]);
00354 Double_t x1, y1, dx, dy;
00355 Double_t safr, safz;
00356 safr = safz = TGeoShape::Big();
00357 Double_t onepls = 1.+TGeoShape::Tolerance();
00358 Double_t onemin = 1.-TGeoShape::Tolerance();
00359 Double_t sqdist = x0*x0/(fRmin*fRmin)+y0*y0/(fRmax*fRmax);
00360 Bool_t in = kTRUE;
00361 if (sqdist>onepls) in = kFALSE;
00362 else if (sqdist<onemin) in = kTRUE;
00363 else return 0.;
00364
00365 if (in) {
00366 x1 = fRmin*TMath::Sqrt(1.-(y0*y0)/(fRmax*fRmax));
00367 y1 = fRmax*TMath::Sqrt(1.-(x0*x0)/(fRmin*fRmin));
00368 dx = x1-x0;
00369 dy = y1-y0;
00370 if (TMath::Abs(dx)<TGeoShape::Tolerance()) return 0;
00371 safr = dx*dy/TMath::Sqrt(dx*dx+dy*dy);
00372 safz = fDz - TMath::Abs(point[2]);
00373 return TMath::Min(safr,safz);
00374 }
00375
00376 if (TMath::Abs(x0)<TGeoShape::Tolerance()) {
00377 safr = y0 - fRmax;
00378 } else {
00379 if (TMath::Abs(y0)<TGeoShape::Tolerance()) {
00380 safr = x0 - fRmin;
00381 } else {
00382 Double_t f = fRmin*fRmax/TMath::Sqrt(x0*x0*fRmax*fRmax+y0*y0*fRmin*fRmin);
00383 x1 = f*x0;
00384 y1 = f*y0;
00385 dx = x0-x1;
00386 dy = y0-y1;
00387 Double_t ast = fRmin*y1/fRmax;
00388 Double_t bct = fRmax*x1/fRmin;
00389 Double_t d = TMath::Sqrt(bct*bct+ast*ast);
00390 safr = (dx*bct+dy*ast)/d;
00391 }
00392 }
00393 safz = TMath::Abs(point[2])-fDz;
00394 return TMath::Max(safr, safz);
00395 }
00396
00397
00398 void TGeoEltu::SavePrimitive(ostream &out, Option_t * )
00399 {
00400
00401 if (TObject::TestBit(kGeoSavePrimitive)) return;
00402 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
00403 out << " a = " << fRmin << ";" << endl;
00404 out << " b = " << fRmax << ";" << endl;
00405 out << " dz = " << fDz << ";" << endl;
00406 out << " TGeoShape *" << GetPointerName() << " = new TGeoEltu(\"" << GetName() << "\",a,b,dz);" << endl;
00407 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00408 }
00409
00410
00411 void TGeoEltu::SetEltuDimensions(Double_t a, Double_t b, Double_t dz)
00412 {
00413
00414 if ((a<=0) || (b<0) || (dz<0)) {
00415 SetShapeBit(kGeoRunTimeShape);
00416 }
00417 fRmin=a;
00418 fRmax=b;
00419 fDz=dz;
00420 }
00421
00422
00423 void TGeoEltu::SetDimensions(Double_t *param)
00424 {
00425
00426 Double_t a = param[0];
00427 Double_t b = param[1];
00428 Double_t dz = param[2];
00429 SetEltuDimensions(a, b, dz);
00430 }
00431
00432
00433 void TGeoEltu::SetPoints(Double_t *points) const
00434 {
00435
00436 Double_t dz;
00437 Int_t j, n;
00438
00439 n = gGeoManager->GetNsegments();
00440 Double_t dphi = 360./n;
00441 Double_t phi = 0;
00442 Double_t cph,sph;
00443 dz = fDz;
00444
00445 Int_t indx = 0;
00446 Double_t r2,r;
00447 Double_t a2=fRmin*fRmin;
00448 Double_t b2=fRmax*fRmax;
00449
00450 if (points) {
00451 for (j = 0; j < n; j++) {
00452 points[indx+6*n] = points[indx] = 0;
00453 indx++;
00454 points[indx+6*n] = points[indx] = 0;
00455 indx++;
00456 points[indx+6*n] = dz;
00457 points[indx] =-dz;
00458 indx++;
00459 }
00460 for (j = 0; j < n; j++) {
00461 phi = j*dphi*TMath::DegToRad();
00462 sph=TMath::Sin(phi);
00463 cph=TMath::Cos(phi);
00464 r2=(a2*b2)/(b2+(a2-b2)*sph*sph);
00465 r=TMath::Sqrt(r2);
00466 points[indx+6*n] = points[indx] = r*cph;
00467 indx++;
00468 points[indx+6*n] = points[indx] = r*sph;
00469 indx++;
00470 points[indx+6*n]= dz;
00471 points[indx] =-dz;
00472 indx++;
00473 }
00474 }
00475 }
00476
00477
00478 void TGeoEltu::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00479 {
00480
00481 TGeoTube::GetMeshNumbers(nvert,nsegs,npols);
00482 }
00483
00484
00485 Int_t TGeoEltu::GetNmeshVertices() const
00486 {
00487
00488 return TGeoTube::GetNmeshVertices();
00489 }
00490
00491
00492 void TGeoEltu::SetPoints(Float_t *points) const
00493 {
00494
00495 Double_t dz;
00496 Int_t j, n;
00497
00498 n = gGeoManager->GetNsegments();
00499 Double_t dphi = 360./n;
00500 Double_t phi = 0;
00501 Double_t cph,sph;
00502 dz = fDz;
00503
00504 Int_t indx = 0;
00505 Double_t r2,r;
00506 Double_t a2=fRmin*fRmin;
00507 Double_t b2=fRmax*fRmax;
00508
00509 if (points) {
00510 for (j = 0; j < n; j++) {
00511 points[indx+6*n] = points[indx] = 0;
00512 indx++;
00513 points[indx+6*n] = points[indx] = 0;
00514 indx++;
00515 points[indx+6*n] = dz;
00516 points[indx] =-dz;
00517 indx++;
00518 }
00519 for (j = 0; j < n; j++) {
00520 phi = j*dphi*TMath::DegToRad();
00521 sph=TMath::Sin(phi);
00522 cph=TMath::Cos(phi);
00523 r2=(a2*b2)/(b2+(a2-b2)*sph*sph);
00524 r=TMath::Sqrt(r2);
00525 points[indx+6*n] = points[indx] = r*cph;
00526 indx++;
00527 points[indx+6*n] = points[indx] = r*sph;
00528 indx++;
00529 points[indx+6*n]= dz;
00530 points[indx] =-dz;
00531 indx++;
00532 }
00533 }
00534 }
00535
00536
00537 const TBuffer3D & TGeoEltu::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
00538 {
00539
00540 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
00541 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
00542
00543 if (reqSections & TBuffer3D::kRawSizes) {
00544 Int_t n = gGeoManager->GetNsegments();
00545 Int_t nbPnts = 4*n;
00546 Int_t nbSegs = 8*n;
00547 Int_t nbPols = 4*n;
00548 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
00549 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
00550 }
00551 }
00552 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
00553 SetPoints(buffer.fPnts);
00554 if (!buffer.fLocalFrame) {
00555 TransformPoints(buffer.fPnts, buffer.NbPnts());
00556 }
00557 SetSegsAndPols(buffer);
00558 buffer.SetSectionsValid(TBuffer3D::kRaw);
00559 }
00560
00561 return buffer;
00562 }