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

Last change on this file since 1236 was 1228, checked in by garnier, 16 years ago

update geant4.9.3 tag

File size: 18.2 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.80 2009/04/24 15:34:20 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-03 $
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
70 G4String unitString("mm");
71 G4String axisString("kUndefined");
72 if (axis==kXAxis) { axisString = "kXAxis"; }
73 else if (axis==kYAxis) { axisString = "kYAxis"; }
74 else if (axis==kZAxis) { axisString = "kZAxis"; }
75 else if (axis==kRho) { axisString = "kRho"; }
76 else if (axis==kPhi) { axisString = "kPhi"; unitString = "degree"; }
77
78 const G4String name
79 = GenerateName(divisionvol->GetName(),divisionvol);
80 const G4String volumeref
81 = GenerateName(divisionvol->GetLogicalVolume()->GetName(),
82 divisionvol->GetLogicalVolume());
83
84 xercesc::DOMElement* divisionvolElement = NewElement("divisionvol");
85 divisionvolElement->setAttributeNode(NewAttribute("axis",axisString));
86 divisionvolElement->setAttributeNode(NewAttribute("number",number));
87 divisionvolElement->setAttributeNode(NewAttribute("width",width));
88 divisionvolElement->setAttributeNode(NewAttribute("offset",offset));
89 divisionvolElement->setAttributeNode(NewAttribute("unit",unitString));
90 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
91 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
92 divisionvolElement->appendChild(volumerefElement);
93 volumeElement->appendChild(divisionvolElement);
94}
95
96void G4GDMLWriteStructure::PhysvolWrite(xercesc::DOMElement* volumeElement,
97 const G4VPhysicalVolume* const physvol,
98 const G4Transform3D& T,
99 const G4String& ModuleName)
100{
101 HepGeom::Scale3D scale;
102 HepGeom::Rotate3D rotate;
103 HepGeom::Translate3D translate;
104
105 T.getDecomposition(scale,rotate,translate);
106
107 const G4ThreeVector scl(scale(0,0),scale(1,1),scale(2,2));
108 const G4ThreeVector rot = GetAngles(rotate.getRotation());
109 const G4ThreeVector pos = T.getTranslation();
110
111 const G4String name = GenerateName(physvol->GetName(),physvol);
112
113 xercesc::DOMElement* physvolElement = NewElement("physvol");
114 physvolElement->setAttributeNode(NewAttribute("name",name));
115 volumeElement->appendChild(physvolElement);
116
117 const G4String volumeref
118 = GenerateName(physvol->GetLogicalVolume()->GetName(),
119 physvol->GetLogicalVolume());
120
121 if (ModuleName.empty())
122 {
123 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
124 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
125 physvolElement->appendChild(volumerefElement);
126 }
127 else
128 {
129 xercesc::DOMElement* fileElement = NewElement("file");
130 fileElement->setAttributeNode(NewAttribute("name",ModuleName));
131 fileElement->setAttributeNode(NewAttribute("volname",volumeref));
132 physvolElement->appendChild(fileElement);
133 }
134
135 if (std::fabs(pos.x()) > kLinearPrecision
136 || std::fabs(pos.y()) > kLinearPrecision
137 || std::fabs(pos.z()) > kLinearPrecision)
138 {
139 PositionWrite(physvolElement,name+"_pos",pos);
140 }
141 if (std::fabs(rot.x()) > kAngularPrecision
142 || std::fabs(rot.y()) > kAngularPrecision
143 || std::fabs(rot.z()) > kAngularPrecision)
144 {
145 RotationWrite(physvolElement,name+"_rot",rot);
146 }
147 if (std::fabs(scl.x()-1.0) > kRelativePrecision
148 || std::fabs(scl.y()-1.0) > kRelativePrecision
149 || std::fabs(scl.z()-1.0) > kRelativePrecision)
150 {
151 ScaleWrite(physvolElement,name+"_scl",scl);
152 }
153}
154
155void G4GDMLWriteStructure::ReplicavolWrite(xercesc::DOMElement* volumeElement,
156 const G4VPhysicalVolume* const replicavol)
157{
158 EAxis axis = kUndefined;
159 G4int number = 0;
160 G4double width = 0.0;
161 G4double offset = 0.0;
162 G4bool consuming = false;
163 G4String unitString("mm");
164
165 replicavol->GetReplicationData(axis,number,width,offset,consuming);
166
167 const G4String volumeref
168 = GenerateName(replicavol->GetLogicalVolume()->GetName(),
169 replicavol->GetLogicalVolume());
170
171 xercesc::DOMElement* replicavolElement = NewElement("replicavol");
172 replicavolElement->setAttributeNode(NewAttribute("number",number));
173 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
174 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
175 replicavolElement->appendChild(volumerefElement);
176 xercesc::DOMElement* replicateElement = NewElement("replicate_along_axis");
177 replicavolElement->appendChild(replicateElement);
178
179 xercesc::DOMElement* dirElement = NewElement("direction");
180 if(axis==kXAxis)
181 { dirElement->setAttributeNode(NewAttribute("x","1")); }
182 else if(axis==kYAxis)
183 { dirElement->setAttributeNode(NewAttribute("y","1")); }
184 else if(axis==kZAxis)
185 { dirElement->setAttributeNode(NewAttribute("z","1")); }
186 else if(axis==kRho)
187 { dirElement->setAttributeNode(NewAttribute("rho","1")); }
188 else if(axis==kPhi)
189 { dirElement->setAttributeNode(NewAttribute("phi","1")); }
190 replicateElement->appendChild(dirElement);
191
192 xercesc::DOMElement* widthElement = NewElement("width");
193 widthElement->setAttributeNode(NewAttribute("value",width));
194 widthElement->setAttributeNode(NewAttribute("unit",unitString));
195 replicateElement->appendChild(widthElement);
196
197 xercesc::DOMElement* offsetElement = NewElement("offset");
198 offsetElement->setAttributeNode(NewAttribute("value",offset));
199 offsetElement->setAttributeNode(NewAttribute("unit",unitString));
200 replicateElement->appendChild(offsetElement);
201
202 volumeElement->appendChild(replicavolElement);
203}
204
205void G4GDMLWriteStructure::
206BorderSurfaceCache(const G4LogicalBorderSurface* const bsurf)
207{
208 if (!bsurf) { return; }
209
210 const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
211
212 // Generate the new element for border-surface
213 //
214 xercesc::DOMElement* borderElement = NewElement("bordersurface");
215 borderElement->setAttributeNode(NewAttribute("name", bsurf->GetName()));
216 borderElement->setAttributeNode(NewAttribute("surfaceproperty",
217 psurf->GetName()));
218
219 const G4String volumeref1 = GenerateName(bsurf->GetVolume1()->GetName(),
220 bsurf->GetVolume1());
221 const G4String volumeref2 = GenerateName(bsurf->GetVolume2()->GetName(),
222 bsurf->GetVolume2());
223 xercesc::DOMElement* volumerefElement1 = NewElement("physvolref");
224 xercesc::DOMElement* volumerefElement2 = NewElement("physvolref");
225 volumerefElement1->setAttributeNode(NewAttribute("ref",volumeref1));
226 volumerefElement2->setAttributeNode(NewAttribute("ref",volumeref2));
227 borderElement->appendChild(volumerefElement1);
228 borderElement->appendChild(volumerefElement2);
229
230 if (FindOpticalSurface(psurf))
231 {
232 OpticalSurfaceWrite(solidsElement,
233 dynamic_cast<const G4OpticalSurface*>(psurf));
234 }
235
236 borderElementVec.push_back(borderElement);
237}
238
239void G4GDMLWriteStructure::
240SkinSurfaceCache(const G4LogicalSkinSurface* const ssurf)
241{
242 if (!ssurf) { return; }
243
244 const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
245
246 // Generate the new element for border-surface
247 //
248 xercesc::DOMElement* skinElement = NewElement("skinsurface");
249 skinElement->setAttributeNode(NewAttribute("name", ssurf->GetName()));
250 skinElement->setAttributeNode(NewAttribute("surfaceproperty",
251 psurf->GetName()));
252
253 const G4String volumeref = GenerateName(ssurf->GetLogicalVolume()->GetName(),
254 ssurf->GetLogicalVolume());
255 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
256 volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
257 skinElement->appendChild(volumerefElement);
258
259 if (FindOpticalSurface(psurf))
260 {
261 OpticalSurfaceWrite(solidsElement,
262 dynamic_cast<const G4OpticalSurface*>(psurf));
263 }
264
265 skinElementVec.push_back(skinElement);
266}
267
268G4bool G4GDMLWriteStructure::FindOpticalSurface(const G4SurfaceProperty* psurf)
269{
270 const G4OpticalSurface* osurf = dynamic_cast<const G4OpticalSurface*>(psurf);
271 std::vector<const G4OpticalSurface*>::const_iterator pos;
272 pos = std::find(opt_vec.begin(), opt_vec.end(), osurf);
273 if (pos != opt_vec.end()) { return false; } // item already created!
274
275 opt_vec.push_back(osurf); // cache it for future reference
276 return true;
277}
278
279const G4LogicalSkinSurface*
280G4GDMLWriteStructure::GetSkinSurface(const G4LogicalVolume* const lvol)
281{
282 G4LogicalSkinSurface* surf = 0;
283 G4int nsurf = G4LogicalSkinSurface::GetNumberOfSkinSurfaces();
284 if (nsurf)
285 {
286 const G4LogicalSkinSurfaceTable* stable =
287 G4LogicalSkinSurface::GetSurfaceTable();
288 std::vector<G4LogicalSkinSurface*>::const_iterator pos;
289 for (pos = stable->begin(); pos != stable->end(); pos++)
290 {
291 if (lvol == (*pos)->GetLogicalVolume())
292 {
293 surf = *pos; break;
294 }
295 }
296 }
297 return surf;
298}
299
300const G4LogicalBorderSurface*
301G4GDMLWriteStructure::GetBorderSurface(const G4VPhysicalVolume* const pvol)
302{
303 G4LogicalBorderSurface* surf = 0;
304 G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
305 if (nsurf)
306 {
307 const G4LogicalBorderSurfaceTable* btable =
308 G4LogicalBorderSurface::GetSurfaceTable();
309 std::vector<G4LogicalBorderSurface*>::const_iterator pos;
310 for (pos = btable->begin(); pos != btable->end(); pos++)
311 {
312 if (pvol == (*pos)->GetVolume1()) // just the first in the couple
313 { // is enough
314 surf = *pos; break;
315 }
316 }
317 }
318 return surf;
319}
320
321void G4GDMLWriteStructure::SurfacesWrite()
322{
323 G4cout << "G4GDML: Writing surfaces..." << G4endl;
324
325 std::vector<xercesc::DOMElement*>::const_iterator pos;
326 for (pos = skinElementVec.begin(); pos != skinElementVec.end(); pos++)
327 {
328 structureElement->appendChild(*pos);
329 }
330 for (pos = borderElementVec.begin(); pos != borderElementVec.end(); pos++)
331 {
332 structureElement->appendChild(*pos);
333 }
334}
335
336void G4GDMLWriteStructure::StructureWrite(xercesc::DOMElement* gdmlElement)
337{
338 G4cout << "G4GDML: Writing structure..." << G4endl;
339
340 structureElement = NewElement("structure");
341 gdmlElement->appendChild(structureElement);
342}
343
344G4Transform3D G4GDMLWriteStructure::
345TraverseVolumeTree(const G4LogicalVolume* const volumePtr, const G4int depth)
346{
347 if (VolumeMap().find(volumePtr) != VolumeMap().end())
348 {
349 return VolumeMap()[volumePtr]; // Volume is already processed
350 }
351
352 G4VSolid* solidPtr = volumePtr->GetSolid();
353 G4Transform3D R,invR;
354 G4int trans=0;
355
356 while (true) // Solve possible displacement/reflection
357 { // of the referenced solid!
358 if (trans>maxTransforms)
359 {
360 G4String ErrorMessage = "Referenced solid in volume '"
361 + volumePtr->GetName()
362 + "' was displaced/reflected too many times!";
363 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
364 "InvalidSetup", FatalException, ErrorMessage);
365 }
366
367 if (G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
368 {
369 R = R*refl->GetTransform3D();
370 solidPtr = refl->GetConstituentMovedSolid();
371 trans++;
372 continue;
373 }
374
375 if (G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
376 {
377 R = R*G4Transform3D(disp->GetObjectRotation(),
378 disp->GetObjectTranslation());
379 solidPtr = disp->GetConstituentMovedSolid();
380 trans++;
381 continue;
382 }
383
384 break;
385 }
386
387 // Only compute the inverse when necessary!
388 //
389 if (trans>0) { invR = R.inverse(); }
390
391 const G4String name
392 = GenerateName(volumePtr->GetName(),volumePtr);
393 const G4String materialref
394 = GenerateName(volumePtr->GetMaterial()->GetName(),
395 volumePtr->GetMaterial());
396 const G4String solidref
397 = GenerateName(solidPtr->GetName(),solidPtr);
398
399 xercesc::DOMElement* volumeElement = NewElement("volume");
400 volumeElement->setAttributeNode(NewAttribute("name",name));
401 xercesc::DOMElement* materialrefElement = NewElement("materialref");
402 materialrefElement->setAttributeNode(NewAttribute("ref",materialref));
403 volumeElement->appendChild(materialrefElement);
404 xercesc::DOMElement* solidrefElement = NewElement("solidref");
405 solidrefElement->setAttributeNode(NewAttribute("ref",solidref));
406 volumeElement->appendChild(solidrefElement);
407
408 const G4int daughterCount = volumePtr->GetNoDaughters();
409
410 for (G4int i=0;i<daughterCount;i++) // Traverse all the children!
411 {
412 const G4VPhysicalVolume* const physvol = volumePtr->GetDaughter(i);
413 const G4String ModuleName = Modularize(physvol,depth);
414
415 G4Transform3D daughterR;
416
417 if (ModuleName.empty()) // Check if subtree requested to be
418 { // a separate module!
419 daughterR = TraverseVolumeTree(physvol->GetLogicalVolume(),depth+1);
420 }
421 else
422 {
423 G4GDMLWriteStructure writer;
424 daughterR = writer.Write(ModuleName,physvol->GetLogicalVolume(),
425 SchemaLocation,depth+1);
426 }
427
428 if (const G4PVDivision* const divisionvol
429 = dynamic_cast<const G4PVDivision*>(physvol)) // Is it division?
430 {
431 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
432 {
433 G4String ErrorMessage = "Division volume in '"
434 + name
435 + "' can not be related to reflected solid!";
436 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
437 "InvalidSetup", FatalException, ErrorMessage);
438 }
439 DivisionvolWrite(volumeElement,divisionvol);
440 } else
441 if (physvol->IsParameterised()) // Is it a paramvol?
442 {
443 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
444 {
445 G4String ErrorMessage = "Parameterised volume in '"
446 + name
447 + "' can not be related to reflected solid!";
448 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
449 "InvalidSetup", FatalException, ErrorMessage);
450 }
451 ParamvolWrite(volumeElement,physvol);
452 } else
453 if (physvol->IsReplicated()) // Is it a replicavol?
454 {
455 if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
456 {
457 G4String ErrorMessage = "Replica volume in '"
458 + name
459 + "' can not be related to reflected solid!";
460 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
461 "InvalidSetup", FatalException, ErrorMessage);
462 }
463 ReplicavolWrite(volumeElement,physvol);
464 }
465 else // Is it a physvol?
466 {
467 G4RotationMatrix rot;
468
469 if (physvol->GetFrameRotation() != 0)
470 {
471 rot = *(physvol->GetFrameRotation());
472 }
473 G4Transform3D P(rot,physvol->GetObjectTranslation());
474 PhysvolWrite(volumeElement,physvol,invR*P*daughterR,ModuleName);
475 }
476 BorderSurfaceCache(GetBorderSurface(physvol));
477 }
478
479 structureElement->appendChild(volumeElement);
480 // Append the volume AFTER traversing the children so that
481 // the order of volumes will be correct!
482
483 VolumeMap()[volumePtr] = R;
484
485 AddExtension(volumeElement, volumePtr);
486 // Add any possible user defined extension attached to a volume
487
488 AddMaterial(volumePtr->GetMaterial());
489 // Add the involved materials and solids!
490
491 AddSolid(solidPtr);
492
493 SkinSurfaceCache(GetSkinSurface(volumePtr));
494
495 return R;
496}
Note: See TracBrowser for help on using the repository browser.