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