9 #include <geometry/modules/overlapchecker/OverlapCheckerModule.h> 
   10 #include <geometry/GeometryManager.h> 
   11 #include <framework/gearbox/Unit.h> 
   13 #include "G4VPhysicalVolume.hh" 
   14 #include "G4LogicalVolume.hh" 
   15 #include "G4UnitsTable.hh" 
   16 #include "G4VExceptionHandler.hh" 
   17 #include "G4StateManager.hh" 
   18 #include "G4AffineTransform.hh" 
   19 #include "G4VSolid.hh" 
   30   class OverlapHandler: 
public G4VExceptionHandler {
 
   33     explicit OverlapHandler(std::function<
void(
const std::string&)> callback): m_callback(std::move(callback)) {}
 
   35     bool Notify(
const char*, 
const char*, G4ExceptionSeverity, 
const char* description)
 override 
   37       m_callback(description);
 
   42     std::function<void(
const std::string&)> m_callback;
 
   53 Number of test points we will generate on randomly on the surface of each geometry volume and then check for all of them that 
   55 1. The points are inside the mother volume 
   56 2. The points are not inside any neighbor volume 
   58 The higher the number the more precise the check for overlaps becomes, and the slower it gets. 
   59 See also https://questions.belle2.org/question/7264/ )DOC", 
   77   G4UnitDefinition::BuildUnitsTable();
 
   80     B2ERROR(
"No geometry found. => Add the Geometry module to the path before the OverlapChecker module.");
 
   87   G4VExceptionHandler* old = G4StateManager::GetStateManager()->GetExceptionHandler();
 
   89   OverlapHandler handler([&](
const std::string & message) { 
handleOverlap(message); });
 
   90   G4StateManager::GetStateManager()->SetExceptionHandler(&handler);
 
   94   G4StateManager::GetStateManager()->SetExceptionHandler(old);
 
   98     B2ERROR(
"Overlaps detected for " << m_overlap);
 
  105   G4VPhysicalVolume* volume = 
m_nav.GetTopVolume();
 
  107   B2ERROR(geant4Message);
 
  108   std::regex r(R
"((mother)?\s*local point \(([-+0-9eE.]+),([-+0-9eE.]+),([-+0-9eE.]+)\))"); 
  110   if (std::regex_search(geant4Message, m, r)) {
 
  111     G4ThreeVector posLocal(std::atof(m[2].str().c_str()), std::atof(m[3].str().c_str()), std::atof(m[4].str().c_str()));
 
  112     if (m[1].length() == 0) {
 
  119       G4AffineTransform trans_volume(volume->GetRotation(), volume->GetTranslation());
 
  120       trans_volume.Invert();
 
  122       G4VSolid* solid = volume->GetLogicalVolume()->GetSolid();
 
  124       std::regex nameRegex(
"with (.*) volume's");
 
  125       std::smatch nameMatch;
 
  127       if (std::regex_search(geant4Message, nameMatch, nameRegex)) {
 
  128         const std::string& name = nameMatch[1].str();
 
  130         for (
size_t i = 0; i < volume->GetMotherLogical()->GetNoDaughters(); ++i) {
 
  131           G4VPhysicalVolume* sister = volume->GetMotherLogical()->GetDaughter(i);
 
  133           std::string sisterName{(sister->GetName()).data()};
 
  134           if (name != sisterName) 
continue;
 
  136           G4AffineTransform trans_sister(sister->GetRotation(), sister->GetTranslation());
 
  137           G4ThreeVector posMother = trans_sister.TransformPoint(posLocal);
 
  138           G4ThreeVector posSister = trans_volume.TransformPoint(posMother);
 
  140           if (solid->Inside(posSister) != kOutside) {
 
  142             B2INFO(
"Found intersecting volume " << sister->GetName() << 
"." << sister->GetCopyNo());
 
  144             G4AffineTransform t = 
m_nav.GetTopTransform().Inverse();
 
  145             G4ThreeVector global = t.TransformPoint(posMother);
 
  150         B2ERROR(
"Could not find name of intersecting volume");
 
  154       G4AffineTransform t = 
m_nav.GetTopTransform().Inverse();
 
  155       G4ThreeVector global = t.TransformPoint(posLocal);
 
  159   m_nav.NewLevel(volume);
 
  167   m_nav.NewLevel(volume);
 
  169   std::string volumePath = path + 
"/" + volume->GetName();
 
  180   G4LogicalVolume* logicalVolume = volume->GetLogicalVolume();
 
  181   for (
size_t iDaughter = 0; iDaughter < logicalVolume->GetNoDaughters(); iDaughter++) {
 
  182     G4VPhysicalVolume* daughter = logicalVolume->GetDaughter(iDaughter);
 
  184     auto it = 
m_seen.insert(daughter);
 
  185     if (!it.second) 
continue;
 
  186     result |= 
checkVolume(daughter, volumePath, depth + 1);
 
void setDescription(const std::string &description)
Sets the description of the module.
OverlapCheckerModule()
Constructor of the module.
double m_tolerance
tolerance of overlap check
void initialize() override
Initialize the module.
std::string m_prefix
check only volumes beginning with prefix
void event() override
event function: this runs the overlap checker for each event
bool checkVolume(G4VPhysicalVolume *volume, const std::string &path, int depth=0)
Check a volume for overlaps.
int m_points
number of test points
int m_maxErrors
maximum number of errors before skipping current volume
void handleOverlap(const std::string &geant4Message)
Handle a G4Exception with the overlap message issued by Geant4.
std::vector< std::string > m_overlaps
list of overlapping volumes
int m_maxDepth
maximum depth to check
std::set< G4VPhysicalVolume * > m_seen
set of logical volumes we already checked
G4NavigationHistory m_nav
navigation history to remember coordinate transformations
StoreObjPtr< DisplayData > m_displayData
Pointer to the DisplayData where we add the overlap points for rendering.
static const double mm
[millimeters]
static GeometryManager & getInstance()
Return a reference to the instance.
G4VPhysicalVolume * getTopVolume()
Return a pointer to the top volume.
REG_MODULE(B2BIIConvertBeamParams)
Register the module.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Abstract base class for different kinds of events.