// // ******************************************************************** // * 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: G4NormalNavigation.cc,v 1.9 2007/05/11 13:43:59 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-02-cand-01 $ // // // class G4NormalNavigation Implementation // // Author: P.Kent, 1996 // // -------------------------------------------------------------------- #include "G4NormalNavigation.hh" #include "G4AffineTransform.hh" #include // ******************************************************************** // Constructor // ******************************************************************** // G4NormalNavigation::G4NormalNavigation() : fCheck(false), fVerbose(0) { } // ******************************************************************** // Destructor // ******************************************************************** // G4NormalNavigation::~G4NormalNavigation() {;} // ******************************************************************** // ComputeStep // ******************************************************************** // G4double G4NormalNavigation::ComputeStep(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo) { G4VPhysicalVolume *motherPhysical, *samplePhysical, *blockedExitedVol=0; G4LogicalVolume *motherLogical; G4VSolid *motherSolid; G4ThreeVector sampleDirection; G4double ourStep=currentProposedStepLength, motherSafety, ourSafety; G4int localNoDaughters, sampleNo; motherPhysical = history.GetTopVolume(); motherLogical = motherPhysical->GetLogicalVolume(); motherSolid = motherLogical->GetSolid(); // Compute mother safety // motherSafety = motherSolid->DistanceToOut(localPoint); ourSafety = motherSafety; // Working isotropic safety #ifdef G4VERBOSE static G4int precVerf= 20; // Precision if ( fCheck ) { if( fVerbose == 1 ) { G4cout << "*** G4NormalNavigation::ComputeStep(): ***" << G4endl << " Invoked DistanceToOut(p) for mother solid: " << motherSolid->GetName() << ". Solid replied: " << motherSafety << G4endl << " For local point p: " << localPoint << G4endl << " To be considered as 'mother safety'." << G4endl; } if ( motherSafety < 0.0 ) { G4cerr << "ERROR - G4NormalNavigation::ComputeStep()" << G4endl << " Current solid " << motherSolid->GetName() << " gave negative safety: " << motherSafety << G4endl << " for the current (local) point " << localPoint << G4endl; motherSolid->DumpInfo(); G4Exception("G4NormalNavigation::ComputeStep()", "NegativeSafetyMotherVol", FatalException, "Negative Safety In Voxel Navigation !" ); } if( motherSolid->Inside(localPoint)==kOutside ) { G4cout << "WARNING - G4NormalNavigation::ComputeStep()" << G4endl << " Point " << localPoint << " is outside current volume " << motherPhysical->GetName() << G4endl; G4double estDistToSolid= motherSolid->DistanceToIn(localPoint); G4cout << " Estimated isotropic distance to solid (distToIn)= " << estDistToSolid << G4endl; if( estDistToSolid > 100.0 * motherSolid->GetTolerance() ) { motherSolid->DumpInfo(); G4Exception("G4NormalNavigation::ComputeStep()", "FarOutsideCurrentVolume", FatalException, "Point is far outside Current Volume !" ); } else G4Exception("G4NormalNavigation::ComputeStep()", "OutsideCurrentVolume", JustWarning, "Point is a little outside Current Volume."); } // Verification / verbosity // if ( fVerbose > 1 ) { G4int oldprec = G4cout.precision(precVerf); G4cout << " G4NormalNavigation::ComputeStep()" << " - Information on mother / key daughters ..." << G4endl; G4cout << " Type " << std::setw(12) << "Solid-Name" << " " << std::setw(3*(6+precVerf)) << " local point" << " " << std::setw(4+precVerf) << "solid-Safety" << " " << std::setw(4+precVerf) << "solid-Step" << " " << std::setw(17) << "distance Method " << std::setw(3*(6+precVerf)) << " local direction" << " " << G4endl; G4cout << " Mother " << std::setw(12) << motherSolid->GetName() << " " << std::setw(4+precVerf) << localPoint << " " << std::setw(4+precVerf) << motherSafety << " " << G4endl; G4cout.precision(oldprec); } } #endif // // Compute daughter safeties & intersections // // Exiting normal optimisation // if ( exiting&&validExitNormal ) { if ( localDirection.dot(exitNormal)>=kMinExitingNormalCosine ) { // Block exited daughter volume // blockedExitedVol =* pBlockedPhysical; ourSafety = 0; } } exiting = false; entering = false; localNoDaughters = motherLogical->GetNoDaughters(); for ( sampleNo=localNoDaughters-1; sampleNo>=0; sampleNo--) { samplePhysical = motherLogical->GetDaughter(sampleNo); if ( samplePhysical!=blockedExitedVol ) { G4AffineTransform sampleTf(samplePhysical->GetRotation(), samplePhysical->GetTranslation()); sampleTf.Invert(); const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint); const G4VSolid *sampleSolid = samplePhysical->GetLogicalVolume()->GetSolid(); const G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint); if ( sampleSafetyDistanceToIn(samplePoint,sampleDirection); #ifdef G4VERBOSE if(( fCheck ) && ( fVerbose == 1 )) { G4cout << "*** G4NormalNavigation::ComputeStep(): ***" << G4endl << " Invoked DistanceToIn(p,v) for daughter solid: " << sampleSolid->GetName() << ". Solid replied: " << sampleStep << G4endl << " For local point p: " << samplePoint << G4endl << " Direction v: " << sampleDirection << ", to be considered as 'daughter step'." << G4endl; } #endif if ( sampleStep<=ourStep ) { ourStep = sampleStep; entering = true; exiting = false; *pBlockedPhysical = samplePhysical; blockedReplicaNo = -1; #ifdef G4VERBOSE // Check to see that the resulting point is indeed in/on volume. // This check could eventually be made only for successful candidate. if ( ( fCheck ) && ( sampleStep < kInfinity ) ) { G4ThreeVector intersectionPoint; intersectionPoint= samplePoint + sampleStep * sampleDirection; EInside insideIntPt= sampleSolid->Inside(intersectionPoint); G4String solidResponse = "-kInside-"; if (insideIntPt == kOutside) solidResponse = "-kOutside-"; else if (insideIntPt == kSurface) solidResponse = "-kSurface-"; if( fVerbose == 1 ) { G4cout << "*** G4NormalNavigation::ComputeStep(): ***" << G4endl << " Invoked Inside() for solid: " << sampleSolid->GetName() << ". Solid replied: " << solidResponse << G4endl << " For point p: " << intersectionPoint << ", considered as 'intersection' point." << G4endl; } if ( insideIntPt != kSurface ) { G4int oldcoutPrec = G4cout.precision(16); G4cout << "WARNING - G4NormalNavigation::ComputeStep()" << G4endl << " Inaccurate DistanceToIn for solid " << sampleSolid->GetName() << G4endl; G4cout << " Solid gave DistanceToIn = " << sampleStep << " yet returns " << solidResponse << " for this point !" << G4endl; G4cout << " Point = " << intersectionPoint << G4endl; if ( insideIntPt != kInside ) G4cout << " DistanceToIn(p) = " << sampleSolid->DistanceToIn(intersectionPoint) << G4endl; if ( insideIntPt != kOutside ) G4cout << " DistanceToOut(p) = " << sampleSolid->DistanceToOut(intersectionPoint) << G4endl; G4Exception("G4NormalNavigation::ComputeStep()", "InaccurateDistanceToIn", JustWarning, "Navigator gets conflicting response from Solid."); G4cout.precision(oldcoutPrec); } } // Verification / verbosity // if ( fVerbose > 1 ) { G4int oldprec = G4cout.precision(precVerf); G4cout << " Daught " << std::setw(12) << sampleSolid->GetName() << " " << std::setw(4+precVerf) << samplePoint << " " << std::setw(4+precVerf) << sampleSafety << " " << std::setw(4+precVerf) << sampleStep << " " << std::setw(16) << "distanceToIn" << " " << std::setw(4+precVerf) << localDirection << " " << G4endl; G4cout.precision(oldprec); } #endif } } } } if ( currentProposedStepLengthDistanceToOut(localPoint, localDirection, true, &validExitNormal, &exitNormal); #ifdef G4VERBOSE if ( fCheck ) { if( fVerbose == 1 ) { G4cout << "*** G4NormalNavigation::ComputeStep(): ***" << G4endl << " Invoked DistanceToOut(p,v,...) for mother solid: " << motherSolid->GetName() << ". Solid replied: " << motherStep << G4endl << " For local point p: " << localPoint << G4endl << " Direction v: " << localDirection << ", to be considered as 'mother step'." << G4endl; } if( ( motherStep < 0.0 ) || ( motherStep >= kInfinity) ) { G4cerr << "ERROR - G4NormalNavigation::ComputeStep()" << G4endl << " Problem in Navigation" << G4endl << " Point (local coordinates): " << localPoint << G4endl << " Local Direction: " << localDirection << G4endl << " Solid: " << motherSolid->GetName() << G4endl; motherSolid->DumpInfo(); G4Exception("G4NormalNavigation::ComputeStep()", "PointDistOutInvalid", FatalException, "Current point is outside the current solid !"); } } if ( fVerbose > 1 ) { G4int oldprec = G4cout.precision(precVerf); G4cout << " Mother " << std::setw(12) << motherSolid->GetName() << " " << std::setw(4+precVerf) << localPoint << " " << std::setw(4+precVerf) << motherSafety << " " << std::setw(4+precVerf) << motherStep << " " << std::setw(16) << "distanceToOut" << " " << std::setw(4+precVerf) << localDirection << " " << G4endl; G4cout.precision(oldprec); } #endif if ( motherStep<=ourStep ) { ourStep = motherStep; exiting = true; entering = false; if ( validExitNormal ) { const G4RotationMatrix *rot = motherPhysical->GetRotation(); if (rot) { exitNormal *= rot->inverse(); } } } else { validExitNormal = false; } } } newSafety = ourSafety; return ourStep; } // ******************************************************************** // ComputeSafety // ******************************************************************** // G4double G4NormalNavigation::ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double) { G4VPhysicalVolume *motherPhysical, *samplePhysical; G4LogicalVolume *motherLogical; G4VSolid *motherSolid; G4double motherSafety, ourSafety; G4int localNoDaughters, sampleNo; motherPhysical = history.GetTopVolume(); motherLogical = motherPhysical->GetLogicalVolume(); motherSolid = motherLogical->GetSolid(); // Compute mother safety // motherSafety = motherSolid->DistanceToOut(localPoint); ourSafety = motherSafety; // Working isotropic safety #ifdef G4VERBOSE if(( fCheck ) && ( fVerbose == 1 )) { G4cout << "*** G4NormalNavigation::ComputeSafety(): ***" << G4endl << " Invoked DistanceToOut(p) for mother solid: " << motherSolid->GetName() << ". Solid replied: " << motherSafety << G4endl << " For local point p: " << localPoint << ", to be considered as 'mother safety'." << G4endl; } #endif // Compute daughter safeties // localNoDaughters = motherLogical->GetNoDaughters(); for ( sampleNo=localNoDaughters-1; sampleNo>=0; sampleNo-- ) { samplePhysical = motherLogical->GetDaughter(sampleNo); G4AffineTransform sampleTf(samplePhysical->GetRotation(), samplePhysical->GetTranslation()); sampleTf.Invert(); const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint); const G4VSolid *sampleSolid = samplePhysical->GetLogicalVolume()->GetSolid(); const G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint); if ( sampleSafetyGetName() << ". Solid replied: " << sampleSafety << G4endl << " For local point p: " << samplePoint << ", to be considered as 'daughter safety'." << G4endl; } #endif } return ourSafety; }