source: trunk/source/persistency/gdml/src/G4GDMLWriteStructure.cc

Last change on this file was 1347, checked in by garnier, 15 years ago

geant4 tag 9.4

File size: 18.7 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id: G4GDMLWriteStructure.cc,v 1.83 2010/10/14 16:19:40 gcosmo Exp $
28// GEANT4 tag $Name: gdml-V09-03-09 $
29//
30// class G4GDMLWriteStructure Implementation
31//
32// Original author: Zoltan Torzsok, November 2007
33//
34// --------------------------------------------------------------------
35
36#include "G4GDMLWriteStructure.hh"
37
38#include "G4Material.hh"
39#include "G4ReflectedSolid.hh"
40#include "G4DisplacedSolid.hh"
41#include "G4LogicalVolumeStore.hh"
42#include "G4PhysicalVolumeStore.hh"
43#include "G4PVDivision.hh"
44#include "G4PVReplica.hh"
45#include "G4OpticalSurface.hh"
46#include "G4LogicalSkinSurface.hh"
47#include "G4LogicalBorderSurface.hh"
48
49G4GDMLWriteStructure::G4GDMLWriteStructure()
50 : G4GDMLWriteParamvol()
51{
52}
53
54G4GDMLWriteStructure::~G4GDMLWriteStructure()
55{
56}
57
58void
59G4GDMLWriteStructure::DivisionvolWrite(xercesc::DOMElement* volumeElement,
60 const G4PVDivision* const divisionvol)
61{
62 EAxis axis = kUndefined;
63 G4int number = 0;
64 G4double width = 0.0;
65 G4double offset = 0.0;
66 G4bool consuming = false;
67
68 divisionvol->GetReplicationData(axis,number,width,offset,consuming);
69 axis = divisionvol->GetDivisionAxis();
70
71 G4String unitString("mm");
72 G4String axisString("kUndefined");
73 if (axis==kXAxis) { axisString = "kXAxis"; }
74 else if (axis==kYAxis) { axisString = "kYAxis"; }
75 else if (axis==kZAxis) { axisString = "kZAxis"; }
76 else if (axis==kRho) { axisString = "kRho"; }
77 else if (axis==kPhi) { axisString = "kPhi"; unitString = "rad"; }
78
79 const G4String name
80 = GenerateName(divisionvol->GetName(),divisionvol);
81 const G4String volumeref
82 = GenerateName(divisionvol->GetLogicalVolume()->GetName(),
83 divisionvol->GetLogicalVolume());
84
85 xercesc::DOMElement* divisionvolElement = NewElement("divisionvol");
86 divisionvolElement->setAttributeNode(NewAttribute("axis",axisString));
87 divisionvolElement->setAttributeNode(NewAttribute("number",number));
88 divisionvolElement->setAttributeNode(NewAttribute("width",width));
89 divisionvolElement->setAttributeNode(NewAttribute("offset",offset));
90 divisionvolElement->setAttributeNode(NewAttribute("unit",unitString));
91 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
92 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
93 divisionvolElement->appendChild(volumerefElement);
94 volumeElement->appendChild(divisionvolElement);
95}
96
97void G4GDMLWriteStructure::PhysvolWrite(xercesc::DOMElement* volumeElement,
98 const G4VPhysicalVolume* const physvol,
99 const G4Transform3D& T,
100 const G4String& ModuleName)
101{
102 HepGeom::Scale3D scale;
103 HepGeom::Rotate3D rotate;
104 HepGeom::Translate3D translate;
105
106 T.getDecomposition(scale,rotate,translate);
107
108 const G4ThreeVector scl(scale(0,0),scale(1,1),scale(2,2));
109 const G4ThreeVector rot = GetAngles(rotate.getRotation());
110 const G4ThreeVector pos = T.getTranslation();
111
112 const G4String name = GenerateName(physvol->GetName(),physvol);
113
114 xercesc::DOMElement* physvolElement = NewElement("physvol");
115 physvolElement->setAttributeNode(NewAttribute("name",name));
116 volumeElement->appendChild(physvolElement);
117
118 const G4String volumeref
119 = GenerateName(physvol->GetLogicalVolume()->GetName(),
120 physvol->GetLogicalVolume());
121
122 if (ModuleName.empty())
123 {
124 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
125 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
126 physvolElement->appendChild(volumerefElement);
127 }
128 else
129 {
130 xercesc::DOMElement* fileElement = NewElement("file");
131 fileElement->setAttributeNode(NewAttribute("name",ModuleName));
132 fileElement->setAttributeNode(NewAttribute("volname",volumeref));
133 physvolElement->appendChild(fileElement);
134 }
135
136 if (std::fabs(pos.x()) > kLinearPrecision
137 || std::fabs(pos.y()) > kLinearPrecision
138 || std::fabs(pos.z()) > kLinearPrecision)
139 {
140 PositionWrite(physvolElement,name+"_pos",pos);
141 }
142 if (std::fabs(rot.x()) > kAngularPrecision
143 || std::fabs(rot.y()) > kAngularPrecision
144 || std::fabs(rot.z()) > kAngularPrecision)
145 {
146 RotationWrite(physvolElement,name+"_rot",rot);
147 }
148 if (std::fabs(scl.x()-1.0) > kRelativePrecision
149 || std::fabs(scl.y()-1.0) > kRelativePrecision
150 || std::fabs(scl.z()-1.0) > kRelativePrecision)
151 {
152 ScaleWrite(physvolElement,name+"_scl",scl);
153 }
154}
155
156void G4GDMLWriteStructure::ReplicavolWrite(xercesc::DOMElement* volumeElement,
157 const G4VPhysicalVolume* const replicavol)
158{
159 EAxis axis = kUndefined;
160 G4int number = 0;
161 G4double width = 0.0;
162 G4double offset = 0.0;
163 G4bool consuming = false;
164 G4String unitString("mm");
165
166 replicavol->GetReplicationData(axis,number,width,offset,consuming);
167
168 const G4String volumeref
169 = GenerateName(replicavol->GetLogicalVolume()->GetName(),
170 replicavol->GetLogicalVolume());
171
172 xercesc::DOMElement* replicavolElement = NewElement("replicavol");
173 replicavolElement->setAttributeNode(NewAttribute("number",number));
174 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
175 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
176 replicavolElement->appendChild(volumerefElement);
177 xercesc::DOMElement* replicateElement = NewElement("replicate_along_axis");
178 replicavolElement->appendChild(replicateElement);
179
180 xercesc::DOMElement* dirElement = NewElement("direction");
181 if(axis==kXAxis)
182 { dirElement->setAttributeNode(NewAttribute("x","1")); }
183 else if(axis==kYAxis)
184 { dirElement->setAttributeNode(NewAttribute("y","1")); }
185 else if(axis==kZAxis)
186 { dirElement->setAttributeNode(NewAttribute("z","1")); }
187 else if(axis==kRho)
188 { dirElement->setAttributeNode(NewAttribute("rho","1")); }
189 else if(axis==kPhi)
190 { dirElement->setAttributeNode(NewAttribute("phi","1"));
191 unitString="rad"; }
192 replicateElement->appendChild(dirElement);
193
194 xercesc::DOMElement* widthElement = NewElement("width");
195 widthElement->setAttributeNode(NewAttribute("value",width));
196 widthElement->setAttributeNode(NewAttribute("unit",unitString));
197 replicateElement->appendChild(widthElement);
198
199 xercesc::DOMElement* offsetElement = NewElement("offset");
200 offsetElement->setAttributeNode(NewAttribute("value",offset));
201 offsetElement->setAttributeNode(NewAttribute("unit",unitString));
202 replicateElement->appendChild(offsetElement);
203
204 volumeElement->appendChild(replicavolElement);
205}
206
207void G4GDMLWriteStructure::
208BorderSurfaceCache(const G4LogicalBorderSurface* const bsurf)
209{
210 if (!bsurf) { return; }
211
212 const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
213
214 // Generate the new element for border-surface
215 //
216 xercesc::DOMElement* borderElement = NewElement("bordersurface");
217 borderElement->setAttributeNode(NewAttribute("name", bsurf->GetName()));
218 borderElement->setAttributeNode(NewAttribute("surfaceproperty",
219 psurf->GetName()));
220
221 const G4String volumeref1 = GenerateName(bsurf->GetVolume1()->GetName(),
222 bsurf->GetVolume1());
223 const G4String volumeref2 = GenerateName(bsurf->GetVolume2()->GetName(),
224 bsurf->GetVolume2());
225 xercesc::DOMElement* volumerefElement1 = NewElement("physvolref");
226 xercesc::DOMElement* volumerefElement2 = NewElement("physvolref");
227 volumerefElement1->setAttributeNode(NewAttribute("ref",volumeref1));
228 volumerefElement2->setAttributeNode(NewAttribute("ref",volumeref2));
229 borderElement->appendChild(volumerefElement1);
230 borderElement->appendChild(volumerefElement2);
231
232 if (FindOpticalSurface(psurf))
233 {
234 const G4OpticalSurface* opsurf =
235 dynamic_cast<const G4OpticalSurface*>(psurf);
236 if (!opsurf)
237 {
238 G4Exception("G4GDMLWriteStructure::BorderSurfaceCache()",
239 "InvalidSetup", FatalException, "No optical surface found!");
240 return;
241 }
242 OpticalSurfaceWrite(solidsElement, opsurf);
243 }
244
245 borderElementVec.push_back(borderElement);
246}
247
248void G4GDMLWriteStructure::
249SkinSurfaceCache(const G4LogicalSkinSurface* const ssurf)
250{
251 if (!ssurf) { return; }
252
253 const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
254
255 // Generate the new element for border-surface
256 //
257 xercesc::DOMElement* skinElement = NewElement("skinsurface");
258 skinElement->setAttributeNode(NewAttribute("name", ssurf->GetName()));
259 skinElement->setAttributeNode(NewAttribute("surfaceproperty",
260 psurf->GetName()));
261
262 const G4String volumeref = GenerateName(ssurf->GetLogicalVolume()->GetName(),
263 ssurf->GetLogicalVolume());
264 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
265 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
266 skinElement->appendChild(volumerefElement);
267
268 if (FindOpticalSurface(psurf))
269 {
270 const G4OpticalSurface* opsurf =
271 dynamic_cast<const G4OpticalSurface*>(psurf);
272 if (!opsurf)
273 {
274 G4Exception("G4GDMLWriteStructure::SkinSurfaceCache()",
275 "InvalidSetup", FatalException, "No optical surface found!");
276 return;
277 }
278 OpticalSurfaceWrite(solidsElement, opsurf);
279 }
280
281 skinElementVec.push_back(skinElement);
282}
283
284G4bool G4GDMLWriteStructure::FindOpticalSurface(const G4SurfaceProperty* psurf)
285{
286 const G4OpticalSurface* osurf = dynamic_cast<const G4OpticalSurface*>(psurf);
287 std::vector<const G4OpticalSurface*>::const_iterator pos;
288 pos = std::find(opt_vec.begin(), opt_vec.end(), osurf);
289 if (pos != opt_vec.end()) { return false; } // item already created!
290
291 opt_vec.push_back(osurf); // cache it for future reference
292 return true;
293}
294
295const G4LogicalSkinSurface*
296G4GDMLWriteStructure::GetSkinSurface(const G4LogicalVolume* const lvol)
297{
298 G4LogicalSkinSurface* surf = 0;
299 G4int nsurf = G4LogicalSkinSurface::GetNumberOfSkinSurfaces();
300 if (nsurf)
301 {
302 const G4LogicalSkinSurfaceTable* stable =
303 G4LogicalSkinSurface::GetSurfaceTable();
304 std::vector<G4LogicalSkinSurface*>::const_iterator pos;
305 for (pos = stable->begin(); pos != stable->end(); pos++)
306 {
307 if (lvol == (*pos)->GetLogicalVolume())
308 {
309 surf = *pos; break;
310 }
311 }
312 }
313 return surf;
314}
315
316const G4LogicalBorderSurface*
317G4GDMLWriteStructure::GetBorderSurface(const G4VPhysicalVolume* const pvol)
318{
319 G4LogicalBorderSurface* surf = 0;
320 G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
321 if (nsurf)
322 {
323 const G4LogicalBorderSurfaceTable* btable =
324 G4LogicalBorderSurface::GetSurfaceTable();
325 std::vector<G4LogicalBorderSurface*>::const_iterator pos;
326 for (pos = btable->begin(); pos != btable->end(); pos++)
327 {
328 if (pvol == (*pos)->GetVolume1()) // just the first in the couple
329 { // is enough
330 surf = *pos; break;
331 }
332 }
333 }
334 return surf;
335}
336
337void G4GDMLWriteStructure::SurfacesWrite()
338{
339 G4cout << "G4GDML: Writing surfaces..." << G4endl;
340
341 std::vector<xercesc::DOMElement*>::const_iterator pos;
342 for (pos = skinElementVec.begin(); pos != skinElementVec.end(); pos++)
343 {
344 structureElement->appendChild(*pos);
345 }
346 for (pos = borderElementVec.begin(); pos != borderElementVec.end(); pos++)
347 {
348 structureElement->appendChild(*pos);
349 }
350}
351
352void G4GDMLWriteStructure::StructureWrite(xercesc::DOMElement* gdmlElement)
353{
354 G4cout << "G4GDML: Writing structure..." << G4endl;
355
356 structureElement = NewElement("structure");
357 gdmlElement->appendChild(structureElement);
358}
359
360G4Transform3D G4GDMLWriteStructure::
361TraverseVolumeTree(const G4LogicalVolume* const volumePtr, const G4int depth)
362{
363 if (VolumeMap().find(volumePtr) != VolumeMap().end())
364 {
365 return VolumeMap()[volumePtr]; // Volume is already processed
366 }
367
368 G4VSolid* solidPtr = volumePtr->GetSolid();
369 G4Transform3D R,invR;
370 G4int trans=0;
371
372 while (true) // Solve possible displacement/reflection
373 { // of the referenced solid!
374 if (trans>maxTransforms)
375 {
376 G4String ErrorMessage = "Referenced solid in volume '"
377 + volumePtr->GetName()
378 + "' was displaced/reflected too many times!";
379 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
380 "InvalidSetup", FatalException, ErrorMessage);
381 }
382
383 if (G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
384 {
385 R = R*refl->GetTransform3D();
386 solidPtr = refl->GetConstituentMovedSolid();
387 trans++;
388 continue;
389 }
390
391 if (G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
392 {
393 R = R*G4Transform3D(disp->GetObjectRotation(),
394 disp->GetObjectTranslation());
395 solidPtr = disp->GetConstituentMovedSolid();
396 trans++;
397 continue;
398 }
399
400 break;
401 }
402
403 // Only compute the inverse when necessary!
404 //
405 if (trans>0) { invR = R.inverse(); }
406
407 const G4String name
408 = GenerateName(volumePtr->GetName(),volumePtr);
409 const G4String materialref
410 = GenerateName(volumePtr->GetMaterial()->GetName(),
411 volumePtr->GetMaterial());
412 const G4String solidref
413 = GenerateName(solidPtr->GetName(),solidPtr);
414
415 xercesc::DOMElement* volumeElement = NewElement("volume");
416 volumeElement->setAttributeNode(NewAttribute("name",name));
417 xercesc::DOMElement* materialrefElement = NewElement("materialref");
418 materialrefElement->setAttributeNode(NewAttribute("ref",materialref));
419 volumeElement->appendChild(materialrefElement);
420 xercesc::DOMElement* solidrefElement = NewElement("solidref");
421 solidrefElement->setAttributeNode(NewAttribute("ref",solidref));
422 volumeElement->appendChild(solidrefElement);
423
424 const G4int daughterCount = volumePtr->GetNoDaughters();
425
426 for (G4int i=0;i<daughterCount;i++) // Traverse all the children!
427 {
428 const G4VPhysicalVolume* const physvol = volumePtr->GetDaughter(i);
429 const G4String ModuleName = Modularize(physvol,depth);
430
431 G4Transform3D daughterR;
432
433 if (ModuleName.empty()) // Check if subtree requested to be
434 { // a separate module!
435 daughterR = TraverseVolumeTree(physvol->GetLogicalVolume(),depth+1);
436 }
437 else
438 {
439 G4GDMLWriteStructure writer;
440 daughterR = writer.Write(ModuleName,physvol->GetLogicalVolume(),
441 SchemaLocation,depth+1);
442 }
443
444 if (const G4PVDivision* const divisionvol
445 = dynamic_cast<const G4PVDivision*>(physvol)) // Is it division?
446 {
447 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
448 {
449 G4String ErrorMessage = "Division volume in '"
450 + name
451 + "' can not be related to reflected solid!";
452 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
453 "InvalidSetup", FatalException, ErrorMessage);
454 }
455 DivisionvolWrite(volumeElement,divisionvol);
456 } else
457 if (physvol->IsParameterised()) // Is it a paramvol?
458 {
459 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
460 {
461 G4String ErrorMessage = "Parameterised volume in '"
462 + name
463 + "' can not be related to reflected solid!";
464 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
465 "InvalidSetup", FatalException, ErrorMessage);
466 }
467 ParamvolWrite(volumeElement,physvol);
468 } else
469 if (physvol->IsReplicated()) // Is it a replicavol?
470 {
471 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
472 {
473 G4String ErrorMessage = "Replica volume in '"
474 + name
475 + "' can not be related to reflected solid!";
476 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
477 "InvalidSetup", FatalException, ErrorMessage);
478 }
479 ReplicavolWrite(volumeElement,physvol);
480 }
481 else // Is it a physvol?
482 {
483 G4RotationMatrix rot;
484
485 if (physvol->GetFrameRotation() != 0)
486 {
487 rot = *(physvol->GetFrameRotation());
488 }
489 G4Transform3D P(rot,physvol->GetObjectTranslation());
490 PhysvolWrite(volumeElement,physvol,invR*P*daughterR,ModuleName);
491 }
492 BorderSurfaceCache(GetBorderSurface(physvol));
493 }
494
495 structureElement->appendChild(volumeElement);
496 // Append the volume AFTER traversing the children so that
497 // the order of volumes will be correct!
498
499 VolumeMap()[volumePtr] = R;
500
501 AddExtension(volumeElement, volumePtr);
502 // Add any possible user defined extension attached to a volume
503
504 AddMaterial(volumePtr->GetMaterial());
505 // Add the involved materials and solids!
506
507 AddSolid(solidPtr);
508
509 SkinSurfaceCache(GetSkinSurface(volumePtr));
510
511 return R;
512}
Note: See TracBrowser for help on using the repository browser.