3 // by I. Hrivnacova, 27.07.2000
5 // See the class description in the header file.
7 #include "TG4XMLGeometryGenerator.h"
8 #include "TG4XMLConvertor.h"
9 #include "TG4Globals.h"
11 #include <G4Material.hh>
12 #include <G4VSolid.hh>
13 #include <G4LogicalVolume.hh>
14 #include <G4VPhysicalVolume.hh>
15 #include <G4PVPlacement.hh>
16 #include <G4PVReplica.hh>
17 #include <G4ThreeVector.hh>
18 #include <G4RotationMatrix.hh>
20 #include <g4std/iomanip>
21 #include <g4std/vector>
23 TG4XMLGeometryGenerator* TG4XMLGeometryGenerator::fgInstance = 0;
25 TG4XMLGeometryGenerator::TG4XMLGeometryGenerator()
29 TG4Globals::Exception(
30 "TG4XMLGeometryGenerator: attempt to create two instances of singleton.");
33 fConvertor = new TG4XMLConvertor(fOutFile);
36 TG4XMLGeometryGenerator::TG4XMLGeometryGenerator(const TG4XMLGeometryGenerator& right)
39 TG4Globals::Exception(
40 "TG4XMLGeometryGenerator: attempt to copy singleton.");
44 TG4XMLGeometryGenerator::~TG4XMLGeometryGenerator() {
50 TG4XMLGeometryGenerator&
51 TG4XMLGeometryGenerator::operator=(const TG4XMLGeometryGenerator& right)
53 // check assignement to self
54 if (this == &right) return *this;
56 TG4Globals::Exception(
57 "Attempt to assign TG4XMLGeometryGenerator singleton.");
65 void TG4XMLGeometryGenerator::CutName(G4String& name) const
67 // Removes spaces after the name if present.
70 G4int i = name.length();
71 while (name(--i) == ' ') name = name(0,i);
74 void TG4XMLGeometryGenerator::ProcessSolids(G4LogicalVolume* lv)
76 // Writes all solids of given logical volume.
79 G4VSolid* solid = lv->GetSolid();
80 G4String lvName = lv->GetName();
81 G4String material = lv->GetMaterial()->GetName();
82 fConvertor->WriteSolid(lvName, solid, material);
84 // store the name of logical volume in the set
85 fVolumeNames.insert(fVolumeNames.begin(), lvName);
88 G4int nofDaughters = lv->GetNoDaughters();
90 for (G4int i=0; i<nofDaughters; i++) {
91 //G4cout << "processing " << i << "th daughter of "
92 // << lv->GetName() << G4endl;
93 G4LogicalVolume* lvd = lv->GetDaughter(i)->GetLogicalVolume();
94 G4String lvdName = lvd->GetName();
96 if (fVolumeNames.find(lvdName) == fVolumeNames.end()) {
97 // process lvd only if it was not yet processed
103 void TG4XMLGeometryGenerator::ProcessMaterials(G4LogicalVolume* lv)
105 // Writes all materials of given logical volume.
108 G4Material* material = lv->GetMaterial();
110 // check if this material was already written
111 G4bool written = false;
112 G4String name = material->GetName();
114 if (fMaterialNames.find(name) != fMaterialNames.end()) written = true;
117 fConvertor->WriteMaterial(material);
118 fMaterialNames.insert(fMaterialNames.begin(), name);
121 // store the name of logical volume in the set
122 G4String lvName = lv->GetName();
123 fVolumeNames.insert(fVolumeNames.begin(), lvName);
125 G4int nofDaughters = lv->GetNoDaughters();
127 for (G4int i=0; i<nofDaughters; i++) {
128 G4LogicalVolume* lvd = lv->GetDaughter(i)->GetLogicalVolume();
129 G4String lvdName = lvd->GetName();
131 if (fVolumeNames.find(lvdName) == fVolumeNames.end()) {
132 // process lvd only if it was not yet processed
133 ProcessMaterials(lvd);
138 void TG4XMLGeometryGenerator::ProcessRotations(G4LogicalVolume* lv)
140 // Writes all rotation matrices of given logical volume.
143 G4String lvName = lv->GetName();
145 // store the name of logical volume in the set
146 fVolumeNames.insert(fVolumeNames.begin(), lvName);
148 G4int nofDaughters = lv->GetNoDaughters();
150 if (nofDaughters>0) {
152 for (i=0; i<nofDaughters; i++) {
154 G4VPhysicalVolume* pvd = lv->GetDaughter(i);
155 const G4RotationMatrix* kRotation = pvd->GetRotation();
157 fConvertor->WriteRotation(kRotation);
159 G4LogicalVolume* lvd = pvd->GetLogicalVolume();
160 G4String lvdName = lvd->GetName();
162 if (fVolumeNames.find(lvdName) == fVolumeNames.end()) {
163 // process lvd only if it was not yet processed
164 ProcessRotations(lvd);
170 void TG4XMLGeometryGenerator::ProcessLogicalVolume(G4LogicalVolume* lv)
172 // Writes logical volume tree.
175 G4int nofDaughters = lv->GetNoDaughters();
176 if (nofDaughters == 0) return;
179 G4String lvName = lv->GetName();
180 G4String name = lvName;
181 name.append("_comp");
182 fConvertor->OpenComposition(name);
186 for (i=0; i<nofDaughters; i++) {
187 // G4cout << "processing " << i << "th daughter of "
188 // << lv->GetName() << G4endl;
190 G4VPhysicalVolume* vpvd = lv->GetDaughter(i);
191 G4LogicalVolume* lvd = vpvd->GetLogicalVolume();
194 G4String lvName = lvd->GetName();
195 G4String compName = lvd->GetName();
196 compName.append("_comp");
197 G4int nd = lvd->GetNoDaughters();
199 G4PVPlacement* pvd = dynamic_cast<G4PVPlacement*>(vpvd);
202 G4ThreeVector position = vpvd->GetTranslation();
204 if (!vpvd->GetRotation()) {
205 fConvertor->WritePosition(lvName, position);
206 // if volume is not leaf node place its logical volume
208 fConvertor->WritePosition(compName, position);
211 const G4RotationMatrix* kMatrix = vpvd->GetObjectRotation();
212 fConvertor->WritePositionWithRotation(lvName, position, kMatrix);
214 fConvertor->WritePositionWithRotation(compName, position, kMatrix);
218 G4PVReplica* pvr = dynamic_cast<G4PVReplica*>(vpvd);
221 fConvertor->WriteReplica(lvName, pvr);
222 // if volume is not leaf node place its logical volume
224 fConvertor->WriteReplica(compName, pvr);
227 G4String text = "TG4XMLGeometryGenerator::ProcessLogicalVolume: \n";
228 text = text + " Limitation: \n";
229 text = text + " Other physical volumes than PVPlacement and PVReplica";
230 text = text + " are not implemented.";
231 TG4Globals::Exception(text);
237 fConvertor->CloseComposition();
238 fConvertor->WriteEmptyLine();
240 // store the name of logical volume in the set
241 fVolumeNames.insert(fVolumeNames.begin(), lvName);
244 for (i=0; i<nofDaughters; i++) {
245 G4LogicalVolume* lvd = lv->GetDaughter(i)->GetLogicalVolume();
246 G4String lvdName = lvd->GetName();
248 if (fVolumeNames.find(lvdName) == fVolumeNames.end()) {
249 // process lvd only if it was not yet processed
250 ProcessLogicalVolume(lvd);
255 void TG4XMLGeometryGenerator::ClearMaterialNames()
257 // Clears the set of material names.
260 fMaterialNames.erase(fMaterialNames.begin(), fMaterialNames.end());
263 void TG4XMLGeometryGenerator::ClearVolumeNames()
265 // Clears the set of volume names.
268 fVolumeNames.erase(fVolumeNames.begin(), fVolumeNames.end());
273 void TG4XMLGeometryGenerator::GenerateMaterials(
274 const G4String& version, const G4String& date,
275 const G4String& author, const G4String dtdVersion,
278 // Generates the XML material element containing
279 // all materials present in given logical volume.
283 fConvertor->OpenMaterials(version, date, author, dtdVersion);
284 fConvertor->WriteEmptyLine();
287 ProcessMaterials(lv);
288 fConvertor->WriteEmptyLine();
289 ClearMaterialNames();
293 fConvertor->CloseMaterials();
294 fConvertor->WriteEmptyLine();
297 void TG4XMLGeometryGenerator::GenerateSection(const G4String& name,
298 const G4String& version, const G4String& date,
299 const G4String& author, const G4String& topVolume,
302 // Generates the XML section element containing
303 // all geometry objects defined in given logical volume:
304 // rotation matrices, solids and volumes hierarchy.
308 fConvertor->OpenSection(name, version, date, author, topVolume);
309 fConvertor->WriteEmptyLine();
312 //ProcessRotations(lv);
313 //fConvertor->WriteEmptyLine();
315 //ClearVolumeNames();
319 fConvertor->WriteEmptyLine();
322 // process geometry tree
323 ProcessLogicalVolume(lv);
324 fConvertor->WriteEmptyLine();
328 fConvertor->CloseSection();
331 void TG4XMLGeometryGenerator::OpenFile(G4String filePath)
333 // Opens output file.
336 fOutFile.open(filePath, G4std::ios::out);
339 G4String text = "Cannot open ";
340 text = text + filePath;
341 TG4Globals::Warning(text);
344 // use FORTRAN compatibility output
345 fOutFile.setf(G4std::ios::fixed, G4std::ios::floatfield);
349 void TG4XMLGeometryGenerator::CloseFile()
351 // Closes output file.