TGeoBBox.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoBBox.cxx 27731 2009-03-09 17:40:56Z brun $// Author: Andrei Gheata   24/10/01
00002 
00003 // Contains() and DistFromOutside/Out() 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 // TGeoBBox - box class. All shape primitives inherit from this, their 
00015 //   constructor filling automatically the parameters of the box that bounds
00016 //   the given shape. Defined by 6 parameters :
00017 //      fDX, fDY, fDZ - half lengths on X, Y and Z axis
00018 //      fOrigin[3]    - position of box origin
00019 //
00020 //--------------------------------------------------------------------------
00021 //
00022 //
00023 //--- Building boxes
00024 //  ==================
00025 //  Normally a box has to be build only with 3 parameters : dx, dy, dz
00026 // representing the half lengths on X, Y and Z axis. In this case, the origin 
00027 // of the box will match the one of its reference frame. The translation of the
00028 // origin is used only by the constructors of all other shapes in order to
00029 // define their own bounding boxes. Users should be aware that building a
00030 // translated box that will represent a physical shape by itself will affect any
00031 // further positioning of other shapes inside. Therefore in order to build a
00032 // positioned box one should follow the recipe described in class TGeoNode.
00033 //
00034 // Creation of boxes
00035 // 1.   TGeoBBox *box = new TGeoBBox("BOX", 20, 30, 40);
00036 //Begin_Html
00037 /*
00038 <img src="gif/t_box.gif">
00039 */
00040 //End_Html
00041 //
00042 // 2. A volume having a box shape can be built in one step:
00043 //      TGeoVolume *vbox = gGeoManager->MakeBox("vbox", ptrMed, 20,30,40);
00044 //
00045 // Divisions of boxes.
00046 //
00047 //   Volumes having box shape can be divided with equal-length slices on 
00048 // X, Y or Z axis. The following options are supported:
00049 // a) Dividing the full range of one axis in N slices
00050 //      TGeoVolume *divx = vbox->Divide("SLICEX", 1, N);
00051 //   - here 1 stands for the division axis (1-X, 2-Y, 3-Z)
00052 //Begin_Html
00053 /*
00054 <img src="gif/t_boxdivX.gif">
00055 */
00056 //End_Html
00057 //
00058 // b) Dividing in a limited range - general case.
00059 //      TGeoVolume *divy = vbox->Divide("SLICEY",2,N,start,step);
00060 //   - start = starting offset within (-fDY, fDY)
00061 //   - step  = slicing step
00062 //
00063 //Begin_Html
00064 /*
00065 <img src="gif/t_boxdivstepZ.gif">
00066 */
00067 //End_Html
00068 //
00069 // Both cases are supported by all shapes.
00070 //   See also class TGeoShape for utility methods provided by any particular 
00071 // shape.
00072 //_____________________________________________________________________________
00073 
00074 #include "Riostream.h"
00075 
00076 #include "TGeoManager.h"
00077 #include "TGeoMatrix.h"
00078 #include "TGeoVolume.h"
00079 #include "TVirtualGeoPainter.h"
00080 #include "TGeoBBox.h"
00081 #include "TVirtualPad.h"
00082 #include "TBuffer3D.h"
00083 #include "TBuffer3DTypes.h"
00084 #include "TMath.h"
00085 #include "TRandom.h"
00086 
00087 ClassImp(TGeoBBox)
00088    
00089 //_____________________________________________________________________________
00090 TGeoBBox::TGeoBBox()
00091 {
00092 // Default constructor
00093    SetShapeBit(TGeoShape::kGeoBox);
00094    fDX = fDY = fDZ = 0;
00095    fOrigin[0] = fOrigin[1] = fOrigin[2] = 0.0;
00096 }   
00097 
00098 //_____________________________________________________________________________
00099 TGeoBBox::TGeoBBox(Double_t dx, Double_t dy, Double_t dz, Double_t *origin)
00100          :TGeoShape("")
00101 {
00102 // Constructor where half-lengths are provided.
00103    SetShapeBit(TGeoShape::kGeoBox);
00104    fOrigin[0] = fOrigin[1] = fOrigin[2] = 0.0;
00105    SetBoxDimensions(dx, dy, dz, origin);
00106 }
00107 
00108 //_____________________________________________________________________________
00109 TGeoBBox::TGeoBBox(const char *name, Double_t dx, Double_t dy, Double_t dz, Double_t *origin)
00110          :TGeoShape(name)
00111 {
00112 // Constructor with shape name.
00113    SetShapeBit(TGeoShape::kGeoBox);
00114    fOrigin[0] = fOrigin[1] = fOrigin[2] = 0.0;
00115    SetBoxDimensions(dx, dy, dz, origin);
00116 }
00117 
00118 //_____________________________________________________________________________
00119 TGeoBBox::TGeoBBox(Double_t *param)
00120          :TGeoShape("")
00121 {
00122 // Constructor based on the array of parameters
00123 // param[0] - half-length in x
00124 // param[1] - half-length in y
00125 // param[2] - half-length in z
00126    SetShapeBit(TGeoShape::kGeoBox);
00127    fOrigin[0] = fOrigin[1] = fOrigin[2] = 0.0;
00128    SetDimensions(param);
00129 }   
00130 
00131 //_____________________________________________________________________________
00132 TGeoBBox::~TGeoBBox()
00133 {
00134 // Destructor
00135 }
00136 
00137 //_____________________________________________________________________________
00138 Bool_t TGeoBBox::AreOverlapping(const TGeoBBox *box1, const TGeoMatrix *mat1, const TGeoBBox *box2, const TGeoMatrix *mat2)
00139 {
00140 // Check if 2 positioned boxes overlap.
00141    Double_t master[3];
00142    Double_t local[3];
00143    Double_t ldir1[3], ldir2[3];
00144    const Double_t *o1 = box1->GetOrigin();
00145    const Double_t *o2 = box2->GetOrigin();
00146    // Convert center of first box to the local frame of second
00147    mat1->LocalToMaster(o1, master);
00148    mat2->MasterToLocal(master, local);
00149    if (TGeoBBox::Contains(local,box2->GetDX(),box2->GetDY(),box2->GetDZ(),o2)) return kTRUE;
00150    Double_t distsq = (local[0]-o2[0])*(local[0]-o2[0]) +
00151                      (local[1]-o2[1])*(local[1]-o2[1]) +
00152                      (local[2]-o2[2])*(local[2]-o2[2]);
00153    // Compute distance between box centers and compare with max value
00154    Double_t rmaxsq = (box1->GetDX()+box2->GetDX())*(box1->GetDX()+box2->GetDX()) +
00155                      (box1->GetDY()+box2->GetDY())*(box1->GetDY()+box2->GetDY()) +
00156                      (box1->GetDZ()+box2->GetDZ())*(box1->GetDZ()+box2->GetDZ());
00157    if (distsq > rmaxsq + TGeoShape::Tolerance()) return kFALSE;
00158    // We are still not sure: shoot a ray from the center of "1" towards the
00159    // center of 2.
00160    Double_t dir[3];
00161    mat1->LocalToMaster(o1, ldir1);
00162    mat2->LocalToMaster(o2, ldir2);
00163    distsq = 1./TMath::Sqrt(distsq);
00164    dir[0] = (ldir2[0]-ldir1[0])*distsq;
00165    dir[1] = (ldir2[1]-ldir1[1])*distsq;
00166    dir[2] = (ldir2[2]-ldir1[2])*distsq;
00167    mat1->MasterToLocalVect(dir, ldir1);
00168    mat2->MasterToLocalVect(dir, ldir2);
00169    // Distance to exit from o1
00170    Double_t dist1 = TGeoBBox::DistFromInside(o1,ldir1,box1->GetDX(),box1->GetDY(),box1->GetDZ(),o1);
00171    // Distance to enter from o2
00172    Double_t dist2 = TGeoBBox::DistFromOutside(local,ldir2,box2->GetDX(),box2->GetDY(),box2->GetDZ(),o2);
00173    if (dist1 > dist2) return kTRUE;
00174    return kFALSE;
00175 }
00176 
00177 //_____________________________________________________________________________
00178 Double_t TGeoBBox::Capacity() const
00179 {
00180 // Computes capacity of the shape in [length^3].
00181    return (8.*fDX*fDY*fDZ);
00182 }
00183 
00184 //_____________________________________________________________________________
00185 void TGeoBBox::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00186 {
00187 // Computes normal to closest surface from POINT. 
00188    memset(norm,0,3*sizeof(Double_t));
00189    Double_t saf[3];
00190    Int_t i;
00191    saf[0]=TMath::Abs(TMath::Abs(point[0]-fOrigin[0])-fDX);
00192    saf[1]=TMath::Abs(TMath::Abs(point[1]-fOrigin[1])-fDY);
00193    saf[2]=TMath::Abs(TMath::Abs(point[2]-fOrigin[2])-fDZ);
00194    i = TMath::LocMin(3,saf);
00195    norm[i] = (dir[i]>0)?1:(-1);
00196 }
00197 
00198 //_____________________________________________________________________________
00199 Bool_t TGeoBBox::CouldBeCrossed(Double_t *point, Double_t *dir) const
00200 {
00201 // Decides fast if the bounding box could be crossed by a vector.
00202    Double_t mind = fDX;
00203    if (fDY<mind) mind=fDY;
00204    if (fDZ<mind) mind=fDZ;
00205    Double_t dx = fOrigin[0]-point[0];
00206    Double_t dy = fOrigin[1]-point[1];
00207    Double_t dz = fOrigin[2]-point[2];
00208    Double_t do2 = dx*dx+dy*dy+dz*dz;
00209    if (do2<=(mind*mind)) return kTRUE;
00210    Double_t rmax2 = fDX*fDX+fDY*fDY+fDZ*fDZ;
00211    if (do2<=rmax2) return kTRUE;
00212    // inside bounding sphere
00213    Double_t doct = dx*dir[0]+dy*dir[1]+dz*dir[2];
00214    // leaving ray
00215    if (doct<=0) return kFALSE;
00216    Double_t dirnorm=dir[0]*dir[0]+dir[1]*dir[1]+dir[2]*dir[2];   
00217    if ((doct*doct)>=(do2-rmax2)*dirnorm) return kTRUE;
00218    return kFALSE;
00219 }
00220 
00221 //_____________________________________________________________________________
00222 Int_t TGeoBBox::DistancetoPrimitive(Int_t px, Int_t py)
00223 {
00224 // Compute closest distance from point px,py to each corner.
00225    const Int_t numPoints = 8;
00226    return ShapeDistancetoPrimitive(numPoints, px, py);
00227 }
00228 
00229 //_____________________________________________________________________________
00230 TGeoVolume *TGeoBBox::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
00231                              Double_t start, Double_t step) 
00232 {
00233 //--- Divide this box shape belonging to volume "voldiv" into ndiv equal volumes
00234 // called divname, from start position with the given step. Returns pointer
00235 // to created division cell volume. In case a wrong division axis is supplied,
00236 // returns pointer to volume to be divided.
00237    TGeoShape *shape;           //--- shape to be created
00238    TGeoVolume *vol;            //--- division volume to be created
00239    TGeoVolumeMulti *vmulti;    //--- generic divided volume
00240    TGeoPatternFinder *finder;  //--- finder to be attached
00241    TString opt = "";           //--- option to be attached
00242    Double_t end = start+ndiv*step;
00243    switch (iaxis) {
00244       case 1:                  //--- divide on X
00245          shape = new TGeoBBox(step/2., fDY, fDZ); 
00246          finder = new TGeoPatternX(voldiv, ndiv, start, end);
00247          opt = "X";
00248          break;
00249       case 2:                  //--- divide on Y
00250          shape = new TGeoBBox(fDX, step/2., fDZ); 
00251          finder = new TGeoPatternY(voldiv, ndiv, start, end);
00252          opt = "Y";
00253          break;
00254       case 3:                  //--- divide on Z
00255          shape = new TGeoBBox(fDX, fDY, step/2.); 
00256          finder = new TGeoPatternZ(voldiv, ndiv, start, end);
00257          opt = "Z";
00258          break;
00259       default:
00260          Error("Divide", "Wrong axis type for division");
00261          return 0;
00262    }
00263    vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00264    vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00265    vmulti->AddVolume(vol);
00266    voldiv->SetFinder(finder);
00267    finder->SetDivIndex(voldiv->GetNdaughters());
00268    for (Int_t ic=0; ic<ndiv; ic++) {
00269       voldiv->AddNodeOffset(vol, ic, start+step/2.+ic*step, opt.Data());
00270       ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00271    }
00272    return vmulti;
00273 }     
00274 
00275 //_____________________________________________________________________________
00276 void TGeoBBox::ComputeBBox()
00277 {
00278 // Compute bounding box - nothing to do in this case.
00279 }   
00280 
00281 //_____________________________________________________________________________
00282 Bool_t TGeoBBox::Contains(Double_t *point) const
00283 {
00284 // Test if point is inside this shape.
00285    if (TMath::Abs(point[2]-fOrigin[2]) > fDZ) return kFALSE;
00286    if (TMath::Abs(point[0]-fOrigin[0]) > fDX) return kFALSE;
00287    if (TMath::Abs(point[1]-fOrigin[1]) > fDY) return kFALSE;
00288    return kTRUE;
00289 }
00290 
00291 //_____________________________________________________________________________
00292 Bool_t TGeoBBox::Contains(const Double_t *point, Double_t dx, Double_t dy, Double_t dz, const Double_t *origin)
00293 {
00294 // Test if point is inside this shape.
00295    if (TMath::Abs(point[2]-origin[2]) > dz) return kFALSE;
00296    if (TMath::Abs(point[0]-origin[0]) > dx) return kFALSE;
00297    if (TMath::Abs(point[1]-origin[1]) > dy) return kFALSE;
00298    return kTRUE;
00299 }
00300 
00301 //_____________________________________________________________________________
00302 Double_t TGeoBBox::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00303 {
00304 // Compute distance from inside point to surface of the box.
00305 // Boundary safe algorithm.
00306    Double_t s,smin,saf[6];
00307    Double_t newpt[3];
00308    Int_t i;
00309    for (i=0; i<3; i++) newpt[i] = point[i] - fOrigin[i];
00310    saf[0] = fDX+newpt[0];
00311    saf[1] = fDX-newpt[0];
00312    saf[2] = fDY+newpt[1];
00313    saf[3] = fDY-newpt[1];
00314    saf[4] = fDZ+newpt[2];
00315    saf[5] = fDZ-newpt[2];
00316    if (iact<3 && safe) {
00317       smin = saf[0];
00318       // compute safe distance
00319       for (i=1;i<6;i++) if (saf[i] < smin) smin = saf[i];
00320       *safe = smin;
00321       if (smin<0) *safe = 0.0;
00322       if (iact==0) return TGeoShape::Big();
00323       if (iact==1 && step<*safe) return TGeoShape::Big();
00324    }
00325    // compute distance to surface
00326    smin=TGeoShape::Big();
00327    for (i=0; i<3; i++) {
00328       if (dir[i]!=0) {
00329          s = (dir[i]>0)?(saf[(i<<1)+1]/dir[i]):(-saf[i<<1]/dir[i]);
00330          if (s < 0) return 0.0;
00331          if (s < smin) smin = s;
00332       }
00333    }
00334    return smin;
00335 }
00336 
00337 //_____________________________________________________________________________
00338 Double_t TGeoBBox::DistFromInside(const Double_t *point,const Double_t *dir, 
00339                                   Double_t dx, Double_t dy, Double_t dz, const Double_t *origin, Double_t /*stepmax*/)
00340 {
00341 // Compute distance from inside point to surface of the box.
00342 // Boundary safe algorithm.
00343    Double_t s,smin,saf[6];
00344    Double_t newpt[3];
00345    Int_t i;
00346    for (i=0; i<3; i++) newpt[i] = point[i] - origin[i];
00347    saf[0] = dx+newpt[0];
00348    saf[1] = dx-newpt[0];
00349    saf[2] = dy+newpt[1];
00350    saf[3] = dy-newpt[1];
00351    saf[4] = dz+newpt[2];
00352    saf[5] = dz-newpt[2];
00353    // compute distance to surface
00354    smin=TGeoShape::Big();
00355    for (i=0; i<3; i++) {
00356       if (dir[i]!=0) {
00357          s = (dir[i]>0)?(saf[(i<<1)+1]/dir[i]):(-saf[i<<1]/dir[i]);
00358          if (s < 0) return 0.0;
00359          if (s < smin) smin = s;
00360       }
00361    }
00362    return smin;
00363 }
00364 
00365 //_____________________________________________________________________________
00366 Double_t TGeoBBox::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00367 {
00368 // Compute distance from outside point to surface of the box.
00369 // Boundary safe algorithm.
00370    Bool_t in = kTRUE;
00371    Double_t saf[3];
00372    Double_t par[3];
00373    Double_t newpt[3];
00374    Int_t i,j;
00375    for (i=0; i<3; i++) newpt[i] = point[i] - fOrigin[i];
00376    par[0] = fDX;
00377    par[1] = fDY;
00378    par[2] = fDZ;
00379    for (i=0; i<3; i++) {
00380       saf[i] = TMath::Abs(newpt[i])-par[i];
00381       if (saf[i]>=step) return TGeoShape::Big();
00382       if (in && saf[i]>0) in=kFALSE;
00383    }   
00384    if (iact<3 && safe) {
00385       // compute safe distance
00386       if (in) {
00387          *safe = 0.0;
00388       } else {   
00389          *safe = saf[0];
00390          if (saf[1] > *safe) *safe = saf[1];
00391          if (saf[2] > *safe) *safe = saf[2];
00392       }   
00393       if (iact==0) return TGeoShape::Big();
00394       if (iact==1 && step<*safe) return TGeoShape::Big();
00395    }
00396    // compute distance from point to box
00397    Double_t coord, snxt=TGeoShape::Big();
00398    Int_t ibreak=0;
00399    // protection in case point is actually inside box
00400    if (in) {
00401       j = 0;
00402       Double_t ss = saf[0];
00403       if (saf[1]>ss) {
00404          ss = saf[1];
00405          j = 1;
00406       }
00407       if (saf[2]>ss) j = 2;
00408       if (newpt[j]*dir[j]>0) return TGeoShape::Big(); // in fact exiting
00409       return 0.0;   
00410    }
00411    for (i=0; i<3; i++) {
00412       if (saf[i]<0) continue;
00413       if (newpt[i]*dir[i] >= 0) continue;
00414       snxt = saf[i]/TMath::Abs(dir[i]);
00415       ibreak = 0;
00416       for (j=0; j<3; j++) {
00417          if (j==i) continue;
00418          coord=newpt[j]+snxt*dir[j];
00419          if (TMath::Abs(coord)>par[j]) {
00420             ibreak=1;
00421             break;
00422          }
00423       }
00424       if (!ibreak) return snxt;
00425    }
00426    return TGeoShape::Big();
00427 }
00428 
00429 //_____________________________________________________________________________
00430 Double_t TGeoBBox::DistFromOutside(const Double_t *point,const Double_t *dir, 
00431                                    Double_t dx, Double_t dy, Double_t dz, const Double_t *origin, Double_t stepmax)
00432 {
00433 // Compute distance from outside point to surface of the box.
00434 // Boundary safe algorithm.
00435    Bool_t in = kTRUE;
00436    Double_t saf[3];
00437    Double_t par[3];
00438    Double_t newpt[3];
00439    Int_t i,j;
00440    for (i=0; i<3; i++) newpt[i] = point[i] - origin[i];
00441    par[0] = dx;
00442    par[1] = dy;
00443    par[2] = dz;
00444    for (i=0; i<3; i++) {
00445       saf[i] = TMath::Abs(newpt[i])-par[i];
00446       if (saf[i]>=stepmax) return TGeoShape::Big();
00447       if (in && saf[i]>0) in=kFALSE;
00448    }   
00449    // In case point is inside return ZERO
00450    if (in) return 0.0;
00451    Double_t coord, snxt=TGeoShape::Big();
00452    Int_t ibreak=0;
00453    for (i=0; i<3; i++) {
00454       if (saf[i]<0) continue;
00455       if (newpt[i]*dir[i] >= 0) continue;
00456       snxt = saf[i]/TMath::Abs(dir[i]);
00457       ibreak = 0;
00458       for (j=0; j<3; j++) {
00459          if (j==i) continue;
00460          coord=newpt[j]+snxt*dir[j];
00461          if (TMath::Abs(coord)>par[j]) {
00462             ibreak=1;
00463             break;
00464          }
00465       }
00466       if (!ibreak) return snxt;
00467    }
00468    return TGeoShape::Big();
00469 }
00470 
00471 //_____________________________________________________________________________
00472 const char *TGeoBBox::GetAxisName(Int_t iaxis) const
00473 {
00474 // Returns name of axis IAXIS.
00475    switch (iaxis) {
00476       case 1:
00477          return "X";
00478       case 2:
00479          return "Y";
00480       case 3:
00481          return "Z";
00482       default:
00483          return "UNDEFINED";
00484    }
00485 }   
00486 
00487 //_____________________________________________________________________________
00488 Double_t TGeoBBox::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00489 {
00490 // Get range of shape for a given axis.
00491    xlo = 0;
00492    xhi = 0;
00493    Double_t dx = 0;
00494    switch (iaxis) {
00495       case 1:
00496          xlo = fOrigin[0]-fDX;
00497          xhi = fOrigin[0]+fDX;
00498          dx = 2*fDX;
00499          return dx;
00500       case 2:
00501          xlo = fOrigin[1]-fDY;
00502          xhi = fOrigin[1]+fDY;
00503          dx = 2*fDY;
00504          return dx;
00505       case 3:
00506          xlo = fOrigin[2]-fDZ;
00507          xhi = fOrigin[2]+fDZ;
00508          dx = 2*fDZ;
00509          return dx;
00510    }
00511    return dx;
00512 }         
00513             
00514 //_____________________________________________________________________________
00515 void TGeoBBox::GetBoundingCylinder(Double_t *param) const
00516 {
00517 // Fill vector param[4] with the bounding cylinder parameters. The order
00518 // is the following : Rmin, Rmax, Phi1, Phi2
00519    param[0] = 0.;                  // Rmin
00520    param[1] = fDX*fDX+fDY*fDY;     // Rmax
00521    param[2] = 0.;                  // Phi1
00522    param[3] = 360.;                // Phi2
00523 }
00524 
00525 //_____________________________________________________________________________
00526 Double_t TGeoBBox::GetFacetArea(Int_t index) const
00527 {
00528 // Get area in internal units of the facet with a given index. 
00529 // Possible index values:
00530 //    0 - all facets togeather
00531 //    1 to 6 - facet index from bottom to top Z
00532    Double_t area = 0.;
00533    switch (index) {
00534       case 0:
00535          area = 8.*(fDX*fDY + fDX*fDZ + fDY*fDZ);
00536          return area;
00537       case 1:
00538       case 6:
00539          area = 4.*fDX*fDY;
00540          return area;
00541       case 2:
00542       case 4:
00543          area = 4.*fDX*fDZ;
00544          return area;
00545       case 3:
00546       case 5:
00547          area = 4.*fDY*fDZ;
00548          return area;
00549    }
00550    return area;
00551 }         
00552 
00553 //_____________________________________________________________________________
00554 Bool_t TGeoBBox::GetPointsOnFacet(Int_t index, Int_t npoints, Double_t *array) const
00555 {
00556 // Fills array with n random points located on the surface of indexed facet.
00557 // The output array must be provided with a length of minimum 3*npoints. Returns
00558 // true if operation succeeded.
00559 // Possible index values:
00560 //    0 - all facets togeather
00561 //    1 to 6 - facet index from bottom to top Z
00562    if (index<0 || index>6) return kFALSE;
00563    Double_t surf[6];
00564    Double_t area = 0.;
00565    if (index==0) {
00566       for (Int_t isurf=0; isurf<6; isurf++) {
00567          surf[isurf] = TGeoBBox::GetFacetArea(isurf+1);
00568          if (isurf>0) surf[isurf] += surf[isurf-1];
00569       }   
00570       area = surf[5];
00571    }
00572    
00573    for (Int_t i=0; i<npoints; i++) {
00574    // Generate randomly a surface index if needed.
00575       Double_t *point = &array[3*i];
00576       Int_t surfindex = index;
00577       if (surfindex==0) {
00578          Double_t val = area*gRandom->Rndm();
00579          surfindex = 2+TMath::BinarySearch(6, surf, val);
00580          if (surfindex>6) surfindex=6;
00581       } 
00582       switch (surfindex) {
00583          case 1:
00584             point[0] = -fDX + 2*fDX*gRandom->Rndm();
00585             point[1] = -fDY + 2*fDY*gRandom->Rndm();
00586             point[2] = -fDZ;
00587             break;
00588          case 2:
00589             point[0] = -fDX + 2*fDX*gRandom->Rndm();
00590             point[1] = -fDY;
00591             point[2] = -fDZ + 2*fDZ*gRandom->Rndm();
00592             break;
00593          case 3:
00594             point[0] = -fDX;
00595             point[1] = -fDY + 2*fDY*gRandom->Rndm();
00596             point[2] = -fDZ + 2*fDZ*gRandom->Rndm();
00597             break;
00598          case 4:
00599             point[0] = -fDX + 2*fDX*gRandom->Rndm();
00600             point[1] = fDY;
00601             point[2] = -fDZ + 2*fDZ*gRandom->Rndm();
00602             break;
00603          case 5:
00604             point[0] = fDX;
00605             point[1] = -fDY + 2*fDY*gRandom->Rndm();
00606             point[2] = -fDZ + 2*fDZ*gRandom->Rndm();
00607             break;
00608          case 6:
00609             point[0] = -fDX + 2*fDX*gRandom->Rndm();
00610             point[1] = -fDY + 2*fDY*gRandom->Rndm();
00611             point[2] = fDZ;
00612             break;
00613       }
00614    }
00615    return kTRUE;
00616 }      
00617 
00618 //_____________________________________________________________________________
00619 Bool_t TGeoBBox::GetPointsOnSegments(Int_t npoints, Double_t *array) const
00620 {
00621 // Fills array with n random points located on the line segments of the shape mesh.
00622 // The output array must be provided with a length of minimum 3*npoints. Returns
00623 // true if operation is implemented.
00624    if (npoints<GetNmeshVertices()) {
00625       Error("GetPointsOnSegments", "You should require at least %d points", GetNmeshVertices());
00626       return kFALSE;
00627    }
00628    TBuffer3D &buff = (TBuffer3D &)GetBuffer3D(TBuffer3D::kRawSizes | TBuffer3D::kRaw, kTRUE);
00629    Int_t npnts = buff.NbPnts();
00630    Int_t nsegs = buff.NbSegs();
00631    // Copy buffered points  in the array
00632    memcpy(array, buff.fPnts, 3*npnts*sizeof(Double_t));
00633    Int_t ipoints = npoints - npnts;
00634    Int_t icrt = 3*npnts;
00635    Int_t nperseg = (Int_t)(Double_t(ipoints)/nsegs);
00636    Double_t *p0, *p1;
00637    Double_t x,y,z, dx,dy,dz;
00638    for (Int_t i=0; i<nsegs; i++) {
00639       p0 = &array[3*buff.fSegs[3*i+1]];
00640       p1 = &array[3*buff.fSegs[3*i+2]];
00641       if (i==(nsegs-1)) nperseg = ipoints;
00642       dx = (p1[0]-p0[0])/(nperseg+1);
00643       dy = (p1[1]-p0[1])/(nperseg+1);
00644       dz = (p1[2]-p0[2])/(nperseg+1);
00645       for (Int_t j=0; j<nperseg; j++) {
00646          x = p0[0] + (j+1)*dx;
00647          y = p0[1] + (j+1)*dy;
00648          z = p0[2] + (j+1)*dz;
00649          array[icrt++] = x; array[icrt++] = y; array[icrt++] = z;
00650          ipoints--;
00651       }
00652    }
00653    return kTRUE;
00654 }      
00655             
00656 //_____________________________________________________________________________
00657 Int_t TGeoBBox::GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const
00658 {
00659 // Fills real parameters of a positioned box inside this one. Returns 0 if successfull.
00660    dx=dy=dz=0;
00661    if (mat->IsRotation()) {
00662       Error("GetFittingBox", "cannot handle parametrized rotated volumes");
00663       return 1; // ### rotation not accepted ###
00664    }
00665    //--> translate the origin of the parametrized box to the frame of this box.
00666    Double_t origin[3];
00667    mat->LocalToMaster(parambox->GetOrigin(), origin);
00668    if (!Contains(origin)) {
00669       Error("GetFittingBox", "wrong matrix - parametrized box is outside this");
00670       return 1; // ### wrong matrix ###
00671    }
00672    //--> now we have to get the valid range for all parametrized axis
00673    Double_t xlo=0, xhi=0;
00674    Double_t dd[3];
00675    dd[0] = parambox->GetDX();
00676    dd[1] = parambox->GetDY();
00677    dd[2] = parambox->GetDZ();
00678    for (Int_t iaxis=0; iaxis<3; iaxis++) {
00679       if (dd[iaxis]>=0) continue;
00680       TGeoBBox::GetAxisRange(iaxis+1, xlo, xhi);
00681       //-> compute best fitting parameter
00682       dd[iaxis] = TMath::Min(origin[iaxis]-xlo, xhi-origin[iaxis]); 
00683       if (dd[iaxis]<0) {
00684          Error("GetFittingBox", "wrong matrix");
00685          return 1;
00686       }   
00687    }
00688    dx = dd[0];
00689    dy = dd[1];
00690    dz = dd[2];
00691    return 0;
00692 }
00693 
00694 //_____________________________________________________________________________
00695 TGeoShape *TGeoBBox::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const
00696 {
00697 // In case shape has some negative parameters, these has to be computed
00698 // in order to fit the mother
00699    if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00700    Double_t dx, dy, dz;
00701    Int_t ierr = mother->GetFittingBox(this, mat, dx, dy, dz);
00702    if (ierr) {
00703       Error("GetMakeRuntimeShape", "cannot fit this to mother");
00704       return 0;
00705    }   
00706    return (new TGeoBBox(dx, dy, dz));
00707 }
00708 
00709 //_____________________________________________________________________________
00710 void TGeoBBox::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00711 {
00712 // Returns numbers of vertices, segments and polygons composing the shape mesh.
00713    nvert = 8;
00714    nsegs = 12;
00715    npols = 6;
00716 }
00717 
00718 //_____________________________________________________________________________
00719 void TGeoBBox::InspectShape() const
00720 {
00721 // Prints shape parameters
00722    printf("*** Shape %s: TGeoBBox ***\n", GetName());
00723    printf("    dX = %11.5f\n", fDX);
00724    printf("    dY = %11.5f\n", fDY);
00725    printf("    dZ = %11.5f\n", fDZ);
00726    printf("    origin: x=%11.5f y=%11.5f z=%11.5f\n", fOrigin[0], fOrigin[1], fOrigin[2]);
00727 }
00728 
00729 //_____________________________________________________________________________
00730 TBuffer3D *TGeoBBox::MakeBuffer3D() const
00731 {
00732 // Creates a TBuffer3D describing *this* shape.
00733 // Coordinates are in local reference frame.   
00734    TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric, 8, 24, 12, 36, 6, 36);
00735    if (buff)
00736    {
00737       SetPoints(buff->fPnts);
00738       SetSegsAndPols(*buff);
00739    }
00740 
00741    return buff;   
00742 }
00743 
00744 //_____________________________________________________________________________
00745 void TGeoBBox::SetSegsAndPols(TBuffer3D &buff) const
00746 {
00747 // Fills TBuffer3D structure for segments and polygons.
00748    Int_t c = GetBasicColor();
00749    
00750    buff.fSegs[ 0] = c   ; buff.fSegs[ 1] = 0   ; buff.fSegs[ 2] = 1   ;
00751    buff.fSegs[ 3] = c+1 ; buff.fSegs[ 4] = 1   ; buff.fSegs[ 5] = 2   ;
00752    buff.fSegs[ 6] = c+1 ; buff.fSegs[ 7] = 2   ; buff.fSegs[ 8] = 3   ;
00753    buff.fSegs[ 9] = c   ; buff.fSegs[10] = 3   ; buff.fSegs[11] = 0   ;
00754    buff.fSegs[12] = c+2 ; buff.fSegs[13] = 4   ; buff.fSegs[14] = 5   ;
00755    buff.fSegs[15] = c+2 ; buff.fSegs[16] = 5   ; buff.fSegs[17] = 6   ;
00756    buff.fSegs[18] = c+3 ; buff.fSegs[19] = 6   ; buff.fSegs[20] = 7   ;
00757    buff.fSegs[21] = c+3 ; buff.fSegs[22] = 7   ; buff.fSegs[23] = 4   ;
00758    buff.fSegs[24] = c   ; buff.fSegs[25] = 0   ; buff.fSegs[26] = 4   ;
00759    buff.fSegs[27] = c+2 ; buff.fSegs[28] = 1   ; buff.fSegs[29] = 5   ;
00760    buff.fSegs[30] = c+1 ; buff.fSegs[31] = 2   ; buff.fSegs[32] = 6   ;
00761    buff.fSegs[33] = c+3 ; buff.fSegs[34] = 3   ; buff.fSegs[35] = 7   ;
00762    
00763    buff.fPols[ 0] = c   ; buff.fPols[ 1] = 4   ;  buff.fPols[ 2] = 0  ;
00764    buff.fPols[ 3] = 9   ; buff.fPols[ 4] = 4   ;  buff.fPols[ 5] = 8  ;
00765    buff.fPols[ 6] = c+1 ; buff.fPols[ 7] = 4   ;  buff.fPols[ 8] = 1  ;
00766    buff.fPols[ 9] = 10  ; buff.fPols[10] = 5   ;  buff.fPols[11] = 9  ;
00767    buff.fPols[12] = c   ; buff.fPols[13] = 4   ;  buff.fPols[14] = 2  ;
00768    buff.fPols[15] = 11  ; buff.fPols[16] = 6   ;  buff.fPols[17] = 10 ;
00769    buff.fPols[18] = c+1 ; buff.fPols[19] = 4   ;  buff.fPols[20] = 3  ;
00770    buff.fPols[21] = 8   ; buff.fPols[22] = 7   ;  buff.fPols[23] = 11 ;
00771    buff.fPols[24] = c+2 ; buff.fPols[25] = 4   ;  buff.fPols[26] = 0  ;
00772    buff.fPols[27] = 3   ; buff.fPols[28] = 2   ;  buff.fPols[29] = 1  ;
00773    buff.fPols[30] = c+3 ; buff.fPols[31] = 4   ;  buff.fPols[32] = 4  ;
00774    buff.fPols[33] = 5   ; buff.fPols[34] = 6   ;  buff.fPols[35] = 7  ;
00775 }
00776 
00777 //_____________________________________________________________________________
00778 Double_t TGeoBBox::Safety(Double_t *point, Bool_t in) const
00779 {
00780 // Computes the closest distance from given point to this shape.
00781 
00782    Double_t safe, safy, safz;
00783    if (in) {
00784       safe = fDX - TMath::Abs(point[0]-fOrigin[0]);
00785       safy = fDY - TMath::Abs(point[1]-fOrigin[1]);
00786       safz = fDZ - TMath::Abs(point[2]-fOrigin[2]);
00787       if (safy < safe) safe = safy;
00788       if (safz < safe) safe = safz;
00789    } else {
00790       safe = -fDX + TMath::Abs(point[0]-fOrigin[0]);
00791       safy = -fDY + TMath::Abs(point[1]-fOrigin[1]);
00792       safz = -fDZ + TMath::Abs(point[2]-fOrigin[2]);
00793       if (safy > safe) safe = safy;
00794       if (safz > safe) safe = safz;
00795    }
00796    return safe;
00797 }
00798 
00799 //_____________________________________________________________________________
00800 void TGeoBBox::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
00801 {
00802 // Save a primitive as a C++ statement(s) on output stream "out".
00803    if (TObject::TestBit(kGeoSavePrimitive)) return;
00804    out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
00805    out << "   dx = " << fDX << ";" << endl;
00806    out << "   dy = " << fDY << ";" << endl;
00807    out << "   dz = " << fDZ << ";" << endl;
00808    if (!TGeoShape::IsSameWithinTolerance(fOrigin[0],0) || 
00809        !TGeoShape::IsSameWithinTolerance(fOrigin[1],0) || 
00810        !TGeoShape::IsSameWithinTolerance(fOrigin[2],0)) { 
00811       out << "   origin[0] = " << fOrigin[0] << ";" << endl;
00812       out << "   origin[1] = " << fOrigin[1] << ";" << endl;
00813       out << "   origin[2] = " << fOrigin[2] << ";" << endl;
00814       out << "   TGeoShape *" << GetPointerName() << " = new TGeoBBox(\"" << GetName() << "\", dx,dy,dz,origin);" << endl;
00815    } else {   
00816       out << "   TGeoShape *" << GetPointerName() << " = new TGeoBBox(\"" << GetName() << "\", dx,dy,dz);" << endl;
00817    }
00818    TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00819 }         
00820 
00821 //_____________________________________________________________________________
00822 void TGeoBBox::SetBoxDimensions(Double_t dx, Double_t dy, Double_t dz, Double_t *origin)
00823 {
00824 // Set parameters of the box.
00825    fDX = dx;
00826    fDY = dy;
00827    fDZ = dz;
00828    if (origin) {
00829       fOrigin[0] = origin[0];
00830       fOrigin[1] = origin[1];
00831       fOrigin[2] = origin[2];
00832    }   
00833    if (TMath::Abs(fDX)<TGeoShape::Tolerance() && 
00834        TMath::Abs(fDY)<TGeoShape::Tolerance() &&
00835        TMath::Abs(fDZ)<TGeoShape::Tolerance()) return;
00836    if ((fDX<0) || (fDY<0) || (fDZ<0)) SetShapeBit(kGeoRunTimeShape);
00837 }        
00838 
00839 //_____________________________________________________________________________
00840 void TGeoBBox::SetDimensions(Double_t *param)
00841 {
00842 // Set dimensions based on the array of parameters
00843 // param[0] - half-length in x
00844 // param[1] - half-length in y
00845 // param[2] - half-length in z
00846    if (!param) {
00847       Error("SetDimensions", "null parameters");
00848       return;
00849    }
00850    fDX = param[0];
00851    fDY = param[1];
00852    fDZ = param[2];
00853    if (TMath::Abs(fDX)<TGeoShape::Tolerance() && 
00854        TMath::Abs(fDY)<TGeoShape::Tolerance() &&
00855        TMath::Abs(fDZ)<TGeoShape::Tolerance()) return;
00856    if ((fDX<0) || (fDY<0) || (fDZ<0)) SetShapeBit(kGeoRunTimeShape);
00857 }   
00858 
00859 //_____________________________________________________________________________
00860 void TGeoBBox::SetBoxPoints(Double_t *points) const
00861 {
00862 // Fill box vertices to an array.
00863    TGeoBBox::SetPoints(points);
00864 }
00865 
00866 //_____________________________________________________________________________
00867 void TGeoBBox::SetPoints(Double_t *points) const
00868 {
00869 // Fill box points.
00870    if (!points) return;
00871    Double_t xmin,xmax,ymin,ymax,zmin,zmax;
00872    xmin = -fDX+fOrigin[0];
00873    xmax =  fDX+fOrigin[0];
00874    ymin = -fDY+fOrigin[1];
00875    ymax =  fDY+fOrigin[1];
00876    zmin = -fDZ+fOrigin[2];
00877    zmax =  fDZ+fOrigin[2];
00878    points[ 0] = xmin; points[ 1] = ymin; points[ 2] = zmin;
00879    points[ 3] = xmin; points[ 4] = ymax; points[ 5] = zmin;
00880    points[ 6] = xmax; points[ 7] = ymax; points[ 8] = zmin;
00881    points[ 9] = xmax; points[10] = ymin; points[11] = zmin;
00882    points[12] = xmin; points[13] = ymin; points[14] = zmax;
00883    points[15] = xmin; points[16] = ymax; points[17] = zmax;
00884    points[18] = xmax; points[19] = ymax; points[20] = zmax;
00885    points[21] = xmax; points[22] = ymin; points[23] = zmax;
00886 }
00887 
00888 //_____________________________________________________________________________
00889 void TGeoBBox::SetPoints(Float_t *points) const
00890 {
00891 // Fill box points.
00892    if (!points) return;
00893    Double_t xmin,xmax,ymin,ymax,zmin,zmax;
00894    xmin = -fDX+fOrigin[0];
00895    xmax =  fDX+fOrigin[0];
00896    ymin = -fDY+fOrigin[1];
00897    ymax =  fDY+fOrigin[1];
00898    zmin = -fDZ+fOrigin[2];
00899    zmax =  fDZ+fOrigin[2];
00900    points[ 0] = xmin; points[ 1] = ymin; points[ 2] = zmin;
00901    points[ 3] = xmin; points[ 4] = ymax; points[ 5] = zmin;
00902    points[ 6] = xmax; points[ 7] = ymax; points[ 8] = zmin;
00903    points[ 9] = xmax; points[10] = ymin; points[11] = zmin;
00904    points[12] = xmin; points[13] = ymin; points[14] = zmax;
00905    points[15] = xmin; points[16] = ymax; points[17] = zmax;
00906    points[18] = xmax; points[19] = ymax; points[20] = zmax;
00907    points[21] = xmax; points[22] = ymin; points[23] = zmax;
00908 }
00909 
00910 //_____________________________________________________________________________
00911 void TGeoBBox::Sizeof3D() const
00912 {
00913 ///// fill size of this 3-D object
00914 ///    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
00915 ///    if (painter) painter->AddSize3D(8, 12, 6);
00916 }
00917 
00918 //_____________________________________________________________________________
00919 const TBuffer3D & TGeoBBox::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
00920 {
00921 // Fills a static 3D buffer and returns a reference.
00922    static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
00923 
00924    FillBuffer3D(buffer, reqSections, localFrame);
00925 
00926    // TODO: A box itself has has nothing more as already described
00927    // by bounding box. How will viewer interpret?
00928    if (reqSections & TBuffer3D::kRawSizes) {
00929       if (buffer.SetRawSizes(8, 3*8, 12, 3*12, 6, 6*6)) {
00930          buffer.SetSectionsValid(TBuffer3D::kRawSizes);
00931       }
00932    }
00933    if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
00934       SetPoints(buffer.fPnts);
00935       if (!buffer.fLocalFrame) {
00936          TransformPoints(buffer.fPnts, buffer.NbPnts());
00937       }
00938 
00939       SetSegsAndPols(buffer);
00940       buffer.SetSectionsValid(TBuffer3D::kRaw);
00941    }
00942       
00943    return buffer;
00944 }
00945 
00946 //_____________________________________________________________________________
00947 void TGeoBBox::FillBuffer3D(TBuffer3D & buffer, Int_t reqSections, Bool_t localFrame) const
00948 {
00949 // Fills the supplied buffer, with sections in desired frame
00950 // See TBuffer3D.h for explanation of sections, frame etc.
00951    TGeoShape::FillBuffer3D(buffer, reqSections, localFrame);
00952 
00953    if (reqSections & TBuffer3D::kBoundingBox) {
00954       Double_t halfLengths[3] = { fDX, fDY, fDZ };
00955       buffer.SetAABoundingBox(fOrigin, halfLengths);
00956 
00957       if (!buffer.fLocalFrame) {
00958          TransformPoints(buffer.fBBVertex[0], 8);
00959       }
00960       buffer.SetSectionsValid(TBuffer3D::kBoundingBox);
00961    }
00962 }

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