G4BoundingBox3D.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // ----------------------------------------------------------------------
00030 // GEANT 4 class source file
00031 //
00032 // G4BoundingBox3D.cc
00033 //
00034 // ----------------------------------------------------------------------
00035 
00036 #include "G4BoundingBox3D.hh"
00037 #include "geomdefs.hh"
00038 #include "G4GeometryTolerance.hh"
00039 
00040 const G4BoundingBox3D G4BoundingBox3D::
00041           space( G4Point3D(-kInfinity, -kInfinity, -kInfinity),
00042                  G4Point3D(+kInfinity, +kInfinity, +kInfinity)  );
00043 
00045 
00046 G4BoundingBox3D::G4BoundingBox3D()
00047 {
00048   distance = 0;
00049   test_result = 0;
00050   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00051 }
00052 
00053 G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p1, const G4Point3D& p2) 
00054 {
00055   Init(p1, p2);
00056 }
00057 
00058 G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p) 
00059 {
00060   Init(p);
00061 }
00062 
00063 G4BoundingBox3D::~G4BoundingBox3D()
00064 {
00065 }
00066 
00067 G4BoundingBox3D::G4BoundingBox3D(const G4BoundingBox3D& right)
00068   : box_min(right.box_min), box_max(right.box_max),
00069     distance(right.distance), test_result(right.test_result),
00070     MiddlePoint(right.MiddlePoint), GeantBox(right.GeantBox),
00071     kCarTolerance(right.kCarTolerance)
00072 {
00073 }
00074 
00075 G4BoundingBox3D& G4BoundingBox3D::operator=(const G4BoundingBox3D& right)
00076 {
00077   if (&right == this) return *this;
00078   box_min  = right.box_min;
00079   box_max  = right.box_max;
00080   distance = right.distance;
00081   test_result = right.test_result;
00082   MiddlePoint = right.MiddlePoint;
00083   GeantBox = right.GeantBox;
00084   kCarTolerance = right.kCarTolerance;
00085   
00086   return *this;
00087 }
00088 
00089 void G4BoundingBox3D::Init(const G4Point3D& p1, const G4Point3D& p2) 
00090 {
00091   // L. Broglia
00092   // Maybe temporary
00093   // Create a BBox bigger than the reality
00094 
00095   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00096 
00097   box_min.setX( std::min(p1.x(), p2.x()) - kCarTolerance );
00098   box_min.setY( std::min(p1.y(), p2.y()) - kCarTolerance );
00099   box_min.setZ( std::min(p1.z(), p2.z()) - kCarTolerance );
00100   box_max.setX( std::max(p1.x(), p2.x()) + kCarTolerance );
00101   box_max.setY( std::max(p1.y(), p2.y()) + kCarTolerance );
00102   box_max.setZ( std::max(p1.z(), p2.z()) + kCarTolerance );
00103   
00104   // Calc half spaces
00105   GeantBox = (box_max - box_min)*0.5;
00106   MiddlePoint = (box_min + box_max)*0.5;
00107 
00108   test_result = 0;
00109   distance = 0;
00110 }
00111 
00112 
00113 void G4BoundingBox3D::Init(const G4Point3D& p) 
00114 {
00115   box_min= box_max= MiddlePoint= p;
00116   GeantBox= G4Point3D(0, 0, 0);
00117   test_result = 0;
00118   distance= 0;
00119   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00120 }
00121 
00122 
00124 
00125 void G4BoundingBox3D::Extend(const G4Point3D& p) 
00126 {
00127   
00128   // L. Broglia
00129   // Maybe temporary
00130   // Create a BBox bigger than the reality
00131 
00132   if (p.x() < box_min.x()) 
00133     box_min.setX( p.x() - kCarTolerance );
00134   else if (p.x() > box_max.x())
00135     box_max.setX( p.x() + kCarTolerance );
00136  
00137   if (p.y() < box_min.y()) 
00138     box_min.setY( p.y() - kCarTolerance );
00139   else if (p.y() > box_max.y()) 
00140     box_max.setY( p.y() + kCarTolerance );
00141 
00142   if (p.z() < box_min.z())
00143     box_min.setZ( p.z() - kCarTolerance );
00144   else if (p.z() > box_max.z())
00145     box_max.setZ( p.z() + kCarTolerance );
00146 
00147   // L. Broglia
00148   // Now re-calculate GeantBox and MiddlePoint
00149   GeantBox    = (box_max - box_min)*0.5;
00150   MiddlePoint = (box_min + box_max)*0.5;
00151   
00152 }
00153 
00155 
00156 
00157 G4int G4BoundingBox3D::Test(const G4Ray& rayref)
00158 {
00159   const G4Point3D&  tmp_ray_start = rayref.GetStart();
00160   const G4Vector3D& tmp_ray_dir   = rayref.GetDir();
00161 
00162   G4Point3D  ray_start = tmp_ray_start ;
00163   G4Vector3D ray_dir   = tmp_ray_dir   ;
00164 
00165   G4double rayx,rayy,rayz;
00166   rayx = ray_start.x();
00167   rayy = ray_start.y();
00168   rayz = ray_start.z();
00169 
00170   // Test if ray starting point is in the bbox or not
00171   if((rayx < box_min.x()) || (rayx > box_max.x()) ||
00172      (rayy < box_min.y()) || (rayy > box_max.y()) ||            
00173      (rayz < box_min.z()) || (rayz > box_max.z())   )
00174   {
00175     // Outside, check for intersection with bbox
00176     
00177     // Adapt ray_starting point to box
00178 
00179     const G4Point3D ray_start2 = G4Point3D( ray_start - MiddlePoint );
00180     distance = DistanceToIn(ray_start2, ray_dir);
00181 
00182     if(!distance)
00183       test_result = 0; // Miss
00184     else
00185       test_result = 1; // Starting point outside box & hits box
00186   }
00187   else
00188   {
00189     // Inside
00190     // G4cout << "\nRay starting point Inside bbox.";
00191     test_result = 1;
00192     distance = 0;
00193   }
00194 
00195   return test_result;
00196 }
00197 
00199 
00200 
00201 // Does an intersection exist?
00202 //
00203 // ALGORITHM:
00204 //
00205 // Check that if point lies outside x/y/z extent of box, travel is towards
00206 // the box (ie. there is a possiblity of an intersection)
00207 
00208 
00209 G4int G4BoundingBox3D::BoxIntersect(const G4Point3D&      , 
00210                                     const G4Point3D&  p   , 
00211                                     const G4Vector3D& v    ) const
00212 {
00213   G4double safx, safy, safz;
00214   G4double  fdx,  fdy,  fdz;
00215   
00216   fdx = GeantBox.x();    
00217   fdy = GeantBox.y();    
00218   fdz = GeantBox.z();
00219 
00220   safx=std::fabs(p.x())-fdx;   // minimum distance to x surface of shape
00221   safy=std::fabs(p.y())-fdy;
00222   safz=std::fabs(p.z())-fdz;
00223   
00224   // Will we Intersect?
00225   // If safx/y/z is >=0 the point is outside/on the box's x/y/z extent.
00226   // If both p.X()/y/z and v.X()/y/z repectively are both positive/negative,
00227   // travel is in a G4ThreeVec away from the shape.
00228 
00229   if ( ( (p.x()*v.x()>=0.0 ) && safx>0.0 ) || 
00230        ( (p.y()*v.y()>=0.0 ) && safy>0.0 ) ||
00231        ( (p.z()*v.z()>=0.0 ) && safz>0.0 )    )
00232     return 0; // No intersection        
00233   else
00234     return 1; // Possible intersection
00235 }
00236 
00238 
00239 
00240 // Distance to in
00241 // Calculate distance to box from outside - return kBig if no intersection
00242 //
00243 // ALGORITHM:
00244 //
00245 // Check that if point lies outside x/y/z extent of box, travel is towards
00246 // the box (ie. there is a possiblity of an intersection)
00247 //
00248 // Calculate pairs of minimum and maximum distances for x/y/z travel for
00249 // intersection with the box's x/y/z extent.
00250 // If there is a valid intersection, it is given by the maximum min distance
00251 // (ie. distance to satisfy x/y/z intersections) *if* <= minimum max distance
00252 // (ie. distance after which 1+ of x/y/z intersections not satisfied)
00253 //
00254 // NOTE:
00255 //
00256 // `Inside' safe - meaningful answers given if point is Inside the exact
00257 // shape.
00258 
00259 //G4double G4BoundingBox::distance_to_in(const G4Point3d& gbox, const G4Point3d& p, const G4ThreeVec& v) const
00260 G4double G4BoundingBox3D::DistanceToIn(const G4Point3D& p, 
00261                                        const G4Vector3D& v) const
00262 {
00263     G4double safx,  safy,  safz,  snxt = 0;  // snxt = default return value
00264     G4double smin, sminx, sminy, sminz;
00265     G4double smax, smaxx, smaxy, smaxz;
00266     G4double stmp;
00267     G4double kBig = 10e20;
00268     G4double fdx,fdy,fdz;
00269     
00270     fdx = GeantBox.x();        
00271     fdy = GeantBox.y();        
00272     fdz = GeantBox.z();    
00273 
00274     safx = std::fabs(p.x())-fdx;   // minimum distance to x surface of shape
00275     safy = std::fabs(p.y())-fdy;
00276     safz = std::fabs(p.z())-fdz;
00277 
00278     // Will we Intersect?
00279     // If safx/y/z is >=0 the point is outside/on the box's x/y/z extent.
00280     // If both p.X()/y/z and v.X()/y/z repectively are both positive/negative,
00281     // travel is in a G4ThreeVec away from the shape.
00282 
00283     if ( ( ( p.x()*v.x()>=0.0 ) && safx>0.0) || 
00284          ( ( p.y()*v.y()>=0.0 ) && safy>0.0) || 
00285          ( ( p.z()*v.z()>=0.0 ) && safz>0.0)    )
00286       return snxt;      
00287     
00288     // Compute min / max distance for x/y/z travel:
00289     if (safx<0.0)
00290     {
00291       // Inside x extent => Calc distance until trajectory leaves extent
00292       sminx=0.0;
00293       if (v.x()) 
00294         smaxx = fdx/std::fabs(v.x()) - p.x()/v.x();
00295       else
00296         smaxx = kBig;
00297     }
00298     else
00299     {
00300       // Outside extent or on boundary
00301       if (v.x()==0)
00302         return snxt; // Travel parallel
00303       else
00304       {
00305         stmp  = std::fabs(v.x());
00306         sminx = safx/stmp;
00307         smaxx = (fdx+std::fabs(p.x()))/stmp;
00308       }
00309     }
00310     
00311     if (safy<0.0)
00312     {
00313       // Inside y extent => Calc distance until trajectory leaves extent
00314       sminy=0.0;
00315       if (v.y()) 
00316         smaxy = fdy/std::fabs(v.y()) - p.y()/v.y();
00317       else
00318         smaxy = kBig;
00319     }
00320     else
00321     {
00322       // Outside extent or on boundary
00323       if (v.y()==0)
00324         return snxt; // Travel parallel
00325       else
00326       {
00327         stmp  = std::fabs(v.y());
00328         sminy = safy/stmp;
00329         smaxy = (fdy+std::fabs(p.y()))/stmp;
00330       }
00331     }
00332     
00333     if (safz<0.0)
00334     {
00335       // Inside z extent => Calc distance until trajectory leaves extent
00336       sminz=0.0;
00337       if (v.z()) 
00338         smaxz = fdz/std::fabs(v.z()) - p.z()/v.z();
00339       else 
00340         smaxz = kBig;
00341     }
00342     else
00343     {
00344       // Outside extent or on boundary
00345       if (v.z()==0)
00346         return snxt; // Travel parallel
00347       else
00348       {
00349         stmp  = std::fabs(v.z());
00350         sminz = safz/stmp;
00351         smaxz = (fdz+std::fabs(p.z()))/stmp;
00352       }
00353     }
00354 
00355     // Find minimum allowed Dist given min/max pairs
00356     if (sminx>sminy) 
00357       smin = sminx; // MAX(sminx,sminy,sminz)
00358     else 
00359       smin = sminy;
00360     
00361     if (sminz>smin) 
00362       smin=sminz;
00363 
00364     if (smaxx<smaxy) 
00365       smax = smaxx; // MIN(smaxx,smaxy,smaxz)
00366     else 
00367       smax = smaxy;
00368     
00369     if (smaxz<smax) 
00370       smax = smaxz;
00371 
00372     // If smin <= kCarTolerance then only clipping `tolerant' Area
00373     // -> no intersection
00374     
00375     if ((smin>0.) && (smin<=smax))  { snxt=smin; }
00376     
00377     return snxt;
00378 }
00379 
00380 
00382 
00383 G4int G4BoundingBox3D::Inside(const G4Point3D& Pt) const
00384 {
00385   if( ( Pt.x() >= box_min.x() && Pt.x() <= box_max.x() ) &&
00386       ( Pt.y() >= box_min.y() && Pt.y() <= box_max.y() ) &&
00387       ( Pt.z() >= box_min.z() && Pt.z() <= box_max.z() )    )
00388     return 1;
00389   else
00390     return 0;
00391 }

Generated on Mon May 27 17:47:46 2013 for Geant4 by  doxygen 1.4.7