160 for (
const auto& xmlFile : fMaterialXmlFiles) {
164 materialMap.
Merge(loaded);
171 bool hasBounds =
false;
174 std::vector<G4LogicalVolume*> solidLogicals;
175 for (std::size_t i = 0; i < fSolidEntries.size(); ++i) {
176 const auto& entry = fSolidEntries[i];
177 auto name = std::filesystem::path(entry.file).stem().string();
178 if (fSolidEntries.size() > 1) {
179 name +=
"_" + std::to_string(i);
185 BRepBndLib::AddOptimal(solid->GetOCCTShape(), bbox, Standard_False);
186 totalBounds.Add(bbox);
190 G4Material* mat =
nullptr;
191 if (!entry.material.empty()) {
192 if (materialMap.
Contains(entry.material)) {
193 mat = materialMap.
Resolve(entry.material);
195 mat = G4NistManager::Instance()->FindOrBuildMaterial(entry.material);
197 G4Exception(
"G4OCCTDetectorConstruction::Construct",
"G4OCCT_App_MatNotFound",
199 (
"Cannot resolve material '" + entry.material +
"' for solid '" + name +
"'")
204 mat = G4NistManager::Instance()->FindOrBuildMaterial(
"G4_AIR");
207 auto* lv =
new G4LogicalVolume(solid, mat, name +
"_lv");
208 solidLogicals.push_back(lv);
212 std::vector<std::unique_ptr<G4OCCTAssemblyVolume>> assemblies;
213 for (
const auto& entry : fAssemblyEntries) {
214 auto assembly = std::unique_ptr<G4OCCTAssemblyVolume>(
216 for (
const auto& [lvName, lv] : assembly->GetLogicalVolumes()) {
217 if (
auto* occSolid =
dynamic_cast<G4OCCTSolid*
>(lv->GetSolid())) {
219 BRepBndLib::AddOptimal(occSolid->GetOCCTShape(), bbox, Standard_False);
220 totalBounds.Add(bbox);
224 assemblies.push_back(std::move(assembly));
228 G4ThreeVector halfSize = fWorldHalfSize;
229 if (halfSize.mag2() == 0.0) {
230 if (hasBounds && !totalBounds.IsVoid()) {
231 Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
232 totalBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
233 const double pad = 1.1;
234 halfSize = G4ThreeVector(pad * std::max(std::abs(xMax), std::abs(xMin)) * mm,
235 pad * std::max(std::abs(yMax), std::abs(yMin)) * mm,
236 pad * std::max(std::abs(zMax), std::abs(zMin)) * mm);
238 for (
int k = 0; k < 3; ++k) {
239 if (halfSize[k] < 100.0 * mm)
240 halfSize[k] = 100.0 * mm;
243 halfSize = G4ThreeVector(500 * mm, 500 * mm, 500 * mm);
248 auto* worldMat = G4NistManager::Instance()->FindOrBuildMaterial(fWorldMaterial);
250 G4Exception(
"G4OCCTDetectorConstruction::Construct",
"G4OCCT_App_WorldMat", FatalException,
251 (
"Cannot find world material: " + std::string(fWorldMaterial)).c_str());
254 auto* worldSolid =
new G4Box(
"world", halfSize.x(), halfSize.y(), halfSize.z());
255 auto* worldLV =
new G4LogicalVolume(worldSolid, worldMat,
"world_lv");
257 new G4PVPlacement(
nullptr, G4ThreeVector(), worldLV,
"world_pv",
nullptr,
false, 0);
260 for (std::size_t i = 0; i < solidLogicals.size(); ++i) {
261 auto* lv = solidLogicals[i];
262 new G4PVPlacement(
nullptr, G4ThreeVector(), lv, lv->GetName() +
"_pv", worldLV,
false,
263 static_cast<G4int
>(i));
267 for (
auto& assembly : assemblies) {
268 G4Transform3D identity;
269 assembly->MakeImprint(worldLV, identity);