TGeoTrd2.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoTrd2.cxx 21301 2007-12-10 16:21:50Z brun $
00002 // Author: Andrei Gheata   31/01/02
00003 // TGeoTrd2::Contains() and DistFromInside() implemented by Mihaela Gheata
00004 
00005 /*************************************************************************
00006  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00007  * All rights reserved.                                                  *
00008  *                                                                       *
00009  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00010  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00011  *************************************************************************/
00012 
00013 //_____________________________________________________________________________
00014 // TGeoTrd2 - a trapezoid with both x and y lengths varying with z. It 
00015 //   has 5 parameters, the half lengths in x at -dz and +dz, the half
00016 //  lengths in y at -dz and +dz, and the half length in z (dz).
00017 //
00018 //_____________________________________________________________________________
00019 //Begin_Html
00020 /*
00021 <img src="gif/t_trd2.gif">
00022 */
00023 //End_Html
00024 
00025 //Begin_Html
00026 /*
00027 <img src="gif/t_trd2divZ.gif">
00028 */
00029 //End_Html
00030 
00031 //Begin_Html
00032 /*
00033 <img src="gif/t_trd2divstepZ.gif">
00034 */
00035 //End_Html
00036 
00037 #include "Riostream.h"
00038 
00039 #include "TGeoManager.h"
00040 #include "TGeoMatrix.h"
00041 #include "TGeoVolume.h"
00042 #include "TGeoTrd2.h"
00043 #include "TMath.h"
00044 
00045 ClassImp(TGeoTrd2)
00046    
00047 //_____________________________________________________________________________
00048 TGeoTrd2::TGeoTrd2()
00049 {
00050    // dummy ctor
00051    SetShapeBit(kGeoTrd2);
00052    fDz = fDx1 = fDx2 = fDy1 = fDy2 = 0;
00053 }
00054 
00055 //_____________________________________________________________________________
00056 TGeoTrd2::TGeoTrd2(Double_t dx1, Double_t dx2, Double_t dy1, Double_t dy2, Double_t dz)
00057          :TGeoBBox(0,0,0)
00058 {
00059 // constructor. 
00060    SetShapeBit(kGeoTrd2);
00061    fDx1 = dx1;
00062    fDx2 = dx2;
00063    fDy1 = dy1;
00064    fDy2 = dy2;
00065    fDz = dz;
00066    if ((fDx1<0) || (fDx2<0) || (fDy1<0) || (fDy2<0) || (fDz<0)) {
00067       SetShapeBit(kGeoRunTimeShape);
00068       printf("trd2 : dx1=%f, dx2=%f, dy1=%f, dy2=%f, dz=%f\n",
00069               dx1,dx2,dy1,dy2,dz);
00070    }
00071    else ComputeBBox();
00072 }
00073 
00074 //_____________________________________________________________________________
00075 TGeoTrd2::TGeoTrd2(const char * name, Double_t dx1, Double_t dx2, Double_t dy1, Double_t dy2, Double_t dz)
00076          :TGeoBBox(name, 0,0,0)
00077 {
00078 // constructor. 
00079    SetShapeBit(kGeoTrd2);
00080    fDx1 = dx1;
00081    fDx2 = dx2;
00082    fDy1 = dy1;
00083    fDy2 = dy2;
00084    fDz = dz;
00085    if ((fDx1<0) || (fDx2<0) || (fDy1<0) || (fDy2<0) || (fDz<0)) {
00086       SetShapeBit(kGeoRunTimeShape);
00087       printf("trd2 : dx1=%f, dx2=%f, dy1=%f, dy2=%f, dz=%f\n",
00088               dx1,dx2,dy1,dy2,dz);
00089    }
00090    else ComputeBBox();
00091 }
00092 
00093 //_____________________________________________________________________________
00094 TGeoTrd2::TGeoTrd2(Double_t *param)
00095          :TGeoBBox(0,0,0)
00096 {
00097    // ctor with an array of parameters
00098    // param[0] = dx1
00099    // param[1] = dx2
00100    // param[2] = dy1
00101    // param[3] = dy2
00102    // param[4] = dz
00103    SetShapeBit(kGeoTrd2);
00104    SetDimensions(param);
00105    if ((fDx1<0) || (fDx2<0) || (fDy1<0) || (fDy2<0) || (fDz<0)) SetShapeBit(kGeoRunTimeShape);
00106    else ComputeBBox();
00107 }
00108 
00109 //_____________________________________________________________________________
00110 TGeoTrd2::~TGeoTrd2()
00111 {
00112 // destructor
00113 }
00114 
00115 //_____________________________________________________________________________
00116 Double_t TGeoTrd2::Capacity() const
00117 {
00118 // Computes capacity of the shape in [length^3]
00119    Double_t capacity = 2*(fDx1+fDx2)*(fDy1+fDy2)*fDz + 
00120                       (2./3.)*(fDx1-fDx2)*(fDy1-fDy2)*fDz;
00121    return capacity;
00122 }   
00123 
00124 //_____________________________________________________________________________
00125 void TGeoTrd2::ComputeBBox()
00126 {
00127 // compute bounding box for a trd2
00128    fDX = TMath::Max(fDx1, fDx2);
00129    fDY = TMath::Max(fDy1, fDy2);
00130    fDZ = fDz;
00131    memset(fOrigin, 0, 3*sizeof(Double_t));
00132 }
00133 
00134 //_____________________________________________________________________________   
00135 void TGeoTrd2::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00136 {
00137 // Compute normal to closest surface from POINT. 
00138    Double_t safe, safemin;
00139    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00140    Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
00141    // check Z facettes
00142    safe = safemin = TMath::Abs(fDz-TMath::Abs(point[2]));
00143    norm[0] = norm[1] = 0;
00144    norm[2] = (dir[2]>=0)?1:-1;
00145    if (safe<1E-6) return;
00146    // check X facettes
00147    Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
00148    if (distx>=0) {
00149       safe=TMath::Abs(distx-TMath::Abs(point[0]))*calf;
00150       if (safe<safemin) {
00151          safemin = safe;
00152          norm[0] = (point[0]>0)?calf:(-calf);
00153          norm[1] = 0;
00154          norm[2] = calf*fx;
00155          Double_t dot = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
00156          if (dot<0) {
00157             norm[0]=-norm[0];
00158             norm[2]=-norm[2];
00159          }   
00160          if (safe<1E-6) return;
00161       }
00162    }
00163    
00164    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00165    calf = 1./TMath::Sqrt(1.0+fy*fy);
00166 
00167    // check Y facettes
00168    distx = 0.5*(fDy1+fDy2)-fy*point[2];
00169    if (distx>=0) {
00170       safe=TMath::Abs(distx-TMath::Abs(point[1]))*calf;
00171       if (safe<safemin) {
00172          norm[0] = 0;
00173          norm[1] = (point[1]>0)?calf:(-calf);
00174          norm[2] = calf*fx;
00175          Double_t dot = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
00176          if (dot<0) {
00177             norm[1]=-norm[1];
00178             norm[2]=-norm[2];
00179          }   
00180       }
00181    }
00182 }
00183 
00184 //_____________________________________________________________________________
00185 Bool_t TGeoTrd2::Contains(Double_t *point) const
00186 {
00187 // test if point is inside this shape
00188    // check Z range
00189    if (TMath::Abs(point[2]) > fDz) return kFALSE;
00190    // then y
00191    Double_t dy = 0.5*(fDy2*(point[2]+fDz)+fDy1*(fDz-point[2]))/fDz;
00192    if (TMath::Abs(point[1]) > dy) return kFALSE;
00193    // then x
00194    Double_t dx = 0.5*(fDx2*(point[2]+fDz)+fDx1*(fDz-point[2]))/fDz;
00195    if (TMath::Abs(point[0]) > dx) return kFALSE;
00196    return kTRUE;
00197 }
00198 
00199 //_____________________________________________________________________________
00200 Double_t TGeoTrd2::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00201 {
00202 // Compute distance from inside point to surface of the trd2
00203 // Boundary safe algorithm
00204    Double_t snxt = TGeoShape::Big();
00205    if (iact<3 && safe) {
00206    // compute safe distance
00207       *safe = Safety(point, kTRUE);
00208       if (iact==0) return TGeoShape::Big();
00209       if (iact==1 && step<*safe) return TGeoShape::Big();
00210    }
00211 
00212    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00213    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00214    Double_t cn;
00215 
00216    Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
00217    Double_t disty = 0.5*(fDy1+fDy2)-fy*point[2];
00218 
00219    //--- Compute distance to this shape
00220    // first check if Z facettes are crossed
00221    Double_t dist[3];
00222    for (Int_t i=0; i<3; i++) dist[i]=TGeoShape::Big();
00223    if (dir[2]<0) {
00224       dist[0]=-(point[2]+fDz)/dir[2];
00225    } else if (dir[2]>0) {
00226       dist[0]=(fDz-point[2])/dir[2];
00227    }      
00228    if (dist[0]<=0) return 0.0;     
00229    // now check X facettes
00230    cn = -dir[0]+fx*dir[2];
00231    if (cn>0) {
00232       dist[1] = point[0]+distx;
00233       if (dist[1]<=0) return 0.0;
00234       dist[1] /= cn;
00235    }   
00236    cn = dir[0]+fx*dir[2];
00237    if (cn>0) {
00238       Double_t s = distx-point[0];
00239       if (s<=0) return 0.0;
00240       s /= cn;
00241       if (s<dist[1]) dist[1] = s;
00242    }
00243    // now check Y facettes
00244    cn = -dir[1]+fy*dir[2];
00245    if (cn>0) {
00246       dist[2] = point[1]+disty;
00247       if (dist[2]<=0) return 0.0;
00248       dist[2] /= cn;
00249    }
00250    cn = dir[1]+fy*dir[2];
00251    if (cn>0) {
00252       Double_t s = disty-point[1];
00253       if (s<=0) return 0.0;
00254       s /= cn;
00255       if (s<dist[2]) dist[2] = s;
00256    }
00257    snxt = dist[TMath::LocMin(3,dist)];
00258    return snxt;
00259 }
00260 
00261 //_____________________________________________________________________________
00262 Double_t TGeoTrd2::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00263 {
00264 // Compute distance from outside point to surface of the trd2
00265 // Boundary safe algorithm
00266    Double_t snxt = TGeoShape::Big();
00267    if (iact<3 && safe) {
00268    // compute safe distance
00269       *safe = Safety(point, kFALSE);
00270       if (iact==0) return TGeoShape::Big();
00271       if (iact==1 && step<*safe) return TGeoShape::Big();
00272    }
00273    // find a visible face
00274    Double_t xnew,ynew,znew;
00275    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00276    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00277    Double_t cn;
00278    // check visibility of X faces
00279    Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
00280    Double_t disty = 0.5*(fDy1+fDy2)-fy*point[2];
00281    Bool_t in = kTRUE;
00282    Double_t safx = distx-TMath::Abs(point[0]);
00283    Double_t safy = disty-TMath::Abs(point[1]);
00284    Double_t safz = fDz-TMath::Abs(point[2]);
00285    //--- Compute distance to this shape
00286    // first check if Z facettes are crossed
00287    if (point[2]<=-fDz) {
00288       cn = -dir[2];
00289       if (cn>=0) return TGeoShape::Big();
00290       in = kFALSE;
00291       snxt = (fDz+point[2])/cn;
00292       // find extrapolated X and Y
00293       xnew = point[0]+snxt*dir[0];
00294       if (TMath::Abs(xnew) < fDx1) {
00295          ynew = point[1]+snxt*dir[1];
00296          if (TMath::Abs(ynew) < fDy1) return snxt;
00297       }
00298    } else if (point[2]>=fDz) {
00299       cn = dir[2];
00300       if (cn>=0) return TGeoShape::Big();
00301       in = kFALSE;
00302       snxt = (fDz-point[2])/cn;
00303       // find extrapolated X and Y
00304       xnew = point[0]+snxt*dir[0];
00305       if (TMath::Abs(xnew) < fDx2) {
00306          ynew = point[1]+snxt*dir[1];
00307          if (TMath::Abs(ynew) < fDy2) return snxt;
00308       }
00309    }
00310    // check if X facettes are crossed
00311    if (point[0]<=-distx) {
00312       cn = -dir[0]+fx*dir[2];
00313       if (cn>=0) return TGeoShape::Big();
00314       in = kFALSE;
00315       snxt = (point[0]+distx)/cn;
00316       // find extrapolated Y and Z
00317       znew = point[2]+snxt*dir[2];
00318       if (TMath::Abs(znew) < fDz) {
00319          Double_t dy = 0.5*(fDy1+fDy2)-fy*znew;
00320          ynew = point[1]+snxt*dir[1];
00321          if (TMath::Abs(ynew) < dy) return snxt;
00322       }
00323    }            
00324    if (point[0]>=distx) {
00325       cn = dir[0]+fx*dir[2];
00326       if (cn>=0) return TGeoShape::Big();
00327       in = kFALSE;
00328       snxt = (distx-point[0])/cn;
00329       // find extrapolated Y and Z
00330       znew = point[2]+snxt*dir[2];
00331       if (TMath::Abs(znew) < fDz) {
00332          Double_t dy = 0.5*(fDy1+fDy2)-fy*znew;
00333          ynew = point[1]+snxt*dir[1];
00334          if (TMath::Abs(ynew) < dy) return snxt;
00335       }
00336    }
00337    // finally check Y facettes
00338    if (point[1]<=-disty) {
00339       cn = -dir[1]+fy*dir[2];
00340       in = kFALSE;
00341       if (cn>=0) return TGeoShape::Big();
00342       snxt = (point[1]+disty)/cn;
00343       // find extrapolated X and Z
00344       znew = point[2]+snxt*dir[2];
00345       if (TMath::Abs(znew) < fDz) {
00346          Double_t dx = 0.5*(fDx1+fDx2)-fx*znew;
00347          xnew = point[0]+snxt*dir[0];
00348          if (TMath::Abs(xnew) < dx) return snxt;
00349       }
00350    }            
00351    if (point[1]>=disty) {
00352       cn = dir[1]+fy*dir[2];
00353       if (cn>=0) return TGeoShape::Big();
00354       in = kFALSE;
00355       snxt = (disty-point[1])/cn;
00356       // find extrapolated X and Z
00357       znew = point[2]+snxt*dir[2];
00358       if (TMath::Abs(znew) < fDz) {
00359          Double_t dx = 0.5*(fDx1+fDx2)-fx*znew;
00360          xnew = point[0]+snxt*dir[0];
00361          if (TMath::Abs(xnew) < dx) return snxt;
00362       }
00363    }
00364    if (!in) return TGeoShape::Big();
00365    // Point actually inside
00366    if (safz<safx && safz<safy) {
00367       if (point[2]*dir[2]>=0) return TGeoShape::Big();
00368       return 0.0;
00369    }
00370    if (safy<safx) {
00371       cn = TMath::Sign(1.0,point[1])*dir[1]+fy*dir[2];     
00372       if (cn>=0) return TGeoShape::Big();
00373       return 0.0;
00374    }   
00375    cn = TMath::Sign(1.0,point[0])*dir[0]+fx*dir[2];     
00376    if (cn>=0) return TGeoShape::Big();
00377    return 0.0;      
00378 }
00379 
00380 //_____________________________________________________________________________
00381 Double_t TGeoTrd2::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00382 {
00383 // Get range of shape for a given axis.
00384    xlo = 0;
00385    xhi = 0;
00386    Double_t dx = 0;
00387    switch (iaxis) {
00388       case 3:
00389          xlo = -fDz;
00390          xhi = fDz;
00391          dx = xhi-xlo;
00392          return dx;
00393    }
00394    return dx;
00395 }         
00396             
00397 //_____________________________________________________________________________
00398 void TGeoTrd2::GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *normals) const
00399 {
00400 // get the most visible corner from outside point and the normals
00401    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00402    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00403    Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
00404    Double_t salf = calf*fx;
00405    Double_t cbet = 1./TMath::Sqrt(1.0+fy*fy);
00406    Double_t sbet = cbet*fy;
00407    // check visibility of X,Y faces
00408    Double_t distx = fDx1-fx*(fDz+point[2]);
00409    Double_t disty = fDy1-fy*(fDz+point[2]);
00410    memset(normals, 0, 9*sizeof(Double_t));
00411    TGeoTrd2 *trd2 = (TGeoTrd2*)this;
00412    if (point[0]>distx) {
00413    // hi x face visible
00414       trd2->SetShapeBit(kGeoVisX);
00415       normals[0]=calf;
00416       normals[2]=salf;
00417    } else {   
00418       trd2->SetShapeBit(kGeoVisX, kFALSE);
00419       normals[0]=-calf;
00420       normals[2]=salf;
00421    }
00422    if (point[1]>disty) {
00423    // hi y face visible
00424       trd2->SetShapeBit(kGeoVisY);
00425       normals[4]=cbet;
00426       normals[5]=sbet;
00427    } else {
00428       trd2->SetShapeBit(kGeoVisY, kFALSE);
00429       normals[4]=-cbet; 
00430       normals[5]=sbet; 
00431    }   
00432    if (point[2]>fDz) {
00433    // hi z face visible
00434       trd2->SetShapeBit(kGeoVisZ);
00435       normals[8]=1;
00436    } else {
00437       trd2->SetShapeBit(kGeoVisZ, kFALSE);
00438       normals[8]=-1;  
00439    }
00440    SetVertex(vertex);
00441 }
00442 
00443 //_____________________________________________________________________________
00444 void TGeoTrd2::GetOppositeCorner(Double_t * /*point*/, Int_t inorm, Double_t *vertex, Double_t *normals) const
00445 {
00446 // get the opposite corner of the intersected face
00447    TGeoTrd2 *trd2 = (TGeoTrd2*)this;
00448    if (inorm != 0) {
00449    // change x face
00450       trd2->SetShapeBit(kGeoVisX, !TestShapeBit(kGeoVisX));
00451       normals[0]=-normals[0];
00452    }
00453    if (inorm != 1) {
00454    // change y face
00455       trd2->SetShapeBit(kGeoVisY, !TestShapeBit(kGeoVisY));
00456       normals[4]=-normals[4];
00457    } 
00458    if (inorm != 2) {
00459    // hi z face visible
00460       trd2->SetShapeBit(kGeoVisZ, !TestShapeBit(kGeoVisZ));
00461       normals[8]=-normals[8];
00462    } 
00463    SetVertex(vertex);
00464 }
00465 
00466 //_____________________________________________________________________________
00467 TGeoVolume *TGeoTrd2::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
00468                              Double_t start, Double_t step) 
00469 {
00470 //--- Divide this trd2 shape belonging to volume "voldiv" into ndiv volumes
00471 // called divname, from start position with the given step. Only Z divisions
00472 // are supported. For Z divisions just return the pointer to the volume to be 
00473 // divided. In case a wrong division axis is supplied, returns pointer to 
00474 // volume that was divided.
00475    TGeoShape *shape;           //--- shape to be created
00476    TGeoVolume *vol;            //--- division volume to be created
00477    TGeoVolumeMulti *vmulti;    //--- generic divided volume
00478    TGeoPatternFinder *finder;  //--- finder to be attached 
00479    TString opt = "";           //--- option to be attached
00480    Double_t zmin, zmax, dx1n, dx2n, dy1n, dy2n;
00481    Int_t id;
00482    Double_t end = start+ndiv*step;
00483    switch (iaxis) {
00484       case 1:
00485          Warning("Divide", "dividing a Trd2 on X not implemented");
00486          return 0;
00487       case 2:
00488          Warning("Divide", "dividing a Trd2 on Y not implemented");
00489          return 0;
00490       case 3:
00491          finder = new TGeoPatternZ(voldiv, ndiv, start, end);
00492          vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00493          voldiv->SetFinder(finder);
00494          finder->SetDivIndex(voldiv->GetNdaughters());            
00495          for (id=0; id<ndiv; id++) {
00496             zmin = start+id*step;
00497             zmax = start+(id+1)*step;
00498             dx1n = 0.5*(fDx1*(fDz-zmin)+fDx2*(fDz+zmin))/fDz;
00499             dx2n = 0.5*(fDx1*(fDz-zmax)+fDx2*(fDz+zmax))/fDz;
00500             dy1n = 0.5*(fDy1*(fDz-zmin)+fDy2*(fDz+zmin))/fDz;
00501             dy2n = 0.5*(fDy1*(fDz-zmax)+fDy2*(fDz+zmax))/fDz;
00502             shape = new TGeoTrd2(dx1n, dx2n, dy1n, dy2n, step/2.);
00503             vol = new TGeoVolume(divname, shape, voldiv->GetMedium()); 
00504             vmulti->AddVolume(vol);
00505             opt = "Z";             
00506             voldiv->AddNodeOffset(vol, id, start+step/2+id*step, opt.Data());
00507             ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00508          }
00509          return vmulti;
00510       default:
00511          Error("Divide", "Wrong axis type for division");
00512          return 0;
00513    }
00514 }
00515 
00516 //_____________________________________________________________________________
00517 void TGeoTrd2::GetBoundingCylinder(Double_t *param) const
00518 {
00519 //--- Fill vector param[4] with the bounding cylinder parameters. The order
00520 // is the following : Rmin, Rmax, Phi1, Phi2
00521    TGeoBBox::GetBoundingCylinder(param);
00522 }   
00523 
00524 //_____________________________________________________________________________
00525 Int_t TGeoTrd2::GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const
00526 {
00527 // Fills real parameters of a positioned box inside this. Returns 0 if successfull.
00528    dx=dy=dz=0;
00529    if (mat->IsRotation()) {
00530       Error("GetFittingBox", "cannot handle parametrized rotated volumes");
00531       return 1; // ### rotation not accepted ###
00532    }
00533    //--> translate the origin of the parametrized box to the frame of this box.
00534    Double_t origin[3];
00535    mat->LocalToMaster(parambox->GetOrigin(), origin);
00536    if (!Contains(origin)) {
00537       Error("GetFittingBox", "wrong matrix - parametrized box is outside this");
00538       return 1; // ### wrong matrix ###
00539    }
00540    //--> now we have to get the valid range for all parametrized axis
00541    Double_t dd[3];
00542    dd[0] = parambox->GetDX();
00543    dd[1] = parambox->GetDY();
00544    dd[2] = parambox->GetDZ();
00545    //-> check if Z range is fixed
00546    if (dd[2]<0) {
00547       dd[2] = TMath::Min(origin[2]+fDz, fDz-origin[2]); 
00548       if (dd[2]<0) {
00549          Error("GetFittingBox", "wrong matrix");
00550          return 1;
00551       }
00552    }
00553    if (dd[0]>=0 && dd[1]>=0) {
00554       dx = dd[0];
00555       dy = dd[1];
00556       dz = dd[2];
00557       return 0;
00558    }
00559    //-> check now range at Z = origin[2] +/- dd[2]
00560    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00561    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00562    Double_t dx0 = 0.5*(fDx1+fDx2);
00563    Double_t dy0 = 0.5*(fDy1+fDy2);
00564    Double_t z=origin[2]-dd[2];
00565    dd[0] = dx0-fx*z-origin[0]; 
00566    dd[1] = dy0-fy*z-origin[1]; 
00567    z=origin[2]+dd[2];
00568    dd[0] = TMath::Min(dd[0], dx0-fx*z-origin[0]);
00569    dd[1] = TMath::Min(dd[1], dy0-fy*z-origin[1]);
00570    if (dd[0]<0 || dd[1]<0) {
00571       Error("GetFittingBox", "wrong matrix");
00572       return 1;
00573    }   
00574    dx = dd[0];
00575    dy = dd[1];
00576    dz = dd[2];
00577    return 0;
00578 }   
00579 
00580 //_____________________________________________________________________________
00581 TGeoShape *TGeoTrd2::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/) const
00582 {
00583 // in case shape has some negative parameters, these has to be computed
00584 // in order to fit the mother
00585    if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00586    if (!mother->TestShapeBit(kGeoTrd2)) {
00587       Error("GetMakeRuntimeShape", "invalid mother");
00588       return 0;
00589    }
00590    Double_t dx1, dx2, dy1, dy2, dz;
00591    if (fDx1<0) dx1=((TGeoTrd2*)mother)->GetDx1();
00592    else dx1=fDx1;
00593    if (fDx2<0) dx2=((TGeoTrd2*)mother)->GetDx2();
00594    else dx2=fDx2;
00595    if (fDy1<0) dy1=((TGeoTrd2*)mother)->GetDy1();
00596    else dy1=fDy1;
00597    if (fDy2<0) dy2=((TGeoTrd2*)mother)->GetDy2();
00598    else dy2=fDy2;
00599    if (fDz<0) dz=((TGeoTrd2*)mother)->GetDz();
00600    else dz=fDz;
00601 
00602    return (new TGeoTrd2(dx1, dx2, dy1, dy2, dz));
00603 }
00604 
00605 //_____________________________________________________________________________
00606 void TGeoTrd2::InspectShape() const
00607 {
00608 // print shape parameters
00609    printf("*** Shape %s: TGeoTrd2 ***\n", GetName());
00610    printf("    dx1 = %11.5f\n", fDx1);
00611    printf("    dx2 = %11.5f\n", fDx2);
00612    printf("    dy1 = %11.5f\n", fDy1);
00613    printf("    dy2 = %11.5f\n", fDy2);
00614    printf("    dz  = %11.5f\n", fDz);
00615    printf(" Bounding box:\n");
00616    TGeoBBox::InspectShape();
00617 }
00618 
00619 //_____________________________________________________________________________
00620 Double_t TGeoTrd2::Safety(Double_t *point, Bool_t in) const
00621 {
00622 // computes the closest distance from given point to this shape, according
00623 // to option. The matching point on the shape is stored in spoint.
00624    Double_t saf[3];
00625    //--- Compute safety first
00626    // check Z facettes
00627    saf[0] = fDz-TMath::Abs(point[2]);
00628    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
00629    Double_t calf = 1./TMath::Sqrt(1.0+fx*fx);
00630    // check X facettes
00631    Double_t distx = 0.5*(fDx1+fDx2)-fx*point[2];
00632    if (distx<0) saf[1]=TGeoShape::Big();
00633    else         saf[1]=(distx-TMath::Abs(point[0]))*calf;
00634 
00635    Double_t fy = 0.5*(fDy1-fDy2)/fDz;
00636    calf = 1./TMath::Sqrt(1.0+fy*fy);
00637    // check Y facettes
00638    distx = 0.5*(fDy1+fDy2)-fy*point[2];
00639    if (distx<0) saf[2]=TGeoShape::Big();
00640    else         saf[2]=(distx-TMath::Abs(point[1]))*calf;
00641    
00642    if (in) return saf[TMath::LocMin(3,saf)];
00643    for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00644    return saf[TMath::LocMax(3,saf)];
00645 }
00646 
00647 //_____________________________________________________________________________
00648 void TGeoTrd2::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
00649 {
00650 // Save a primitive as a C++ statement(s) on output stream "out".
00651    if (TObject::TestBit(kGeoSavePrimitive)) return;
00652    out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
00653    out << "   dx1 = " << fDx1 << ";" << endl;
00654    out << "   dx2 = " << fDx2 << ";" << endl;
00655    out << "   dy1 = " << fDy1 << ";" << endl;
00656    out << "   dy2 = " << fDy2 << ";" << endl;
00657    out << "   dz  = " << fDZ  << ";" << endl;
00658    out << "   TGeoShape *" << GetPointerName() << " = new TGeoTrd2(\"" << GetName() << "\", dx1,dx2,dy1,dy2,dz);" << endl;  
00659    TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00660 } 
00661         
00662 //_____________________________________________________________________________
00663 void TGeoTrd2::SetDimensions(Double_t *param)
00664 {
00665 // set arb8 params in one step :
00666    fDx1 = param[0];
00667    fDx2 = param[1];
00668    fDy1 = param[2];
00669    fDy2 = param[3];
00670    fDz  = param[4];
00671    ComputeBBox();
00672 }   
00673 
00674 //_____________________________________________________________________________
00675 void TGeoTrd2::SetPoints(Double_t *points) const
00676 {
00677 // create trd2 mesh points
00678    if (!points) return;
00679    points[ 0] = -fDx1; points[ 1] = -fDy1; points[ 2] = -fDz;
00680    points[ 3] = -fDx1; points[ 4] =  fDy1; points[ 5] = -fDz;
00681    points[ 6] =  fDx1; points[ 7] =  fDy1; points[ 8] = -fDz;
00682    points[ 9] =  fDx1; points[10] = -fDy1; points[11] = -fDz;
00683    points[12] = -fDx2; points[13] = -fDy2; points[14] =  fDz;
00684    points[15] = -fDx2; points[16] =  fDy2; points[17] =  fDz;
00685    points[18] =  fDx2; points[19] =  fDy2; points[20] =  fDz;
00686    points[21] =  fDx2; points[22] = -fDy2; points[23] =  fDz;
00687 }
00688 
00689 //_____________________________________________________________________________
00690 void TGeoTrd2::SetPoints(Float_t *points) const
00691 {
00692 // create trd2 mesh points
00693    if (!points) return;
00694    points[ 0] = -fDx1; points[ 1] = -fDy1; points[ 2] = -fDz;
00695    points[ 3] = -fDx1; points[ 4] =  fDy1; points[ 5] = -fDz;
00696    points[ 6] =  fDx1; points[ 7] =  fDy1; points[ 8] = -fDz;
00697    points[ 9] =  fDx1; points[10] = -fDy1; points[11] = -fDz;
00698    points[12] = -fDx2; points[13] = -fDy2; points[14] =  fDz;
00699    points[15] = -fDx2; points[16] =  fDy2; points[17] =  fDz;
00700    points[18] =  fDx2; points[19] =  fDy2; points[20] =  fDz;
00701    points[21] =  fDx2; points[22] = -fDy2; points[23] =  fDz;
00702 }
00703 
00704 //_____________________________________________________________________________
00705 void TGeoTrd2::SetVertex(Double_t *vertex) const
00706 {
00707 // set vertex of a corner according to visibility flags
00708    if (TestShapeBit(kGeoVisX)) {
00709       if (TestShapeBit(kGeoVisZ)) {
00710          vertex[0] = fDx2;
00711          vertex[2] = fDz;
00712          vertex[1] = (TestShapeBit(kGeoVisY))?fDy2:-fDy2;
00713       } else {   
00714          vertex[0] = fDx1;
00715          vertex[2] = -fDz;
00716          vertex[1] = (TestShapeBit(kGeoVisY))?fDy1:-fDy1;
00717       }
00718    } else {
00719       if (TestShapeBit(kGeoVisZ)) {
00720          vertex[0] = -fDx2;
00721          vertex[2] = fDz;
00722          vertex[1] = (TestShapeBit(kGeoVisY))?fDy2:-fDy2;
00723       } else {   
00724          vertex[0] = -fDx1;
00725          vertex[2] = -fDz;
00726          vertex[1] = (TestShapeBit(kGeoVisY))?fDy1:-fDy1;
00727       }
00728    }            
00729 } 
00730 
00731 //_____________________________________________________________________________
00732 void TGeoTrd2::Sizeof3D() const
00733 {
00734 // fill size of this 3-D object
00735    TGeoBBox::Sizeof3D();
00736 }
00737 

Generated on Tue Jul 5 14:12:58 2011 for ROOT_528-00b_version by  doxygen 1.5.1