BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSGeometryWriter.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSDebug.hh"
19#include "BDSException.hh"
20#include "BDSGeometryWriter.hh"
21#include "BDSUtilities.hh"
22
23#include "globals.hh" // geant4 types / globals
24
25#ifdef USE_GDML
26#include "G4Colour.hh"
27#include "G4GDMLAuxStructType.hh"
28#include "G4GDMLParser.hh"
29#include "G4VisAttributes.hh"
30#endif
31
32#include "G4FileUtilities.hh"
33#include "G4String.hh"
34#include "G4TransportationManager.hh"
35
36#include <array>
37#include <map>
38#include <sstream>
39
40class G4VPhysicalVolume;
41
43const G4String BDSGeometryWriter::auxType = "bds_vrgba";
44
45BDSGeometryWriter::~BDSGeometryWriter()
46{;}
47
48BDSGeometryWriter::BDSGeometryWriter()
49{;}
50
51void BDSGeometryWriter::ExportGeometry(const G4String& geometryType,
52 const G4String& geometryFileName)
53{
54 if (geometryType == "gdml")
55 {
56#ifdef USE_GDML
57 WriteToGDML(geometryFileName);
58#else
59 throw BDSException(__METHOD_NAME__, "Unable to write out " + geometryFileName + ", as compiled without GDML support");
60#endif
61 }
62 else
63 {throw BDSException(__METHOD_NAME__, "unknown geometry export type \"" + geometryType + "\".");}
64}
65
66#ifdef USE_GDML
67void BDSGeometryWriter::WriteToGDML(const G4String& outputFileName,
68 G4VPhysicalVolume* volume)
69{
70 if (!volume)
71 {volume = G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume();}
72 // gdml parser throws exception if file exists. Delete file in that case
73 if (BDS::FileExists(outputFileName))
74 {
75 G4FileUtilities fileUtilities;
76 G4cout << "Removing existing file: \"" << outputFileName << "\"" << G4endl;
77 fileUtilities.DeleteFile(outputFileName, "");
78 }
79
80 // if the filename is in part a path to a directory, check that directory exists
81 // otherwise the GDML writer will give an abort trap bad access
82 if (BDS::StrContains(outputFileName, "/"))
83 {
84 G4String dirName = BDS::GetFullPath(outputFileName, true);
85 if (!BDS::DirectoryExists(dirName))
86 {throw BDSException(__METHOD_NAME__, "directory \"" + dirName + "\" does not exist - please create it first.");}
87 }
88
89 auto volToAuxMap = PrepareColourInformation(volume);
90
91 G4GDMLParser parser;
92 RegisterVolumeAuxiliaryInformation(parser, volToAuxMap);
93 parser.Write(outputFileName, volume, true);
94}
95
97 const G4Colour& colour)
98{
99 std::array<G4double, 4> numbers = {colour.GetRed(),
100 colour.GetGreen(),
101 colour.GetBlue(),
102 colour.GetAlpha()};
103 std::stringstream ss;
104 ss << visible << " ";
105 for (auto cv : numbers)
106 {ss << std::setprecision(4) << cv << " ";} // colours are already normalised 0 to 1.
107 G4String result = ss.str();
108 result.pop_back(); // remove last space
109 return result;
110}
111
112std::map<G4LogicalVolume*, G4GDMLAuxStructType> BDSGeometryWriter::PrepareColourInformation(G4VPhysicalVolume* volume)
113{
114 std::map<G4LogicalVolume*, G4GDMLAuxStructType> result;
115 auto lv = volume->GetLogicalVolume();
116 AddLVColour(result, lv);
117 return result;
118}
119
121 const std::map<G4LogicalVolume*, G4GDMLAuxStructType>& volToAuxMap)
122{
123 for (const auto& lvAux : volToAuxMap)
124 {parser.AddVolumeAuxiliary(lvAux.second, lvAux.first);}
125}
126
127void BDSGeometryWriter::AddLVColour(std::map<G4LogicalVolume*, G4GDMLAuxStructType>& map, G4LogicalVolume* lv)
128{
129 const G4VisAttributes* visAttr = lv->GetVisAttributes();
130 if (visAttr)
131 {
132 G4GDMLAuxStructType c;
133 c.type = auxType;
134 c.value = ColourToVRGBAString(visAttr->IsVisible(), visAttr->GetColour());
135 c.auxList = nullptr;
136 map[lv] = c;
137 }
138 for (std::size_t i = 0; i < lv->GetNoDaughters(); i++)
139 {
140 auto dlv = lv->GetDaughter(i)->GetLogicalVolume();
141 AddLVColour(map, dlv);
142 }
143}
144
145#endif
General exception with possible name of object and message.
void WriteToGDML(const G4String &outputFileName, G4VPhysicalVolume *volume=nullptr)
static std::map< G4LogicalVolume *, G4GDMLAuxStructType > PrepareColourInformation(G4VPhysicalVolume *volume)
static const G4String auxType
"bds_vrgba" - short to minimise output file size: "bdsim visibility rgba"
static void AddLVColour(std::map< G4LogicalVolume *, G4GDMLAuxStructType > &, G4LogicalVolume *lv)
static G4String ColourToVRGBAString(G4bool visible, const G4Colour &colour)
static void RegisterVolumeAuxiliaryInformation(G4GDMLParser &parser, const std::map< G4LogicalVolume *, G4GDMLAuxStructType > &volToAuxMap)
Register the auxiliary information with the GDML parser (writer).
void ExportGeometry(const G4String &geometryType, const G4String &geometryFileName)
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4bool DirectoryExists(const G4String &path)
Check if directory exists.
G4bool FileExists(const G4String &filename)
Checks if filename exists.