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 #include "Riostream.h"
00045
00046 #include "TGeoManager.h"
00047 #include "TGeoMatrix.h"
00048 #include "TGeoVolume.h"
00049 #include "TGeoPara.h"
00050 #include "TMath.h"
00051
00052 ClassImp(TGeoPara)
00053
00054
00055 TGeoPara::TGeoPara()
00056 {
00057
00058 SetShapeBit(TGeoShape::kGeoPara);
00059 fX = fY = fZ = 0;
00060 fAlpha = 0;
00061 fTheta = 0;
00062 fPhi = 0;
00063 fTxy = 0;
00064 fTxz = 0;
00065 fTyz = 0;
00066 }
00067
00068
00069 TGeoPara::TGeoPara(Double_t dx, Double_t dy, Double_t dz, Double_t alpha,
00070 Double_t theta, Double_t phi)
00071 :TGeoBBox(0, 0, 0)
00072 {
00073
00074 SetShapeBit(TGeoShape::kGeoPara);
00075 fX = dx;
00076 fY = dy;
00077 fZ = dz;
00078 fAlpha = alpha;
00079 fTheta = theta;
00080 fPhi = phi;
00081 fTxy = TMath::Tan(alpha*TMath::DegToRad());
00082 Double_t tth = TMath::Tan(theta*TMath::DegToRad());
00083 Double_t ph = phi*TMath::DegToRad();
00084 fTxz = tth*TMath::Cos(ph);
00085 fTyz = tth*TMath::Sin(ph);
00086 if ((fX<0) || (fY<0) || (fZ<0)) {
00087
00088 SetShapeBit(kGeoRunTimeShape);
00089 }
00090 else ComputeBBox();
00091 }
00092
00093
00094 TGeoPara::TGeoPara(const char *name, Double_t dx, Double_t dy, Double_t dz, Double_t alpha,
00095 Double_t theta, Double_t phi)
00096 :TGeoBBox(name, 0, 0, 0)
00097 {
00098
00099 SetShapeBit(TGeoShape::kGeoPara);
00100 fX = dx;
00101 fY = dy;
00102 fZ = dz;
00103 fAlpha = alpha;
00104 fTheta = theta;
00105 fPhi = phi;
00106 fTxy = TMath::Tan(alpha*TMath::DegToRad());
00107 Double_t tth = TMath::Tan(theta*TMath::DegToRad());
00108 Double_t ph = phi*TMath::DegToRad();
00109 fTxz = tth*TMath::Cos(ph);
00110 fTyz = tth*TMath::Sin(ph);
00111 if ((fX<0) || (fY<0) || (fZ<0)) {
00112
00113 SetShapeBit(kGeoRunTimeShape);
00114 }
00115 else ComputeBBox();
00116 }
00117
00118
00119 TGeoPara::TGeoPara(Double_t *param)
00120 :TGeoBBox(0, 0, 0)
00121 {
00122
00123
00124
00125
00126
00127
00128
00129 SetShapeBit(TGeoShape::kGeoPara);
00130 SetDimensions(param);
00131 if ((fX<0) || (fY<0) || (fZ<0)) SetShapeBit(kGeoRunTimeShape);
00132 else ComputeBBox();
00133 }
00134
00135
00136 TGeoPara::~TGeoPara()
00137 {
00138
00139 }
00140
00141
00142 Double_t TGeoPara::Capacity() const
00143 {
00144
00145 Double_t capacity = 8.*fX*fY*fZ;
00146 return capacity;
00147 }
00148
00149
00150 void TGeoPara::ComputeBBox()
00151 {
00152
00153 Double_t dx = fX+fY*TMath::Abs(fTxy)+fZ*TMath::Abs(fTxz);
00154 Double_t dy = fY+fZ*TMath::Abs(fTyz);
00155 Double_t dz = fZ;
00156 TGeoBBox::SetBoxDimensions(dx, dy, dz);
00157 memset(fOrigin, 0, 3*sizeof(Double_t));
00158 }
00159
00160
00161 void TGeoPara::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00162 {
00163
00164 Double_t saf[3];
00165
00166 saf[0] = TMath::Abs(fZ-TMath::Abs(point[2]));
00167
00168 Double_t yt = point[1]-fTyz*point[2];
00169 saf[1] = TMath::Abs(fY-TMath::Abs(yt));
00170
00171 Double_t cty = 1.0/TMath::Sqrt(1.0+fTyz*fTyz);
00172
00173 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
00174 saf[2] = TMath::Abs(fX-TMath::Abs(xt));
00175
00176 Double_t ctx = 1.0/TMath::Sqrt(1.0+fTxy*fTxy+fTxz*fTxz);
00177 saf[2] *= ctx;
00178 saf[1] *= cty;
00179 Int_t i = TMath::LocMin(3,saf);
00180 switch (i) {
00181 case 0:
00182 norm[0] = norm[1] = 0;
00183 norm[2] = TMath::Sign(1.,dir[2]);
00184 return;
00185 case 1:
00186 norm[0] = 0;
00187 norm[1] = cty;
00188 norm[2] = - fTyz*cty;
00189 break;
00190 case 2:
00191 norm[0] = TMath::Cos(fTheta*TMath::DegToRad())*TMath::Cos(fAlpha*TMath::DegToRad());
00192 norm[1] = - TMath::Cos(fTheta*TMath::DegToRad())*TMath::Sin(fAlpha*TMath::DegToRad());
00193 norm[2] = -TMath::Sin(fTheta*TMath::DegToRad());
00194 }
00195 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
00196 norm[0] = -norm[0];
00197 norm[1] = -norm[1];
00198 norm[2] = -norm[2];
00199 }
00200 }
00201
00202
00203 Bool_t TGeoPara::Contains(Double_t *point) const
00204 {
00205
00206
00207 if (TMath::Abs(point[2]) > fZ) return kFALSE;
00208
00209 Double_t yt=point[1]-fTyz*point[2];
00210 if (TMath::Abs(yt) > fY) return kFALSE;
00211 Double_t xt=point[0]-fTxz*point[2]-fTxy*yt;
00212 if (TMath::Abs(xt) > fX) return kFALSE;
00213 return kTRUE;
00214 }
00215
00216
00217 Double_t TGeoPara::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00218 {
00219
00220
00221 if (iact<3 && safe) {
00222
00223 *safe = Safety(point, kTRUE);
00224 if (iact==0) return TGeoShape::Big();
00225 if (iact==1 && step<*safe) return TGeoShape::Big();
00226 }
00227 Double_t saf[2];
00228 Double_t snxt = TGeoShape::Big();
00229 Double_t s;
00230 saf[0] = fZ+point[2];
00231 saf[1] = fZ-point[2];
00232 if (!TGeoShape::IsSameWithinTolerance(dir[2],0)) {
00233 s = (dir[2]>0)?(saf[1]/dir[2]):(-saf[0]/dir[2]);
00234 if (s<0) return 0.0;
00235 if (s<snxt) snxt = s;
00236 }
00237
00238 Double_t yt = point[1]-fTyz*point[2];
00239 saf[0] = fY+yt;
00240 saf[1] = fY-yt;
00241 Double_t dy = dir[1]-fTyz*dir[2];
00242 if (!TGeoShape::IsSameWithinTolerance(dy,0)) {
00243 s = (dy>0)?(saf[1]/dy):(-saf[0]/dy);
00244 if (s<0) return 0.0;
00245 if (s<snxt) snxt = s;
00246 }
00247
00248 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
00249 saf[0] = fX+xt;
00250 saf[1] = fX-xt;
00251 Double_t dx = dir[0]-fTxz*dir[2]-fTxy*dy;
00252 if (!TGeoShape::IsSameWithinTolerance(dx,0)) {
00253 s = (dx>0)?(saf[1]/dx):(-saf[0]/dx);
00254 if (s<0) return 0.0;
00255 if (s<snxt) snxt = s;
00256 }
00257 return snxt;
00258 }
00259
00260
00261 Double_t TGeoPara::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00262 {
00263
00264 Double_t snxt=TGeoShape::Big();
00265 if (iact<3 && safe) {
00266
00267 *safe = Safety(point, kFALSE);
00268 if (iact==0) return TGeoShape::Big();
00269 if (iact==1 && step<*safe) return TGeoShape::Big();
00270 }
00271 Bool_t in = kTRUE;
00272 Double_t safz;
00273 safz = TMath::Abs(point[2])-fZ;
00274 if (safz>0) {
00275
00276 if (point[2]*dir[2]>=0) return TGeoShape::Big();
00277 in = kFALSE;
00278 }
00279 Double_t yt=point[1]-fTyz*point[2];
00280 Double_t safy = TMath::Abs(yt)-fY;
00281 Double_t dy=dir[1]-fTyz*dir[2];
00282 if (safy>0) {
00283 if (yt*dy>=0) return TGeoShape::Big();
00284 in = kFALSE;
00285 }
00286 Double_t xt=point[0]-fTxy*yt-fTxz*point[2];
00287 Double_t safx = TMath::Abs(xt)-fX;
00288 Double_t dx=dir[0]-fTxy*dy-fTxz*dir[2];
00289 if (safx>0) {
00290 if (xt*dx>=0) return TGeoShape::Big();
00291 in = kFALSE;
00292 }
00293
00294 if (in) {
00295 if (safz>safx && safz>safy) {
00296 if (point[2]*dir[2]>0) return TGeoShape::Big();
00297 return 0.0;
00298 }
00299 if (safx>safy) {
00300 if (xt*dx>0) return TGeoShape::Big();
00301 return 0.0;
00302 }
00303 if (yt*dy>0) return TGeoShape::Big();
00304 return 0.0;
00305 }
00306 Double_t xnew,ynew,znew;
00307 if (safz>0) {
00308 snxt = safz/TMath::Abs(dir[2]);
00309 xnew = point[0]+snxt*dir[0];
00310 ynew = point[1]+snxt*dir[1];
00311 znew = (point[2]>0)?fZ:(-fZ);
00312 Double_t ytn = ynew-fTyz*znew;
00313 if (TMath::Abs(ytn)<=fY) {
00314 Double_t xtn = xnew-fTxy*ytn-fTxz*znew;
00315 if (TMath::Abs(xtn)<=fX) return snxt;
00316 }
00317 }
00318 if (safy>0) {
00319 snxt = safy/TMath::Abs(dy);
00320 znew = point[2]+snxt*dir[2];
00321 if (TMath::Abs(znew)<=fZ) {
00322 Double_t ytn = (yt>0)?fY:(-fY);
00323 xnew = point[0]+snxt*dir[0];
00324 Double_t xtn = xnew-fTxy*ytn-fTxz*znew;
00325 if (TMath::Abs(xtn)<=fX) return snxt;
00326 }
00327 }
00328 if (safx>0) {
00329 snxt = safx/TMath::Abs(dx);
00330 znew = point[2]+snxt*dir[2];
00331 if (TMath::Abs(znew)<=fZ) {
00332 ynew = point[1]+snxt*dir[1];
00333 Double_t ytn = ynew-fTyz*znew;
00334 if (TMath::Abs(ytn)<=fY) return snxt;
00335 }
00336 }
00337 return TGeoShape::Big();
00338 }
00339
00340
00341 TGeoVolume *TGeoPara::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
00342 Double_t start, Double_t step)
00343 {
00344
00345
00346
00347
00348 TGeoShape *shape;
00349 TGeoVolume *vol;
00350 TGeoVolumeMulti *vmulti;
00351 TGeoPatternFinder *finder;
00352 TString opt = "";
00353 Double_t end=start+ndiv*step;
00354 switch (iaxis) {
00355 case 1:
00356 shape = new TGeoPara(step/2, fY, fZ,fAlpha,fTheta, fPhi);
00357 finder = new TGeoPatternParaX(voldiv, ndiv, start, end);
00358 opt = "X";
00359 break;
00360 case 2:
00361 shape = new TGeoPara(fX, step/2, fZ, fAlpha, fTheta, fPhi);
00362 finder = new TGeoPatternParaY(voldiv, ndiv, start, end);
00363 opt = "Y";
00364 break;
00365 case 3:
00366 shape = new TGeoPara(fX, fY, step/2, fAlpha, fTheta, fPhi);
00367 finder = new TGeoPatternParaZ(voldiv, ndiv, start, end);
00368 opt = "Z";
00369 break;
00370 default:
00371 Error("Divide", "Wrong axis type for division");
00372 return 0;
00373 }
00374 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00375 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00376 vmulti->AddVolume(vol);
00377 voldiv->SetFinder(finder);
00378 finder->SetDivIndex(voldiv->GetNdaughters());
00379 for (Int_t ic=0; ic<ndiv; ic++) {
00380 voldiv->AddNodeOffset(vol, ic, start+step/2.+ic*step, opt.Data());
00381 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00382 }
00383 return vmulti;
00384 }
00385
00386
00387 Double_t TGeoPara::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00388 {
00389
00390 xlo = 0;
00391 xhi = 0;
00392 Double_t dx = 0;
00393 switch (iaxis) {
00394 case 1:
00395 xlo = -fX;
00396 xhi = fX;
00397 dx = xhi-xlo;
00398 return dx;
00399 case 2:
00400 xlo = -fY;
00401 xhi = fY;
00402 dx = xhi-xlo;
00403 return dx;
00404 case 3:
00405 xlo = -fZ;
00406 xhi = fZ;
00407 dx = xhi-xlo;
00408 return dx;
00409 }
00410 return dx;
00411 }
00412
00413
00414 void TGeoPara::GetBoundingCylinder(Double_t *param) const
00415 {
00416
00417
00418 TGeoBBox::GetBoundingCylinder(param);
00419 }
00420
00421
00422 Int_t TGeoPara::GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const
00423 {
00424
00425 dx=dy=dz=0;
00426 if (mat->IsRotation()) {
00427 Error("GetFittingBox", "cannot handle parametrized rotated volumes");
00428 return 1;
00429 }
00430
00431 Double_t origin[3];
00432 mat->LocalToMaster(parambox->GetOrigin(), origin);
00433 if (!Contains(origin)) {
00434 Error("GetFittingBox", "wrong matrix - parametrized box is outside this");
00435 return 1;
00436 }
00437
00438 Double_t dd[3];
00439 dd[0] = parambox->GetDX();
00440 dd[1] = parambox->GetDY();
00441 dd[2] = parambox->GetDZ();
00442
00443 if (dd[2]<0) {
00444 dd[2] = TMath::Min(origin[2]+fZ, fZ-origin[2]);
00445 if (dd[2]<0) {
00446 Error("GetFittingBox", "wrong matrix");
00447 return 1;
00448 }
00449 }
00450 if (dd[0]>=0 && dd[1]>=0) {
00451 dx = dd[0];
00452 dy = dd[1];
00453 dz = dd[2];
00454 return 0;
00455 }
00456
00457 Double_t upper[8];
00458 Double_t lower[8];
00459 Double_t z=origin[2]-dd[2];
00460 lower[0]=z*fTxz-fTxy*fY-fX;
00461 lower[1]=-fY+z*fTyz;
00462 lower[2]=z*fTxz+fTxy*fY-fX;
00463 lower[3]=fY+z*fTyz;
00464 lower[4]=z*fTxz+fTxy*fY+fX;
00465 lower[5]=fY+z*fTyz;
00466 lower[6]=z*fTxz-fTxy*fY+fX;
00467 lower[7]=-fY+z*fTyz;
00468 z=origin[2]+dd[2];
00469 upper[0]=z*fTxz-fTxy*fY-fX;
00470 upper[1]=-fY+z*fTyz;
00471 upper[2]=z*fTxz+fTxy*fY-fX;
00472 upper[3]=fY+z*fTyz;
00473 upper[4]=z*fTxz+fTxy*fY+fX;
00474 upper[5]=fY+z*fTyz;
00475 upper[6]=z*fTxz-fTxy*fY+fX;
00476 upper[7]=-fY+z*fTyz;
00477
00478 Double_t ddmin=TGeoShape::Big();
00479 for (Int_t iaxis=0; iaxis<2; iaxis++) {
00480 if (dd[iaxis]>=0) continue;
00481 ddmin=TGeoShape::Big();
00482 for (Int_t ivert=0; ivert<4; ivert++) {
00483 ddmin = TMath::Min(ddmin, TMath::Abs(origin[iaxis]-lower[2*ivert+iaxis]));
00484 ddmin = TMath::Min(ddmin, TMath::Abs(origin[iaxis]-upper[2*ivert+iaxis]));
00485 }
00486 dd[iaxis] = ddmin;
00487 }
00488 dx = dd[0];
00489 dy = dd[1];
00490 dz = dd[2];
00491 return 0;
00492 }
00493
00494
00495 TGeoShape *TGeoPara::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
00496 {
00497
00498
00499 if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00500 if (!mother->TestShapeBit(kGeoPara)) {
00501 Error("GetMakeRuntimeShape", "invalid mother");
00502 return 0;
00503 }
00504 Double_t dx, dy, dz;
00505 if (fX<0) dx=((TGeoPara*)mother)->GetX();
00506 else dx=fX;
00507 if (fY<0) dy=((TGeoPara*)mother)->GetY();
00508 else dy=fY;
00509 if (fZ<0) dz=((TGeoPara*)mother)->GetZ();
00510 else dz=fZ;
00511 return (new TGeoPara(dx, dy, dz, fAlpha, fTheta, fPhi));
00512 }
00513
00514
00515 void TGeoPara::InspectShape() const
00516 {
00517
00518 printf("*** Shape %s: TGeoPara ***\n", GetName());
00519 printf(" dX = %11.5f\n", fX);
00520 printf(" dY = %11.5f\n", fY);
00521 printf(" dZ = %11.5f\n", fZ);
00522 printf(" alpha = %11.5f\n", fAlpha);
00523 printf(" theta = %11.5f\n", fTheta);
00524 printf(" phi = %11.5f\n", fPhi);
00525 printf(" Bounding box:\n");
00526 TGeoBBox::InspectShape();
00527 }
00528
00529
00530 Double_t TGeoPara::Safety(Double_t *point, Bool_t in) const
00531 {
00532
00533
00534 Double_t saf[3];
00535
00536 saf[0] = fZ-TMath::Abs(point[2]);
00537
00538 Double_t yt = point[1]-fTyz*point[2];
00539 saf[1] = fY-TMath::Abs(yt);
00540
00541 Double_t cty = 1.0/TMath::Sqrt(1.0+fTyz*fTyz);
00542
00543 Double_t xt = point[0]-fTxz*point[2]-fTxy*yt;
00544 saf[2] = fX-TMath::Abs(xt);
00545
00546 Double_t ctx = 1.0/TMath::Sqrt(1.0+fTxy*fTxy+fTxz*fTxz);
00547 saf[2] *= ctx;
00548 saf[1] *= cty;
00549 if (in) return saf[TMath::LocMin(3,saf)];
00550 for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00551 return saf[TMath::LocMax(3,saf)];
00552 }
00553
00554
00555 void TGeoPara::SavePrimitive(ostream &out, Option_t * )
00556 {
00557
00558 if (TObject::TestBit(kGeoSavePrimitive)) return;
00559 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
00560 out << " dx = " << fX << ";" << endl;
00561 out << " dy = " << fY << ";" << endl;
00562 out << " dz = " << fZ << ";" << endl;
00563 out << " alpha = " << fAlpha<< ";" << endl;
00564 out << " theta = " << fTheta << ";" << endl;
00565 out << " phi = " << fPhi << ";" << endl;
00566 out << " TGeoShape *" << GetPointerName() << " = new TGeoPara(\"" << GetName() << "\",dx,dy,dz,alpha,theta,phi);" << endl;
00567 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00568 }
00569
00570
00571 void TGeoPara::SetDimensions(Double_t *param)
00572 {
00573
00574 fX = param[0];
00575 fY = param[1];
00576 fZ = param[2];
00577 fAlpha = param[3];
00578 fTheta = param[4];
00579 fPhi = param[5];
00580 fTxy = TMath::Tan(param[3]*TMath::DegToRad());
00581 Double_t tth = TMath::Tan(param[4]*TMath::DegToRad());
00582 Double_t ph = param[5]*TMath::DegToRad();
00583 fTxz = tth*TMath::Cos(ph);
00584 fTyz = tth*TMath::Sin(ph);
00585 }
00586
00587
00588 void TGeoPara::SetPoints(Double_t *points) const
00589 {
00590
00591 if (!points) return;
00592 Double_t txy = fTxy;
00593 Double_t txz = fTxz;
00594 Double_t tyz = fTyz;
00595 *points++ = -fZ*txz-txy*fY-fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
00596 *points++ = -fZ*txz+txy*fY-fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
00597 *points++ = -fZ*txz+txy*fY+fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
00598 *points++ = -fZ*txz-txy*fY+fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
00599 *points++ = +fZ*txz-txy*fY-fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
00600 *points++ = +fZ*txz+txy*fY-fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
00601 *points++ = +fZ*txz+txy*fY+fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
00602 *points++ = +fZ*txz-txy*fY+fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
00603 }
00604
00605
00606 void TGeoPara::SetPoints(Float_t *points) const
00607 {
00608
00609 if (!points) return;
00610 Double_t txy = fTxy;
00611 Double_t txz = fTxz;
00612 Double_t tyz = fTyz;
00613 *points++ = -fZ*txz-txy*fY-fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
00614 *points++ = -fZ*txz+txy*fY-fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
00615 *points++ = -fZ*txz+txy*fY+fX; *points++ = +fY-fZ*tyz; *points++ = -fZ;
00616 *points++ = -fZ*txz-txy*fY+fX; *points++ = -fY-fZ*tyz; *points++ = -fZ;
00617 *points++ = +fZ*txz-txy*fY-fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
00618 *points++ = +fZ*txz+txy*fY-fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
00619 *points++ = +fZ*txz+txy*fY+fX; *points++ = +fY+fZ*tyz; *points++ = +fZ;
00620 *points++ = +fZ*txz-txy*fY+fX; *points++ = -fY+fZ*tyz; *points++ = +fZ;
00621 }
00622
00623
00624 void TGeoPara::Sizeof3D() const
00625 {
00626
00627 TGeoBBox::Sizeof3D();
00628 }
00629