g4system
Loading...
Searching...
No Matches
buildSolid.cc
Go to the documentation of this file.
1
6
7// gemc
8#include "gutilities.h"
9
10// g4system
11#include "cadSystemFactory.h"
12
13// ───────────────── CADMesh single-header library ────────────────
14// https://github.com/christopherpoole/CADMesh
15//
16// *Modifications applied to the vendor header:*
17// - Marked the following classes `final`
18// • BuiltInReader
19// • TessellatedMesh
20// - Reason: https://devblogs.microsoft.com/oldnewthing/20200619-00/?p=103877
21//
22// *Optional Dependencies*
23// Define `USE_CADMESH_ASSIMP_READER` **before** including `CADMesh.hh`
24// to enable Assimp-based file loading.
25//
26// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27// !!! SET THIS BEFORE INCLUDING CADMESH.HH TO USE THE ASSIMP READER
28// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
29#define USE_CADMESH_ASSIMP_READER
30// If you want Assimp to be the default reader, uncomment:
31// #define CADMESH_DEFAULT_READER ASSIMP
32
33#include "CADMesh.hh"
34
35// Geant4 units
36#include "CLHEP/Units/SystemOfUnits.h"
37
38namespace {
39 bool numeric_value(const std::string& value, double& result) {
40 try {
41 size_t parsed = 0;
42 result = std::stod(value, &parsed);
43 return parsed == value.size();
44 }
45 catch (const std::exception&) { return false; }
46 }
47}
48
50 std::unordered_map<std::string,
51 G4Volume*>* g4s) {
52 std::string g4name = s->getG4Name();
53
54 // Dependency check: solids can require other solids (copy/boolean operations).
55 if (!checkSolidDependencies(s, g4s)) return nullptr;
56
57 // Locate or allocate the wrapper used to cache solid/logical/physical pointers.
58 auto thisG4Volume = getOrCreateG4Volume(g4name, g4s);
59 if (thisG4Volume->getSolid() != nullptr) return thisG4Volume->getSolid();
60
61 // If this is a copy of another volume, reuse the source mesh solid instead of loading a mesh:
62 // the copy carries no mesh file of its own (e.g. the LTCC frame plates placed in every sector).
63 const auto& copyOf = s->getCopyOf();
64 if (copyOf) {
65 auto sourceName = s->getSystem() + "/" + *copyOf;
66 auto sourceG4Volume = getOrCreateG4Volume(sourceName, g4s);
67 if (sourceG4Volume->getSolid() != nullptr) return sourceG4Volume->getSolid();
68 }
69
70 // Current rows store "<mesh path>, <scale>" in parameters. For compatibility, an old row may
71 // store only its numeric scale there and its mesh path in description.
72 std::string fileName = s->getDescription();
73 double scale = 1.0;
74 std::vector<std::string> cadParameters;
75 if (s->getParameters()) {
77 }
78 if (cadParameters.size() > 1) {
79 fileName = cadParameters[0];
80 if (!numeric_value(cadParameters[1], scale)) {
81 log->warning("G4CadSystemFactory: volume <", g4name,
82 "> has a non-numeric scale <", cadParameters[1], ">; using 1.0");
83 scale = 1.0;
84 }
85 }
86 else if (cadParameters.size() == 1) {
87 double legacyScale = 1.0;
88 if (numeric_value(cadParameters[0], legacyScale)) { scale = legacyScale; }
89 else { fileName = cadParameters[0]; }
90 }
91
92 G4String g4filename = fileName;
93
94 // File extension (last token after '.').
95 std::string extension =
97
98 // PLY / STL via CADMesh & Assimp reader.
99 if (extension == "ply" || extension == "stl") {
100 auto mesh = CADMesh::TessellatedMesh::From(g4filename,
101 CADMesh::File::ASSIMP());
102
103 // The CAD file is interpreted in millimetres (times the per-volume scale) to match
104 // typical detector CAD conventions.
105 mesh->SetScale(CLHEP::mm * scale);
106
107 // Do not flip vertex winding unless the CAD source requires it.
108 mesh->SetReverse(false);
109
110 thisG4Volume->setSolid(mesh->GetSolid(), log);
111 return thisG4Volume->getSolid();
112 }
113
114 // Unsupported extension: return nullptr so the caller can decide whether to treat it as fatal.
115 log->warning("G4CadSystemFactory: file <", fileName,
116 "> has unsupported extension <", extension, ">");
117 return nullptr;
118}
Factory that converts CAD files (PLY / STL) into Geant4 tessellated solids via CADMesh.
G4VSolid * buildSolid(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s) override
Create (or fetch) a tessellated solid from a CAD file.
Definition buildSolid.cc:49
G4Volume * getOrCreateG4Volume(const std::string &volume_name, std::unordered_map< std::string, G4Volume * > *g4s)
Get or create a G4Volume wrapper entry in the map.
bool checkSolidDependencies(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Check whether all prerequisites to build a solid are satisfied.
Convenience container holding a Geant4 solid, logical, and physical volume.
Definition g4volume.h:52
std::shared_ptr< GLogger > log
std::string getDescription() const
const std::string & getG4Name() const
const std::optional< std::string > & getParameters() const
const std::optional< std::string > & getCopyOf() const
std::string getSystem() const
vector< string > getStringVectorFromStringWithDelimiter(const string &input, const string &x)