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"
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;
53Number of test points we will generate on randomly on the surface of each geometry volume and then check for all of them that
551. The points are inside the mother volume
562. The points are not inside any neighbor volume
58The higher the number the more precise the check for overlaps becomes, and the slower it gets.
59See 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);
146 m_displayData->addPoint(geant4Message, ROOT::Math::XYZVector(global[0], global[1], global[2]) *
Unit::mm);
150 B2ERROR(
"Could not find name of intersecting volume");
154 G4AffineTransform t =
m_nav.GetTopTransform().Inverse();
155 G4ThreeVector global = t.TransformPoint(posLocal);
156 m_displayData->addPoint(geant4Message, ROOT::Math::XYZVector(global[0], global[1], global[2]) *
Unit::mm);
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]
G4VPhysicalVolume * getTopVolume()
Return a pointer to the top volume.
static GeometryManager & getInstance()
Return a reference to the instance.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.