18#include "G4LogicalVolumeStore.hh"
19#include "G4Material.hh"
20#include "G4NistManager.hh"
21#include "G4PVPlacement.hh"
31 std::vector<std::string> tokenizeRotation(std::string rotation) {
32 std::replace(rotation.begin(), rotation.end(),
',',
' ');
36 std::string lowercase(std::string value) {
37 std::transform(value.begin(), value.end(), value.begin(),
38 [](
unsigned char c) { return static_cast<char>(std::tolower(c)); });
42 void requireRotationTokenCount(
const std::vector<std::string> &tokens,
45 if (tokens.size() == expected) {
return; }
46 std::cerr <<
" >> ERROR: rotation <" << s->
getRot() <<
"> for " << s->
getName()
47 <<
" has wrong number of entries. Exiting." << std::endl;
51 void applyOrderedRotation(G4RotationMatrix *rot,
52 const std::string &order,
53 const std::vector<double> &angles,
56 rot->rotateX(angles[0]);
57 rot->rotateZ(angles[1]);
58 rot->rotateY(angles[2]);
60 else if (order ==
"yxz") {
61 rot->rotateY(angles[0]);
62 rot->rotateX(angles[1]);
63 rot->rotateZ(angles[2]);
65 else if (order ==
"yzx") {
66 rot->rotateY(angles[0]);
67 rot->rotateZ(angles[1]);
68 rot->rotateX(angles[2]);
70 else if (order ==
"zxy") {
71 rot->rotateZ(angles[0]);
72 rot->rotateX(angles[1]);
73 rot->rotateY(angles[2]);
75 else if (order ==
"zyx") {
76 rot->rotateZ(angles[0]);
77 rot->rotateY(angles[1]);
78 rot->rotateX(angles[2]);
81 std::cerr <<
" >> ERROR: Ordered rotation <" << order <<
"> for " << s->
getName()
82 <<
" is wrong, it's none of the following: xzy, yxz, yzx, zxy or zyx. Exiting."
91 const std::optional<std::string> &backup_mat) {
98 std::unordered_map<std::string, G4Volume *> *g4s) {
99 auto it = g4s->find(vname);
100 return (it != g4s->end()) ? it->second->getSolid() :
nullptr;
105 std::unordered_map<std::string, G4Volume *> *g4s) {
106 auto it = g4s->find(volume_name);
107 return (it != g4s->end()) ? it->second->getLogical() :
nullptr;
112 std::unordered_map<std::string, G4Volume *> *g4s) {
113 auto it = g4s->find(vname);
114 return (it != g4s->end()) ? it->second->getPhysical() :
nullptr;
119 std::string_view color = s->
getColor();
124 log->info(2,
className(),
" createVisualAttributes for color ", color,
125 " resulted in RGB = (", g4color.GetRed(),
", ", g4color.GetGreen(),
", ", g4color.GetBlue(),
126 ", opacity: ", opacity,
")");
128 G4VisAttributes attr(g4color);
131 s->
isVisible() ? attr.SetVisibility(
true) : attr.SetVisibility(
false);
135 attr.SetForceWireframe(
true);
138 attr.SetForceSolid(
true);
141 attr.SetForceCloud(
true);
152 auto rot =
new G4RotationMatrix();
154 const auto applyRotation = [&](
const std::string& expression) {
155 const auto tokens = tokenizeRotation(expression);
156 if (tokens.empty())
return;
158 const auto rotationType = tokens[0];
159 if (rotationType !=
"ordered:" && rotationType !=
"doubleRotation:") {
160 requireRotationTokenCount(tokens, 3, s);
162 rot->rotateX(pars[0]);
163 rot->rotateY(pars[1]);
164 rot->rotateZ(pars[2]);
166 else if (rotationType ==
"doubleRotation:") {
167 requireRotationTokenCount(tokens, 7, s);
169 {tokens[1], tokens[2], tokens[3], tokens[4], tokens[5], tokens[6]});
170 rot->rotateX(pars[0]);
171 rot->rotateY(pars[1]);
172 rot->rotateZ(pars[2]);
173 rot->rotateX(pars[3]);
174 rot->rotateY(pars[4]);
175 rot->rotateZ(pars[5]);
178 requireRotationTokenCount(tokens, 5, s);
179 const auto order = lowercase(tokens[1]);
181 applyOrderedRotation(rot, order, pars, s);
185 applyRotation(s->
getRot());
192 G4ThreeVector pos(0., 0., 0.);
194 if (vec.size() == 3) pos.set(vec[0], vec[1], vec[2]);
199 if (shift.size() == 3) pos += G4ThreeVector(shift[0], shift[1], shift[2]);
205 std::unordered_map<std::string, G4Volume *> *g4s) {
206 const std::string g4name = s->
getG4Name();
210 if (thisG4Volume->getLogical())
return thisG4Volume->getLogical();
216 auto volume_copy =
gsystem +
"/" + *copyOf;
218 if (copyG4Volume->getLogical() !=
nullptr) {
219 return copyG4Volume->getLogical();
226 auto *nist = G4NistManager::Instance();
227 auto *mat = nist->FindOrBuildMaterial(s->
getMaterial());
230 log->warning(
"Material <", s->
getMaterial(),
"> not found. Using backup material <",
241 if (thisG4Volume->getSolid() ==
nullptr) {
return nullptr; }
244 auto *logical =
new G4LogicalVolume(thisG4Volume->getSolid(),
249 thisG4Volume->setLogical(logical,
log);
254 std::unordered_map<std::string, G4Volume *> *g4s) {
261 const std::string g4name = s->
getG4Name();
263 auto logicalVolume = thisG4Volume->getLogical();
269 auto volume_copy =
gsystem +
"/" + *copyOf;
271 if (copyG4Volume->getLogical() !=
nullptr) {
272 logicalVolume = copyG4Volume->getLogical();
277 if (!thisG4Volume->getPhysical()) {
282 if (placementType ==
"active") {
283 G4RotationMatrix rotation_instance = *rotation;
285 thisG4Volume->setPhysical(
new G4PVPlacement(G4Transform3D(rotation_instance, translation),
294 else if (placementType ==
"passive") {
295 thisG4Volume->setPhysical(
new G4PVPlacement(rotation,
307 "GVolume <", s->
getName(),
"> has unsupported g4placement_type <",
308 placementType,
">. Use 'active' or 'passive'.");
311 return thisG4Volume->getPhysical();
315 std::unordered_map<std::string, G4Volume *> *g4s) {
322 log->info(2,
className(),
" result for component ", name,
": solid: ", solid !=
nullptr);
323 return solid !=
nullptr;
331 if (sbuild ==
nullptr) {
332 log->info(2,
className(),
" result for ", name,
": solid not ready, deferring");
338 const bool okSolid = (sbuild !=
nullptr);
339 const bool okLogical = (lbuild !=
nullptr);
340 const bool okPhysical = (pbuild !=
nullptr);
341 const bool okAll = okSolid && okLogical && okPhysical;
345 ": solid: ", okSolid,
346 " logical: ", okLogical,
347 " physical: ", okPhysical);
G4Volume * getOrCreateG4Volume(const std::string &volume_name, std::unordered_map< std::string, G4Volume * > *g4s)
Get or create a G4Volume wrapper entry in the map.
virtual G4LogicalVolume * buildLogical(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Build or retrieve the G4LogicalVolume for a volume.
virtual G4VPhysicalVolume * buildPhysical(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Build or retrieve the G4VPhysicalVolume for a volume.
static G4VPhysicalVolume * getPhysicalFromMap(const std::string &volume_name, std::unordered_map< std::string, G4Volume * > *g4s)
Lookup physical volume in the g4s map.
bool build_g4volume(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Build (or retrieve) solid, logical, and physical volumes for a given GVolume.
static G4RotationMatrix * getRotation(const GVolume *s)
Parse rotation string and build a Geant4 rotation matrix.
virtual std::string_view className() const =0
Short, human-readable factory name for logging.
std::optional< std::string > backupMaterial
Backup material name used if the requested material is absent.
virtual G4VSolid * buildSolid(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)=0
Build the G4VSolid for a volume.
bool checkPhysicalDependencies(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Verify prerequisites to build a physical placement.
void initialize_context(int checkOverlaps, const std::optional< std::string > &backupMaterial)
Configure overlap checking and backup material behavior for this factory.
static G4VSolid * getSolidFromMap(const std::string &volume_name, std::unordered_map< std::string, G4Volume * > *g4s)
Lookup solid in the g4s map.
static G4LogicalVolume * getLogicalFromMap(const std::string &volume_name, std::unordered_map< std::string, G4Volume * > *g4s)
Lookup logical volume in the g4s map.
static G4ThreeVector getPosition(const GVolume *s)
Parse position and optional shift strings to compute placement translation.
G4VisAttributes createVisualAttributes(const GVolume *s)
Build visualization attributes from the volume definition.
std::shared_ptr< GLogger > log
const std::optional< std::string > & getTilt() const
std::string getRot() const
const std::string & getG4Name() const
const std::optional< std::string > & getCopyOf() const
bool getExistence() const
std::string getPos() const
std::string getG4PlacementType() const
const std::optional< std::string > & getShift() const
std::string getName() const
std::string getMaterial() const
std::string getSystem() const
const std::string & getG4MotherName() const
std::string_view getColor() const
double getOpacity() const
Abstract factory that converts a GEMC DB GVolume into Geant4 objects.
Conventions, labels, and error codes used by the g4system geometry/material layer.
constexpr int ERR_G4MATERIALNOTFOUND
Material lookup failed and no fallback was available.
constexpr char GSYSTEMCOMPONENTMATERIAL[]
constexpr int ERR_G4PLACEMENTTYPE
vector< double > getG4NumbersFromString(const string &vstring, bool warnIfNotUnit=false)
G4Colour makeG4Colour(std::string_view code, double opacity)
vector< double > getG4NumbersFromStringVector(const vector< string > &vstring, bool warnIfNotUnit=false)
vector< std::string > getStringVectorFromString(const std::string &input)