// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4BoundingBox3D.cc,v 1.12 2007/07/16 08:06:55 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-04-beta-01 $ // // ---------------------------------------------------------------------- // GEANT 4 class source file // // G4BoundingBox3D.cc // // ---------------------------------------------------------------------- #include "G4BoundingBox3D.hh" #include "geomdefs.hh" #include "G4GeometryTolerance.hh" const G4BoundingBox3D G4BoundingBox3D:: space( G4Point3D(-kInfinity, -kInfinity, -kInfinity), G4Point3D(+kInfinity, +kInfinity, +kInfinity) ); ///////////////////////////////////////////////////////////////////////////// G4BoundingBox3D::G4BoundingBox3D() { distance =0; kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); } G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p1, const G4Point3D& p2) { Init(p1, p2); } G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p) { Init(p); } G4BoundingBox3D::~G4BoundingBox3D() { } G4BoundingBox3D::G4BoundingBox3D(const G4BoundingBox3D& right) : box_min(right.box_min), box_max(right.box_max), distance(right.distance), test_result(right.test_result), MiddlePoint(right.MiddlePoint), GeantBox(right.GeantBox), kCarTolerance(right.kCarTolerance) { } G4BoundingBox3D& G4BoundingBox3D::operator=(const G4BoundingBox3D& right) { if (&right == this) return *this; box_min = right.box_min; box_max = right.box_max; distance = right.distance; test_result = right.test_result; MiddlePoint = right.MiddlePoint; GeantBox = right.GeantBox; kCarTolerance = right.kCarTolerance; return *this; } void G4BoundingBox3D::Init(const G4Point3D& p1, const G4Point3D& p2) { // L. Broglia // Maybe temporary // Create a BBox bigger than the reality kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); box_min.setX( std::min(p1.x(), p2.x()) - kCarTolerance ); box_min.setY( std::min(p1.y(), p2.y()) - kCarTolerance ); box_min.setZ( std::min(p1.z(), p2.z()) - kCarTolerance ); box_max.setX( std::max(p1.x(), p2.x()) + kCarTolerance ); box_max.setY( std::max(p1.y(), p2.y()) + kCarTolerance ); box_max.setZ( std::max(p1.z(), p2.z()) + kCarTolerance ); // Calc half spaces GeantBox = (box_max - box_min)*0.5; MiddlePoint = (box_min + box_max)*0.5; distance = 0; } void G4BoundingBox3D::Init(const G4Point3D& p) { box_min= box_max= MiddlePoint= p; GeantBox= G4Point3D(0, 0, 0); distance= 0; kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); } ///////////////////////////////////////////////////////////////////////////// void G4BoundingBox3D::Extend(const G4Point3D& p) { // L. Broglia // Maybe temporary // Create a BBox bigger than the reality if (p.x() < box_min.x()) box_min.setX( p.x() - kCarTolerance ); else if (p.x() > box_max.x()) box_max.setX( p.x() + kCarTolerance ); if (p.y() < box_min.y()) box_min.setY( p.y() - kCarTolerance ); else if (p.y() > box_max.y()) box_max.setY( p.y() + kCarTolerance ); if (p.z() < box_min.z()) box_min.setZ( p.z() - kCarTolerance ); else if (p.z() > box_max.z()) box_max.setZ( p.z() + kCarTolerance ); // L. Broglia // Now re-calculate GeantBox and MiddlePoint GeantBox = (box_max - box_min)*0.5; MiddlePoint = (box_min + box_max)*0.5; } //////////////////////////////////////////////////////////////////////////// G4int G4BoundingBox3D::Test(const G4Ray& rayref) { const G4Point3D& tmp_ray_start = rayref.GetStart(); const G4Vector3D& tmp_ray_dir = rayref.GetDir(); G4Point3D ray_start = tmp_ray_start ; G4Vector3D ray_dir = tmp_ray_dir ; G4double rayx,rayy,rayz; rayx = ray_start.x(); rayy = ray_start.y(); rayz = ray_start.z(); // Test if ray starting point is in the bbox or not if((rayx < box_min.x()) || (rayx > box_max.x()) || (rayy < box_min.y()) || (rayy > box_max.y()) || (rayz < box_min.z()) || (rayz > box_max.z()) ) { // Outside, check for intersection with bbox // Adapt ray_starting point to box const G4Point3D ray_start2 = G4Point3D( ray_start - MiddlePoint ); distance = DistanceToIn(ray_start2, ray_dir); if(!distance) test_result = 0; // Miss else test_result = 1; // Starting point outside box & hits box } else { // Inside // G4cout << "\nRay starting point Inside bbox."; test_result = 1; distance = 0; } return test_result; } /////////////////////////////////////////////////////////////////////////////// // Does an intersection exist? // // ALGORITHM: // // Check that if point lies outside x/y/z extent of box, travel is towards // the box (ie. there is a possiblity of an intersection) G4int G4BoundingBox3D::BoxIntersect(const G4Point3D& , const G4Point3D& p , const G4Vector3D& v ) const { G4double safx, safy, safz; G4double fdx, fdy, fdz; fdx = GeantBox.x(); fdy = GeantBox.y(); fdz = GeantBox.z(); safx=std::fabs(p.x())-fdx; // minimum distance to x surface of shape safy=std::fabs(p.y())-fdy; safz=std::fabs(p.z())-fdz; // Will we Intersect? // If safx/y/z is >=0 the point is outside/on the box's x/y/z extent. // If both p.X()/y/z and v.X()/y/z repectively are both positive/negative, // travel is in a G4ThreeVec away from the shape. if ( ( (p.x()*v.x()>=0.0 ) && safx>0.0 ) || ( (p.y()*v.y()>=0.0 ) && safy>0.0 ) || ( (p.z()*v.z()>=0.0 ) && safz>0.0 ) ) return 0; // No intersection else return 1; // Possible intersection } /////////////////////////////////////////////////////////////////////////////// // Distance to in // Calculate distance to box from outside - return kBig if no intersection // // ALGORITHM: // // Check that if point lies outside x/y/z extent of box, travel is towards // the box (ie. there is a possiblity of an intersection) // // Calculate pairs of minimum and maximum distances for x/y/z travel for // intersection with the box's x/y/z extent. // If there is a valid intersection, it is given by the maximum min distance // (ie. distance to satisfy x/y/z intersections) *if* <= minimum max distance // (ie. distance after which 1+ of x/y/z intersections not satisfied) // // NOTE: // // `Inside' safe - meaningful answers given if point is Inside the exact // shape. //G4double G4BoundingBox::distance_to_in(const G4Point3d& gbox, const G4Point3d& p, const G4ThreeVec& v) const G4double G4BoundingBox3D::DistanceToIn(const G4Point3D& p, const G4Vector3D& v) const { G4double safx, safy, safz, snxt = 0; // snxt = default return value G4double smin, sminx, sminy, sminz; G4double smax, smaxx, smaxy, smaxz; G4double stmp; G4double kBig = 10e20; G4double fdx,fdy,fdz; fdx = GeantBox.x(); fdy = GeantBox.y(); fdz = GeantBox.z(); safx = std::fabs(p.x())-fdx; // minimum distance to x surface of shape safy = std::fabs(p.y())-fdy; safz = std::fabs(p.z())-fdz; // Will we Intersect? // If safx/y/z is >=0 the point is outside/on the box's x/y/z extent. // If both p.X()/y/z and v.X()/y/z repectively are both positive/negative, // travel is in a G4ThreeVec away from the shape. if ( ( ( p.x()*v.x()>=0.0 ) && safx>0.0) || ( ( p.y()*v.y()>=0.0 ) && safy>0.0) || ( ( p.z()*v.z()>=0.0 ) && safz>0.0) ) return snxt; // Compute min / max distance for x/y/z travel: if (safx<0.0) { // Inside x extent => Calc distance until trajectory leaves extent sminx=0.0; if (v.x()) smaxx = fdx/std::fabs(v.x()) - p.x()/v.x(); else smaxx = kBig; } else { // Outside extent or on boundary if (v.x()==0) return snxt; // Travel parallel else { stmp = std::fabs(v.x()); sminx = safx/stmp; smaxx = (fdx+std::fabs(p.x()))/stmp; } } if (safy<0.0) { // Inside y extent => Calc distance until trajectory leaves extent sminy=0.0; if (v.y()) smaxy = fdy/std::fabs(v.y()) - p.y()/v.y(); else smaxy = kBig; } else { // Outside extent or on boundary if (v.y()==0) return snxt; // Travel parallel else { stmp = std::fabs(v.y()); sminy = safy/stmp; smaxy = (fdy+std::fabs(p.y()))/stmp; } } if (safz<0.0) { // Inside z extent => Calc distance until trajectory leaves extent sminz=0.0; if (v.z()) smaxz = fdz/std::fabs(v.z()) - p.z()/v.z(); else smaxz = kBig; } else { // Outside extent or on boundary if (v.z()==0) return snxt; // Travel parallel else { stmp = std::fabs(v.z()); sminz = safz/stmp; smaxz = (fdz+std::fabs(p.z()))/stmp; } } // Find minimum allowed Dist given min/max pairs if (sminx>sminy) smin = sminx; // MAX(sminx,sminy,sminz) else smin = sminy; if (sminz>smin) smin=sminz; if (smaxx no intersection if ((smin>0.) && (smin<=smax)) { snxt=smin; } return snxt; } /////////////////////////////////////////////////////////////////////////////// G4int G4BoundingBox3D::Inside(const G4Point3D& Pt) const { if( ( Pt.x() >= box_min.x() && Pt.x() <= box_max.x() ) && ( Pt.y() >= box_min.y() && Pt.y() <= box_max.y() ) && ( Pt.z() >= box_min.z() && Pt.z() <= box_max.z() ) ) return 1; else return 0; }