TGeoShapeAssembly.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoShapeAssembly.cxx 36632 2010-11-12 15:57:07Z agheata $
00002 // Author: Andrei Gheata   02/06/05
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 #include "Riostream.h"
00014 
00015 #include "TGeoManager.h"
00016 #include "TGeoVoxelFinder.h"
00017 #include "TGeoMatrix.h"
00018 #include "TGeoVolume.h"
00019 #include "TGeoNode.h"
00020 #include "TGeoShapeAssembly.h"
00021 #include "TBuffer3D.h"
00022 #include "TBuffer3DTypes.h"
00023 #include "TMath.h"
00024 
00025 //_____________________________________________________________________________
00026 // TGeoShapeAssembly - The shape encapsulating an assembly (union) of volumes.
00027 //    
00028 //_____________________________________________________________________________
00029 
00030 
00031 ClassImp(TGeoShapeAssembly)
00032    
00033 //_____________________________________________________________________________
00034 TGeoShapeAssembly::TGeoShapeAssembly()
00035 {
00036 // Default constructor
00037    fCurrent = 0;
00038    fNext = 0;
00039    fVolume  = 0;
00040    fBBoxOK = kFALSE;
00041 }   
00042 
00043 
00044 //_____________________________________________________________________________
00045 TGeoShapeAssembly::TGeoShapeAssembly(TGeoVolumeAssembly *vol)
00046 {
00047 // Constructor specifying hyperboloid parameters.
00048    fVolume  = vol;
00049    fCurrent = 0;
00050    fNext = 0;
00051    fBBoxOK = kFALSE;
00052 }
00053 
00054 
00055 //_____________________________________________________________________________
00056 TGeoShapeAssembly::~TGeoShapeAssembly()
00057 {
00058 // destructor
00059 }
00060 
00061 //_____________________________________________________________________________   
00062 void TGeoShapeAssembly::ComputeBBox()
00063 {
00064 // Compute bounding box of the assembly
00065    if (!fVolume) {
00066       Fatal("ComputeBBox", "Assembly shape %s without volume", GetName());
00067       return;
00068    } 
00069    // Make sure bbox is computed only once or recomputed only if invalidated (by alignment)
00070    if (fBBoxOK) return;
00071    Int_t nd = fVolume->GetNdaughters();
00072    if (!nd) {fBBoxOK = kTRUE; return;}
00073    TGeoNode *node;
00074    TGeoBBox *box;
00075    Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00076    xmin = ymin = zmin = TGeoShape::Big();
00077    xmax = ymax = zmax = -TGeoShape::Big();
00078    Double_t vert[24];
00079    Double_t pt[3];
00080    for (Int_t i=0; i<nd; i++) {
00081       node = fVolume->GetNode(i);
00082       // Make sure that all assembly daughters have computed their bboxes
00083       if (node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
00084       box = (TGeoBBox*)node->GetVolume()->GetShape();
00085       box->SetBoxPoints(vert);
00086       for (Int_t ipt=0; ipt<8; ipt++) {
00087          node->LocalToMaster(&vert[3*ipt], pt);
00088          if (pt[0]<xmin) xmin=pt[0];
00089          if (pt[0]>xmax) xmax=pt[0];
00090          if (pt[1]<ymin) ymin=pt[1];
00091          if (pt[1]>ymax) ymax=pt[1];
00092          if (pt[2]<zmin) zmin=pt[2];
00093          if (pt[2]>zmax) zmax=pt[2];
00094       }
00095    }
00096    fDX = 0.5*(xmax-xmin);
00097    fOrigin[0] = 0.5*(xmin+xmax);
00098    fDY = 0.5*(ymax-ymin);
00099    fOrigin[1] = 0.5*(ymin+ymax);
00100    fDZ = 0.5*(zmax-zmin);
00101    fOrigin[2] = 0.5*(zmin+zmax);   
00102    fBBoxOK = kTRUE;      
00103 }   
00104 
00105 //_____________________________________________________________________________   
00106 void TGeoShapeAssembly::RecomputeBoxLast()
00107 {
00108 // Recompute bounding box of the assembly after adding a node.
00109    Int_t nd = fVolume->GetNdaughters();
00110    if (!nd) {
00111       Warning("RecomputeBoxLast", "No daughters for volume %s yet", fVolume->GetName());
00112       return;
00113    }   
00114    TGeoNode *node = fVolume->GetNode(nd-1);
00115    Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00116    if (nd==1) {
00117       xmin = ymin = zmin = TGeoShape::Big();
00118       xmax = ymax = zmax = -TGeoShape::Big();
00119    } else {
00120       xmin = fOrigin[0]-fDX;
00121       xmax = fOrigin[0]+fDX;
00122       ymin = fOrigin[1]-fDY;
00123       ymax = fOrigin[1]+fDY;
00124       zmin = fOrigin[2]-fDZ;
00125       zmax = fOrigin[2]+fDZ;
00126    }      
00127    Double_t vert[24];
00128    Double_t pt[3];
00129    TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
00130    if (TGeoShape::IsSameWithinTolerance(box->GetDX(), 0) ||
00131        node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
00132    box->SetBoxPoints(vert);
00133    for (Int_t ipt=0; ipt<8; ipt++) {
00134       node->LocalToMaster(&vert[3*ipt], pt);
00135       if (pt[0]<xmin) xmin=pt[0];
00136       if (pt[0]>xmax) xmax=pt[0];
00137       if (pt[1]<ymin) ymin=pt[1];
00138       if (pt[1]>ymax) ymax=pt[1];
00139       if (pt[2]<zmin) zmin=pt[2];
00140       if (pt[2]>zmax) zmax=pt[2];
00141    }
00142    fDX = 0.5*(xmax-xmin);
00143    fOrigin[0] = 0.5*(xmin+xmax);
00144    fDY = 0.5*(ymax-ymin);
00145    fOrigin[1] = 0.5*(ymin+ymax);
00146    fDZ = 0.5*(zmax-zmin);
00147    fOrigin[2] = 0.5*(zmin+zmax);   
00148    fBBoxOK = kTRUE;      
00149 }  
00150 
00151 //_____________________________________________________________________________   
00152 void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00153 {
00154 // Compute normal to closest surface from POINT. Should not be called.
00155    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00156    Int_t inext = fVolume->GetNextNodeIndex();
00157    if (inext<0) {
00158       DistFromOutside(point,dir,3);
00159       inext = fVolume->GetNextNodeIndex();
00160       if (inext<0) {
00161          Error("ComputeNormal","Invalid inext=%i (Ncomponents=%i)",inext,fVolume->GetNdaughters());
00162          return;
00163       }   
00164    }   
00165    TGeoNode *node = fVolume->GetNode(inext);
00166    Double_t local[3],ldir[3],lnorm[3];
00167    node->MasterToLocal(point,local);
00168    node->MasterToLocalVect(dir,ldir);
00169    node->GetVolume()->GetShape()->ComputeNormal(local,ldir,lnorm);
00170    node->LocalToMasterVect(lnorm,norm);
00171 }
00172 
00173 //_____________________________________________________________________________
00174 Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
00175 {
00176 // Test if point is inside the assembly
00177    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00178    if (!TGeoBBox::Contains(point)) return kFALSE;
00179    TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00180    TGeoNode *node;
00181    TGeoShape *shape;
00182    Int_t *check_list = 0;
00183    Int_t ncheck, id;
00184    Double_t local[3];
00185    if (voxels) {
00186       // get the list of nodes passing thorough the current voxel
00187       check_list = voxels->GetCheckList(&point[0], ncheck);
00188       if (!check_list) return kFALSE;
00189       for (id=0; id<ncheck; id++) {
00190          node = fVolume->GetNode(check_list[id]);
00191          shape = node->GetVolume()->GetShape();
00192          node->MasterToLocal(point,local);
00193          if (shape->Contains(local)) {
00194             fVolume->SetCurrentNodeIndex(check_list[id]);
00195             fVolume->SetNextNodeIndex(check_list[id]);
00196             return kTRUE;
00197          }   
00198       }
00199       return kFALSE;
00200    }      
00201    Int_t nd = fVolume->GetNdaughters();
00202    for (id=0; id<nd; id++) {
00203       node = fVolume->GetNode(id);
00204       shape = node->GetVolume()->GetShape();
00205       node->MasterToLocal(point,local);
00206       if (shape->Contains(local)) {
00207          fVolume->SetCurrentNodeIndex(id);
00208          fVolume->SetNextNodeIndex(id);      
00209          return kTRUE;
00210       }   
00211    }
00212    return kFALSE;   
00213 }
00214 
00215 //_____________________________________________________________________________
00216 Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
00217 {
00218 // compute closest distance from point px,py to each vertex. Should not be called.
00219    return 9999;
00220 }
00221 
00222 //_____________________________________________________________________________
00223 Double_t TGeoShapeAssembly::DistFromInside(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
00224 {
00225 // Compute distance from inside point to surface of the hyperboloid.
00226    Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)"); 
00227    return TGeoShape::Big();
00228 }
00229 
00230 
00231 //_____________________________________________________________________________
00232 Double_t TGeoShapeAssembly::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00233 {
00234 // compute distance from outside point to surface of the hyperboloid.
00235 //   fVolume->SetNextNodeIndex(-1);
00236    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00237    if (iact<3 && safe) {
00238       *safe = Safety(point, kFALSE);
00239       if (iact==0) return TGeoShape::Big();
00240       if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
00241    }
00242    // find distance to assembly
00243    Double_t snext = 0.0;
00244    Double_t dist;
00245    Double_t stepmax = step;
00246    Double_t pt[3];
00247    Int_t i;
00248    Bool_t found = kFALSE;
00249    memcpy(pt,point,3*sizeof(Double_t));
00250    if (!TGeoBBox::Contains(point)) {
00251       snext = TGeoBBox::DistFromOutside(point, dir, 3, stepmax);
00252       if (snext > stepmax) return TGeoShape::Big();
00253       for (i=0; i<3; i++) pt[i] += (snext+TGeoShape::Tolerance())*dir[i];
00254       if (Contains(pt)) {
00255          fVolume->SetNextNodeIndex(fVolume->GetCurrentNodeIndex());
00256          return snext;
00257       }   
00258       snext += TGeoShape::Tolerance();
00259       stepmax -= snext;
00260    }
00261    // Point represented by pt is now inside the bounding box - find distance to components   
00262    Int_t nd = fVolume->GetNdaughters();
00263    TGeoNode *node;
00264    Double_t lpoint[3],ldir[3];
00265    TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00266    if (nd<5 || !voxels) {
00267       for (i=0; i<nd; i++) {
00268          node = fVolume->GetNode(i);
00269          if (voxels && voxels->IsSafeVoxel(pt, i, stepmax)) continue;
00270          node->MasterToLocal(pt, lpoint);
00271          node->MasterToLocalVect(dir, ldir);
00272          dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
00273          if (dist<stepmax) {
00274             stepmax = dist;
00275             fVolume->SetNextNodeIndex(i);
00276             found = kTRUE;
00277          }
00278       }
00279       if (found) {
00280          snext += stepmax;
00281          return snext;
00282       }
00283       return TGeoShape::Big();   
00284    }
00285    // current volume is voxelized, first get current voxel
00286    Int_t ncheck = 0;
00287    Int_t *vlist = 0;
00288    voxels->SortCrossedVoxels(pt, dir);
00289    while ((vlist=voxels->GetNextVoxel(pt, dir, ncheck))) {
00290       for (i=0; i<ncheck; i++) {
00291          node = fVolume->GetNode(vlist[i]);
00292          node->MasterToLocal(pt, lpoint);
00293          node->MasterToLocalVect(dir, ldir);
00294          dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
00295          if (dist<stepmax) {
00296             stepmax = dist;
00297             fVolume->SetNextNodeIndex(vlist[i]);
00298             found = kTRUE;
00299          }
00300       }
00301    }
00302    if (found) {
00303       snext += stepmax;
00304       return snext;
00305    }
00306    return TGeoShape::Big();      
00307 }
00308    
00309 //_____________________________________________________________________________
00310 TGeoVolume *TGeoShapeAssembly::Divide(TGeoVolume * /*voldiv*/, const char *divname, Int_t /*iaxis*/, Int_t /*ndiv*/, 
00311                              Double_t /*start*/, Double_t /*step*/) 
00312 {
00313 // Cannot divide assemblies.
00314    Error("Divide", "Assemblies cannot be divided. Division volume %s not created", divname);
00315    return 0;
00316 }   
00317 
00318 //_____________________________________________________________________________
00319 TGeoShape *TGeoShapeAssembly::GetMakeRuntimeShape(TGeoShape * /*mother*/, TGeoMatrix * /*mat*/) const
00320 {
00321 // in case shape has some negative parameters, these has to be computed
00322 // in order to fit the mother
00323    Error("GetMakeRuntimeShape", "Assemblies cannot be parametrized.");
00324    return NULL;
00325 }
00326 
00327 //_____________________________________________________________________________
00328 void TGeoShapeAssembly::InspectShape() const
00329 {
00330 // print shape parameters
00331    printf("*** Shape %s: TGeoShapeAssembly ***\n", GetName());
00332    printf("    Volume assembly %s with %i nodes\n", fVolume->GetName(), fVolume->GetNdaughters());   
00333    printf(" Bounding box:\n");
00334    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00335    TGeoBBox::InspectShape();
00336 }
00337 
00338 //_____________________________________________________________________________
00339 void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & /*buff*/) const
00340 {
00341 // Fill TBuffer3D structure for segments and polygons.
00342    Error("SetSegsAndPols", "Drawing functions should not be called for assemblies, but rather for their content");   
00343 }
00344 
00345 //_____________________________________________________________________________
00346 Double_t TGeoShapeAssembly::Safety(Double_t *point, Bool_t in) const
00347 {
00348 // computes the closest distance from given point to this shape, according
00349 // to option. The matching point on the shape is stored in spoint.
00350    Double_t safety = TGeoShape::Big();
00351    Double_t pt[3], loc[3];
00352    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00353    if (in) {
00354       Int_t index = fVolume->GetCurrentNodeIndex();
00355       TGeoVolume *vol = fVolume;
00356       TGeoNode *node;
00357       memcpy(loc, point, 3*sizeof(Double_t));
00358       while (index>=0) {
00359          memcpy(pt, loc, 3*sizeof(Double_t));
00360          node = vol->GetNode(index);
00361          node->GetMatrix()->MasterToLocal(pt,loc);
00362          vol = node->GetVolume();
00363          index = vol->GetCurrentNodeIndex();
00364          if (index<0) {
00365             safety = vol->GetShape()->Safety(loc, in);
00366             return safety;
00367          }
00368       }
00369       return TGeoShape::Big();
00370    }         
00371    Double_t safe;
00372    TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00373    Int_t nd = fVolume->GetNdaughters();
00374    Double_t *boxes = 0;
00375    if (voxels) boxes = voxels->GetBoxes();   
00376    TGeoNode *node;
00377    for (Int_t id=0; id<nd; id++) {
00378       if (boxes && id>0) {
00379          Int_t ist = 6*id;
00380          Double_t dxyz = 0.;
00381          Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
00382          if (dxyz0 > safety) continue;
00383          Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
00384          if (dxyz1 > safety) continue;
00385          Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
00386          if (dxyz2 > safety) continue;
00387          if (dxyz0>0) dxyz+=dxyz0*dxyz0;
00388          if (dxyz1>0) dxyz+=dxyz1*dxyz1;
00389          if (dxyz2>0) dxyz+=dxyz2*dxyz2;
00390          if (dxyz >= safety*safety) continue;
00391       }
00392       node = fVolume->GetNode(id);
00393       safe = node->Safety(point, kFALSE);
00394       if (safe<=0.0) return 0.0;
00395       if (safe<safety) safety = safe;
00396    }   
00397    return safety;        
00398 }
00399 
00400 //_____________________________________________________________________________
00401 void TGeoShapeAssembly::SavePrimitive(ostream & /*out*/, Option_t * /*option*/ /*= ""*/)
00402 {
00403 // Save a primitive as a C++ statement(s) on output stream "out".
00404 }
00405 
00406 //_____________________________________________________________________________
00407 void TGeoShapeAssembly::SetPoints(Double_t * /*points*/) const
00408 {
00409 // No mesh for assemblies.
00410    Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
00411 }
00412 
00413 //_____________________________________________________________________________
00414 void TGeoShapeAssembly::SetPoints(Float_t * /*points*/) const
00415 {
00416 // No mesh for assemblies.
00417    Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
00418 }
00419 
00420 //_____________________________________________________________________________
00421 void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00422 {
00423 // Returns numbers of vertices, segments and polygons composing the shape mesh.
00424    nvert = 0;
00425    nsegs = 0;
00426    npols = 0;
00427 }
00428 

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