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 #include "Riostream.h"
00028 #include "TGeoManager.h"
00029 #include "TGeoVolume.h"
00030 #include "TVirtualGeoPainter.h"
00031 #include "TGeoParaboloid.h"
00032 #include "TVirtualPad.h"
00033 #include "TBuffer3D.h"
00034 #include "TBuffer3DTypes.h"
00035 #include "TMath.h"
00036
00037 ClassImp(TGeoParaboloid)
00038
00039
00040 TGeoParaboloid::TGeoParaboloid()
00041 {
00042
00043 fRlo = 0;
00044 fRhi = 0;
00045 fDz = 0;
00046 fA = 0;
00047 fB = 0;
00048 SetShapeBit(TGeoShape::kGeoParaboloid);
00049 }
00050
00051
00052 TGeoParaboloid::TGeoParaboloid(Double_t rlo, Double_t rhi, Double_t dz)
00053 :TGeoBBox(0,0,0)
00054 {
00055
00056 fRlo = 0;
00057 fRhi = 0;
00058 fDz = 0;
00059 fA = 0;
00060 fB = 0;
00061 SetShapeBit(TGeoShape::kGeoParaboloid);
00062 SetParaboloidDimensions(rlo, rhi, dz);
00063 ComputeBBox();
00064 }
00065
00066
00067 TGeoParaboloid::TGeoParaboloid(const char *name, Double_t rlo, Double_t rhi, Double_t dz)
00068 :TGeoBBox(name, 0, 0, 0)
00069 {
00070
00071 fRlo = 0;
00072 fRhi = 0;
00073 fDz = 0;
00074 fA = 0;
00075 fB = 0;
00076 SetShapeBit(TGeoShape::kGeoParaboloid);
00077 SetParaboloidDimensions(rlo, rhi, dz);
00078 ComputeBBox();
00079 }
00080
00081
00082 TGeoParaboloid::TGeoParaboloid(Double_t *param)
00083 {
00084
00085
00086
00087
00088 SetShapeBit(TGeoShape::kGeoParaboloid);
00089 SetDimensions(param);
00090 ComputeBBox();
00091 }
00092
00093
00094 TGeoParaboloid::~TGeoParaboloid()
00095 {
00096
00097 }
00098
00099
00100 Double_t TGeoParaboloid::Capacity() const
00101 {
00102
00103 Double_t capacity = TMath::Pi()*fDz*(fRlo*fRlo+fRhi*fRhi);
00104 return capacity;
00105 }
00106
00107
00108 void TGeoParaboloid::ComputeBBox()
00109 {
00110
00111 fDX = TMath::Max(fRlo, fRhi);
00112 fDY = fDX;
00113 fDZ = fDz;
00114 }
00115
00116
00117 void TGeoParaboloid::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00118 {
00119
00120 if ((TMath::Abs(point[2])-fDz) > -1E-5) {
00121 norm[0] = norm[1] = 0.0;
00122 norm[2] = TMath::Sign(1., dir[2]);
00123 return;
00124 }
00125 Double_t talf = 2.*TMath::Sqrt(fA*(point[2]-fB))*TMath::Sign(1.0, fA);
00126 Double_t calf = 1./TMath::Sqrt(1.+talf*talf);
00127 Double_t salf = talf * calf;
00128 Double_t phi = TMath::ATan2(point[1], point[0]);
00129 if (phi<0) phi+=2.*TMath::Pi();
00130 Double_t cphi = TMath::Cos(phi);
00131 Double_t sphi = TMath::Sin(phi);
00132 Double_t ct = - calf*TMath::Sign(1.,fA);
00133 Double_t st = salf*TMath::Sign(1.,fA);
00134
00135 norm[0] = st*cphi;
00136 norm[1] = st*sphi;
00137 norm[2] = ct;
00138 Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
00139 if (ndotd < 0) {
00140 norm[0] = -norm[0];
00141 norm[1] = -norm[1];
00142 norm[2] = -norm[2];
00143 }
00144 }
00145
00146
00147 Bool_t TGeoParaboloid::Contains(Double_t *point) const
00148 {
00149
00150 if (TMath::Abs(point[2])>fDz) return kFALSE;
00151 Double_t aa = fA*(point[2]-fB);
00152 if (aa < 0) return kFALSE;
00153 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00154 if (aa < fA*fA*rsq) return kFALSE;
00155 return kTRUE;
00156 }
00157
00158
00159 Int_t TGeoParaboloid::DistancetoPrimitive(Int_t px, Int_t py)
00160 {
00161
00162 Int_t n = gGeoManager->GetNsegments();
00163 const Int_t numPoints=n*(n+1)+2;
00164 return ShapeDistancetoPrimitive(numPoints, px, py);
00165 }
00166
00167
00168 Double_t TGeoParaboloid::DistToParaboloid(Double_t *point, Double_t *dir) const
00169 {
00170
00171
00172 Double_t a = fA * (dir[0]*dir[0] + dir[1]*dir[1]);
00173 Double_t b = 2.*fA*(point[0]*dir[0]+point[1]*dir[1])-dir[2];
00174 Double_t c = fA*(point[0]*point[0]+point[1]*point[1]) + fB - point[2];
00175 Double_t dist = TGeoShape::Big();
00176 if (TMath::Abs(a)<TGeoShape::Tolerance()) {
00177 if (TMath::Abs(b)<TGeoShape::Tolerance()) return dist;
00178 dist = -c/b;
00179 if (dist < 0) return TGeoShape::Big();
00180 return dist;
00181 }
00182 Double_t ainv = 1./a;
00183 Double_t sum = - b*ainv;
00184 Double_t prod = c*ainv;
00185 Double_t delta = sum*sum - 4.*prod;
00186 if (delta<0) return dist;
00187 if (TMath::Abs(prod)<TGeoShape::Tolerance()) return 0.;
00188 if (prod < 0) {
00189 dist = 0.5*(sum + TMath::Sqrt(delta));
00190 return dist;
00191 }
00192 if (sum < 0) return dist;
00193 dist = 0.5 * (sum - TMath::Sqrt(delta));
00194 return dist;
00195 }
00196
00197
00198 Double_t TGeoParaboloid::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00199 {
00200
00201 if (iact<3 && safe) {
00202
00203 *safe = Safety(point, kTRUE);
00204 if (iact==0) return TGeoShape::Big();
00205 if (iact==1 && step<*safe) return TGeoShape::Big();
00206 }
00207
00208 Double_t dz = TGeoShape::Big();
00209 if (dir[2]<0) {
00210 dz = -(point[2]+fDz)/dir[2];
00211 } else if (dir[2]>0) {
00212 dz = (fDz-point[2])/dir[2];
00213 }
00214 Double_t dpara = DistToParaboloid(point, dir);
00215 return TMath::Min(dz, dpara);
00216 }
00217
00218
00219 Double_t TGeoParaboloid::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00220 {
00221
00222 Double_t snxt = TGeoShape::Big();
00223 if (iact<3 && safe) {
00224
00225 *safe = Safety(point, kFALSE);
00226 if (iact==0) return TGeoShape::Big();
00227 if (iact==1 && step<*safe) return TGeoShape::Big();
00228 }
00229 Double_t xnew, ynew, znew;
00230 if (point[2]<=-fDz) {
00231 if (dir[2]<=0) return TGeoShape::Big();
00232 snxt = -(fDz+point[2])/dir[2];
00233
00234 xnew = point[0]+snxt*dir[0];
00235 ynew = point[1]+snxt*dir[1];
00236 if ((xnew*xnew+ynew*ynew) <= fRlo*fRlo) return snxt;
00237 } else if (point[2]>=fDz) {
00238 if (dir[2]>=0) return TGeoShape::Big();
00239 snxt = (fDz-point[2])/dir[2];
00240
00241 xnew = point[0]+snxt*dir[0];
00242 ynew = point[1]+snxt*dir[1];
00243 if ((xnew*xnew+ynew*ynew) <= fRhi*fRhi) return snxt;
00244 }
00245 snxt = DistToParaboloid(point, dir);
00246 if (snxt > 1E20) return snxt;
00247 znew = point[2]+snxt*dir[2];
00248 if (TMath::Abs(znew) <= fDz) return snxt;
00249 return TGeoShape::Big();
00250 }
00251
00252
00253 TGeoVolume *TGeoParaboloid::Divide(TGeoVolume * , const char * , Int_t , Int_t ,
00254 Double_t , Double_t )
00255 {
00256
00257 Error("Divide", "Paraboloid divisions not implemented");
00258 return 0;
00259 }
00260
00261
00262 void TGeoParaboloid::GetBoundingCylinder(Double_t *param) const
00263 {
00264
00265
00266 param[0] = 0.;
00267 param[1] = fDX;
00268 param[1] *= param[1];
00269 param[2] = 0.;
00270 param[3] = 360.;
00271 }
00272
00273
00274 TGeoShape *TGeoParaboloid::GetMakeRuntimeShape(TGeoShape *, TGeoMatrix *) const
00275 {
00276
00277
00278 return 0;
00279 }
00280
00281
00282 void TGeoParaboloid::InspectShape() const
00283 {
00284
00285 printf("*** Shape %s: TGeoParaboloid ***\n", GetName());
00286 printf(" rlo = %11.5f\n", fRlo);
00287 printf(" rhi = %11.5f\n", fRhi);
00288 printf(" dz = %11.5f\n", fDz);
00289 printf(" Bounding box:\n");
00290 TGeoBBox::InspectShape();
00291 }
00292
00293
00294 TBuffer3D *TGeoParaboloid::MakeBuffer3D() const
00295 {
00296
00297
00298
00299 Int_t n = gGeoManager->GetNsegments();
00300 Int_t nbPnts = n*(n+1)+2;
00301 Int_t nbSegs = n*(2*n+3);
00302 Int_t nbPols = n*(n+2);
00303
00304 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00305 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 2*n*5 + n*n*6);
00306
00307 if (buff)
00308 {
00309 SetPoints(buff->fPnts);
00310 SetSegsAndPols(*buff);
00311 }
00312
00313 return buff;
00314 }
00315
00316
00317 void TGeoParaboloid::SetSegsAndPols(TBuffer3D &buff) const
00318 {
00319
00320 Int_t indx, i, j;
00321 Int_t n = gGeoManager->GetNsegments();
00322
00323 Int_t c = GetBasicColor();
00324
00325 Int_t nn1 = (n+1)*n+1;
00326 indx = 0;
00327
00328 for (j=0; j<n; j++) {
00329 buff.fSegs[indx++] = c+2;
00330 buff.fSegs[indx++] = 0;
00331 buff.fSegs[indx++] = j+1;
00332 }
00333
00334 for (i=0; i<n+1; i++) {
00335
00336 for (j=0; j<n; j++) {
00337 buff.fSegs[indx++] = c;
00338 buff.fSegs[indx++] = n*i+1+j;
00339 buff.fSegs[indx++] = n*i+1+((j+1)%n);
00340 }
00341 if (i==n) break;
00342
00343 for (j=0; j<n; j++) {
00344 buff.fSegs[indx++] = c;
00345 buff.fSegs[indx++] = n*i+1+j;
00346 buff.fSegs[indx++] = n*(i+1)+1+j;
00347 }
00348 }
00349
00350 for (j=0; j<n; j++) {
00351 buff.fSegs[indx++] = c+1;
00352 buff.fSegs[indx++] = n*n+1+j;
00353 buff.fSegs[indx++] = nn1;
00354 }
00355
00356 indx = 0;
00357
00358
00359 for (j=0; j<n; j++) {
00360 buff.fPols[indx++] = c+2;
00361 buff.fPols[indx++] = 3;
00362 buff.fPols[indx++] = n+j;
00363 buff.fPols[indx++] = (j+1)%n;
00364 buff.fPols[indx++] = j;
00365 }
00366
00367 for (i=0; i<n; i++) {
00368
00369 for (j=0; j<n; j++) {
00370 buff.fPols[indx++] = c;
00371 buff.fPols[indx++] = 4;
00372 buff.fPols[indx++] = (2*i+1)*n+j;
00373 buff.fPols[indx++] = 2*(i+1)*n+j;
00374 buff.fPols[indx++] = (2*i+3)*n+j;
00375 buff.fPols[indx++] = 2*(i+1)*n+((j+1)%n);
00376 }
00377 }
00378
00379 for (j=0; j<n; j++) {
00380 buff.fPols[indx++] = c+1;
00381 buff.fPols[indx++] = 3;
00382 buff.fPols[indx++] = 2*n*(n+1)+j;
00383 buff.fPols[indx++] = 2*n*(n+1)+((j+1)%n);
00384 buff.fPols[indx++] = (2*n+1)*n+j;
00385 }
00386 }
00387
00388
00389 Double_t TGeoParaboloid::Safety(Double_t * , Bool_t ) const
00390 {
00391
00392
00393 return TGeoShape::Big();
00394 }
00395
00396
00397 void TGeoParaboloid::SetParaboloidDimensions(Double_t rlo, Double_t rhi, Double_t dz)
00398 {
00399
00400 if ((rlo<0) || (rlo<0) || (dz<=0) || TMath::Abs(rlo-rhi)<TGeoShape::Tolerance()) {
00401 SetShapeBit(kGeoRunTimeShape);
00402 Error("SetParaboloidDimensions", "Dimensions of %s invalid: check (rlo>=0) (rhi>=0) (rlo!=rhi) dz>0",GetName());
00403 return;
00404 }
00405 fRlo = rlo;
00406 fRhi = rhi;
00407 fDz = dz;
00408 Double_t dd = 1./(fRhi*fRhi - fRlo*fRlo);
00409 fA = 2.*fDz*dd;
00410 fB = - fDz * (fRlo*fRlo + fRhi*fRhi)*dd;
00411 }
00412
00413
00414 void TGeoParaboloid::SetDimensions(Double_t *param)
00415 {
00416
00417 Double_t rlo = param[0];
00418 Double_t rhi = param[1];
00419 Double_t dz = param[2];
00420 SetParaboloidDimensions(rlo, rhi, dz);
00421 }
00422
00423
00424 void TGeoParaboloid::SetPoints(Double_t *points) const
00425 {
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 if (!points) return;
00442 Double_t ttmin, ttmax;
00443 ttmin = TMath::ATan2(-fDz, fRlo);
00444 ttmax = TMath::ATan2(fDz, fRhi);
00445 Int_t n = gGeoManager->GetNsegments();
00446 Double_t dtt = (ttmax-ttmin)/n;
00447 Double_t dphi = 360./n;
00448 Double_t tt;
00449 Double_t r, z, delta;
00450 Double_t phi, sph, cph;
00451 Int_t indx = 0;
00452
00453 points[indx++] = 0;
00454 points[indx++] = 0;
00455 points[indx++] = -fDz;
00456 for (Int_t i=0; i<n+1; i++) {
00457 if (i==0) {
00458 r = fRlo;
00459 z = -fDz;
00460 } else if (i==n) {
00461 r = fRhi;
00462 z = fDz;
00463 } else {
00464 tt = TMath::Tan(ttmin + i*dtt);
00465 delta = tt*tt - 4*fA*fB;
00466 r = 0.5*(tt+TMath::Sqrt(delta))/fA;
00467 z = r*tt;
00468 }
00469 for (Int_t j=0; j<n; j++) {
00470 phi = j*dphi*TMath::DegToRad();
00471 sph=TMath::Sin(phi);
00472 cph=TMath::Cos(phi);
00473 points[indx++] = r*cph;
00474 points[indx++] = r*sph;
00475 points[indx++] = z;
00476 }
00477 }
00478
00479 points[indx++] = 0;
00480 points[indx++] = 0;
00481 points[indx++] = fDz;
00482 }
00483
00484
00485 void TGeoParaboloid::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00486 {
00487
00488 Int_t n = gGeoManager->GetNsegments();
00489 nvert = n*(n+1)+2;
00490 nsegs = n*(2*n+3);
00491 npols = n*(n+2);
00492 }
00493
00494
00495 Int_t TGeoParaboloid::GetNmeshVertices() const
00496 {
00497
00498 Int_t n = gGeoManager->GetNsegments();
00499 return (n*(n+1)+2);
00500 }
00501
00502
00503 void TGeoParaboloid::SavePrimitive(ostream &out, Option_t * )
00504 {
00505
00506 if (TObject::TestBit(kGeoSavePrimitive)) return;
00507 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
00508 out << " rlo = " << fRlo << ";" << endl;
00509 out << " rhi = " << fRhi << ";" << endl;
00510 out << " dz = " << fDZ << ";" << endl;
00511 out << " TGeoShape *" << GetPointerName() << " = new TGeoParaboloid(\"" << GetName() << "\", rlo,rhi,dz);" << endl;
00512 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00513 }
00514
00515
00516 void TGeoParaboloid::SetPoints(Float_t *points) const
00517 {
00518
00519 if (!points) return;
00520 Double_t ttmin, ttmax;
00521 ttmin = TMath::ATan2(-fDz, fRlo);
00522 ttmax = TMath::ATan2(fDz, fRhi);
00523 Int_t n = gGeoManager->GetNsegments();
00524 Double_t dtt = (ttmax-ttmin)/n;
00525 Double_t dphi = 360./n;
00526 Double_t tt;
00527 Double_t r, z, delta;
00528 Double_t phi, sph, cph;
00529 Int_t indx = 0;
00530
00531 points[indx++] = 0;
00532 points[indx++] = 0;
00533 points[indx++] = -fDz;
00534 for (Int_t i=0; i<n+1; i++) {
00535 if (i==0) {
00536 r = fRlo;
00537 z = -fDz;
00538 } else if (i==n) {
00539 r = fRhi;
00540 z = fDz;
00541 } else {
00542 tt = TMath::Tan(ttmin + i*dtt);
00543 delta = tt*tt - 4*fA*fB;
00544 r = 0.5*(tt+TMath::Sqrt(delta))/fA;
00545 z = r*tt;
00546 }
00547 for (Int_t j=0; j<n; j++) {
00548 phi = j*dphi*TMath::DegToRad();
00549 sph=TMath::Sin(phi);
00550 cph=TMath::Cos(phi);
00551 points[indx++] = r*cph;
00552 points[indx++] = r*sph;
00553 points[indx++] = z;
00554 }
00555 }
00556
00557 points[indx++] = 0;
00558 points[indx++] = 0;
00559 points[indx++] = fDz;
00560 }
00561
00562
00563 void TGeoParaboloid::Sizeof3D() const
00564 {
00565
00566
00567
00568 }
00569
00570
00571 const TBuffer3D & TGeoParaboloid::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
00572 {
00573
00574 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
00575 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
00576
00577 if (reqSections & TBuffer3D::kRawSizes) {
00578 Int_t n = gGeoManager->GetNsegments();
00579 Int_t nbPnts = n*(n+1)+2;
00580 Int_t nbSegs = n*(2*n+3);
00581 Int_t nbPols = n*(n+2);
00582 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 2*n*5 + n*n*6)) {
00583 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
00584 }
00585 }
00586 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
00587 SetPoints(buffer.fPnts);
00588 if (!buffer.fLocalFrame) {
00589 TransformPoints(buffer.fPnts, buffer.NbPnts());
00590 }
00591 SetSegsAndPols(buffer);
00592 buffer.SetSectionsValid(TBuffer3D::kRaw);
00593 }
00594
00595 return buffer;
00596 }