G4OCCT 0.1.0
Geant4 interface to Open CASCADE Technology (OCCT) geometry definitions
Loading...
Searching...
No Matches
G4OCCT_STEPAssembly.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later
2// Copyright (C) 2026 G4OCCT Contributors
3
34
35// Two header worlds must not meet in the same TU:
36// DD4hep → ROOT → TString.h declares: extern void Printf(...)
37// G4OCCT → OCCT → Standard_CString.h declares: int Printf(...)
38// Keeping them in separate TUs (firewall pattern) resolves both this Printf
39// conflict and the Handle(Class) macro collision.
40// G4OCCT_STEPAssembly_impl.{hh,cc} is the OCCT-side TU; this file is the
41// DD4hep-side TU.
42#include <DD4hep/DetFactoryHelper.h>
43#include <DD4hep/Printout.h>
44
46
47#include <G4Material.hh>
48#include <G4NistManager.hh>
49
50#include <map>
51#include <stdexcept>
52#include <string>
53#include <vector>
54
55using namespace dd4hep;
56
57static Ref_t create_step_assembly(Detector& description, xml_h e, SensitiveDetector /*sens*/) {
58 xml_det_t x_det = e;
59 xml_comp_t x_step = x_det.child(_Unicode(step_file));
60 xml_comp_t x_pos = x_det.child(_Unicode(position));
61 xml_comp_t x_map = x_det.child(_Unicode(material_map));
62
63 std::string name = x_det.nameStr();
64 std::string path = x_step.attr<std::string>(_Unicode(path));
65
66 // ── Build the material map from the compact XML entries ───────────────────
67 std::map<std::string, G4Material*> materials;
68 for (xml_coll_t it(x_map, _Unicode(entry)); it; ++it) {
69 xml_comp_t x_entry = it;
70 std::string stepName = x_entry.attr<std::string>(_Unicode(step_name));
71 std::string dd4hepMatName = x_entry.attr<std::string>(_Unicode(dd4hep_material));
72
73 // Resolve the G4Material via NIST manager (already constructed by DD4hep
74 // material loading) — look up by the Geant4 material name.
75 G4Material* g4mat = G4NistManager::Instance()->FindOrBuildMaterial(dd4hepMatName);
76 if (!g4mat) {
77 // Fall back to the Geant4 material table (materials defined inline in the
78 // compact file are registered under their compact name, not a NIST name).
79 g4mat = G4Material::GetMaterial(dd4hepMatName, /*warn=*/false);
80 }
81 if (!g4mat) {
82 throw std::runtime_error("G4OCCT_STEPAssembly: Geant4 material '" + dd4hepMatName +
83 "' not found for STEP name '" + stepName + "'");
84 }
85 materials[stepName] = g4mat;
86 printout(DEBUG, "G4OCCT_STEPAssembly", "Mapped STEP material '%s' → G4Material '%s'",
87 stepName.c_str(), dd4hepMatName.c_str());
88 }
89
90 // ── Parse optional <sensitive_volumes> ───────────────────────────────────
91 std::vector<std::string> sensitiveNames;
92 if (x_det.hasChild(_Unicode(sensitive_volumes))) {
93 xml_comp_t x_svols = x_det.child(_Unicode(sensitive_volumes));
94 for (xml_coll_t it(x_svols, _Unicode(volume)); it; ++it) {
95 xml_comp_t x_vol = it;
96 sensitiveNames.push_back(x_vol.attr<std::string>(_Unicode(name)));
97 }
98 }
99
100 // ── Import the STEP assembly (OCCT side, separate TU) ────────────────────
101 int nConstituents = G4OCCT_ImportSTEPAssembly(path, materials, name, sensitiveNames);
102
103 // ── Create a DD4hep assembly container (no per-solid placements here) ────
104 // Phase 1 limitation: the STEP assembly is imported on the OCCT side and its
105 // constituent G4LogicalVolumes live in the Geant4 volume store, but they are
106 // not placed into this dd4hep::Assembly. The assembly is therefore empty
107 // from the TGeo/DD4hep perspective.
108 // @todo Phase 2: return per-solid placement data from the OCCT-side TU and
109 // populate dd4hepAssembly with TGeo placeholder volumes so DD4hep and
110 // visualisation tools can see the constituent geometry.
111 Assembly dd4hepAssembly(name + "_assembly");
112
113 printout(INFO, "G4OCCT_STEPAssembly",
114 "Imported STEP assembly '%s' from '%s'; %d constituent solid(s) on "
115 "OCCT side; created empty dd4hep::Assembly '%s' as top-level container",
116 name.c_str(), path.c_str(), nConstituents, (name + "_assembly").c_str());
117
118 // ── DetElement and placement ─────────────────────────────────────────────
119 DetElement det(name, x_det.id());
120 Position pos(x_pos.x(), x_pos.y(), x_pos.z());
121
122 PlacedVolume pv = description.pickMotherVolume(det).placeVolume(dd4hepAssembly, pos);
123 pv.addPhysVolID("system", x_det.id());
124 det.setPlacement(pv);
125 return det;
126}
127
128DECLARE_DETELEMENT(G4OCCT_STEPAssembly, create_step_assembly)
static Ref_t create_step_assembly(Detector &description, xml_h e, SensitiveDetector)
int G4OCCT_ImportSTEPAssembly(const std::string &path, const std::map< std::string, G4Material * > &materials, const std::string &detectorName, const std::vector< std::string > &)
Firewall bridge between the DD4hep plugin TU and G4OCCT/OCCT.