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 if (name != sister->GetName())
continue;
135 G4AffineTransform trans_sister(sister->GetRotation(), sister->GetTranslation());
136 G4ThreeVector posMother = trans_sister.TransformPoint(posLocal);
137 G4ThreeVector posSister = trans_volume.TransformPoint(posMother);
139 if (solid->Inside(posSister) != kOutside) {
141 B2INFO(
"Found intersecting volume " << sister->GetName() <<
"." << sister->GetCopyNo());
143 G4AffineTransform t =
m_nav.GetTopTransform().Inverse();
144 G4ThreeVector global = t.TransformPoint(posMother);
149 B2ERROR(
"Could not find name of intersecting volume");
153 G4AffineTransform t =
m_nav.GetTopTransform().Inverse();
154 G4ThreeVector global = t.TransformPoint(posLocal);
158 m_nav.NewLevel(volume);
166 m_nav.NewLevel(volume);
168 std::string volumePath = path +
"/" + volume->GetName();
179 G4LogicalVolume* logicalVolume = volume->GetLogicalVolume();
180 for (
size_t iDaughter = 0; iDaughter < logicalVolume->GetNoDaughters(); iDaughter++) {
181 G4VPhysicalVolume* daughter = logicalVolume->GetDaughter(iDaughter);
183 auto it =
m_seen.insert(daughter);
184 if (!it.second)
continue;
185 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.
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.