Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/persistency/gdml/src/G4GDMLWriteSolids.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 // G4GDMLWriteSolids implementation
 27 //
 28 // Author: Zoltan Torzsok, November 2007
 29 // --------------------------------------------------------------------
 30 
 31 #include "G4GDMLWriteSolids.hh"
 32 
 33 #include "G4SystemOfUnits.hh"
 34 #include "G4BooleanSolid.hh"
 35 #include "G4ScaledSolid.hh"
 36 #include "G4Box.hh"
 37 #include "G4Cons.hh"
 38 #include "G4Ellipsoid.hh"
 39 #include "G4EllipticalCone.hh"
 40 #include "G4EllipticalTube.hh"
 41 #include "G4ExtrudedSolid.hh"
 42 #include "G4Hype.hh"
 43 #include "G4Orb.hh"
 44 #include "G4Para.hh"
 45 #include "G4Paraboloid.hh"
 46 #include "G4IntersectionSolid.hh"
 47 #include "G4Polycone.hh"
 48 #include "G4GenericPolycone.hh"
 49 #include "G4Polyhedra.hh"
 50 #include "G4ReflectedSolid.hh"
 51 #include "G4Sphere.hh"
 52 #include "G4SubtractionSolid.hh"
 53 #include "G4GenericTrap.hh"
 54 #include "G4TessellatedSolid.hh"
 55 #include "G4Tet.hh"
 56 #include "G4Torus.hh"
 57 #include "G4Trap.hh"
 58 #include "G4Trd.hh"
 59 #include "G4Tubs.hh"
 60 #include "G4CutTubs.hh"
 61 #include "G4TwistedBox.hh"
 62 #include "G4TwistedTrap.hh"
 63 #include "G4TwistedTrd.hh"
 64 #include "G4TwistedTubs.hh"
 65 #include "G4UnionSolid.hh"
 66 #include "G4OpticalSurface.hh"
 67 #include "G4SurfaceProperty.hh"
 68 #include "G4MaterialPropertiesTable.hh"
 69 
 70 // --------------------------------------------------------------------
 71 G4GDMLWriteSolids::G4GDMLWriteSolids()
 72   : G4GDMLWriteMaterials()
 73 {
 74 }
 75 
 76 // --------------------------------------------------------------------
 77 G4GDMLWriteSolids::~G4GDMLWriteSolids()
 78 {
 79 }
 80 
 81 // --------------------------------------------------------------------
 82 void G4GDMLWriteSolids::MultiUnionWrite(xercesc::DOMElement* solElement,
 83                                         const G4MultiUnion* const munionSolid)
 84 {
 85   G4int numSolids = munionSolid->GetNumberOfSolids();
 86   G4String tag("multiUnion");
 87 
 88   G4VSolid* solid;
 89   G4Transform3D transform;
 90 
 91   const G4String& name = GenerateName(munionSolid->GetName(), munionSolid);
 92   xercesc::DOMElement* multiUnionElement = NewElement(tag);
 93   multiUnionElement->setAttributeNode(NewAttribute("name", name));
 94 
 95   for(G4int i = 0; i < numSolids; ++i)
 96   {
 97     solid     = munionSolid->GetSolid(i);
 98     transform = munionSolid->GetTransformation(i);
 99 
100     HepGeom::Rotate3D rot3d;
101     HepGeom::Translate3D transl;
102     HepGeom::Scale3D scale;
103     transform.getDecomposition(scale, rot3d, transl);
104 
105     G4ThreeVector pos = transl.getTranslation();
106     G4RotationMatrix rotm(CLHEP::HepRep3x3(rot3d.xx(), rot3d.xy(), rot3d.xz(),
107                                            rot3d.yx(), rot3d.yy(), rot3d.yz(),
108                                            rot3d.zx(), rot3d.zy(), rot3d.zz()));
109     G4ThreeVector rot = GetAngles(rotm);
110 
111     AddSolid(solid);
112     const G4String& solidref = GenerateName(solid->GetName(), solid);
113     std::ostringstream os;
114     os << i + 1;
115     const G4String& nodeName          = "Node-" + G4String(os.str());
116     xercesc::DOMElement* solidElement = NewElement("solid");
117     solidElement->setAttributeNode(NewAttribute("ref", solidref));
118     xercesc::DOMElement* multiUnionNodeElement = NewElement("multiUnionNode");
119     multiUnionNodeElement->setAttributeNode(NewAttribute("name", name+"_"+nodeName));
120     multiUnionNodeElement->appendChild(solidElement);  // Append solid to node
121     if((std::fabs(pos.x()) > kLinearPrecision) ||
122        (std::fabs(pos.y()) > kLinearPrecision) ||
123        (std::fabs(pos.z()) > kLinearPrecision))
124     {
125       PositionWrite(multiUnionNodeElement,name+"_"+nodeName+"_pos",pos);
126     }
127     if((std::fabs(rot.x()) > kAngularPrecision) ||
128        (std::fabs(rot.y()) > kAngularPrecision) ||
129        (std::fabs(rot.z()) > kAngularPrecision))
130     {
131       RotationWrite(multiUnionNodeElement,name+"_"+nodeName+"_rot",rot);
132     }
133     multiUnionElement->appendChild(multiUnionNodeElement);  // Append node
134   }
135 
136   solElement->appendChild(multiUnionElement);
137   // Add the multiUnion solid AFTER the constituent nodes!
138 }
139 
140 // --------------------------------------------------------------------
141 void G4GDMLWriteSolids::BooleanWrite(xercesc::DOMElement* solElement,
142                                      const G4BooleanSolid* const boolean)
143 {
144   G4int displaced = 0;
145 
146   G4String tag("undefined");
147   if(dynamic_cast<const G4IntersectionSolid*>(boolean))
148   {
149     tag = "intersection";
150   }
151   else if(dynamic_cast<const G4SubtractionSolid*>(boolean))
152   {
153     tag = "subtraction";
154   }
155   else if(dynamic_cast<const G4UnionSolid*>(boolean))
156   {
157     tag = "union";
158   }
159 
160   G4VSolid* firstPtr  = const_cast<G4VSolid*>(boolean->GetConstituentSolid(0));
161   G4VSolid* secondPtr = const_cast<G4VSolid*>(boolean->GetConstituentSolid(1));
162 
163   G4ThreeVector firstpos, firstrot, pos, rot;
164 
165   // Solve possible displacement of referenced solids!
166   //
167   while(true)
168   {
169     if(displaced > 8)
170     {
171       G4String ErrorMessage = "The referenced solid '" + firstPtr->GetName() +
172                               +"in the Boolean shape '" + +boolean->GetName() +
173                               +"' was displaced too many times!";
174       G4Exception("G4GDMLWriteSolids::BooleanWrite()", "InvalidSetup",
175                   FatalException, ErrorMessage);
176     }
177 
178     if(G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(firstPtr))
179     {
180       firstpos += disp->GetObjectTranslation();
181       firstrot += GetAngles(disp->GetObjectRotation());
182       firstPtr = disp->GetConstituentMovedSolid();
183       ++displaced;
184       continue;
185     }
186     break;
187   }
188   displaced = 0;
189   while(true)
190   {
191     if(displaced > maxTransforms)
192     {
193       G4String ErrorMessage = "The referenced solid '" + secondPtr->GetName() +
194                               +"in the Boolean shape '" + +boolean->GetName() +
195                               +"' was displaced too many times!";
196       G4Exception("G4GDMLWriteSolids::BooleanWrite()", "InvalidSetup",
197                   FatalException, ErrorMessage);
198     }
199 
200     if(G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(secondPtr))
201     {
202       pos += disp->GetObjectTranslation();
203       rot += GetAngles(disp->GetObjectRotation());
204       secondPtr = disp->GetConstituentMovedSolid();
205       ++displaced;
206       continue;
207     }
208     break;
209   }
210 
211   AddSolid(firstPtr);  // At first add the constituent solids!
212   AddSolid(secondPtr);
213 
214   const G4String& name      = GenerateName(boolean->GetName(), boolean);
215   const G4String& firstref  = GenerateName(firstPtr->GetName(), firstPtr);
216   const G4String& secondref = GenerateName(secondPtr->GetName(), secondPtr);
217 
218   xercesc::DOMElement* booleanElement = NewElement(tag);
219   booleanElement->setAttributeNode(NewAttribute("name", name));
220   xercesc::DOMElement* firstElement = NewElement("first");
221   firstElement->setAttributeNode(NewAttribute("ref", firstref));
222   booleanElement->appendChild(firstElement);
223   xercesc::DOMElement* secondElement = NewElement("second");
224   secondElement->setAttributeNode(NewAttribute("ref", secondref));
225   booleanElement->appendChild(secondElement);
226   solElement->appendChild(booleanElement);
227   // Add the boolean solid AFTER the constituent solids!
228 
229   if((std::fabs(pos.x()) > kLinearPrecision) ||
230      (std::fabs(pos.y()) > kLinearPrecision) ||
231      (std::fabs(pos.z()) > kLinearPrecision))
232   {
233     PositionWrite(booleanElement, name + "_pos", pos);
234   }
235 
236   if((std::fabs(rot.x()) > kAngularPrecision) ||
237      (std::fabs(rot.y()) > kAngularPrecision) ||
238      (std::fabs(rot.z()) > kAngularPrecision))
239   {
240     RotationWrite(booleanElement, name + "_rot", rot);
241   }
242 
243   if((std::fabs(firstpos.x()) > kLinearPrecision) ||
244      (std::fabs(firstpos.y()) > kLinearPrecision) ||
245      (std::fabs(firstpos.z()) > kLinearPrecision))
246   {
247     FirstpositionWrite(booleanElement, name + "_fpos", firstpos);
248   }
249 
250   if((std::fabs(firstrot.x()) > kAngularPrecision) ||
251      (std::fabs(firstrot.y()) > kAngularPrecision) ||
252      (std::fabs(firstrot.z()) > kAngularPrecision))
253   {
254     FirstrotationWrite(booleanElement, name + "_frot", firstrot);
255   }
256 }
257 
258 // --------------------------------------------------------------------
259 void G4GDMLWriteSolids::ScaledWrite(xercesc::DOMElement* solElement,
260                                     const G4ScaledSolid* const scaled)
261 {
262   G4String tag("scaledSolid");
263 
264   G4VSolid* solid         = const_cast<G4VSolid*>(scaled->GetUnscaledSolid());
265   G4Scale3D scale         = scaled->GetScaleTransform();
266   G4ThreeVector sclVector = G4ThreeVector(scale.xx(), scale.yy(), scale.zz());
267 
268   AddSolid(solid);  // Add the constituent solid!
269 
270   const G4String& name     = GenerateName(scaled->GetName(), scaled);
271   const G4String& solidref = GenerateName(solid->GetName(), solid);
272 
273   xercesc::DOMElement* scaledElement = NewElement(tag);
274   scaledElement->setAttributeNode(NewAttribute("name", name));
275 
276   xercesc::DOMElement* solidElement = NewElement("solidref");
277   solidElement->setAttributeNode(NewAttribute("ref", solidref));
278   scaledElement->appendChild(solidElement);
279 
280   if((std::fabs(scale.xx()) > kLinearPrecision) &&
281      (std::fabs(scale.yy()) > kLinearPrecision) &&
282      (std::fabs(scale.zz()) > kLinearPrecision))
283   {
284     ScaleWrite(scaledElement, name + "_scl", sclVector);
285   }
286 
287   solElement->appendChild(scaledElement);
288   // Add the scaled solid AFTER its constituent solid!
289 }
290 
291 // --------------------------------------------------------------------
292 void G4GDMLWriteSolids::BoxWrite(xercesc::DOMElement* solElement,
293                                  const G4Box* const box)
294 {
295   const G4String& name = GenerateName(box->GetName(), box);
296 
297   xercesc::DOMElement* boxElement = NewElement("box");
298   boxElement->setAttributeNode(NewAttribute("name", name));
299   boxElement->setAttributeNode(
300     NewAttribute("x", 2.0 * box->GetXHalfLength() / mm));
301   boxElement->setAttributeNode(
302     NewAttribute("y", 2.0 * box->GetYHalfLength() / mm));
303   boxElement->setAttributeNode(
304     NewAttribute("z", 2.0 * box->GetZHalfLength() / mm));
305   boxElement->setAttributeNode(NewAttribute("lunit", "mm"));
306   solElement->appendChild(boxElement);
307 }
308 
309 // --------------------------------------------------------------------
310 void G4GDMLWriteSolids::ConeWrite(xercesc::DOMElement* solElement,
311                                   const G4Cons* const cone)
312 {
313   const G4String& name = GenerateName(cone->GetName(), cone);
314 
315   xercesc::DOMElement* coneElement = NewElement("cone");
316   coneElement->setAttributeNode(NewAttribute("name", name));
317   coneElement->setAttributeNode(
318     NewAttribute("rmin1", cone->GetInnerRadiusMinusZ() / mm));
319   coneElement->setAttributeNode(
320     NewAttribute("rmax1", cone->GetOuterRadiusMinusZ() / mm));
321   coneElement->setAttributeNode(
322     NewAttribute("rmin2", cone->GetInnerRadiusPlusZ() / mm));
323   coneElement->setAttributeNode(
324     NewAttribute("rmax2", cone->GetOuterRadiusPlusZ() / mm));
325   coneElement->setAttributeNode(
326     NewAttribute("z", 2.0 * cone->GetZHalfLength() / mm));
327   coneElement->setAttributeNode(
328     NewAttribute("startphi", cone->GetStartPhiAngle() / degree));
329   coneElement->setAttributeNode(
330     NewAttribute("deltaphi", cone->GetDeltaPhiAngle() / degree));
331   coneElement->setAttributeNode(NewAttribute("aunit", "deg"));
332   coneElement->setAttributeNode(NewAttribute("lunit", "mm"));
333   solElement->appendChild(coneElement);
334 }
335 
336 // --------------------------------------------------------------------
337 void G4GDMLWriteSolids::ElconeWrite(xercesc::DOMElement* solElement,
338                                     const G4EllipticalCone* const elcone)
339 {
340   const G4String& name = GenerateName(elcone->GetName(), elcone);
341 
342   xercesc::DOMElement* elconeElement = NewElement("elcone");
343   elconeElement->setAttributeNode(NewAttribute("name", name));
344   elconeElement->setAttributeNode(
345     NewAttribute("dx", elcone->GetSemiAxisX() / mm));
346   elconeElement->setAttributeNode(
347     NewAttribute("dy", elcone->GetSemiAxisY() / mm));
348   elconeElement->setAttributeNode(NewAttribute("zmax", elcone->GetZMax() / mm));
349   elconeElement->setAttributeNode(
350     NewAttribute("zcut", elcone->GetZTopCut() / mm));
351   elconeElement->setAttributeNode(NewAttribute("lunit", "mm"));
352   solElement->appendChild(elconeElement);
353 }
354 
355 // --------------------------------------------------------------------
356 void G4GDMLWriteSolids::EllipsoidWrite(xercesc::DOMElement* solElement,
357                                        const G4Ellipsoid* const ellipsoid)
358 {
359   const G4String& name = GenerateName(ellipsoid->GetName(), ellipsoid);
360 
361   xercesc::DOMElement* ellipsoidElement = NewElement("ellipsoid");
362   ellipsoidElement->setAttributeNode(NewAttribute("name", name));
363   ellipsoidElement->setAttributeNode(
364     NewAttribute("ax", ellipsoid->GetSemiAxisMax(0) / mm));
365   ellipsoidElement->setAttributeNode(
366     NewAttribute("by", ellipsoid->GetSemiAxisMax(1) / mm));
367   ellipsoidElement->setAttributeNode(
368     NewAttribute("cz", ellipsoid->GetSemiAxisMax(2) / mm));
369   ellipsoidElement->setAttributeNode(
370     NewAttribute("zcut1", ellipsoid->GetZBottomCut() / mm));
371   ellipsoidElement->setAttributeNode(
372     NewAttribute("zcut2", ellipsoid->GetZTopCut() / mm));
373   ellipsoidElement->setAttributeNode(NewAttribute("lunit", "mm"));
374   solElement->appendChild(ellipsoidElement);
375 }
376 
377 // --------------------------------------------------------------------
378 void G4GDMLWriteSolids::EltubeWrite(xercesc::DOMElement* solElement,
379                                     const G4EllipticalTube* const eltube)
380 {
381   const G4String& name = GenerateName(eltube->GetName(), eltube);
382 
383   xercesc::DOMElement* eltubeElement = NewElement("eltube");
384   eltubeElement->setAttributeNode(NewAttribute("name", name));
385   eltubeElement->setAttributeNode(NewAttribute("dx", eltube->GetDx() / mm));
386   eltubeElement->setAttributeNode(NewAttribute("dy", eltube->GetDy() / mm));
387   eltubeElement->setAttributeNode(NewAttribute("dz", eltube->GetDz() / mm));
388   eltubeElement->setAttributeNode(NewAttribute("lunit", "mm"));
389   solElement->appendChild(eltubeElement);
390 }
391 
392 // --------------------------------------------------------------------
393 void G4GDMLWriteSolids::XtruWrite(xercesc::DOMElement* solElement,
394                                   const G4ExtrudedSolid* const xtru)
395 {
396   const G4String& name = GenerateName(xtru->GetName(), xtru);
397 
398   xercesc::DOMElement* xtruElement = NewElement("xtru");
399   xtruElement->setAttributeNode(NewAttribute("name", name));
400   xtruElement->setAttributeNode(NewAttribute("lunit", "mm"));
401   solElement->appendChild(xtruElement);
402 
403   const G4int NumVertex = xtru->GetNofVertices();
404 
405   for(G4int i = 0; i < NumVertex; ++i)
406   {
407     xercesc::DOMElement* twoDimVertexElement = NewElement("twoDimVertex");
408     xtruElement->appendChild(twoDimVertexElement);
409 
410     const G4TwoVector& vertex = xtru->GetVertex(i);
411 
412     twoDimVertexElement->setAttributeNode(NewAttribute("x", vertex.x() / mm));
413     twoDimVertexElement->setAttributeNode(NewAttribute("y", vertex.y() / mm));
414   }
415 
416   const G4int NumSection = xtru->GetNofZSections();
417 
418   for(G4int i = 0; i < NumSection; ++i)
419   {
420     xercesc::DOMElement* sectionElement = NewElement("section");
421     xtruElement->appendChild(sectionElement);
422 
423     const G4ExtrudedSolid::ZSection section = xtru->GetZSection(i);
424 
425     sectionElement->setAttributeNode(NewAttribute("zOrder", i));
426     sectionElement->setAttributeNode(
427       NewAttribute("zPosition", section.fZ / mm));
428     sectionElement->setAttributeNode(
429       NewAttribute("xOffset", section.fOffset.x() / mm));
430     sectionElement->setAttributeNode(
431       NewAttribute("yOffset", section.fOffset.y() / mm));
432     sectionElement->setAttributeNode(
433       NewAttribute("scalingFactor", section.fScale));
434   }
435 }
436 
437 // --------------------------------------------------------------------
438 void G4GDMLWriteSolids::HypeWrite(xercesc::DOMElement* solElement,
439                                   const G4Hype* const hype)
440 {
441   const G4String& name = GenerateName(hype->GetName(), hype);
442 
443   xercesc::DOMElement* hypeElement = NewElement("hype");
444   hypeElement->setAttributeNode(NewAttribute("name", name));
445   hypeElement->setAttributeNode(
446     NewAttribute("rmin", hype->GetInnerRadius() / mm));
447   hypeElement->setAttributeNode(
448     NewAttribute("rmax", hype->GetOuterRadius() / mm));
449   hypeElement->setAttributeNode(
450     NewAttribute("inst", hype->GetInnerStereo() / degree));
451   hypeElement->setAttributeNode(
452     NewAttribute("outst", hype->GetOuterStereo() / degree));
453   hypeElement->setAttributeNode(
454     NewAttribute("z", 2.0 * hype->GetZHalfLength() / mm));
455   hypeElement->setAttributeNode(NewAttribute("aunit", "deg"));
456   hypeElement->setAttributeNode(NewAttribute("lunit", "mm"));
457   solElement->appendChild(hypeElement);
458 }
459 
460 // --------------------------------------------------------------------
461 void G4GDMLWriteSolids::OrbWrite(xercesc::DOMElement* solElement,
462                                  const G4Orb* const orb)
463 {
464   const G4String& name = GenerateName(orb->GetName(), orb);
465 
466   xercesc::DOMElement* orbElement = NewElement("orb");
467   orbElement->setAttributeNode(NewAttribute("name", name));
468   orbElement->setAttributeNode(NewAttribute("r", orb->GetRadius() / mm));
469   orbElement->setAttributeNode(NewAttribute("lunit", "mm"));
470   solElement->appendChild(orbElement);
471 }
472 
473 // --------------------------------------------------------------------
474 void G4GDMLWriteSolids::ParaWrite(xercesc::DOMElement* solElement,
475                                   const G4Para* const para)
476 {
477   const G4String& name = GenerateName(para->GetName(), para);
478 
479   const G4ThreeVector simaxis = para->GetSymAxis();
480   const G4double alpha        = std::atan(para->GetTanAlpha());
481   const G4double phi          = simaxis.phi();
482   const G4double theta        = simaxis.theta();
483 
484   xercesc::DOMElement* paraElement = NewElement("para");
485   paraElement->setAttributeNode(NewAttribute("name", name));
486   paraElement->setAttributeNode(
487     NewAttribute("x", 2.0 * para->GetXHalfLength() / mm));
488   paraElement->setAttributeNode(
489     NewAttribute("y", 2.0 * para->GetYHalfLength() / mm));
490   paraElement->setAttributeNode(
491     NewAttribute("z", 2.0 * para->GetZHalfLength() / mm));
492   paraElement->setAttributeNode(NewAttribute("alpha", alpha / degree));
493   paraElement->setAttributeNode(NewAttribute("theta", theta / degree));
494   paraElement->setAttributeNode(NewAttribute("phi", phi / degree));
495   paraElement->setAttributeNode(NewAttribute("aunit", "deg"));
496   paraElement->setAttributeNode(NewAttribute("lunit", "mm"));
497   solElement->appendChild(paraElement);
498 }
499 
500 // --------------------------------------------------------------------
501 void G4GDMLWriteSolids::ParaboloidWrite(xercesc::DOMElement* solElement,
502                                         const G4Paraboloid* const paraboloid)
503 {
504   const G4String& name = GenerateName(paraboloid->GetName(), paraboloid);
505 
506   xercesc::DOMElement* paraboloidElement = NewElement("paraboloid");
507   paraboloidElement->setAttributeNode(NewAttribute("name", name));
508   paraboloidElement->setAttributeNode(
509     NewAttribute("rlo", paraboloid->GetRadiusMinusZ() / mm));
510   paraboloidElement->setAttributeNode(
511     NewAttribute("rhi", paraboloid->GetRadiusPlusZ() / mm));
512   paraboloidElement->setAttributeNode(
513     NewAttribute("dz", paraboloid->GetZHalfLength() / mm));
514   paraboloidElement->setAttributeNode(NewAttribute("lunit", "mm"));
515   solElement->appendChild(paraboloidElement);
516 }
517 
518 // --------------------------------------------------------------------
519 void G4GDMLWriteSolids::PolyconeWrite(xercesc::DOMElement* solElement,
520                                       const G4Polycone* const polycone)
521 {
522   const G4String& name = GenerateName(polycone->GetName(), polycone);
523 
524   xercesc::DOMElement* polyconeElement = NewElement("polycone");
525   polyconeElement->setAttributeNode(NewAttribute("name", name));
526   polyconeElement->setAttributeNode(NewAttribute(
527     "startphi", polycone->GetOriginalParameters()->Start_angle / degree));
528   polyconeElement->setAttributeNode(NewAttribute(
529     "deltaphi", polycone->GetOriginalParameters()->Opening_angle / degree));
530   polyconeElement->setAttributeNode(NewAttribute("aunit", "deg"));
531   polyconeElement->setAttributeNode(NewAttribute("lunit", "mm"));
532   solElement->appendChild(polyconeElement);
533 
534   const std::size_t num_zplanes
535         = polycone->GetOriginalParameters()->Num_z_planes;
536   const G4double* z_array    = polycone->GetOriginalParameters()->Z_values;
537   const G4double* rmin_array = polycone->GetOriginalParameters()->Rmin;
538   const G4double* rmax_array = polycone->GetOriginalParameters()->Rmax;
539 
540   for(std::size_t i = 0; i < num_zplanes; ++i)
541   {
542     ZplaneWrite(polyconeElement, z_array[i], rmin_array[i], rmax_array[i]);
543   }
544 }
545 
546 // --------------------------------------------------------------------
547 void G4GDMLWriteSolids::GenericPolyconeWrite(
548   xercesc::DOMElement* solElement, const G4GenericPolycone* const polycone)
549 {
550   const G4String& name = GenerateName(polycone->GetName(), polycone);
551   xercesc::DOMElement* polyconeElement = NewElement("genericPolycone");
552   const G4double startPhi              = polycone->GetStartPhi();
553   polyconeElement->setAttributeNode(NewAttribute("name", name));
554   polyconeElement->setAttributeNode(
555     NewAttribute("startphi", startPhi / degree));
556   polyconeElement->setAttributeNode(
557     NewAttribute("deltaphi", (polycone->GetEndPhi() - startPhi) / degree));
558   polyconeElement->setAttributeNode(NewAttribute("aunit", "deg"));
559   polyconeElement->setAttributeNode(NewAttribute("lunit", "mm"));
560   solElement->appendChild(polyconeElement);
561 
562   const G4int num_rzpoints = (G4int)polycone->GetNumRZCorner();
563   for(G4int i = 0; i < num_rzpoints; ++i)
564   {
565     const G4double r_point = polycone->GetCorner(i).r;
566     const G4double z_point = polycone->GetCorner(i).z;
567     RZPointWrite(polyconeElement, r_point, z_point);
568   }
569 }
570 
571 // --------------------------------------------------------------------
572 void G4GDMLWriteSolids::PolyhedraWrite(xercesc::DOMElement* solElement,
573                                        const G4Polyhedra* const polyhedra)
574 {
575   const G4String& name = GenerateName(polyhedra->GetName(), polyhedra);
576   if(polyhedra->IsGeneric() == false)
577   {
578     xercesc::DOMElement* polyhedraElement = NewElement("polyhedra");
579     polyhedraElement->setAttributeNode(NewAttribute("name", name));
580     polyhedraElement->setAttributeNode(NewAttribute(
581       "startphi", polyhedra->GetOriginalParameters()->Start_angle / degree));
582     polyhedraElement->setAttributeNode(NewAttribute(
583       "deltaphi", polyhedra->GetOriginalParameters()->Opening_angle / degree));
584     polyhedraElement->setAttributeNode(
585       NewAttribute("numsides", polyhedra->GetOriginalParameters()->numSide));
586     polyhedraElement->setAttributeNode(NewAttribute("aunit", "deg"));
587     polyhedraElement->setAttributeNode(NewAttribute("lunit", "mm"));
588     solElement->appendChild(polyhedraElement);
589 
590     const std::size_t num_zplanes
591           = polyhedra->GetOriginalParameters()->Num_z_planes;
592     const G4double* z_array  = polyhedra->GetOriginalParameters()->Z_values;
593     const G4double* rmin_array = polyhedra->GetOriginalParameters()->Rmin;
594     const G4double* rmax_array = polyhedra->GetOriginalParameters()->Rmax;
595 
596     const G4double convertRad =
597       std::cos(0.5 * polyhedra->GetOriginalParameters()->Opening_angle /
598                polyhedra->GetOriginalParameters()->numSide);
599 
600     for(std::size_t i = 0; i < num_zplanes; ++i)
601     {
602       ZplaneWrite(polyhedraElement, z_array[i], rmin_array[i] * convertRad,
603                   rmax_array[i] * convertRad);
604     }
605   }
606   else  // generic polyhedra
607   {
608     xercesc::DOMElement* polyhedraElement = NewElement("genericPolyhedra");
609     polyhedraElement->setAttributeNode(NewAttribute("name", name));
610     polyhedraElement->setAttributeNode(NewAttribute(
611       "startphi", polyhedra->GetOriginalParameters()->Start_angle / degree));
612     polyhedraElement->setAttributeNode(NewAttribute(
613       "deltaphi", polyhedra->GetOriginalParameters()->Opening_angle / degree));
614     polyhedraElement->setAttributeNode(
615       NewAttribute("numsides", polyhedra->GetOriginalParameters()->numSide));
616     polyhedraElement->setAttributeNode(NewAttribute("aunit", "deg"));
617     polyhedraElement->setAttributeNode(NewAttribute("lunit", "mm"));
618     solElement->appendChild(polyhedraElement);
619 
620     const G4int num_rzpoints = (G4int)polyhedra->GetNumRZCorner();
621 
622     for(G4int i = 0; i < num_rzpoints; ++i)
623     {
624       const G4double r_point = polyhedra->GetCorner(i).r;
625       const G4double z_point = polyhedra->GetCorner(i).z;
626       RZPointWrite(polyhedraElement, r_point, z_point);
627     }
628   }
629 }
630 
631 // --------------------------------------------------------------------
632 void G4GDMLWriteSolids::SphereWrite(xercesc::DOMElement* solElement,
633                                     const G4Sphere* const sphere)
634 {
635   const G4String& name = GenerateName(sphere->GetName(), sphere);
636 
637   xercesc::DOMElement* sphereElement = NewElement("sphere");
638   sphereElement->setAttributeNode(NewAttribute("name", name));
639   sphereElement->setAttributeNode(
640     NewAttribute("rmin", sphere->GetInnerRadius() / mm));
641   sphereElement->setAttributeNode(
642     NewAttribute("rmax", sphere->GetOuterRadius() / mm));
643   sphereElement->setAttributeNode(
644     NewAttribute("startphi", sphere->GetStartPhiAngle() / degree));
645   sphereElement->setAttributeNode(
646     NewAttribute("deltaphi", sphere->GetDeltaPhiAngle() / degree));
647   sphereElement->setAttributeNode(
648     NewAttribute("starttheta", sphere->GetStartThetaAngle() / degree));
649   sphereElement->setAttributeNode(
650     NewAttribute("deltatheta", sphere->GetDeltaThetaAngle() / degree));
651   sphereElement->setAttributeNode(NewAttribute("aunit", "deg"));
652   sphereElement->setAttributeNode(NewAttribute("lunit", "mm"));
653   solElement->appendChild(sphereElement);
654 }
655 
656 // --------------------------------------------------------------------
657 void G4GDMLWriteSolids::TessellatedWrite(
658   xercesc::DOMElement* solElement, const G4TessellatedSolid* const tessellated)
659 {
660   const G4String& solid_name = tessellated->GetName();
661   const G4String& name       = GenerateName(solid_name, tessellated);
662 
663   xercesc::DOMElement* tessellatedElement = NewElement("tessellated");
664   tessellatedElement->setAttributeNode(NewAttribute("name", name));
665   tessellatedElement->setAttributeNode(NewAttribute("aunit", "deg"));
666   tessellatedElement->setAttributeNode(NewAttribute("lunit", "mm"));
667   solElement->appendChild(tessellatedElement);
668 
669   std::map<G4ThreeVector, G4String, G4ThreeVectorCompare> vertexMap;
670 
671   const std::size_t NumFacets = tessellated->GetNumberOfFacets();
672   std::size_t NumVertex = 0;
673 
674   for(std::size_t i = 0; i < NumFacets; ++i)
675   {
676     const G4VFacet* facet          = tessellated->GetFacet((G4int)i);
677     const size_t NumVertexPerFacet = facet->GetNumberOfVertices();
678 
679     G4String FacetTag;
680 
681     if(NumVertexPerFacet == 3)
682     {
683       FacetTag = "triangular";
684     }
685     else if(NumVertexPerFacet == 4)
686     {
687       FacetTag = "quadrangular";
688     }
689     else
690     {
691       G4Exception("G4GDMLWriteSolids::TessellatedWrite()", "InvalidSetup",
692                   FatalException, "Facet should contain 3 or 4 vertices!");
693     }
694 
695     xercesc::DOMElement* facetElement = NewElement(FacetTag);
696     tessellatedElement->appendChild(facetElement);
697 
698     for(std::size_t j = 0; j < NumVertexPerFacet; ++j)
699     {
700       std::stringstream name_stream;
701       std::stringstream ref_stream;
702 
703       name_stream << "vertex" << (j + 1);
704       ref_stream << solid_name << "_v" << NumVertex;
705 
706       const G4String& fname = name_stream.str();  // facet's tag variable
707       G4String ref          = ref_stream.str();   // vertex tag to be associated
708 
709       // Now search for the existance of the current vertex in the
710       // map of cached vertices. If existing, do NOT store it as
711       // position in the GDML file, so avoiding duplication; otherwise
712       // cache it in the local map and add it as position in the
713       // "define" section of the GDML file.
714 
715       const G4ThreeVector& vertex = facet->GetVertex((G4int)j);
716 
717       if(vertexMap.find(vertex) != vertexMap.cend())  // Vertex is cached
718       {
719         ref = vertexMap[vertex];  // Set the proper tag for it
720       }
721       else  // Vertex not found
722       {
723         if ( ! vertexMap.insert(std::make_pair(vertex, ref)).second )
724         {
725           G4ExceptionDescription description;
726           description << "Failed to insert [vertex, ref] " << vertex << ", "
727                       << ref << " in map.";
728           G4Exception("G4GDMLWriteSolids::TessellatedWrite", "WriteError",
729                        JustWarning, description);
730         }
731         AddPosition(ref, vertex);  // ... add it to define section!
732         ++NumVertex;
733       }
734 
735       // Now create association of the vertex with its facet
736       //
737       facetElement->setAttributeNode(NewAttribute(fname, ref));
738     }
739   }
740 }
741 
742 // --------------------------------------------------------------------
743 void G4GDMLWriteSolids::TetWrite(xercesc::DOMElement* solElement,
744                                  const G4Tet* const tet)
745 {
746   const G4String& solid_name = tet->GetName();
747   const G4String& name       = GenerateName(solid_name, tet);
748 
749   std::vector<G4ThreeVector> vertexList = tet->GetVertices();
750 
751   xercesc::DOMElement* tetElement = NewElement("tet");
752   tetElement->setAttributeNode(NewAttribute("name", name));
753   tetElement->setAttributeNode(NewAttribute("vertex1", solid_name + "_v1"));
754   tetElement->setAttributeNode(NewAttribute("vertex2", solid_name + "_v2"));
755   tetElement->setAttributeNode(NewAttribute("vertex3", solid_name + "_v3"));
756   tetElement->setAttributeNode(NewAttribute("vertex4", solid_name + "_v4"));
757   tetElement->setAttributeNode(NewAttribute("lunit", "mm"));
758   solElement->appendChild(tetElement);
759 
760   AddPosition(solid_name + "_v1", vertexList[0]);
761   AddPosition(solid_name + "_v2", vertexList[1]);
762   AddPosition(solid_name + "_v3", vertexList[2]);
763   AddPosition(solid_name + "_v4", vertexList[3]);
764 }
765 
766 // --------------------------------------------------------------------
767 void G4GDMLWriteSolids::TorusWrite(xercesc::DOMElement* solElement,
768                                    const G4Torus* const torus)
769 {
770   const G4String& name = GenerateName(torus->GetName(), torus);
771 
772   xercesc::DOMElement* torusElement = NewElement("torus");
773   torusElement->setAttributeNode(NewAttribute("name", name));
774   torusElement->setAttributeNode(NewAttribute("rmin", torus->GetRmin() / mm));
775   torusElement->setAttributeNode(NewAttribute("rmax", torus->GetRmax() / mm));
776   torusElement->setAttributeNode(NewAttribute("rtor", torus->GetRtor() / mm));
777   torusElement->setAttributeNode(
778     NewAttribute("startphi", torus->GetSPhi() / degree));
779   torusElement->setAttributeNode(
780     NewAttribute("deltaphi", torus->GetDPhi() / degree));
781   torusElement->setAttributeNode(NewAttribute("aunit", "deg"));
782   torusElement->setAttributeNode(NewAttribute("lunit", "mm"));
783   solElement->appendChild(torusElement);
784 }
785 
786 // --------------------------------------------------------------------
787 void G4GDMLWriteSolids::GenTrapWrite(xercesc::DOMElement* solElement,
788                                      const G4GenericTrap* const gtrap)
789 {
790   const G4String& name = GenerateName(gtrap->GetName(), gtrap);
791 
792   std::vector<G4TwoVector> vertices = gtrap->GetVertices();
793 
794   xercesc::DOMElement* gtrapElement = NewElement("arb8");
795   gtrapElement->setAttributeNode(NewAttribute("name", name));
796   gtrapElement->setAttributeNode(
797     NewAttribute("dz", gtrap->GetZHalfLength() / mm));
798   gtrapElement->setAttributeNode(NewAttribute("v1x", vertices[0].x()));
799   gtrapElement->setAttributeNode(NewAttribute("v1y", vertices[0].y()));
800   gtrapElement->setAttributeNode(NewAttribute("v2x", vertices[1].x()));
801   gtrapElement->setAttributeNode(NewAttribute("v2y", vertices[1].y()));
802   gtrapElement->setAttributeNode(NewAttribute("v3x", vertices[2].x()));
803   gtrapElement->setAttributeNode(NewAttribute("v3y", vertices[2].y()));
804   gtrapElement->setAttributeNode(NewAttribute("v4x", vertices[3].x()));
805   gtrapElement->setAttributeNode(NewAttribute("v4y", vertices[3].y()));
806   gtrapElement->setAttributeNode(NewAttribute("v5x", vertices[4].x()));
807   gtrapElement->setAttributeNode(NewAttribute("v5y", vertices[4].y()));
808   gtrapElement->setAttributeNode(NewAttribute("v6x", vertices[5].x()));
809   gtrapElement->setAttributeNode(NewAttribute("v6y", vertices[5].y()));
810   gtrapElement->setAttributeNode(NewAttribute("v7x", vertices[6].x()));
811   gtrapElement->setAttributeNode(NewAttribute("v7y", vertices[6].y()));
812   gtrapElement->setAttributeNode(NewAttribute("v8x", vertices[7].x()));
813   gtrapElement->setAttributeNode(NewAttribute("v8y", vertices[7].y()));
814   gtrapElement->setAttributeNode(NewAttribute("lunit", "mm"));
815   solElement->appendChild(gtrapElement);
816 }
817 
818 // --------------------------------------------------------------------
819 void G4GDMLWriteSolids::TrapWrite(xercesc::DOMElement* solElement,
820                                   const G4Trap* const trap)
821 {
822   const G4String& name = GenerateName(trap->GetName(), trap);
823 
824   const G4ThreeVector& simaxis = trap->GetSymAxis();
825   const G4double phi           = simaxis.phi();
826   const G4double theta         = simaxis.theta();
827   const G4double alpha1        = std::atan(trap->GetTanAlpha1());
828   const G4double alpha2        = std::atan(trap->GetTanAlpha2());
829 
830   xercesc::DOMElement* trapElement = NewElement("trap");
831   trapElement->setAttributeNode(NewAttribute("name", name));
832   trapElement->setAttributeNode(
833     NewAttribute("z", 2.0 * trap->GetZHalfLength() / mm));
834   trapElement->setAttributeNode(NewAttribute("theta", theta / degree));
835   trapElement->setAttributeNode(NewAttribute("phi", phi / degree));
836   trapElement->setAttributeNode(
837     NewAttribute("y1", 2.0 * trap->GetYHalfLength1() / mm));
838   trapElement->setAttributeNode(
839     NewAttribute("x1", 2.0 * trap->GetXHalfLength1() / mm));
840   trapElement->setAttributeNode(
841     NewAttribute("x2", 2.0 * trap->GetXHalfLength2() / mm));
842   trapElement->setAttributeNode(NewAttribute("alpha1", alpha1 / degree));
843   trapElement->setAttributeNode(
844     NewAttribute("y2", 2.0 * trap->GetYHalfLength2() / mm));
845   trapElement->setAttributeNode(
846     NewAttribute("x3", 2.0 * trap->GetXHalfLength3() / mm));
847   trapElement->setAttributeNode(
848     NewAttribute("x4", 2.0 * trap->GetXHalfLength4() / mm));
849   trapElement->setAttributeNode(NewAttribute("alpha2", alpha2 / degree));
850   trapElement->setAttributeNode(NewAttribute("aunit", "deg"));
851   trapElement->setAttributeNode(NewAttribute("lunit", "mm"));
852   solElement->appendChild(trapElement);
853 }
854 
855 // --------------------------------------------------------------------
856 void G4GDMLWriteSolids::TrdWrite(xercesc::DOMElement* solElement,
857                                  const G4Trd* const trd)
858 {
859   const G4String& name = GenerateName(trd->GetName(), trd);
860 
861   xercesc::DOMElement* trdElement = NewElement("trd");
862   trdElement->setAttributeNode(NewAttribute("name", name));
863   trdElement->setAttributeNode(
864     NewAttribute("x1", 2.0 * trd->GetXHalfLength1() / mm));
865   trdElement->setAttributeNode(
866     NewAttribute("x2", 2.0 * trd->GetXHalfLength2() / mm));
867   trdElement->setAttributeNode(
868     NewAttribute("y1", 2.0 * trd->GetYHalfLength1() / mm));
869   trdElement->setAttributeNode(
870     NewAttribute("y2", 2.0 * trd->GetYHalfLength2() / mm));
871   trdElement->setAttributeNode(
872     NewAttribute("z", 2.0 * trd->GetZHalfLength() / mm));
873   trdElement->setAttributeNode(NewAttribute("lunit", "mm"));
874   solElement->appendChild(trdElement);
875 }
876 
877 // --------------------------------------------------------------------
878 void G4GDMLWriteSolids::TubeWrite(xercesc::DOMElement* solElement,
879                                   const G4Tubs* const tube)
880 {
881   const G4String& name = GenerateName(tube->GetName(), tube);
882 
883   xercesc::DOMElement* tubeElement = NewElement("tube");
884   tubeElement->setAttributeNode(NewAttribute("name", name));
885   tubeElement->setAttributeNode(
886     NewAttribute("rmin", tube->GetInnerRadius() / mm));
887   tubeElement->setAttributeNode(
888     NewAttribute("rmax", tube->GetOuterRadius() / mm));
889   tubeElement->setAttributeNode(
890     NewAttribute("z", 2.0 * tube->GetZHalfLength() / mm));
891   tubeElement->setAttributeNode(
892     NewAttribute("startphi", tube->GetStartPhiAngle() / degree));
893   tubeElement->setAttributeNode(
894     NewAttribute("deltaphi", tube->GetDeltaPhiAngle() / degree));
895   tubeElement->setAttributeNode(NewAttribute("aunit", "deg"));
896   tubeElement->setAttributeNode(NewAttribute("lunit", "mm"));
897   solElement->appendChild(tubeElement);
898 }
899 
900 // --------------------------------------------------------------------
901 void G4GDMLWriteSolids::CutTubeWrite(xercesc::DOMElement* solElement,
902                                      const G4CutTubs* const cuttube)
903 {
904   const G4String& name = GenerateName(cuttube->GetName(), cuttube);
905 
906   xercesc::DOMElement* cuttubeElement = NewElement("cutTube");
907   cuttubeElement->setAttributeNode(NewAttribute("name", name));
908   cuttubeElement->setAttributeNode(
909     NewAttribute("rmin", cuttube->GetInnerRadius() / mm));
910   cuttubeElement->setAttributeNode(
911     NewAttribute("rmax", cuttube->GetOuterRadius() / mm));
912   cuttubeElement->setAttributeNode(
913     NewAttribute("z", 2.0 * cuttube->GetZHalfLength() / mm));
914   cuttubeElement->setAttributeNode(
915     NewAttribute("startphi", cuttube->GetStartPhiAngle() / degree));
916   cuttubeElement->setAttributeNode(
917     NewAttribute("deltaphi", cuttube->GetDeltaPhiAngle() / degree));
918   cuttubeElement->setAttributeNode(
919     NewAttribute("lowX", cuttube->GetLowNorm().getX() / mm));
920   cuttubeElement->setAttributeNode(
921     NewAttribute("lowY", cuttube->GetLowNorm().getY() / mm));
922   cuttubeElement->setAttributeNode(
923     NewAttribute("lowZ", cuttube->GetLowNorm().getZ() / mm));
924   cuttubeElement->setAttributeNode(
925     NewAttribute("highX", cuttube->GetHighNorm().getX() / mm));
926   cuttubeElement->setAttributeNode(
927     NewAttribute("highY", cuttube->GetHighNorm().getY() / mm));
928   cuttubeElement->setAttributeNode(
929     NewAttribute("highZ", cuttube->GetHighNorm().getZ() / mm));
930   cuttubeElement->setAttributeNode(NewAttribute("aunit", "deg"));
931   cuttubeElement->setAttributeNode(NewAttribute("lunit", "mm"));
932   solElement->appendChild(cuttubeElement);
933 }
934 
935 // --------------------------------------------------------------------
936 void G4GDMLWriteSolids::TwistedboxWrite(xercesc::DOMElement* solElement,
937                                         const G4TwistedBox* const twistedbox)
938 {
939   const G4String& name = GenerateName(twistedbox->GetName(), twistedbox);
940 
941   xercesc::DOMElement* twistedboxElement = NewElement("twistedbox");
942   twistedboxElement->setAttributeNode(NewAttribute("name", name));
943   twistedboxElement->setAttributeNode(
944     NewAttribute("x", 2.0 * twistedbox->GetXHalfLength() / mm));
945   twistedboxElement->setAttributeNode(
946     NewAttribute("y", 2.0 * twistedbox->GetYHalfLength() / mm));
947   twistedboxElement->setAttributeNode(
948     NewAttribute("z", 2.0 * twistedbox->GetZHalfLength() / mm));
949   twistedboxElement->setAttributeNode(
950     NewAttribute("PhiTwist", twistedbox->GetPhiTwist() / degree));
951   twistedboxElement->setAttributeNode(NewAttribute("aunit", "deg"));
952   twistedboxElement->setAttributeNode(NewAttribute("lunit", "mm"));
953   solElement->appendChild(twistedboxElement);
954 }
955 
956 // --------------------------------------------------------------------
957 void G4GDMLWriteSolids::TwistedtrapWrite(xercesc::DOMElement* solElement,
958                                          const G4TwistedTrap* const twistedtrap)
959 {
960   const G4String& name = GenerateName(twistedtrap->GetName(), twistedtrap);
961 
962   xercesc::DOMElement* twistedtrapElement = NewElement("twistedtrap");
963   twistedtrapElement->setAttributeNode(NewAttribute("name", name));
964   twistedtrapElement->setAttributeNode(
965     NewAttribute("y1", 2.0 * twistedtrap->GetY1HalfLength() / mm));
966   twistedtrapElement->setAttributeNode(
967     NewAttribute("x1", 2.0 * twistedtrap->GetX1HalfLength() / mm));
968   twistedtrapElement->setAttributeNode(
969     NewAttribute("x2", 2.0 * twistedtrap->GetX2HalfLength() / mm));
970   twistedtrapElement->setAttributeNode(
971     NewAttribute("y2", 2.0 * twistedtrap->GetY2HalfLength() / mm));
972   twistedtrapElement->setAttributeNode(
973     NewAttribute("x3", 2.0 * twistedtrap->GetX3HalfLength() / mm));
974   twistedtrapElement->setAttributeNode(
975     NewAttribute("x4", 2.0 * twistedtrap->GetX4HalfLength() / mm));
976   twistedtrapElement->setAttributeNode(
977     NewAttribute("z", 2.0 * twistedtrap->GetZHalfLength() / mm));
978   twistedtrapElement->setAttributeNode(
979     NewAttribute("Alph", twistedtrap->GetTiltAngleAlpha() / degree));
980   twistedtrapElement->setAttributeNode(
981     NewAttribute("Theta", twistedtrap->GetPolarAngleTheta() / degree));
982   twistedtrapElement->setAttributeNode(
983     NewAttribute("Phi", twistedtrap->GetAzimuthalAnglePhi() / degree));
984   twistedtrapElement->setAttributeNode(
985     NewAttribute("PhiTwist", twistedtrap->GetPhiTwist() / degree));
986   twistedtrapElement->setAttributeNode(NewAttribute("aunit", "deg"));
987   twistedtrapElement->setAttributeNode(NewAttribute("lunit", "mm"));
988 
989   solElement->appendChild(twistedtrapElement);
990 }
991 
992 // --------------------------------------------------------------------
993 void G4GDMLWriteSolids::TwistedtrdWrite(xercesc::DOMElement* solElement,
994                                         const G4TwistedTrd* const twistedtrd)
995 {
996   const G4String& name = GenerateName(twistedtrd->GetName(), twistedtrd);
997 
998   xercesc::DOMElement* twistedtrdElement = NewElement("twistedtrd");
999   twistedtrdElement->setAttributeNode(NewAttribute("name", name));
1000   twistedtrdElement->setAttributeNode(
1001     NewAttribute("x1", 2.0 * twistedtrd->GetX1HalfLength() / mm));
1002   twistedtrdElement->setAttributeNode(
1003     NewAttribute("x2", 2.0 * twistedtrd->GetX2HalfLength() / mm));
1004   twistedtrdElement->setAttributeNode(
1005     NewAttribute("y1", 2.0 * twistedtrd->GetY1HalfLength() / mm));
1006   twistedtrdElement->setAttributeNode(
1007     NewAttribute("y2", 2.0 * twistedtrd->GetY2HalfLength() / mm));
1008   twistedtrdElement->setAttributeNode(
1009     NewAttribute("z", 2.0 * twistedtrd->GetZHalfLength() / mm));
1010   twistedtrdElement->setAttributeNode(
1011     NewAttribute("PhiTwist", twistedtrd->GetPhiTwist() / degree));
1012   twistedtrdElement->setAttributeNode(NewAttribute("aunit", "deg"));
1013   twistedtrdElement->setAttributeNode(NewAttribute("lunit", "mm"));
1014   solElement->appendChild(twistedtrdElement);
1015 }
1016 
1017 // --------------------------------------------------------------------
1018 void G4GDMLWriteSolids::TwistedtubsWrite(xercesc::DOMElement* solElement,
1019                                          const G4TwistedTubs* const twistedtubs)
1020 {
1021   const G4String& name = GenerateName(twistedtubs->GetName(), twistedtubs);
1022 
1023   xercesc::DOMElement* twistedtubsElement = NewElement("twistedtubs");
1024   twistedtubsElement->setAttributeNode(NewAttribute("name", name));
1025   twistedtubsElement->setAttributeNode(
1026     NewAttribute("twistedangle", twistedtubs->GetPhiTwist() / degree));
1027   twistedtubsElement->setAttributeNode(
1028     NewAttribute("midinnerrad", twistedtubs->GetInnerRadius() / mm));
1029   twistedtubsElement->setAttributeNode(
1030     NewAttribute("midouterrad", twistedtubs->GetOuterRadius() / mm));
1031   twistedtubsElement->setAttributeNode(
1032     NewAttribute("negativeEndz", twistedtubs->GetEndZ(0) / mm));
1033   twistedtubsElement->setAttributeNode(
1034     NewAttribute("positiveEndz", twistedtubs->GetEndZ(1) / mm));
1035   twistedtubsElement->setAttributeNode(
1036     NewAttribute("phi", twistedtubs->GetDPhi() / degree));
1037   twistedtubsElement->setAttributeNode(NewAttribute("aunit", "deg"));
1038   twistedtubsElement->setAttributeNode(NewAttribute("lunit", "mm"));
1039   solElement->appendChild(twistedtubsElement);
1040 }
1041 
1042 // --------------------------------------------------------------------
1043 void G4GDMLWriteSolids::ZplaneWrite(xercesc::DOMElement* element,
1044                                     const G4double& z, const G4double& rmin,
1045                                     const G4double& rmax)
1046 {
1047   xercesc::DOMElement* zplaneElement = NewElement("zplane");
1048   zplaneElement->setAttributeNode(NewAttribute("z", z / mm));
1049   zplaneElement->setAttributeNode(NewAttribute("rmin", rmin / mm));
1050   zplaneElement->setAttributeNode(NewAttribute("rmax", rmax / mm));
1051   element->appendChild(zplaneElement);
1052 }
1053 
1054 // --------------------------------------------------------------------
1055 void G4GDMLWriteSolids::RZPointWrite(xercesc::DOMElement* element,
1056                                      const G4double& r, const G4double& z)
1057 {
1058   xercesc::DOMElement* rzpointElement = NewElement("rzpoint");
1059   rzpointElement->setAttributeNode(NewAttribute("r", r / mm));
1060   rzpointElement->setAttributeNode(NewAttribute("z", z / mm));
1061   element->appendChild(rzpointElement);
1062 }
1063 
1064 // --------------------------------------------------------------------
1065 void G4GDMLWriteSolids::OpticalSurfaceWrite(xercesc::DOMElement* solElement,
1066                                             const G4OpticalSurface* const surf)
1067 {
1068   xercesc::DOMElement* optElement = NewElement("opticalsurface");
1069   G4OpticalSurfaceModel smodel    = surf->GetModel();
1070   G4double sval =
1071     (smodel == glisur) ? surf->GetPolish() : surf->GetSigmaAlpha();
1072   const G4String& name = GenerateName(surf->GetName(), surf);
1073 
1074   optElement->setAttributeNode(NewAttribute("name", name));
1075   optElement->setAttributeNode(NewAttribute("model", smodel));
1076   optElement->setAttributeNode(NewAttribute("finish", surf->GetFinish()));
1077   optElement->setAttributeNode(NewAttribute("type", surf->GetType()));
1078   optElement->setAttributeNode(NewAttribute("value", sval));
1079 
1080   // Write any property attached to the optical surface...
1081   //
1082   if(surf->GetMaterialPropertiesTable())
1083   {
1084     PropertyWrite(optElement, surf);
1085   }
1086 
1087   solElement->appendChild(optElement);
1088 }
1089 
1090 // --------------------------------------------------------------------
1091 void G4GDMLWriteSolids::PropertyWrite(xercesc::DOMElement* optElement,
1092                                       const G4OpticalSurface* const surf)
1093 {
1094   xercesc::DOMElement* propElement;
1095   G4MaterialPropertiesTable* ptable = surf->GetMaterialPropertiesTable();
1096   auto pvec = ptable->GetProperties();
1097   auto cvec = ptable->GetConstProperties();
1098 
1099   for(size_t i = 0; i < pvec.size(); ++i)
1100   {
1101     if(pvec[i] != nullptr) {
1102       propElement = NewElement("property");
1103       propElement->setAttributeNode(
1104         NewAttribute("name", ptable->GetMaterialPropertyNames()[i]));
1105       propElement->setAttributeNode(NewAttribute(
1106         "ref", GenerateName(ptable->GetMaterialPropertyNames()[i],
1107                             pvec[i])));
1108       PropertyVectorWrite(ptable->GetMaterialPropertyNames()[i],
1109                           pvec[i]);
1110       optElement->appendChild(propElement);
1111     }
1112   }
1113   for(size_t i = 0; i < cvec.size(); ++i)
1114   {
1115     if (cvec[i].second == true) {
1116       propElement = NewElement("property");
1117       propElement->setAttributeNode(NewAttribute(
1118         "name", ptable->GetMaterialConstPropertyNames()[i]));
1119       propElement->setAttributeNode(NewAttribute(
1120         "ref", ptable->GetMaterialConstPropertyNames()[i]));
1121       xercesc::DOMElement* constElement = NewElement("constant");
1122       constElement->setAttributeNode(NewAttribute(
1123         "name", ptable->GetMaterialConstPropertyNames()[i]));
1124       constElement->setAttributeNode(NewAttribute("value", cvec[i].first));
1125       defineElement->appendChild(constElement);
1126       optElement->appendChild(propElement);
1127     }
1128   }
1129 }
1130 
1131 // --------------------------------------------------------------------
1132 void G4GDMLWriteSolids::SolidsWrite(xercesc::DOMElement* gdmlElement)
1133 {
1134 #ifdef G4VERBOSE
1135   G4cout << "G4GDML: Writing solids..." << G4endl;
1136 #endif
1137   solidsElement = NewElement("solids");
1138   gdmlElement->appendChild(solidsElement);
1139 
1140   solidList.clear();
1141 }
1142 
1143 // --------------------------------------------------------------------
1144 void G4GDMLWriteSolids::AddSolid(const G4VSolid* const solidPtr)
1145 {
1146   for(std::size_t i = 0; i < solidList.size(); ++i)  // Check if solid is
1147   {                                                  // already in the list!
1148     if(solidList[i] == solidPtr)
1149     {
1150       return;
1151     }
1152   }
1153 
1154   solidList.push_back(solidPtr);
1155 
1156   if(const G4BooleanSolid* const booleanPtr =
1157        dynamic_cast<const G4BooleanSolid*>(solidPtr))
1158   {
1159     BooleanWrite(solidsElement, booleanPtr);
1160   }
1161   else if(const G4ScaledSolid* const scaledPtr =
1162             dynamic_cast<const G4ScaledSolid*>(solidPtr))
1163   {
1164     ScaledWrite(solidsElement, scaledPtr);
1165   }
1166   else if(solidPtr->GetEntityType() == "G4MultiUnion")
1167   {
1168     const G4MultiUnion* const munionPtr =
1169       static_cast<const G4MultiUnion*>(solidPtr);
1170     MultiUnionWrite(solidsElement, munionPtr);
1171   }
1172   else if(solidPtr->GetEntityType() == "G4Box")
1173   {
1174     const G4Box* const boxPtr = static_cast<const G4Box*>(solidPtr);
1175     BoxWrite(solidsElement, boxPtr);
1176   }
1177   else if(solidPtr->GetEntityType() == "G4Cons")
1178   {
1179     const G4Cons* const conePtr = static_cast<const G4Cons*>(solidPtr);
1180     ConeWrite(solidsElement, conePtr);
1181   }
1182   else if(solidPtr->GetEntityType() == "G4EllipticalCone")
1183   {
1184     const G4EllipticalCone* const elconePtr =
1185       static_cast<const G4EllipticalCone*>(solidPtr);
1186     ElconeWrite(solidsElement, elconePtr);
1187   }
1188   else if(solidPtr->GetEntityType() == "G4Ellipsoid")
1189   {
1190     const G4Ellipsoid* const ellipsoidPtr =
1191       static_cast<const G4Ellipsoid*>(solidPtr);
1192     EllipsoidWrite(solidsElement, ellipsoidPtr);
1193   }
1194   else if(solidPtr->GetEntityType() == "G4EllipticalTube")
1195   {
1196     const G4EllipticalTube* const eltubePtr =
1197       static_cast<const G4EllipticalTube*>(solidPtr);
1198     EltubeWrite(solidsElement, eltubePtr);
1199   }
1200   else if(solidPtr->GetEntityType() == "G4ExtrudedSolid")
1201   {
1202     const G4ExtrudedSolid* const xtruPtr =
1203       static_cast<const G4ExtrudedSolid*>(solidPtr);
1204     XtruWrite(solidsElement, xtruPtr);
1205   }
1206   else if(solidPtr->GetEntityType() == "G4Hype")
1207   {
1208     const G4Hype* const hypePtr = static_cast<const G4Hype*>(solidPtr);
1209     HypeWrite(solidsElement, hypePtr);
1210   }
1211   else if(solidPtr->GetEntityType() == "G4Orb")
1212   {
1213     const G4Orb* const orbPtr = static_cast<const G4Orb*>(solidPtr);
1214     OrbWrite(solidsElement, orbPtr);
1215   }
1216   else if(solidPtr->GetEntityType() == "G4Para")
1217   {
1218     const G4Para* const paraPtr = static_cast<const G4Para*>(solidPtr);
1219     ParaWrite(solidsElement, paraPtr);
1220   }
1221   else if(solidPtr->GetEntityType() == "G4Paraboloid")
1222   {
1223     const G4Paraboloid* const paraboloidPtr =
1224       static_cast<const G4Paraboloid*>(solidPtr);
1225     ParaboloidWrite(solidsElement, paraboloidPtr);
1226   }
1227   else if(solidPtr->GetEntityType() == "G4Polycone")
1228   {
1229     const G4Polycone* const polyconePtr =
1230       static_cast<const G4Polycone*>(solidPtr);
1231     PolyconeWrite(solidsElement, polyconePtr);
1232   }
1233   else if(solidPtr->GetEntityType() == "G4GenericPolycone")
1234   {
1235     const G4GenericPolycone* const genpolyconePtr =
1236       static_cast<const G4GenericPolycone*>(solidPtr);
1237     GenericPolyconeWrite(solidsElement, genpolyconePtr);
1238   }
1239   else if(solidPtr->GetEntityType() == "G4Polyhedra")
1240   {
1241     const G4Polyhedra* const polyhedraPtr =
1242       static_cast<const G4Polyhedra*>(solidPtr);
1243     PolyhedraWrite(solidsElement, polyhedraPtr);
1244   }
1245   else if(solidPtr->GetEntityType() == "G4Sphere")
1246   {
1247     const G4Sphere* const spherePtr = static_cast<const G4Sphere*>(solidPtr);
1248     SphereWrite(solidsElement, spherePtr);
1249   }
1250   else if(solidPtr->GetEntityType() == "G4TessellatedSolid")
1251   {
1252     const G4TessellatedSolid* const tessellatedPtr =
1253       static_cast<const G4TessellatedSolid*>(solidPtr);
1254     TessellatedWrite(solidsElement, tessellatedPtr);
1255   }
1256   else if(solidPtr->GetEntityType() == "G4Tet")
1257   {
1258     const G4Tet* const tetPtr = static_cast<const G4Tet*>(solidPtr);
1259     TetWrite(solidsElement, tetPtr);
1260   }
1261   else if(solidPtr->GetEntityType() == "G4Torus")
1262   {
1263     const G4Torus* const torusPtr = static_cast<const G4Torus*>(solidPtr);
1264     TorusWrite(solidsElement, torusPtr);
1265   }
1266   else if(solidPtr->GetEntityType() == "G4GenericTrap")
1267   {
1268     const G4GenericTrap* const gtrapPtr =
1269       static_cast<const G4GenericTrap*>(solidPtr);
1270     GenTrapWrite(solidsElement, gtrapPtr);
1271   }
1272   else if(solidPtr->GetEntityType() == "G4Trap")
1273   {
1274     const G4Trap* const trapPtr = static_cast<const G4Trap*>(solidPtr);
1275     TrapWrite(solidsElement, trapPtr);
1276   }
1277   else if(solidPtr->GetEntityType() == "G4Trd")
1278   {
1279     const G4Trd* const trdPtr = static_cast<const G4Trd*>(solidPtr);
1280     TrdWrite(solidsElement, trdPtr);
1281   }
1282   else if(solidPtr->GetEntityType() == "G4Tubs")
1283   {
1284     const G4Tubs* const tubePtr = static_cast<const G4Tubs*>(solidPtr);
1285     TubeWrite(solidsElement, tubePtr);
1286   }
1287   else if(solidPtr->GetEntityType() == "G4CutTubs")
1288   {
1289     const G4CutTubs* const cuttubePtr = static_cast<const G4CutTubs*>(solidPtr);
1290     CutTubeWrite(solidsElement, cuttubePtr);
1291   }
1292   else if(solidPtr->GetEntityType() == "G4TwistedBox")
1293   {
1294     const G4TwistedBox* const twistedboxPtr =
1295       static_cast<const G4TwistedBox*>(solidPtr);
1296     TwistedboxWrite(solidsElement, twistedboxPtr);
1297   }
1298   else if(solidPtr->GetEntityType() == "G4TwistedTrap")
1299   {
1300     const G4TwistedTrap* const twistedtrapPtr =
1301       static_cast<const G4TwistedTrap*>(solidPtr);
1302     TwistedtrapWrite(solidsElement, twistedtrapPtr);
1303   }
1304   else if(solidPtr->GetEntityType() == "G4TwistedTrd")
1305   {
1306     const G4TwistedTrd* const twistedtrdPtr =
1307       static_cast<const G4TwistedTrd*>(solidPtr);
1308     TwistedtrdWrite(solidsElement, twistedtrdPtr);
1309   }
1310   else if(solidPtr->GetEntityType() == "G4TwistedTubs")
1311   {
1312     const G4TwistedTubs* const twistedtubsPtr =
1313       static_cast<const G4TwistedTubs*>(solidPtr);
1314     TwistedtubsWrite(solidsElement, twistedtubsPtr);
1315   }
1316   else
1317   {
1318     G4String error_msg = "Unknown solid: " + solidPtr->GetName() +
1319                          "; Type: " + solidPtr->GetEntityType();
1320     G4Exception("G4GDMLWriteSolids::AddSolid()", "WriteError", FatalException,
1321                 error_msg);
1322   }
1323 }
1324