Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/persistency/gdml/src/G4GDMLReadSolids.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 // G4GDMLReadSolids implementation
 27 //
 28 // Author: Zoltan Torzsok, November 2007
 29 // --------------------------------------------------------------------
 30 
 31 #include "G4GDMLReadSolids.hh"
 32 #include "G4Box.hh"
 33 #include "G4Cons.hh"
 34 #include "G4Ellipsoid.hh"
 35 #include "G4EllipticalCone.hh"
 36 #include "G4EllipticalTube.hh"
 37 #include "G4Hype.hh"
 38 #include "G4IntersectionSolid.hh"
 39 #include "G4Orb.hh"
 40 #include "G4Para.hh"
 41 #include "G4Paraboloid.hh"
 42 #include "G4Polycone.hh"
 43 #include "G4GenericPolycone.hh"
 44 #include "G4Polyhedra.hh"
 45 #include "G4QuadrangularFacet.hh"
 46 #include "G4ReflectedSolid.hh"
 47 #include "G4ScaledSolid.hh"
 48 #include "G4Sphere.hh"
 49 #include "G4SolidStore.hh"
 50 #include "G4SubtractionSolid.hh"
 51 #include "G4GenericTrap.hh"
 52 #include "G4TessellatedSolid.hh"
 53 #include "G4Tet.hh"
 54 #include "G4Torus.hh"
 55 #include "G4Transform3D.hh"
 56 #include "G4Trap.hh"
 57 #include "G4Trd.hh"
 58 #include "G4TriangularFacet.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 "G4UnitsTable.hh"
 68 #include "G4SurfaceProperty.hh"
 69 
 70 // --------------------------------------------------------------------
 71 G4GDMLReadSolids::G4GDMLReadSolids()
 72   : G4GDMLReadMaterials()
 73 {
 74 }
 75 
 76 // --------------------------------------------------------------------
 77 G4GDMLReadSolids::~G4GDMLReadSolids()
 78 {
 79 }
 80 
 81 // --------------------------------------------------------------------
 82 void G4GDMLReadSolids::BooleanRead(
 83   const xercesc::DOMElement* const booleanElement, const BooleanOp op)
 84 {
 85   G4String name;
 86   G4String first;
 87   G4String scnd;
 88   G4ThreeVector position(0.0, 0.0, 0.0);
 89   G4ThreeVector rotation(0.0, 0.0, 0.0);
 90   G4ThreeVector firstposition(0.0, 0.0, 0.0);
 91   G4ThreeVector firstrotation(0.0, 0.0, 0.0);
 92 
 93   const xercesc::DOMNamedNodeMap* const attributes =
 94     booleanElement->getAttributes();
 95   XMLSize_t attributeCount = attributes->getLength();
 96 
 97   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
 98       ++attribute_index)
 99   {
100     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
101 
102     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
103     {
104       continue;
105     }
106 
107     const xercesc::DOMAttr* const attribute =
108       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
109     if(attribute == nullptr)
110     {
111       G4Exception("G4GDMLReadSolids::BooleanRead()", "InvalidRead",
112                   FatalException, "No attribute found!");
113       return;
114     }
115     const G4String attName  = Transcode(attribute->getName());
116     const G4String attValue = Transcode(attribute->getValue());
117 
118     if(attName == "name")
119     {
120       name = GenerateName(attValue);
121     }
122   }
123 
124   for(xercesc::DOMNode* iter = booleanElement->getFirstChild(); iter != nullptr;
125       iter                   = iter->getNextSibling())
126   {
127     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
128     {
129       continue;
130     }
131 
132     const xercesc::DOMElement* const child =
133       dynamic_cast<xercesc::DOMElement*>(iter);
134     if(child == nullptr)
135     {
136       G4Exception("G4GDMLReadSolids::BooleanRead()", "InvalidRead",
137                   FatalException, "No child found!");
138       return;
139     }
140     const G4String tag = Transcode(child->getTagName());
141 
142     if(tag == "first")
143     {
144       first = RefRead(child);
145     }
146     else if(tag == "second")
147     {
148       scnd = RefRead(child);
149     }
150     else if(tag == "position")
151     {
152       VectorRead(child, position);
153     }
154     else if(tag == "rotation")
155     {
156       VectorRead(child, rotation);
157     }
158     else if(tag == "positionref")
159     {
160       position = GetPosition(GenerateName(RefRead(child)));
161     }
162     else if(tag == "rotationref")
163     {
164       rotation = GetRotation(GenerateName(RefRead(child)));
165     }
166     else if(tag == "firstposition")
167     {
168       VectorRead(child, firstposition);
169     }
170     else if(tag == "firstrotation")
171     {
172       VectorRead(child, firstrotation);
173     }
174     else if(tag == "firstpositionref")
175     {
176       firstposition = GetPosition(GenerateName(RefRead(child)));
177     }
178     else if(tag == "firstrotationref")
179     {
180       firstrotation = GetRotation(GenerateName(RefRead(child)));
181     }
182     else
183     {
184       G4String error_msg = "Unknown tag in boolean solid: " + tag;
185       G4Exception("G4GDMLReadSolids::BooleanRead()", "ReadError",
186                   FatalException, error_msg);
187     }
188   }
189 
190   G4VSolid* firstSolid  = GetSolid(GenerateName(first));
191   G4VSolid* secondSolid = GetSolid(GenerateName(scnd));
192 
193   G4Transform3D transform(GetRotationMatrix(rotation), position);
194 
195   if(((firstrotation.x() != 0.0) || (firstrotation.y() != 0.0) ||
196       (firstrotation.z() != 0.0)) ||
197      ((firstposition.x() != 0.0) || (firstposition.y() != 0.0) ||
198       (firstposition.z() != 0.0)))
199   {
200     G4Transform3D firsttransform(GetRotationMatrix(firstrotation),
201                                  firstposition);
202     firstSolid = new G4DisplacedSolid(GenerateName("displaced_" + first),
203                                       firstSolid, firsttransform);
204   }
205 
206   if(op == UNION)
207   {
208     new G4UnionSolid(name, firstSolid, secondSolid, transform);
209   }
210   else if(op == SUBTRACTION)
211   {
212     new G4SubtractionSolid(name, firstSolid, secondSolid, transform);
213   }
214   else if(op == INTERSECTION)
215   {
216     new G4IntersectionSolid(name, firstSolid, secondSolid, transform);
217   }
218 }
219 
220 // --------------------------------------------------------------------
221 void G4GDMLReadSolids::BoxRead(const xercesc::DOMElement* const boxElement)
222 {
223   G4String name;
224   G4double lunit = 1.0;
225   G4double x     = 0.0;
226   G4double y     = 0.0;
227   G4double z     = 0.0;
228 
229   const xercesc::DOMNamedNodeMap* const attributes =
230     boxElement->getAttributes();
231   XMLSize_t attributeCount = attributes->getLength();
232 
233   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
234       ++attribute_index)
235   {
236     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
237 
238     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
239     {
240       continue;
241     }
242 
243     const xercesc::DOMAttr* const attribute =
244       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
245     if(attribute == nullptr)
246     {
247       G4Exception("G4GDMLReadSolids::BoxRead()", "InvalidRead", FatalException,
248                   "No attribute found!");
249       return;
250     }
251     const G4String attName  = Transcode(attribute->getName());
252     const G4String attValue = Transcode(attribute->getValue());
253 
254     if(attName == "name")
255     {
256       name = GenerateName(attValue);
257     }
258     else if(attName == "lunit")
259     {
260       lunit = G4UnitDefinition::GetValueOf(attValue);
261       if(G4UnitDefinition::GetCategory(attValue) != "Length")
262       {
263         G4Exception("G4GDMLReadSolids::BoxRead()", "InvalidRead",
264                     FatalException, "Invalid unit for length!");
265       }
266     }
267     else if(attName == "x")
268     {
269       x = eval.Evaluate(attValue);
270     }
271     else if(attName == "y")
272     {
273       y = eval.Evaluate(attValue);
274     }
275     else if(attName == "z")
276     {
277       z = eval.Evaluate(attValue);
278     }
279   }
280 
281   x *= 0.5 * lunit;
282   y *= 0.5 * lunit;
283   z *= 0.5 * lunit;
284 
285   new G4Box(name, x, y, z);
286 }
287 
288 // --------------------------------------------------------------------
289 void G4GDMLReadSolids::ConeRead(const xercesc::DOMElement* const coneElement)
290 {
291   G4String name;
292   G4double lunit    = 1.0;
293   G4double aunit    = 1.0;
294   G4double rmin1    = 0.0;
295   G4double rmax1    = 0.0;
296   G4double rmin2    = 0.0;
297   G4double rmax2    = 0.0;
298   G4double z        = 0.0;
299   G4double startphi = 0.0;
300   G4double deltaphi = 0.0;
301 
302   const xercesc::DOMNamedNodeMap* const attributes =
303     coneElement->getAttributes();
304   XMLSize_t attributeCount = attributes->getLength();
305 
306   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
307       ++attribute_index)
308   {
309     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
310 
311     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
312     {
313       continue;
314     }
315 
316     const xercesc::DOMAttr* const attribute =
317       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
318     if(attribute == nullptr)
319     {
320       G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead", FatalException,
321                   "No attribute found!");
322       return;
323     }
324     const G4String attName  = Transcode(attribute->getName());
325     const G4String attValue = Transcode(attribute->getValue());
326 
327     if(attName == "name")
328     {
329       name = GenerateName(attValue);
330     }
331     else if(attName == "lunit")
332     {
333       lunit = G4UnitDefinition::GetValueOf(attValue);
334       if(G4UnitDefinition::GetCategory(attValue) != "Length")
335       {
336         G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead",
337                     FatalException, "Invalid unit for length!");
338       }
339     }
340     else if(attName == "aunit")
341     {
342       aunit = G4UnitDefinition::GetValueOf(attValue);
343       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
344       {
345         G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead",
346                     FatalException, "Invalid unit for angle!");
347       }
348     }
349     else if(attName == "rmin1")
350     {
351       rmin1 = eval.Evaluate(attValue);
352     }
353     else if(attName == "rmax1")
354     {
355       rmax1 = eval.Evaluate(attValue);
356     }
357     else if(attName == "rmin2")
358     {
359       rmin2 = eval.Evaluate(attValue);
360     }
361     else if(attName == "rmax2")
362     {
363       rmax2 = eval.Evaluate(attValue);
364     }
365     else if(attName == "z")
366     {
367       z = eval.Evaluate(attValue);
368     }
369     else if(attName == "startphi")
370     {
371       startphi = eval.Evaluate(attValue);
372     }
373     else if(attName == "deltaphi")
374     {
375       deltaphi = eval.Evaluate(attValue);
376     }
377   }
378 
379   rmin1 *= lunit;
380   rmax1 *= lunit;
381   rmin2 *= lunit;
382   rmax2 *= lunit;
383   z *= 0.5 * lunit;
384   startphi *= aunit;
385   deltaphi *= aunit;
386 
387   new G4Cons(name, rmin1, rmax1, rmin2, rmax2, z, startphi, deltaphi);
388 }
389 
390 // --------------------------------------------------------------------
391 void G4GDMLReadSolids::ElconeRead(
392   const xercesc::DOMElement* const elconeElement)
393 {
394   G4String name;
395   G4double lunit = 1.0;
396   G4double dx    = 0.0;
397   G4double dy    = 0.0;
398   G4double zmax  = 0.0;
399   G4double zcut  = 0.0;
400 
401   const xercesc::DOMNamedNodeMap* const attributes =
402     elconeElement->getAttributes();
403   XMLSize_t attributeCount = attributes->getLength();
404 
405   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
406       ++attribute_index)
407   {
408     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
409 
410     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
411     {
412       continue;
413     }
414 
415     const xercesc::DOMAttr* const attribute =
416       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
417     if(attribute == nullptr)
418     {
419       G4Exception("G4GDMLReadSolids::ElconeRead()", "InvalidRead",
420                   FatalException, "No attribute found!");
421       return;
422     }
423     const G4String attName  = Transcode(attribute->getName());
424     const G4String attValue = Transcode(attribute->getValue());
425 
426     if(attName == "name")
427     {
428       name = GenerateName(attValue);
429     }
430     else if(attName == "lunit")
431     {
432       lunit = G4UnitDefinition::GetValueOf(attValue);
433       if(G4UnitDefinition::GetCategory(attValue) != "Length")
434       {
435         G4Exception("G4GDMLReadSolids::ElconeRead()", "InvalidRead",
436                     FatalException, "Invalid unit for length!");
437       }
438     }
439     else if(attName == "dx")
440     {
441       dx = eval.Evaluate(attValue);
442     }
443     else if(attName == "dy")
444     {
445       dy = eval.Evaluate(attValue);
446     }
447     else if(attName == "zmax")
448     {
449       zmax = eval.Evaluate(attValue);
450     }
451     else if(attName == "zcut")
452     {
453       zcut = eval.Evaluate(attValue);
454     }
455   }
456 
457   zmax *= lunit;
458   zcut *= lunit;
459 
460   new G4EllipticalCone(name, dx, dy, zmax, zcut);
461 }
462 
463 // --------------------------------------------------------------------
464 void G4GDMLReadSolids::EllipsoidRead(
465   const xercesc::DOMElement* const ellipsoidElement)
466 {
467   G4String name;
468   G4double lunit = 1.0;
469   G4double ax    = 0.0;
470   G4double by    = 0.0;
471   G4double cz    = 0.0;
472   G4double zcut1 = 0.0;
473   G4double zcut2 = 0.0;
474 
475   const xercesc::DOMNamedNodeMap* const attributes =
476     ellipsoidElement->getAttributes();
477   XMLSize_t attributeCount = attributes->getLength();
478 
479   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
480       ++attribute_index)
481   {
482     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
483 
484     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
485     {
486       continue;
487     }
488 
489     const xercesc::DOMAttr* const attribute =
490       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
491     if(attribute == nullptr)
492     {
493       G4Exception("G4GDMLReadSolids::EllipsoidRead()", "InvalidRead",
494                   FatalException, "No attribute found!");
495       return;
496     }
497     const G4String attName  = Transcode(attribute->getName());
498     const G4String attValue = Transcode(attribute->getValue());
499 
500     if(attName == "name")
501     {
502       name = GenerateName(attValue);
503     }
504     else if(attName == "lunit")
505     {
506       lunit = G4UnitDefinition::GetValueOf(attValue);
507       if(G4UnitDefinition::GetCategory(attValue) != "Length")
508       {
509         G4Exception("G4GDMLReadSolids::EllipsoidRead()", "InvalidRead",
510                     FatalException, "Invalid unit for length!");
511       }
512     }
513     else if(attName == "ax")
514     {
515       ax = eval.Evaluate(attValue);
516     }
517     else if(attName == "by")
518     {
519       by = eval.Evaluate(attValue);
520     }
521     else if(attName == "cz")
522     {
523       cz = eval.Evaluate(attValue);
524     }
525     else if(attName == "zcut1")
526     {
527       zcut1 = eval.Evaluate(attValue);
528     }
529     else if(attName == "zcut2")
530     {
531       zcut2 = eval.Evaluate(attValue);
532     }
533   }
534 
535   ax *= lunit;
536   by *= lunit;
537   cz *= lunit;
538   zcut1 *= lunit;
539   zcut2 *= lunit;
540 
541   new G4Ellipsoid(name, ax, by, cz, zcut1, zcut2);
542 }
543 
544 // --------------------------------------------------------------------
545 void G4GDMLReadSolids::EltubeRead(
546   const xercesc::DOMElement* const eltubeElement)
547 {
548   G4String name;
549   G4double lunit = 1.0;
550   G4double dx    = 0.0;
551   G4double dy    = 0.0;
552   G4double dz    = 0.0;
553 
554   const xercesc::DOMNamedNodeMap* const attributes =
555     eltubeElement->getAttributes();
556   XMLSize_t attributeCount = attributes->getLength();
557 
558   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
559       ++attribute_index)
560   {
561     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
562 
563     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
564     {
565       continue;
566     }
567 
568     const xercesc::DOMAttr* const attribute =
569       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
570     if(attribute == nullptr)
571     {
572       G4Exception("G4GDMLReadSolids::EltubeRead()", "InvalidRead",
573                   FatalException, "No attribute found!");
574       return;
575     }
576     const G4String attName  = Transcode(attribute->getName());
577     const G4String attValue = Transcode(attribute->getValue());
578 
579     if(attName == "name")
580     {
581       name = GenerateName(attValue);
582     }
583     else if(attName == "lunit")
584     {
585       lunit = G4UnitDefinition::GetValueOf(attValue);
586       if(G4UnitDefinition::GetCategory(attValue) != "Length")
587       {
588         G4Exception("G4GDMLReadSolids::EltubeRead()", "InvalidRead",
589                     FatalException, "Invalid unit for length!");
590       }
591     }
592     else if(attName == "dx")
593     {
594       dx = eval.Evaluate(attValue);
595     }
596     else if(attName == "dy")
597     {
598       dy = eval.Evaluate(attValue);
599     }
600     else if(attName == "dz")
601     {
602       dz = eval.Evaluate(attValue);
603     }
604   }
605 
606   dx *= lunit;
607   dy *= lunit;
608   dz *= lunit;
609 
610   new G4EllipticalTube(name, dx, dy, dz);
611 }
612 
613 // --------------------------------------------------------------------
614 void G4GDMLReadSolids::XtruRead(const xercesc::DOMElement* const xtruElement)
615 {
616   G4String name;
617   G4double lunit = 1.0;
618 
619   const xercesc::DOMNamedNodeMap* const attributes =
620     xtruElement->getAttributes();
621   XMLSize_t attributeCount = attributes->getLength();
622 
623   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
624       ++attribute_index)
625   {
626     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
627 
628     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
629     {
630       continue;
631     }
632 
633     const xercesc::DOMAttr* const attribute =
634       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
635     if(attribute == nullptr)
636     {
637       G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead", FatalException,
638                   "No attribute found!");
639       return;
640     }
641     const G4String attName  = Transcode(attribute->getName());
642     const G4String attValue = Transcode(attribute->getValue());
643 
644     if(attName == "name")
645     {
646       name = GenerateName(attValue);
647     }
648     else if(attName == "lunit")
649     {
650       lunit = G4UnitDefinition::GetValueOf(attValue);
651       if(G4UnitDefinition::GetCategory(attValue) != "Length")
652       {
653         G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead",
654                     FatalException, "Invalid unit for length!");
655       }
656     }
657   }
658 
659   std::vector<G4TwoVector> twoDimVertexList;
660   std::vector<G4ExtrudedSolid::ZSection> sectionList;
661 
662   for(xercesc::DOMNode* iter = xtruElement->getFirstChild(); iter != nullptr;
663       iter                   = iter->getNextSibling())
664   {
665     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
666     {
667       continue;
668     }
669 
670     const xercesc::DOMElement* const child =
671       dynamic_cast<xercesc::DOMElement*>(iter);
672     if(child == nullptr)
673     {
674       G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead", FatalException,
675                   "No child found!");
676       return;
677     }
678     const G4String tag = Transcode(child->getTagName());
679 
680     if(tag == "twoDimVertex")
681     {
682       twoDimVertexList.push_back(TwoDimVertexRead(child, lunit));
683     }
684     else if(tag == "section")
685     {
686       sectionList.push_back(SectionRead(child, lunit));
687     }
688   }
689 
690   new G4ExtrudedSolid(name, twoDimVertexList, sectionList);
691 }
692 
693 // --------------------------------------------------------------------
694 void G4GDMLReadSolids::HypeRead(const xercesc::DOMElement* const hypeElement)
695 {
696   G4String name;
697   G4double lunit = 1.0;
698   G4double aunit = 1.0;
699   G4double rmin  = 0.0;
700   G4double rmax  = 0.0;
701   G4double inst  = 0.0;
702   G4double outst = 0.0;
703   G4double z     = 0.0;
704 
705   const xercesc::DOMNamedNodeMap* const attributes =
706     hypeElement->getAttributes();
707   XMLSize_t attributeCount = attributes->getLength();
708 
709   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
710       ++attribute_index)
711   {
712     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
713 
714     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
715     {
716       continue;
717     }
718 
719     const xercesc::DOMAttr* const attribute =
720       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
721     if(attribute == nullptr)
722     {
723       G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead", FatalException,
724                   "No attribute found!");
725       return;
726     }
727     const G4String attName  = Transcode(attribute->getName());
728     const G4String attValue = Transcode(attribute->getValue());
729 
730     if(attName == "name")
731     {
732       name = GenerateName(attValue);
733     }
734     else if(attName == "lunit")
735     {
736       lunit = G4UnitDefinition::GetValueOf(attValue);
737       if(G4UnitDefinition::GetCategory(attValue) != "Length")
738       {
739         G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead",
740                     FatalException, "Invalid unit for length!");
741       }
742     }
743     else if(attName == "aunit")
744     {
745       aunit = G4UnitDefinition::GetValueOf(attValue);
746       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
747       {
748         G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead",
749                     FatalException, "Invalid unit for angle!");
750       }
751     }
752     else if(attName == "rmin")
753     {
754       rmin = eval.Evaluate(attValue);
755     }
756     else if(attName == "rmax")
757     {
758       rmax = eval.Evaluate(attValue);
759     }
760     else if(attName == "inst")
761     {
762       inst = eval.Evaluate(attValue);
763     }
764     else if(attName == "outst")
765     {
766       outst = eval.Evaluate(attValue);
767     }
768     else if(attName == "z")
769     {
770       z = eval.Evaluate(attValue);
771     }
772   }
773 
774   rmin *= lunit;
775   rmax *= lunit;
776   inst *= aunit;
777   outst *= aunit;
778   z *= 0.5 * lunit;
779 
780   new G4Hype(name, rmin, rmax, inst, outst, z);
781 }
782 
783 // --------------------------------------------------------------------
784 void G4GDMLReadSolids::MultiUnionNodeRead(
785   const xercesc::DOMElement* const unionNodeElement,
786   G4MultiUnion* const multiUnionSolid)
787 {
788   G4String name;
789   G4String solid;
790   G4ThreeVector position(0.0, 0.0, 0.0);
791   G4ThreeVector rotation(0.0, 0.0, 0.0);
792 
793   const xercesc::DOMNamedNodeMap* const attributes =
794     unionNodeElement->getAttributes();
795   XMLSize_t attributeCount = attributes->getLength();
796 
797   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
798       ++attribute_index)
799   {
800     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
801 
802     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
803     {
804       continue;
805     }
806 
807     const xercesc::DOMAttr* const attribute =
808       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
809     if(attribute == nullptr)
810     {
811       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "InvalidRead",
812                   FatalException, "No attribute found!");
813       return;
814     }
815     const G4String attName  = Transcode(attribute->getName());
816     const G4String attValue = Transcode(attribute->getValue());
817 
818     if(attName == "name")
819     {
820       name = GenerateName(attValue);
821     }
822   }
823 
824   for(xercesc::DOMNode* iter = unionNodeElement->getFirstChild();
825                         iter != nullptr; iter = iter->getNextSibling())
826   {
827     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
828     {
829       continue;
830     }
831 
832     const xercesc::DOMElement* const child =
833       dynamic_cast<xercesc::DOMElement*>(iter);
834     if(child == nullptr)
835     {
836       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "InvalidRead",
837                   FatalException, "No child found!");
838       return;
839     }
840     const G4String tag = Transcode(child->getTagName());
841 
842     if(tag == "position")
843     {
844       VectorRead(child, position);
845     }
846     else if(tag == "rotation")
847     {
848       VectorRead(child, rotation);
849     }
850     else if(tag == "positionref")
851     {
852       position = GetPosition(GenerateName(RefRead(child)));
853     }
854     else if(tag == "rotationref")
855     {
856       rotation = GetRotation(GenerateName(RefRead(child)));
857     }
858     else if(tag == "solid")
859     {
860       solid = RefRead(child);
861     }
862     else
863     {
864       G4String error_msg = "Unknown tag in MultiUnion structure: " + tag;
865       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "ReadError",
866                   FatalException, error_msg);
867     }
868   }
869   G4VSolid* solidNode = GetSolid(GenerateName(solid));
870   G4Transform3D transform(GetRotationMatrix(rotation), position);
871   multiUnionSolid->AddNode(*solidNode, transform);
872 }
873 
874 // --------------------------------------------------------------------
875 void G4GDMLReadSolids::MultiUnionRead(
876   const xercesc::DOMElement* const unionElement)
877 {
878   G4String name;
879 
880   const xercesc::DOMNamedNodeMap* const attributes =
881     unionElement->getAttributes();
882   XMLSize_t attributeCount = attributes->getLength();
883 
884   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
885       ++attribute_index)
886   {
887     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
888 
889     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
890     {
891       continue;
892     }
893 
894     const xercesc::DOMAttr* const attribute =
895       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
896     if(attribute == nullptr)
897     {
898       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "InvalidRead",
899                   FatalException, "No attribute found!");
900       return;
901     }
902     const G4String attName  = Transcode(attribute->getName());
903     const G4String attValue = Transcode(attribute->getValue());
904 
905     if(attName == "name")
906     {
907       name = GenerateName(attValue);
908     }
909   }
910 
911   G4MultiUnion* multiUnion = new G4MultiUnion(name);
912 
913   for(xercesc::DOMNode* iter = unionElement->getFirstChild(); iter != nullptr;
914       iter                   = iter->getNextSibling())
915   {
916     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
917     {
918       continue;
919     }
920 
921     const xercesc::DOMElement* const child =
922       dynamic_cast<xercesc::DOMElement*>(iter);
923     if(child == nullptr)
924     {
925       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "InvalidRead",
926                   FatalException, "No child found!");
927       return;
928     }
929     const G4String tag = Transcode(child->getTagName());
930 
931     if(tag == "multiUnionNode")
932     {
933       MultiUnionNodeRead(child, multiUnion);
934     }
935     else
936     {
937       G4String error_msg = "Unknown tag in MultiUnion structure: " + tag;
938       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "ReadError",
939                   FatalException, error_msg);
940     }
941   }
942   multiUnion->Voxelize();
943 }
944 
945 // --------------------------------------------------------------------
946 void G4GDMLReadSolids::OrbRead(const xercesc::DOMElement* const orbElement)
947 {
948   G4String name;
949   G4double lunit = 1.0;
950   G4double r     = 0.0;
951 
952   const xercesc::DOMNamedNodeMap* const attributes =
953     orbElement->getAttributes();
954   XMLSize_t attributeCount = attributes->getLength();
955 
956   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
957       ++attribute_index)
958   {
959     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
960 
961     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
962     {
963       continue;
964     }
965 
966     const xercesc::DOMAttr* const attribute =
967       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
968     if(attribute == nullptr)
969     {
970       G4Exception("G4GDMLReadSolids::OrbRead()", "InvalidRead", FatalException,
971                   "No attribute found!");
972       return;
973     }
974     const G4String attName  = Transcode(attribute->getName());
975     const G4String attValue = Transcode(attribute->getValue());
976 
977     if(attName == "name")
978     {
979       name = GenerateName(attValue);
980     }
981     else if(attName == "lunit")
982     {
983       lunit = G4UnitDefinition::GetValueOf(attValue);
984       if(G4UnitDefinition::GetCategory(attValue) != "Length")
985       {
986         G4Exception("G4GDMLReadSolids::OrbRead()", "InvalidRead",
987                     FatalException, "Invalid unit for length!");
988       }
989     }
990     else if(attName == "r")
991     {
992       r = eval.Evaluate(attValue);
993     }
994   }
995 
996   r *= lunit;
997 
998   new G4Orb(name, r);
999 }
1000 
1001 // --------------------------------------------------------------------
1002 void G4GDMLReadSolids::ParaRead(const xercesc::DOMElement* const paraElement)
1003 {
1004   G4String name;
1005   G4double lunit = 1.0;
1006   G4double aunit = 1.0;
1007   G4double x     = 0.0;
1008   G4double y     = 0.0;
1009   G4double z     = 0.0;
1010   G4double alpha = 0.0;
1011   G4double theta = 0.0;
1012   G4double phi   = 0.0;
1013 
1014   const xercesc::DOMNamedNodeMap* const attributes =
1015     paraElement->getAttributes();
1016   XMLSize_t attributeCount = attributes->getLength();
1017 
1018   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1019       ++attribute_index)
1020   {
1021     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1022 
1023     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1024     {
1025       continue;
1026     }
1027 
1028     const xercesc::DOMAttr* const attribute =
1029       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1030     if(attribute == nullptr)
1031     {
1032       G4Exception("G4GDMLReadSolids::ParaRead()", "InvalidRead", FatalException,
1033                   "No attribute found!");
1034       return;
1035     }
1036     const G4String attName  = Transcode(attribute->getName());
1037     const G4String attValue = Transcode(attribute->getValue());
1038 
1039     if(attName == "name")
1040     {
1041       name = GenerateName(attValue);
1042     }
1043     else if(attName == "lunit")
1044     {
1045       lunit = G4UnitDefinition::GetValueOf(attValue);
1046       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1047       {
1048         G4Exception("G4GDMLReadSolids::ParaRead()", "InvalidRead",
1049                     FatalException, "Invalid unit for length!");
1050       }
1051     }
1052     else if(attName == "aunit")
1053     {
1054       aunit = G4UnitDefinition::GetValueOf(attValue);
1055       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1056       {
1057         G4Exception("G4GDMLReadSolids::ParaRead()", "InvalidRead",
1058                     FatalException, "Invalid unit for angle!");
1059       }
1060     }
1061     else if(attName == "x")
1062     {
1063       x = eval.Evaluate(attValue);
1064     }
1065     else if(attName == "y")
1066     {
1067       y = eval.Evaluate(attValue);
1068     }
1069     else if(attName == "z")
1070     {
1071       z = eval.Evaluate(attValue);
1072     }
1073     else if(attName == "alpha")
1074     {
1075       alpha = eval.Evaluate(attValue);
1076     }
1077     else if(attName == "theta")
1078     {
1079       theta = eval.Evaluate(attValue);
1080     }
1081     else if(attName == "phi")
1082     {
1083       phi = eval.Evaluate(attValue);
1084     }
1085   }
1086 
1087   x *= 0.5 * lunit;
1088   y *= 0.5 * lunit;
1089   z *= 0.5 * lunit;
1090   alpha *= aunit;
1091   theta *= aunit;
1092   phi *= aunit;
1093 
1094   new G4Para(name, x, y, z, alpha, theta, phi);
1095 }
1096 
1097 // --------------------------------------------------------------------
1098 void G4GDMLReadSolids::ParaboloidRead(
1099   const xercesc::DOMElement* const paraElement)
1100 {
1101   G4String name;
1102   G4double lunit = 1.0;
1103   G4double rlo   = 0.0;
1104   G4double rhi   = 0.0;
1105   G4double dz    = 0.0;
1106 
1107   const xercesc::DOMNamedNodeMap* const attributes =
1108     paraElement->getAttributes();
1109   XMLSize_t attributeCount = attributes->getLength();
1110 
1111   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1112       ++attribute_index)
1113   {
1114     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1115 
1116     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1117     {
1118       continue;
1119     }
1120 
1121     const xercesc::DOMAttr* const attribute =
1122       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1123     if(attribute == nullptr)
1124     {
1125       G4Exception("G4GDMLReadSolids::ParaboloidRead()", "InvalidRead",
1126                   FatalException, "No attribute found!");
1127       return;
1128     }
1129     const G4String attName  = Transcode(attribute->getName());
1130     const G4String attValue = Transcode(attribute->getValue());
1131 
1132     if(attName == "name")
1133     {
1134       name = GenerateName(attValue);
1135     }
1136     else if(attName == "lunit")
1137     {
1138       lunit = G4UnitDefinition::GetValueOf(attValue);
1139       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1140       {
1141         G4Exception("G4GDMLReadSolids::ParaboloidRead()", "InvalidRead",
1142                     FatalException, "Invalid unit for length!");
1143       }
1144     }
1145     else if(attName == "rlo")
1146     {
1147       rlo = eval.Evaluate(attValue);
1148     }
1149     else if(attName == "rhi")
1150     {
1151       rhi = eval.Evaluate(attValue);
1152     }
1153     else if(attName == "dz")
1154     {
1155       dz = eval.Evaluate(attValue);
1156     }
1157   }
1158 
1159   rlo *= 1. * lunit;
1160   rhi *= 1. * lunit;
1161   dz *= 1. * lunit;
1162 
1163   new G4Paraboloid(name, dz, rlo, rhi);
1164 }
1165 
1166 // --------------------------------------------------------------------
1167 void G4GDMLReadSolids::PolyconeRead(
1168   const xercesc::DOMElement* const polyconeElement)
1169 {
1170   G4String name;
1171   G4double lunit    = 1.0;
1172   G4double aunit    = 1.0;
1173   G4double startphi = 0.0;
1174   G4double deltaphi = 0.0;
1175 
1176   const xercesc::DOMNamedNodeMap* const attributes =
1177     polyconeElement->getAttributes();
1178   XMLSize_t attributeCount = attributes->getLength();
1179 
1180   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1181       ++attribute_index)
1182   {
1183     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1184 
1185     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1186     {
1187       continue;
1188     }
1189 
1190     const xercesc::DOMAttr* const attribute =
1191       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1192     if(attribute == nullptr)
1193     {
1194       G4Exception("G4GDMLReadSolids::PolyconeRead()", "InvalidRead",
1195                   FatalException, "No attribute found!");
1196       return;
1197     }
1198     const G4String attName  = Transcode(attribute->getName());
1199     const G4String attValue = Transcode(attribute->getValue());
1200 
1201     if(attName == "name")
1202     {
1203       name = GenerateName(attValue);
1204     }
1205     else if(attName == "lunit")
1206     {
1207       lunit = G4UnitDefinition::GetValueOf(attValue);
1208       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1209       {
1210         G4Exception("G4GDMLReadSolids::PolyconeRead()", "InvalidRead",
1211                     FatalException, "Invalid unit for length!");
1212       }
1213     }
1214     else if(attName == "aunit")
1215     {
1216       aunit = G4UnitDefinition::GetValueOf(attValue);
1217       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1218       {
1219         G4Exception("G4GDMLReadSolids::PolyconeRead()", "InvalidRead",
1220                     FatalException, "Invalid unit for angle!");
1221       }
1222     }
1223     else if(attName == "startphi")
1224     {
1225       startphi = eval.Evaluate(attValue);
1226     }
1227     else if(attName == "deltaphi")
1228     {
1229       deltaphi = eval.Evaluate(attValue);
1230     }
1231   }
1232 
1233   startphi *= aunit;
1234   deltaphi *= aunit;
1235 
1236   std::vector<zplaneType> zplaneList;
1237 
1238   for(xercesc::DOMNode* iter = polyconeElement->getFirstChild(); iter!= nullptr;
1239       iter                   = iter->getNextSibling())
1240   {
1241     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
1242     {
1243       continue;
1244     }
1245 
1246     const xercesc::DOMElement* const child =
1247       dynamic_cast<xercesc::DOMElement*>(iter);
1248     if(child == nullptr)
1249     {
1250       G4Exception("G4GDMLReadSolids::PolyconeRead()", "InvalidRead",
1251                   FatalException, "No child found!");
1252       return;
1253     }
1254     const G4String tag = Transcode(child->getTagName());
1255 
1256     if(tag == "zplane")
1257     {
1258       zplaneList.push_back(ZplaneRead(child));
1259     }
1260   }
1261 
1262   std::size_t numZPlanes = zplaneList.size();
1263 
1264   G4double* rmin_array = new G4double[numZPlanes];
1265   G4double* rmax_array = new G4double[numZPlanes];
1266   G4double* z_array    = new G4double[numZPlanes];
1267 
1268   for(std::size_t i = 0; i < numZPlanes; ++i)
1269   {
1270     rmin_array[i] = zplaneList[i].rmin * lunit;
1271     rmax_array[i] = zplaneList[i].rmax * lunit;
1272     z_array[i]    = zplaneList[i].z * lunit;
1273   }
1274 
1275   new G4Polycone(name, startphi, deltaphi, (G4int)numZPlanes, z_array,
1276                  rmin_array, rmax_array);
1277 
1278   delete[] rmin_array;
1279   delete[] rmax_array;
1280   delete[] z_array;
1281 }
1282 
1283 // --------------------------------------------------------------------
1284 void G4GDMLReadSolids::GenericPolyconeRead(
1285   const xercesc::DOMElement* const polyconeElement)
1286 {
1287   G4String name;
1288   G4double lunit    = 1.0;
1289   G4double aunit    = 1.0;
1290   G4double startphi = 0.0;
1291   G4double deltaphi = 0.0;
1292 
1293   const xercesc::DOMNamedNodeMap* const attributes =
1294     polyconeElement->getAttributes();
1295   XMLSize_t attributeCount = attributes->getLength();
1296 
1297   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1298       ++attribute_index)
1299   {
1300     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1301 
1302     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1303     {
1304       continue;
1305     }
1306 
1307     const xercesc::DOMAttr* const attribute =
1308       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1309     if(attribute == nullptr)
1310     {
1311       G4Exception("G4GDMLReadSolids::GenericPolyconeRead()", "InvalidRead",
1312                   FatalException, "No attribute found!");
1313       return;
1314     }
1315     const G4String attName  = Transcode(attribute->getName());
1316     const G4String attValue = Transcode(attribute->getValue());
1317 
1318     if(attName == "name")
1319     {
1320       name = GenerateName(attValue);
1321     }
1322     else if(attName == "lunit")
1323     {
1324       lunit = G4UnitDefinition::GetValueOf(attValue);
1325       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1326       {
1327         G4Exception("G4GDMLReadSolids::GenericPolyconeRead()", "InvalidRead",
1328                     FatalException, "Invalid unit for length!");
1329       }
1330     }
1331     else if(attName == "aunit")
1332     {
1333       aunit = G4UnitDefinition::GetValueOf(attValue);
1334       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1335       {
1336         G4Exception("G4GDMLReadSolids::GenericPolyconeRead()", "InvalidRead",
1337                     FatalException, "Invalid unit for angle!");
1338       }
1339     }
1340     else if(attName == "startphi")
1341     {
1342       startphi = eval.Evaluate(attValue);
1343     }
1344     else if(attName == "deltaphi")
1345     {
1346       deltaphi = eval.Evaluate(attValue);
1347     }
1348   }
1349 
1350   startphi *= aunit;
1351   deltaphi *= aunit;
1352 
1353   std::vector<rzPointType> rzPointList;
1354 
1355   for(xercesc::DOMNode* iter = polyconeElement->getFirstChild();
1356                         iter != nullptr; iter = iter->getNextSibling())
1357   {
1358     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
1359     {
1360       continue;
1361     }
1362 
1363     const xercesc::DOMElement* const child =
1364       dynamic_cast<xercesc::DOMElement*>(iter);
1365     if(child == nullptr)
1366     {
1367       G4Exception("G4GDMLReadSolids::GenericPolyconeRead()", "InvalidRead",
1368                   FatalException, "No child found!");
1369       return;
1370     }
1371     const G4String tag = Transcode(child->getTagName());
1372 
1373     if(tag == "rzpoint")
1374     {
1375       rzPointList.push_back(RZPointRead(child));
1376     }
1377   }
1378 
1379   std::size_t numRZPoints = rzPointList.size();
1380 
1381   G4double* r_array = new G4double[numRZPoints];
1382   G4double* z_array = new G4double[numRZPoints];
1383 
1384   for(std::size_t i = 0; i < numRZPoints; ++i)
1385   {
1386     r_array[i] = rzPointList[i].r * lunit;
1387     z_array[i] = rzPointList[i].z * lunit;
1388   }
1389   new G4GenericPolycone(name, startphi, deltaphi, (G4int)numRZPoints,
1390                         r_array, z_array);
1391   delete[] r_array;
1392   delete[] z_array;
1393 }
1394 
1395 // --------------------------------------------------------------------
1396 void G4GDMLReadSolids::PolyhedraRead(
1397   const xercesc::DOMElement* const polyhedraElement)
1398 {
1399   G4String name;
1400   G4double lunit    = 1.0;
1401   G4double aunit    = 1.0;
1402   G4double startphi = 0.0;
1403   G4double deltaphi = 0.0;
1404   G4int numsides    = 0;
1405 
1406   const xercesc::DOMNamedNodeMap* const attributes =
1407     polyhedraElement->getAttributes();
1408   XMLSize_t attributeCount = attributes->getLength();
1409 
1410   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1411       ++attribute_index)
1412   {
1413     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1414 
1415     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1416     {
1417       continue;
1418     }
1419 
1420     const xercesc::DOMAttr* const attribute =
1421       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1422     if(attribute == nullptr)
1423     {
1424       G4Exception("G4GDMLReadSolids::PolyhedraRead()", "InvalidRead",
1425                   FatalException, "No attribute found!");
1426       return;
1427     }
1428     const G4String attName  = Transcode(attribute->getName());
1429     const G4String attValue = Transcode(attribute->getValue());
1430 
1431     if(attName == "name")
1432     {
1433       name = GenerateName(attValue);
1434     }
1435     else if(attName == "lunit")
1436     {
1437       lunit = G4UnitDefinition::GetValueOf(attValue);
1438       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1439       {
1440         G4Exception("G4GDMLReadSolids::PolyhedraRead()", "InvalidRead",
1441                     FatalException, "Invalid unit for length!");
1442       }
1443     }
1444     else if(attName == "aunit")
1445     {
1446       aunit = G4UnitDefinition::GetValueOf(attValue);
1447       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1448       {
1449         G4Exception("G4GDMLReadSolids::PolyhedraRead()", "InvalidRead",
1450                     FatalException, "Invalid unit for angle!");
1451       }
1452     }
1453     else if(attName == "startphi")
1454     {
1455       startphi = eval.Evaluate(attValue);
1456     }
1457     else if(attName == "deltaphi")
1458     {
1459       deltaphi = eval.Evaluate(attValue);
1460     }
1461     else if(attName == "numsides")
1462     {
1463       numsides = eval.EvaluateInteger(attValue);
1464     }
1465   }
1466 
1467   startphi *= aunit;
1468   deltaphi *= aunit;
1469 
1470   std::vector<zplaneType> zplaneList;
1471 
1472   for(xercesc::DOMNode* iter = polyhedraElement->getFirstChild();
1473                         iter != nullptr; iter = iter->getNextSibling())
1474   {
1475     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
1476     {
1477       continue;
1478     }
1479 
1480     const xercesc::DOMElement* const child =
1481       dynamic_cast<xercesc::DOMElement*>(iter);
1482     if(child == nullptr)
1483     {
1484       G4Exception("G4GDMLReadSolids::PolyhedraRead()", "InvalidRead",
1485                   FatalException, "No child found!");
1486       return;
1487     }
1488     const G4String tag = Transcode(child->getTagName());
1489 
1490     if(tag == "zplane")
1491     {
1492       zplaneList.push_back(ZplaneRead(child));
1493     }
1494   }
1495 
1496   std::size_t numZPlanes = zplaneList.size();
1497 
1498   G4double* rmin_array = new G4double[numZPlanes];
1499   G4double* rmax_array = new G4double[numZPlanes];
1500   G4double* z_array    = new G4double[numZPlanes];
1501 
1502   for(std::size_t i = 0; i < numZPlanes; ++i)
1503   {
1504     rmin_array[i] = zplaneList[i].rmin * lunit;
1505     rmax_array[i] = zplaneList[i].rmax * lunit;
1506     z_array[i]    = zplaneList[i].z * lunit;
1507   }
1508 
1509   new G4Polyhedra(name, startphi, deltaphi, numsides, (G4int)numZPlanes,
1510                   z_array, rmin_array, rmax_array);
1511 
1512   delete[] rmin_array;
1513   delete[] rmax_array;
1514   delete[] z_array;
1515 }
1516 
1517 // --------------------------------------------------------------------
1518 void G4GDMLReadSolids::GenericPolyhedraRead(
1519   const xercesc::DOMElement* const polyhedraElement)
1520 {
1521   G4String name;
1522   G4double lunit    = 1.0;
1523   G4double aunit    = 1.0;
1524   G4double startphi = 0.0;
1525   G4double deltaphi = 0.0;
1526   G4int numsides    = 0;
1527 
1528   const xercesc::DOMNamedNodeMap* const attributes =
1529     polyhedraElement->getAttributes();
1530   XMLSize_t attributeCount = attributes->getLength();
1531 
1532   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1533       ++attribute_index)
1534   {
1535     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1536 
1537     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1538     {
1539       continue;
1540     }
1541 
1542     const xercesc::DOMAttr* const attribute =
1543       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1544     if(attribute == nullptr)
1545     {
1546       G4Exception("G4GDMLReadSolids::GenericPolyhedraRead()", "InvalidRead",
1547                   FatalException, "No attribute found!");
1548       return;
1549     }
1550     const G4String attName  = Transcode(attribute->getName());
1551     const G4String attValue = Transcode(attribute->getValue());
1552 
1553     if(attName == "name")
1554     {
1555       name = GenerateName(attValue);
1556     }
1557     else if(attName == "lunit")
1558     {
1559       lunit = G4UnitDefinition::GetValueOf(attValue);
1560       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1561       {
1562         G4Exception("G4GDMLReadSolids::GenericPolyhedraRead()", "InvalidRead",
1563                     FatalException, "Invalid unit for length!");
1564       }
1565     }
1566     else if(attName == "aunit")
1567     {
1568       aunit = G4UnitDefinition::GetValueOf(attValue);
1569       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1570       {
1571         G4Exception("G4GDMLReadSolids::GenericPolyhedraRead()", "InvalidRead",
1572                     FatalException, "Invalid unit for angle!");
1573       }
1574     }
1575     else if(attName == "startphi")
1576     {
1577       startphi = eval.Evaluate(attValue);
1578     }
1579     else if(attName == "deltaphi")
1580     {
1581       deltaphi = eval.Evaluate(attValue);
1582     }
1583     else if(attName == "numsides")
1584     {
1585       numsides = eval.EvaluateInteger(attValue);
1586     }
1587   }
1588 
1589   startphi *= aunit;
1590   deltaphi *= aunit;
1591 
1592   std::vector<rzPointType> rzpointList;
1593 
1594   for(xercesc::DOMNode* iter = polyhedraElement->getFirstChild();
1595                         iter != nullptr; iter = iter->getNextSibling())
1596   {
1597     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
1598     {
1599       continue;
1600     }
1601 
1602     const xercesc::DOMElement* const child =
1603       dynamic_cast<xercesc::DOMElement*>(iter);
1604     if(child == nullptr)
1605     {
1606       G4Exception("G4GDMLReadSolids::GenericPolyhedraRead()", "InvalidRead",
1607                   FatalException, "No child found!");
1608       return;
1609     }
1610     const G4String tag = Transcode(child->getTagName());
1611 
1612     if(tag == "rzpoint")
1613     {
1614       rzpointList.push_back(RZPointRead(child));
1615     }
1616   }
1617 
1618   std::size_t numRZPoints = rzpointList.size();
1619 
1620   G4double* r_array = new G4double[numRZPoints];
1621   G4double* z_array = new G4double[numRZPoints];
1622 
1623   for(std::size_t i = 0; i < numRZPoints; ++i)
1624   {
1625     r_array[i] = rzpointList[i].r * lunit;
1626     z_array[i] = rzpointList[i].z * lunit;
1627   }
1628 
1629   new G4Polyhedra(name, startphi, deltaphi, numsides, (G4int)numRZPoints,
1630                   r_array, z_array);
1631 
1632   delete[] r_array;
1633   delete[] z_array;
1634 }
1635 
1636 // --------------------------------------------------------------------
1637 G4QuadrangularFacet* G4GDMLReadSolids::QuadrangularRead(
1638   const xercesc::DOMElement* const quadrangularElement)
1639 {
1640   G4ThreeVector vertex1;
1641   G4ThreeVector vertex2;
1642   G4ThreeVector vertex3;
1643   G4ThreeVector vertex4;
1644   G4FacetVertexType type = ABSOLUTE;
1645   G4double lunit         = 1.0;
1646 
1647   const xercesc::DOMNamedNodeMap* const attributes =
1648     quadrangularElement->getAttributes();
1649   XMLSize_t attributeCount = attributes->getLength();
1650 
1651   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1652       ++attribute_index)
1653   {
1654     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1655 
1656     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1657     {
1658       continue;
1659     }
1660 
1661     const xercesc::DOMAttr* const attribute =
1662       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1663     if(attribute == nullptr)
1664     {
1665       G4Exception("G4GDMLReadSolids::QuadrangularRead()", "InvalidRead",
1666                   FatalException, "No attribute found!");
1667       return nullptr;
1668     }
1669     const G4String attName  = Transcode(attribute->getName());
1670     const G4String attValue = Transcode(attribute->getValue());
1671 
1672     if(attName == "vertex1")
1673     {
1674       vertex1 = GetPosition(GenerateName(attValue));
1675     }
1676     else if(attName == "vertex2")
1677     {
1678       vertex2 = GetPosition(GenerateName(attValue));
1679     }
1680     else if(attName == "vertex3")
1681     {
1682       vertex3 = GetPosition(GenerateName(attValue));
1683     }
1684     else if(attName == "vertex4")
1685     {
1686       vertex4 = GetPosition(GenerateName(attValue));
1687     }
1688     else if(attName == "lunit")
1689     {
1690       lunit = G4UnitDefinition::GetValueOf(attValue);
1691       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1692       {
1693         G4Exception("G4GDMLReadSolids::QuadrangularRead()", "InvalidRead",
1694                     FatalException, "Invalid unit for length!");
1695       }
1696     }
1697     else if(attName == "type")
1698     {
1699       if(attValue == "RELATIVE")
1700       {
1701         type = RELATIVE;
1702       }
1703     }
1704   }
1705 
1706   return new G4QuadrangularFacet(vertex1 * lunit, vertex2 * lunit,
1707                                  vertex3 * lunit, vertex4 * lunit, type);
1708 }
1709 
1710 // --------------------------------------------------------------------
1711 void G4GDMLReadSolids::ReflectedSolidRead(
1712   const xercesc::DOMElement* const reflectedSolidElement)
1713 {
1714   G4String name;
1715   G4double lunit = 1.0;
1716   G4double aunit = 1.0;
1717   G4String solid;
1718   G4ThreeVector scale(1.0, 1.0, 1.0);
1719   G4ThreeVector rotation;
1720   G4ThreeVector position;
1721 
1722   const xercesc::DOMNamedNodeMap* const attributes =
1723     reflectedSolidElement->getAttributes();
1724   XMLSize_t attributeCount = attributes->getLength();
1725 
1726   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1727       ++attribute_index)
1728   {
1729     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1730 
1731     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1732     {
1733       continue;
1734     }
1735 
1736     const xercesc::DOMAttr* const attribute =
1737       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1738     if(attribute == nullptr)
1739     {
1740       G4Exception("G4GDMLReadSolids::ReflectedSolidRead()", "InvalidRead",
1741                   FatalException, "No attribute found!");
1742       return;
1743     }
1744     const G4String attName  = Transcode(attribute->getName());
1745     const G4String attValue = Transcode(attribute->getValue());
1746 
1747     if(attName == "name")
1748     {
1749       name = GenerateName(attValue);
1750     }
1751     else if(attName == "lunit")
1752     {
1753       lunit = G4UnitDefinition::GetValueOf(attValue);
1754       if(G4UnitDefinition::GetCategory(attValue) != "Length")
1755       {
1756         G4Exception("G4GDMLReadSolids::ReflectedSolidRead()", "InvalidRead",
1757                     FatalException, "Invalid unit for length!");
1758       }
1759     }
1760     else if(attName == "aunit")
1761     {
1762       aunit = G4UnitDefinition::GetValueOf(attValue);
1763       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
1764       {
1765         G4Exception("G4GDMLReadSolids::ReflectedSolidRead()", "InvalidRead",
1766                     FatalException, "Invalid unit for angle!");
1767       }
1768     }
1769     else if(attName == "solid")
1770     {
1771       solid = GenerateName(attValue);
1772     }
1773     else if(attName == "sx")
1774     {
1775       scale.setX(eval.Evaluate(attValue));
1776     }
1777     else if(attName == "sy")
1778     {
1779       scale.setY(eval.Evaluate(attValue));
1780     }
1781     else if(attName == "sz")
1782     {
1783       scale.setZ(eval.Evaluate(attValue));
1784     }
1785     else if(attName == "rx")
1786     {
1787       rotation.setX(eval.Evaluate(attValue));
1788     }
1789     else if(attName == "ry")
1790     {
1791       rotation.setY(eval.Evaluate(attValue));
1792     }
1793     else if(attName == "rz")
1794     {
1795       rotation.setZ(eval.Evaluate(attValue));
1796     }
1797     else if(attName == "dx")
1798     {
1799       position.setX(eval.Evaluate(attValue));
1800     }
1801     else if(attName == "dy")
1802     {
1803       position.setY(eval.Evaluate(attValue));
1804     }
1805     else if(attName == "dz")
1806     {
1807       position.setZ(eval.Evaluate(attValue));
1808     }
1809   }
1810 
1811   rotation *= aunit;
1812   position *= lunit;
1813 
1814   G4Transform3D transform(GetRotationMatrix(rotation), position);
1815   transform = transform * G4Scale3D(scale.x(), scale.y(), scale.z());
1816 
1817   new G4ReflectedSolid(name, GetSolid(solid), transform);
1818 }
1819 
1820 // --------------------------------------------------------------------
1821 void G4GDMLReadSolids::ScaledSolidRead(
1822   const xercesc::DOMElement* const scaledSolidElement)
1823 {
1824   G4String name;
1825   G4VSolid* solid = nullptr;
1826   G4ThreeVector scale(1.0, 1.0, 1.0);
1827 
1828   const xercesc::DOMNamedNodeMap* const attributes =
1829     scaledSolidElement->getAttributes();
1830   XMLSize_t attributeCount = attributes->getLength();
1831 
1832   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1833       ++attribute_index)
1834   {
1835     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1836 
1837     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1838     {
1839       continue;
1840     }
1841 
1842     const xercesc::DOMAttr* const attribute =
1843       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1844     if(attribute == nullptr)
1845     {
1846       G4Exception("G4GDMLReadSolids::ScaledSolidRead()", "InvalidRead",
1847                   FatalException, "No attribute found!");
1848       return;
1849     }
1850     const G4String attName  = Transcode(attribute->getName());
1851     const G4String attValue = Transcode(attribute->getValue());
1852 
1853     if(attName == "name")
1854     {
1855       name = GenerateName(attValue);
1856     }
1857   }
1858 
1859   for(xercesc::DOMNode* iter = scaledSolidElement->getFirstChild();
1860                         iter != nullptr; iter = iter->getNextSibling())
1861   {
1862     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
1863     {
1864       continue;
1865     }
1866 
1867     const xercesc::DOMElement* const child =
1868       dynamic_cast<xercesc::DOMElement*>(iter);
1869     if(child == nullptr)
1870     {
1871       G4Exception("G4GDMLReadSolids::ScaledSolidRead()", "InvalidRead",
1872                   FatalException, "No child found!");
1873       return;
1874     }
1875     const G4String tag = Transcode(child->getTagName());
1876 
1877     if(tag == "solidref")
1878     {
1879       solid = GetSolid(GenerateName(RefRead(child)));
1880     }
1881     else if(tag == "scale")
1882     {
1883       VectorRead(child, scale);
1884     }
1885     else if(tag == "scaleref")
1886     {
1887       scale = GetScale(GenerateName(RefRead(child)));
1888     }
1889     else
1890     {
1891       G4String error_msg = "Unknown tag in scaled solid: " + tag;
1892       G4Exception("G4GDMLReadSolids::ScaledSolidRead()", "ReadError",
1893                   FatalException, error_msg);
1894       return;
1895     }
1896   }
1897 
1898   G4Scale3D transform = G4Scale3D(scale.x(), scale.y(), scale.z());
1899 
1900   new G4ScaledSolid(name, solid, transform);
1901 }
1902 
1903 // --------------------------------------------------------------------
1904 G4ExtrudedSolid::ZSection G4GDMLReadSolids::SectionRead(
1905   const xercesc::DOMElement* const sectionElement, G4double lunit)
1906 {
1907   G4double zPosition = 0.0;
1908   G4TwoVector Offset;
1909   G4double scalingFactor = 1.0;
1910 
1911   const xercesc::DOMNamedNodeMap* const attributes =
1912     sectionElement->getAttributes();
1913   XMLSize_t attributeCount = attributes->getLength();
1914 
1915   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1916       ++attribute_index)
1917   {
1918     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1919 
1920     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1921     {
1922       continue;
1923     }
1924 
1925     const xercesc::DOMAttr* const attribute =
1926       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1927     if(attribute == nullptr)
1928     {
1929       G4Exception("G4GDMLReadSolids::SectionRead()", "InvalidRead",
1930                   FatalException, "No attribute found!");
1931       return G4ExtrudedSolid::ZSection(zPosition, Offset, scalingFactor);
1932     }
1933     const G4String attName  = Transcode(attribute->getName());
1934     const G4String attValue = Transcode(attribute->getValue());
1935 
1936     if(attName == "zPosition")
1937     {
1938       zPosition = eval.Evaluate(attValue) * lunit;
1939     }
1940     else if(attName == "xOffset")
1941     {
1942       Offset.setX(eval.Evaluate(attValue) * lunit);
1943     }
1944     else if(attName == "yOffset")
1945     {
1946       Offset.setY(eval.Evaluate(attValue) * lunit);
1947     }
1948     else if(attName == "scalingFactor")
1949     {
1950       scalingFactor = eval.Evaluate(attValue);
1951     }
1952   }
1953 
1954   return G4ExtrudedSolid::ZSection(zPosition, Offset, scalingFactor);
1955 }
1956 
1957 // --------------------------------------------------------------------
1958 void G4GDMLReadSolids::SphereRead(
1959   const xercesc::DOMElement* const sphereElement)
1960 {
1961   G4String name;
1962   G4double lunit      = 1.0;
1963   G4double aunit      = 1.0;
1964   G4double rmin       = 0.0;
1965   G4double rmax       = 0.0;
1966   G4double startphi   = 0.0;
1967   G4double deltaphi   = 0.0;
1968   G4double starttheta = 0.0;
1969   G4double deltatheta = 0.0;
1970 
1971   const xercesc::DOMNamedNodeMap* const attributes =
1972     sphereElement->getAttributes();
1973   XMLSize_t attributeCount = attributes->getLength();
1974 
1975   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
1976       ++attribute_index)
1977   {
1978     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
1979 
1980     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
1981     {
1982       continue;
1983     }
1984 
1985     const xercesc::DOMAttr* const attribute =
1986       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
1987     if(attribute == nullptr)
1988     {
1989       G4Exception("G4GDMLReadSolids::SphereRead()", "InvalidRead",
1990                   FatalException, "No attribute found!");
1991       return;
1992     }
1993     const G4String attName  = Transcode(attribute->getName());
1994     const G4String attValue = Transcode(attribute->getValue());
1995 
1996     if(attName == "name")
1997     {
1998       name = GenerateName(attValue);
1999     }
2000     else if(attName == "lunit")
2001     {
2002       lunit = G4UnitDefinition::GetValueOf(attValue);
2003       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2004       {
2005         G4Exception("G4GDMLReadSolids::SphereRead()", "InvalidRead",
2006                     FatalException, "Invalid unit for length!");
2007       }
2008     }
2009     else if(attName == "aunit")
2010     {
2011       aunit = G4UnitDefinition::GetValueOf(attValue);
2012       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2013       {
2014         G4Exception("G4GDMLReadSolids::SphereRead()", "InvalidRead",
2015                     FatalException, "Invalid unit for angle!");
2016       }
2017     }
2018     else if(attName == "rmin")
2019     {
2020       rmin = eval.Evaluate(attValue);
2021     }
2022     else if(attName == "rmax")
2023     {
2024       rmax = eval.Evaluate(attValue);
2025     }
2026     else if(attName == "startphi")
2027     {
2028       startphi = eval.Evaluate(attValue);
2029     }
2030     else if(attName == "deltaphi")
2031     {
2032       deltaphi = eval.Evaluate(attValue);
2033     }
2034     else if(attName == "starttheta")
2035     {
2036       starttheta = eval.Evaluate(attValue);
2037     }
2038     else if(attName == "deltatheta")
2039     {
2040       deltatheta = eval.Evaluate(attValue);
2041     }
2042   }
2043 
2044   rmin *= lunit;
2045   rmax *= lunit;
2046   startphi *= aunit;
2047   deltaphi *= aunit;
2048   starttheta *= aunit;
2049   deltatheta *= aunit;
2050 
2051   new G4Sphere(name, rmin, rmax, startphi, deltaphi, starttheta, deltatheta);
2052 }
2053 
2054 // --------------------------------------------------------------------
2055 void G4GDMLReadSolids::TessellatedRead(
2056   const xercesc::DOMElement* const tessellatedElement)
2057 {
2058   G4String name;
2059 
2060   const xercesc::DOMNamedNodeMap* const attributes =
2061     tessellatedElement->getAttributes();
2062   XMLSize_t attributeCount = attributes->getLength();
2063 
2064   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2065       ++attribute_index)
2066   {
2067     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2068 
2069     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2070     {
2071       continue;
2072     }
2073 
2074     const xercesc::DOMAttr* const attribute =
2075       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2076     if(attribute == nullptr)
2077     {
2078       G4Exception("G4GDMLReadSolids::TessellatedRead()", "InvalidRead",
2079                   FatalException, "No attribute found!");
2080       return;
2081     }
2082     const G4String attName  = Transcode(attribute->getName());
2083     const G4String attValue = Transcode(attribute->getValue());
2084 
2085     if(attName == "name")
2086     {
2087       name = GenerateName(attValue);
2088     }
2089   }
2090 
2091   G4TessellatedSolid* tessellated = new G4TessellatedSolid(name);
2092 
2093   for(xercesc::DOMNode* iter = tessellatedElement->getFirstChild();
2094                         iter != nullptr; iter = iter->getNextSibling())
2095   {
2096     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
2097     {
2098       continue;
2099     }
2100 
2101     const xercesc::DOMElement* const child =
2102       dynamic_cast<xercesc::DOMElement*>(iter);
2103     if(child == nullptr)
2104     {
2105       G4Exception("G4GDMLReadSolids::TessellatedRead()", "InvalidRead",
2106                   FatalException, "No child found!");
2107       return;
2108     }
2109     const G4String tag = Transcode(child->getTagName());
2110 
2111     if(tag == "triangular")
2112     {
2113       tessellated->AddFacet(TriangularRead(child));
2114     }
2115     else if(tag == "quadrangular")
2116     {
2117       tessellated->AddFacet(QuadrangularRead(child));
2118     }
2119   }
2120 
2121   tessellated->SetSolidClosed(true);
2122 }
2123 
2124 // --------------------------------------------------------------------
2125 void G4GDMLReadSolids::TetRead(const xercesc::DOMElement* const tetElement)
2126 {
2127   G4String name;
2128   G4ThreeVector vertex1;
2129   G4ThreeVector vertex2;
2130   G4ThreeVector vertex3;
2131   G4ThreeVector vertex4;
2132   G4double lunit = 1.0;
2133 
2134   const xercesc::DOMNamedNodeMap* const attributes =
2135     tetElement->getAttributes();
2136   XMLSize_t attributeCount = attributes->getLength();
2137 
2138   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2139       ++attribute_index)
2140   {
2141     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2142 
2143     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2144     {
2145       continue;
2146     }
2147 
2148     const xercesc::DOMAttr* const attribute =
2149       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2150     if(attribute == nullptr)
2151     {
2152       G4Exception("G4GDMLReadSolids::TetRead()", "InvalidRead", FatalException,
2153                   "No attribute found!");
2154       return;
2155     }
2156     const G4String attName  = Transcode(attribute->getName());
2157     const G4String attValue = Transcode(attribute->getValue());
2158 
2159     if(attName == "name")
2160     {
2161       name = GenerateName(attValue);
2162     }
2163     else if(attName == "lunit")
2164     {
2165       lunit = G4UnitDefinition::GetValueOf(attValue);
2166       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2167       {
2168         G4Exception("G4GDMLReadSolids::TetRead()", "InvalidRead",
2169                     FatalException, "Invalid unit for length!");
2170       }
2171     }
2172     else if(attName == "vertex1")
2173     {
2174       vertex1 = GetPosition(GenerateName(attValue));
2175     }
2176     else if(attName == "vertex2")
2177     {
2178       vertex2 = GetPosition(GenerateName(attValue));
2179     }
2180     else if(attName == "vertex3")
2181     {
2182       vertex3 = GetPosition(GenerateName(attValue));
2183     }
2184     else if(attName == "vertex4")
2185     {
2186       vertex4 = GetPosition(GenerateName(attValue));
2187     }
2188   }
2189 
2190   new G4Tet(name, vertex1 * lunit, vertex2 * lunit, vertex3 * lunit,
2191             vertex4 * lunit);
2192 }
2193 
2194 // --------------------------------------------------------------------
2195 void G4GDMLReadSolids::TorusRead(const xercesc::DOMElement* const torusElement)
2196 {
2197   G4String name;
2198   G4double lunit    = 1.0;
2199   G4double aunit    = 1.0;
2200   G4double rmin     = 0.0;
2201   G4double rmax     = 0.0;
2202   G4double rtor     = 0.0;
2203   G4double startphi = 0.0;
2204   G4double deltaphi = 0.0;
2205 
2206   const xercesc::DOMNamedNodeMap* const attributes =
2207     torusElement->getAttributes();
2208   XMLSize_t attributeCount = attributes->getLength();
2209 
2210   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2211       ++attribute_index)
2212   {
2213     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2214 
2215     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2216     {
2217       continue;
2218     }
2219 
2220     const xercesc::DOMAttr* const attribute =
2221       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2222     if(attribute == nullptr)
2223     {
2224       G4Exception("G4GDMLReadSolids::TorusRead()", "InvalidRead",
2225                   FatalException, "No attribute found!");
2226       return;
2227     }
2228     const G4String attName  = Transcode(attribute->getName());
2229     const G4String attValue = Transcode(attribute->getValue());
2230 
2231     if(attName == "name")
2232     {
2233       name = GenerateName(attValue);
2234     }
2235     else if(attName == "lunit")
2236     {
2237       lunit = G4UnitDefinition::GetValueOf(attValue);
2238       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2239       {
2240         G4Exception("G4GDMLReadSolids::TorusRead()", "InvalidRead",
2241                     FatalException, "Invalid unit for length!");
2242       }
2243     }
2244     else if(attName == "aunit")
2245     {
2246       aunit = G4UnitDefinition::GetValueOf(attValue);
2247       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2248       {
2249         G4Exception("G4GDMLReadSolids::TorusRead()", "InvalidRead",
2250                     FatalException, "Invalid unit for angle!");
2251       }
2252     }
2253     else if(attName == "rmin")
2254     {
2255       rmin = eval.Evaluate(attValue);
2256     }
2257     else if(attName == "rmax")
2258     {
2259       rmax = eval.Evaluate(attValue);
2260     }
2261     else if(attName == "rtor")
2262     {
2263       rtor = eval.Evaluate(attValue);
2264     }
2265     else if(attName == "startphi")
2266     {
2267       startphi = eval.Evaluate(attValue);
2268     }
2269     else if(attName == "deltaphi")
2270     {
2271       deltaphi = eval.Evaluate(attValue);
2272     }
2273   }
2274 
2275   rmin *= lunit;
2276   rmax *= lunit;
2277   rtor *= lunit;
2278   startphi *= aunit;
2279   deltaphi *= aunit;
2280 
2281   new G4Torus(name, rmin, rmax, rtor, startphi, deltaphi);
2282 }
2283 
2284 // --------------------------------------------------------------------
2285 void G4GDMLReadSolids::GenTrapRead(
2286   const xercesc::DOMElement* const gtrapElement)
2287 {
2288   G4String name;
2289   G4double lunit = 1.0;
2290   G4double dz    = 0.0;
2291   G4double v1x = 0.0, v1y = 0.0, v2x = 0.0, v2y = 0.0, v3x = 0.0, v3y = 0.0,
2292            v4x = 0.0, v4y = 0.0, v5x = 0.0, v5y = 0.0, v6x = 0.0, v6y = 0.0,
2293            v7x = 0.0, v7y = 0.0, v8x = 0.0, v8y = 0.0;
2294 
2295   const xercesc::DOMNamedNodeMap* const attributes =
2296     gtrapElement->getAttributes();
2297   XMLSize_t attributeCount = attributes->getLength();
2298 
2299   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2300       ++attribute_index)
2301   {
2302     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2303 
2304     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2305     {
2306       continue;
2307     }
2308 
2309     const xercesc::DOMAttr* const attribute =
2310       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2311     if(attribute == nullptr)
2312     {
2313       G4Exception("G4GDMLReadSolids::GenTrapRead()", "InvalidRead",
2314                   FatalException, "No attribute found!");
2315       return;
2316     }
2317     const G4String attName  = Transcode(attribute->getName());
2318     const G4String attValue = Transcode(attribute->getValue());
2319 
2320     if(attName == "name")
2321     {
2322       name = GenerateName(attValue);
2323     }
2324     else if(attName == "lunit")
2325     {
2326       lunit = G4UnitDefinition::GetValueOf(attValue);
2327       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2328       {
2329         G4Exception("G4GDMLReadSolids::GenTrapRead()", "InvalidRead",
2330                     FatalException, "Invalid unit for length!");
2331       }
2332     }
2333     else if(attName == "dz")
2334     {
2335       dz = eval.Evaluate(attValue);
2336     }
2337     else if(attName == "v1x")
2338     {
2339       v1x = eval.Evaluate(attValue);
2340     }
2341     else if(attName == "v1y")
2342     {
2343       v1y = eval.Evaluate(attValue);
2344     }
2345     else if(attName == "v2x")
2346     {
2347       v2x = eval.Evaluate(attValue);
2348     }
2349     else if(attName == "v2y")
2350     {
2351       v2y = eval.Evaluate(attValue);
2352     }
2353     else if(attName == "v3x")
2354     {
2355       v3x = eval.Evaluate(attValue);
2356     }
2357     else if(attName == "v3y")
2358     {
2359       v3y = eval.Evaluate(attValue);
2360     }
2361     else if(attName == "v4x")
2362     {
2363       v4x = eval.Evaluate(attValue);
2364     }
2365     else if(attName == "v4y")
2366     {
2367       v4y = eval.Evaluate(attValue);
2368     }
2369     else if(attName == "v5x")
2370     {
2371       v5x = eval.Evaluate(attValue);
2372     }
2373     else if(attName == "v5y")
2374     {
2375       v5y = eval.Evaluate(attValue);
2376     }
2377     else if(attName == "v6x")
2378     {
2379       v6x = eval.Evaluate(attValue);
2380     }
2381     else if(attName == "v6y")
2382     {
2383       v6y = eval.Evaluate(attValue);
2384     }
2385     else if(attName == "v7x")
2386     {
2387       v7x = eval.Evaluate(attValue);
2388     }
2389     else if(attName == "v7y")
2390     {
2391       v7y = eval.Evaluate(attValue);
2392     }
2393     else if(attName == "v8x")
2394     {
2395       v8x = eval.Evaluate(attValue);
2396     }
2397     else if(attName == "v8y")
2398     {
2399       v8y = eval.Evaluate(attValue);
2400     }
2401   }
2402 
2403   dz *= lunit;
2404   std::vector<G4TwoVector> vertices;
2405   vertices.push_back(G4TwoVector(v1x * lunit, v1y * lunit));
2406   vertices.push_back(G4TwoVector(v2x * lunit, v2y * lunit));
2407   vertices.push_back(G4TwoVector(v3x * lunit, v3y * lunit));
2408   vertices.push_back(G4TwoVector(v4x * lunit, v4y * lunit));
2409   vertices.push_back(G4TwoVector(v5x * lunit, v5y * lunit));
2410   vertices.push_back(G4TwoVector(v6x * lunit, v6y * lunit));
2411   vertices.push_back(G4TwoVector(v7x * lunit, v7y * lunit));
2412   vertices.push_back(G4TwoVector(v8x * lunit, v8y * lunit));
2413   new G4GenericTrap(name, dz, vertices);
2414 }
2415 
2416 // --------------------------------------------------------------------
2417 void G4GDMLReadSolids::TrapRead(const xercesc::DOMElement* const trapElement)
2418 {
2419   G4String name;
2420   G4double lunit  = 1.0;
2421   G4double aunit  = 1.0;
2422   G4double z      = 0.0;
2423   G4double theta  = 0.0;
2424   G4double phi    = 0.0;
2425   G4double y1     = 0.0;
2426   G4double x1     = 0.0;
2427   G4double x2     = 0.0;
2428   G4double alpha1 = 0.0;
2429   G4double y2     = 0.0;
2430   G4double x3     = 0.0;
2431   G4double x4     = 0.0;
2432   G4double alpha2 = 0.0;
2433 
2434   const xercesc::DOMNamedNodeMap* const attributes =
2435     trapElement->getAttributes();
2436   XMLSize_t attributeCount = attributes->getLength();
2437 
2438   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2439       ++attribute_index)
2440   {
2441     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2442 
2443     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2444     {
2445       continue;
2446     }
2447 
2448     const xercesc::DOMAttr* const attribute =
2449       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2450     if(attribute == nullptr)
2451     {
2452       G4Exception("G4GDMLReadSolids::TrapRead()", "InvalidRead", FatalException,
2453                   "No attribute found!");
2454       return;
2455     }
2456     const G4String attName  = Transcode(attribute->getName());
2457     const G4String attValue = Transcode(attribute->getValue());
2458 
2459     if(attName == "name")
2460     {
2461       name = GenerateName(attValue);
2462     }
2463     else if(attName == "lunit")
2464     {
2465       lunit = G4UnitDefinition::GetValueOf(attValue);
2466       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2467       {
2468         G4Exception("G4GDMLReadSolids::TrapRead()", "InvalidRead",
2469                     FatalException, "Invalid unit for length!");
2470       }
2471     }
2472     else if(attName == "aunit")
2473     {
2474       aunit = G4UnitDefinition::GetValueOf(attValue);
2475       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2476       {
2477         G4Exception("G4GDMLReadSolids::TrapRead()", "InvalidRead",
2478                     FatalException, "Invalid unit for angle!");
2479       }
2480     }
2481     else if(attName == "z")
2482     {
2483       z = eval.Evaluate(attValue);
2484     }
2485     else if(attName == "theta")
2486     {
2487       theta = eval.Evaluate(attValue);
2488     }
2489     else if(attName == "phi")
2490     {
2491       phi = eval.Evaluate(attValue);
2492     }
2493     else if(attName == "y1")
2494     {
2495       y1 = eval.Evaluate(attValue);
2496     }
2497     else if(attName == "x1")
2498     {
2499       x1 = eval.Evaluate(attValue);
2500     }
2501     else if(attName == "x2")
2502     {
2503       x2 = eval.Evaluate(attValue);
2504     }
2505     else if(attName == "alpha1")
2506     {
2507       alpha1 = eval.Evaluate(attValue);
2508     }
2509     else if(attName == "y2")
2510     {
2511       y2 = eval.Evaluate(attValue);
2512     }
2513     else if(attName == "x3")
2514     {
2515       x3 = eval.Evaluate(attValue);
2516     }
2517     else if(attName == "x4")
2518     {
2519       x4 = eval.Evaluate(attValue);
2520     }
2521     else if(attName == "alpha2")
2522     {
2523       alpha2 = eval.Evaluate(attValue);
2524     }
2525   }
2526 
2527   z *= 0.5 * lunit;
2528   theta *= aunit;
2529   phi *= aunit;
2530   y1 *= 0.5 * lunit;
2531   x1 *= 0.5 * lunit;
2532   x2 *= 0.5 * lunit;
2533   alpha1 *= aunit;
2534   y2 *= 0.5 * lunit;
2535   x3 *= 0.5 * lunit;
2536   x4 *= 0.5 * lunit;
2537   alpha2 *= aunit;
2538 
2539   new G4Trap(name, z, theta, phi, y1, x1, x2, alpha1, y2, x3, x4, alpha2);
2540 }
2541 
2542 // --------------------------------------------------------------------
2543 void G4GDMLReadSolids::TrdRead(const xercesc::DOMElement* const trdElement)
2544 {
2545   G4String name;
2546   G4double lunit = 1.0;
2547   G4double x1    = 0.0;
2548   G4double x2    = 0.0;
2549   G4double y1    = 0.0;
2550   G4double y2    = 0.0;
2551   G4double z     = 0.0;
2552 
2553   const xercesc::DOMNamedNodeMap* const attributes =
2554     trdElement->getAttributes();
2555   XMLSize_t attributeCount = attributes->getLength();
2556 
2557   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2558       ++attribute_index)
2559   {
2560     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2561 
2562     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2563     {
2564       continue;
2565     }
2566 
2567     const xercesc::DOMAttr* const attribute =
2568       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2569     if(attribute == nullptr)
2570     {
2571       G4Exception("G4GDMLReadSolids::TrdRead()", "InvalidRead", FatalException,
2572                   "No attribute found!");
2573       return;
2574     }
2575     const G4String attName  = Transcode(attribute->getName());
2576     const G4String attValue = Transcode(attribute->getValue());
2577 
2578     if(attName == "name")
2579     {
2580       name = GenerateName(attValue);
2581     }
2582     else if(attName == "lunit")
2583     {
2584       lunit = G4UnitDefinition::GetValueOf(attValue);
2585       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2586       {
2587         G4Exception("G4GDMLReadSolids::TrdRead()", "InvalidRead",
2588                     FatalException, "Invalid unit for length!");
2589       }
2590     }
2591     else if(attName == "x1")
2592     {
2593       x1 = eval.Evaluate(attValue);
2594     }
2595     else if(attName == "x2")
2596     {
2597       x2 = eval.Evaluate(attValue);
2598     }
2599     else if(attName == "y1")
2600     {
2601       y1 = eval.Evaluate(attValue);
2602     }
2603     else if(attName == "y2")
2604     {
2605       y2 = eval.Evaluate(attValue);
2606     }
2607     else if(attName == "z")
2608     {
2609       z = eval.Evaluate(attValue);
2610     }
2611   }
2612 
2613   x1 *= 0.5 * lunit;
2614   x2 *= 0.5 * lunit;
2615   y1 *= 0.5 * lunit;
2616   y2 *= 0.5 * lunit;
2617   z *= 0.5 * lunit;
2618 
2619   new G4Trd(name, x1, x2, y1, y2, z);
2620 }
2621 
2622 // --------------------------------------------------------------------
2623 G4TriangularFacet* G4GDMLReadSolids::TriangularRead(
2624   const xercesc::DOMElement* const triangularElement)
2625 {
2626   G4ThreeVector vertex1;
2627   G4ThreeVector vertex2;
2628   G4ThreeVector vertex3;
2629   G4FacetVertexType type = ABSOLUTE;
2630   G4double lunit         = 1.0;
2631 
2632   const xercesc::DOMNamedNodeMap* const attributes =
2633     triangularElement->getAttributes();
2634   XMLSize_t attributeCount = attributes->getLength();
2635 
2636   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2637       ++attribute_index)
2638   {
2639     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2640 
2641     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2642     {
2643       continue;
2644     }
2645 
2646     const xercesc::DOMAttr* const attribute =
2647       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2648     if(attribute == nullptr)
2649     {
2650       G4Exception("G4GDMLReadSolids::TriangularRead()", "InvalidRead",
2651                   FatalException, "No attribute found!");
2652       return nullptr;
2653     }
2654     const G4String attName  = Transcode(attribute->getName());
2655     const G4String attValue = Transcode(attribute->getValue());
2656 
2657     if(attName == "vertex1")
2658     {
2659       vertex1 = GetPosition(GenerateName(attValue));
2660     }
2661     else if(attName == "vertex2")
2662     {
2663       vertex2 = GetPosition(GenerateName(attValue));
2664     }
2665     else if(attName == "vertex3")
2666     {
2667       vertex3 = GetPosition(GenerateName(attValue));
2668     }
2669     else if(attName == "lunit")
2670     {
2671       lunit = G4UnitDefinition::GetValueOf(attValue);
2672       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2673       {
2674         G4Exception("G4GDMLReadSolids::TriangularRead()", "InvalidRead",
2675                     FatalException, "Invalid unit for length!");
2676       }
2677     }
2678     else if(attName == "type")
2679     {
2680       if(attValue == "RELATIVE")
2681       {
2682         type = RELATIVE;
2683       }
2684     }
2685   }
2686 
2687   return new G4TriangularFacet(vertex1 * lunit, vertex2 * lunit,
2688                                vertex3 * lunit, type);
2689 }
2690 
2691 // --------------------------------------------------------------------
2692 void G4GDMLReadSolids::TubeRead(const xercesc::DOMElement* const tubeElement)
2693 {
2694   G4String name;
2695   G4double lunit    = 1.0;
2696   G4double aunit    = 1.0;
2697   G4double rmin     = 0.0;
2698   G4double rmax     = 0.0;
2699   G4double z        = 0.0;
2700   G4double startphi = 0.0;
2701   G4double deltaphi = 0.0;
2702 
2703   const xercesc::DOMNamedNodeMap* const attributes =
2704     tubeElement->getAttributes();
2705   XMLSize_t attributeCount = attributes->getLength();
2706 
2707   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2708       ++attribute_index)
2709   {
2710     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2711 
2712     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2713     {
2714       continue;
2715     }
2716 
2717     const xercesc::DOMAttr* const attribute =
2718       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2719     if(attribute == nullptr)
2720     {
2721       G4Exception("G4GDMLReadSolids::TubeRead()", "InvalidRead", FatalException,
2722                   "No attribute found!");
2723       return;
2724     }
2725     const G4String attName  = Transcode(attribute->getName());
2726     const G4String attValue = Transcode(attribute->getValue());
2727 
2728     if(attName == "name")
2729     {
2730       name = GenerateName(attValue);
2731     }
2732     else if(attName == "lunit")
2733     {
2734       lunit = G4UnitDefinition::GetValueOf(attValue);
2735       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2736       {
2737         G4Exception("G4GDMLReadSolids::TubeRead()", "InvalidRead",
2738                     FatalException, "Invalid unit for length!");
2739       }
2740     }
2741     else if(attName == "aunit")
2742     {
2743       aunit = G4UnitDefinition::GetValueOf(attValue);
2744       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2745       {
2746         G4Exception("G4GDMLReadSolids::TubeRead()", "InvalidRead",
2747                     FatalException, "Invalid unit for angle!");
2748       }
2749     }
2750     else if(attName == "rmin")
2751     {
2752       rmin = eval.Evaluate(attValue);
2753     }
2754     else if(attName == "rmax")
2755     {
2756       rmax = eval.Evaluate(attValue);
2757     }
2758     else if(attName == "z")
2759     {
2760       z = eval.Evaluate(attValue);
2761     }
2762     else if(attName == "startphi")
2763     {
2764       startphi = eval.Evaluate(attValue);
2765     }
2766     else if(attName == "deltaphi")
2767     {
2768       deltaphi = eval.Evaluate(attValue);
2769     }
2770   }
2771 
2772   rmin *= lunit;
2773   rmax *= lunit;
2774   z *= 0.5 * lunit;
2775   startphi *= aunit;
2776   deltaphi *= aunit;
2777 
2778   new G4Tubs(name, rmin, rmax, z, startphi, deltaphi);
2779 }
2780 
2781 // --------------------------------------------------------------------
2782 void G4GDMLReadSolids::CutTubeRead(
2783   const xercesc::DOMElement* const cuttubeElement)
2784 {
2785   G4String name;
2786   G4double lunit    = 1.0;
2787   G4double aunit    = 1.0;
2788   G4double rmin     = 0.0;
2789   G4double rmax     = 0.0;
2790   G4double z        = 0.0;
2791   G4double startphi = 0.0;
2792   G4double deltaphi = 0.0;
2793   G4ThreeVector lowNorm(0);
2794   G4ThreeVector highNorm(0);
2795 
2796   const xercesc::DOMNamedNodeMap* const attributes =
2797     cuttubeElement->getAttributes();
2798   XMLSize_t attributeCount = attributes->getLength();
2799 
2800   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2801       ++attribute_index)
2802   {
2803     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2804 
2805     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2806     {
2807       continue;
2808     }
2809 
2810     const xercesc::DOMAttr* const attribute =
2811       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2812     if(attribute == nullptr)
2813     {
2814       G4Exception("G4GDMLReadSolids::CutTubeRead()", "InvalidRead",
2815                   FatalException, "No attribute found!");
2816       return;
2817     }
2818     const G4String attName  = Transcode(attribute->getName());
2819     const G4String attValue = Transcode(attribute->getValue());
2820 
2821     if(attName == "name")
2822     {
2823       name = GenerateName(attValue);
2824     }
2825     else if(attName == "lunit")
2826     {
2827       lunit = G4UnitDefinition::GetValueOf(attValue);
2828       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2829       {
2830         G4Exception("G4GDMLReadSolids::CutTubeRead()", "InvalidRead",
2831                     FatalException, "Invalid unit for length!");
2832       }
2833     }
2834     else if(attName == "aunit")
2835     {
2836       aunit = G4UnitDefinition::GetValueOf(attValue);
2837       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2838       {
2839         G4Exception("G4GDMLReadSolids::CutTubeRead()", "InvalidRead",
2840                     FatalException, "Invalid unit for angle!");
2841       }
2842     }
2843     else if(attName == "rmin")
2844     {
2845       rmin = eval.Evaluate(attValue);
2846     }
2847     else if(attName == "rmax")
2848     {
2849       rmax = eval.Evaluate(attValue);
2850     }
2851     else if(attName == "z")
2852     {
2853       z = eval.Evaluate(attValue);
2854     }
2855     else if(attName == "startphi")
2856     {
2857       startphi = eval.Evaluate(attValue);
2858     }
2859     else if(attName == "deltaphi")
2860     {
2861       deltaphi = eval.Evaluate(attValue);
2862     }
2863     else if(attName == "lowX")
2864     {
2865       lowNorm.setX(eval.Evaluate(attValue));
2866     }
2867     else if(attName == "lowY")
2868     {
2869       lowNorm.setY(eval.Evaluate(attValue));
2870     }
2871     else if(attName == "lowZ")
2872     {
2873       lowNorm.setZ(eval.Evaluate(attValue));
2874     }
2875     else if(attName == "highX")
2876     {
2877       highNorm.setX(eval.Evaluate(attValue));
2878     }
2879     else if(attName == "highY")
2880     {
2881       highNorm.setY(eval.Evaluate(attValue));
2882     }
2883     else if(attName == "highZ")
2884     {
2885       highNorm.setZ(eval.Evaluate(attValue));
2886     }
2887   }
2888 
2889   rmin *= lunit;
2890   rmax *= lunit;
2891   z *= 0.5 * lunit;
2892   startphi *= aunit;
2893   deltaphi *= aunit;
2894 
2895   new G4CutTubs(name, rmin, rmax, z, startphi, deltaphi, lowNorm, highNorm);
2896 }
2897 
2898 // --------------------------------------------------------------------
2899 void G4GDMLReadSolids::TwistedboxRead(
2900   const xercesc::DOMElement* const twistedboxElement)
2901 {
2902   G4String name;
2903   G4double lunit    = 1.0;
2904   G4double aunit    = 1.0;
2905   G4double PhiTwist = 0.0;
2906   G4double x        = 0.0;
2907   G4double y        = 0.0;
2908   G4double z        = 0.0;
2909 
2910   const xercesc::DOMNamedNodeMap* const attributes =
2911     twistedboxElement->getAttributes();
2912   XMLSize_t attributeCount = attributes->getLength();
2913 
2914   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
2915       ++attribute_index)
2916   {
2917     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
2918 
2919     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
2920     {
2921       continue;
2922     }
2923 
2924     const xercesc::DOMAttr* const attribute =
2925       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
2926     if(attribute == nullptr)
2927     {
2928       G4Exception("G4GDMLReadSolids::TwistedboxRead()", "InvalidRead",
2929                   FatalException, "No attribute found!");
2930       return;
2931     }
2932     const G4String attName  = Transcode(attribute->getName());
2933     const G4String attValue = Transcode(attribute->getValue());
2934 
2935     if(attName == "name")
2936     {
2937       name = GenerateName(attValue);
2938     }
2939     else if(attName == "lunit")
2940     {
2941       lunit = G4UnitDefinition::GetValueOf(attValue);
2942       if(G4UnitDefinition::GetCategory(attValue) != "Length")
2943       {
2944         G4Exception("G4GDMLReadSolids::TwistedBoxRead()", "InvalidRead",
2945                     FatalException, "Invalid unit for length!");
2946       }
2947     }
2948     else if(attName == "aunit")
2949     {
2950       aunit = G4UnitDefinition::GetValueOf(attValue);
2951       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
2952       {
2953         G4Exception("G4GDMLReadSolids::TwistedboxRead()", "InvalidRead",
2954                     FatalException, "Invalid unit for angle!");
2955       }
2956     }
2957     else if(attName == "PhiTwist")
2958     {
2959       PhiTwist = eval.Evaluate(attValue);
2960     }
2961     else if(attName == "x")
2962     {
2963       x = eval.Evaluate(attValue);
2964     }
2965     else if(attName == "y")
2966     {
2967       y = eval.Evaluate(attValue);
2968     }
2969     else if(attName == "z")
2970     {
2971       z = eval.Evaluate(attValue);
2972     }
2973   }
2974 
2975   PhiTwist *= aunit;
2976   x *= 0.5 * lunit;
2977   y *= 0.5 * lunit;
2978   z *= 0.5 * lunit;
2979 
2980   new G4TwistedBox(name, PhiTwist, x, y, z);
2981 }
2982 
2983 // --------------------------------------------------------------------
2984 void G4GDMLReadSolids::TwistedtrapRead(
2985   const xercesc::DOMElement* const twistedtrapElement)
2986 {
2987   G4String name;
2988   G4double lunit    = 1.0;
2989   G4double aunit    = 1.0;
2990   G4double PhiTwist = 0.0;
2991   G4double z        = 0.0;
2992   G4double Theta    = 0.0;
2993   G4double Phi      = 0.0;
2994   G4double y1       = 0.0;
2995   G4double x1       = 0.0;
2996   G4double x2       = 0.0;
2997   G4double y2       = 0.0;
2998   G4double x3       = 0.0;
2999   G4double x4       = 0.0;
3000   G4double Alph     = 0.0;
3001 
3002   const xercesc::DOMNamedNodeMap* const attributes =
3003     twistedtrapElement->getAttributes();
3004   XMLSize_t attributeCount = attributes->getLength();
3005 
3006   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3007       ++attribute_index)
3008   {
3009     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3010 
3011     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3012     {
3013       continue;
3014     }
3015 
3016     const xercesc::DOMAttr* const attribute =
3017       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3018     if(attribute == nullptr)
3019     {
3020       G4Exception("G4GDMLReadSolids::TwistedtrapRead()", "InvalidRead",
3021                   FatalException, "No attribute found!");
3022       return;
3023     }
3024     const G4String attName  = Transcode(attribute->getName());
3025     const G4String attValue = Transcode(attribute->getValue());
3026 
3027     if(attName == "name")
3028     {
3029       name = GenerateName(attValue);
3030     }
3031     else if(attName == "lunit")
3032     {
3033       lunit = G4UnitDefinition::GetValueOf(attValue);
3034       if(G4UnitDefinition::GetCategory(attValue) != "Length")
3035       {
3036         G4Exception("G4GDMLReadSolids::TwistedtrapRead()", "InvalidRead",
3037                     FatalException, "Invalid unit for length!");
3038       }
3039     }
3040     else if(attName == "aunit")
3041     {
3042       aunit = G4UnitDefinition::GetValueOf(attValue);
3043       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
3044       {
3045         G4Exception("G4GDMLReadSolids::TwistedtrapRead()", "InvalidRead",
3046                     FatalException, "Invalid unit for angle!");
3047       }
3048     }
3049     else if(attName == "PhiTwist")
3050     {
3051       PhiTwist = eval.Evaluate(attValue);
3052     }
3053     else if(attName == "z")
3054     {
3055       z = eval.Evaluate(attValue);
3056     }
3057     else if(attName == "Theta")
3058     {
3059       Theta = eval.Evaluate(attValue);
3060     }
3061     else if(attName == "Phi")
3062     {
3063       Phi = eval.Evaluate(attValue);
3064     }
3065     else if(attName == "y1")
3066     {
3067       y1 = eval.Evaluate(attValue);
3068     }
3069     else if(attName == "x1")
3070     {
3071       x1 = eval.Evaluate(attValue);
3072     }
3073     else if(attName == "x2")
3074     {
3075       x2 = eval.Evaluate(attValue);
3076     }
3077     else if(attName == "y2")
3078     {
3079       y2 = eval.Evaluate(attValue);
3080     }
3081     else if(attName == "x3")
3082     {
3083       x3 = eval.Evaluate(attValue);
3084     }
3085     else if(attName == "x4")
3086     {
3087       x4 = eval.Evaluate(attValue);
3088     }
3089     else if(attName == "Alph")
3090     {
3091       Alph = eval.Evaluate(attValue);
3092     }
3093   }
3094 
3095   PhiTwist *= aunit;
3096   z *= 0.5 * lunit;
3097   Theta *= aunit;
3098   Phi *= aunit;
3099   Alph *= aunit;
3100   y1 *= 0.5 * lunit;
3101   x1 *= 0.5 * lunit;
3102   x2 *= 0.5 * lunit;
3103   y2 *= 0.5 * lunit;
3104   x3 *= 0.5 * lunit;
3105   x4 *= 0.5 * lunit;
3106 
3107   new G4TwistedTrap(name, PhiTwist, z, Theta, Phi, y1, x1, x2, y2, x3, x4,
3108                     Alph);
3109 }
3110 
3111 // --------------------------------------------------------------------
3112 void G4GDMLReadSolids::TwistedtrdRead(
3113   const xercesc::DOMElement* const twistedtrdElement)
3114 {
3115   G4String name;
3116   G4double lunit    = 1.0;
3117   G4double aunit    = 1.0;
3118   G4double x1       = 0.0;
3119   G4double x2       = 0.0;
3120   G4double y1       = 0.0;
3121   G4double y2       = 0.0;
3122   G4double z        = 0.0;
3123   G4double PhiTwist = 0.0;
3124 
3125   const xercesc::DOMNamedNodeMap* const attributes =
3126     twistedtrdElement->getAttributes();
3127   XMLSize_t attributeCount = attributes->getLength();
3128 
3129   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3130       ++attribute_index)
3131   {
3132     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3133 
3134     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3135     {
3136       continue;
3137     }
3138 
3139     const xercesc::DOMAttr* const attribute =
3140       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3141     if(attribute == nullptr)
3142     {
3143       G4Exception("G4GDMLReadSolids::TwistedtrdRead()", "InvalidRead",
3144                   FatalException, "No attribute found!");
3145       return;
3146     }
3147     const G4String attName  = Transcode(attribute->getName());
3148     const G4String attValue = Transcode(attribute->getValue());
3149 
3150     if(attName == "name")
3151     {
3152       name = GenerateName(attValue);
3153     }
3154     else if(attName == "lunit")
3155     {
3156       lunit = G4UnitDefinition::GetValueOf(attValue);
3157       if(G4UnitDefinition::GetCategory(attValue) != "Length")
3158       {
3159         G4Exception("G4GDMLReadSolids::TwistedtrdRead()", "InvalidRead",
3160                     FatalException, "Invalid unit for length!");
3161       }
3162     }
3163     else if(attName == "aunit")
3164     {
3165       aunit = G4UnitDefinition::GetValueOf(attValue);
3166       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
3167       {
3168         G4Exception("G4GDMLReadSolids::TwistedtrdRead()", "InvalidRead",
3169                     FatalException, "Invalid unit for angle!");
3170       }
3171     }
3172     else if(attName == "x1")
3173     {
3174       x1 = eval.Evaluate(attValue);
3175     }
3176     else if(attName == "x2")
3177     {
3178       x2 = eval.Evaluate(attValue);
3179     }
3180     else if(attName == "y1")
3181     {
3182       y1 = eval.Evaluate(attValue);
3183     }
3184     else if(attName == "y2")
3185     {
3186       y2 = eval.Evaluate(attValue);
3187     }
3188     else if(attName == "z")
3189     {
3190       z = eval.Evaluate(attValue);
3191     }
3192     else if(attName == "PhiTwist")
3193     {
3194       PhiTwist = eval.Evaluate(attValue);
3195     }
3196   }
3197 
3198   x1 *= 0.5 * lunit;
3199   x2 *= 0.5 * lunit;
3200   y1 *= 0.5 * lunit;
3201   y2 *= 0.5 * lunit;
3202   z *= 0.5 * lunit;
3203   PhiTwist *= aunit;
3204 
3205   new G4TwistedTrd(name, x1, x2, y1, y2, z, PhiTwist);
3206 }
3207 
3208 // --------------------------------------------------------------------
3209 void G4GDMLReadSolids::TwistedtubsRead(
3210   const xercesc::DOMElement* const twistedtubsElement)
3211 {
3212   G4String name;
3213   G4double lunit        = 1.0;
3214   G4double aunit        = 1.0;
3215   G4double twistedangle = 0.0;
3216   G4double endinnerrad  = 0.0;
3217   G4double endouterrad  = 0.0;
3218   G4double zlen         = 0.0;
3219   G4double phi          = 0.0;
3220   G4double totphi       = 0.0;
3221   G4double midinnerrad  = 0.0;
3222   G4double midouterrad  = 0.0;
3223   G4double positiveEndz = 0.0;
3224   G4double negativeEndz = 0.0;
3225   G4int nseg            = 0;
3226 
3227   const xercesc::DOMNamedNodeMap* const attributes =
3228     twistedtubsElement->getAttributes();
3229   XMLSize_t attributeCount = attributes->getLength();
3230 
3231   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3232       ++attribute_index)
3233   {
3234     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3235 
3236     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3237     {
3238       continue;
3239     }
3240 
3241     const xercesc::DOMAttr* const attribute =
3242       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3243     if(attribute == nullptr)
3244     {
3245       G4Exception("G4GDMLReadSolids::TwistedtubsRead()", "InvalidRead",
3246                   FatalException, "No attribute found!");
3247       return;
3248     }
3249     const G4String attName  = Transcode(attribute->getName());
3250     const G4String attValue = Transcode(attribute->getValue());
3251 
3252     if(attName == "name")
3253     {
3254       name = GenerateName(attValue);
3255     }
3256     else if(attName == "lunit")
3257     {
3258       lunit = G4UnitDefinition::GetValueOf(attValue);
3259       if(G4UnitDefinition::GetCategory(attValue) != "Length")
3260       {
3261         G4Exception("G4GDMLReadSolids::TwistedtubsRead()", "InvalidRead",
3262                     FatalException, "Invalid unit for length!");
3263       }
3264     }
3265     else if(attName == "aunit")
3266     {
3267       aunit = G4UnitDefinition::GetValueOf(attValue);
3268       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
3269       {
3270         G4Exception("G4GDMLReadSolids::TwistedtubsRead()", "InvalidRead",
3271                     FatalException, "Invalid unit for angle!");
3272       }
3273     }
3274     else if(attName == "twistedangle")
3275     {
3276       twistedangle = eval.Evaluate(attValue);
3277     }
3278     else if(attName == "endinnerrad")
3279     {
3280       endinnerrad = eval.Evaluate(attValue);
3281     }
3282     else if(attName == "endouterrad")
3283     {
3284       endouterrad = eval.Evaluate(attValue);
3285     }
3286     else if(attName == "zlen")
3287     {
3288       zlen = eval.Evaluate(attValue);
3289     }
3290     else if(attName == "midinnerrad")
3291     {
3292       midinnerrad = eval.Evaluate(attValue);
3293     }
3294     else if(attName == "midouterrad")
3295     {
3296       midouterrad = eval.Evaluate(attValue);
3297     }
3298     else if(attName == "negativeEndz")
3299     {
3300       negativeEndz = eval.Evaluate(attValue);
3301     }
3302     else if(attName == "positiveEndz")
3303     {
3304       positiveEndz = eval.Evaluate(attValue);
3305     }
3306     else if(attName == "nseg")
3307     {
3308       nseg = eval.Evaluate(attValue);
3309     }
3310     else if(attName == "totphi")
3311     {
3312       totphi = eval.Evaluate(attValue);
3313     }
3314     else if(attName == "phi")
3315     {
3316       phi = eval.Evaluate(attValue);
3317     }
3318   }
3319 
3320   twistedangle *= aunit;
3321   endinnerrad *= lunit;
3322   endouterrad *= lunit;
3323   zlen *= 0.5 * lunit;
3324   midinnerrad *= lunit;
3325   midouterrad *= lunit;
3326   positiveEndz *= lunit;
3327   negativeEndz *= lunit;
3328   phi *= aunit;
3329   totphi *= aunit;
3330 
3331   if(zlen != 0.0)
3332   {
3333     if(nseg != 0)
3334       new G4TwistedTubs(name, twistedangle, endinnerrad, endouterrad, zlen,
3335                         nseg, totphi);
3336     else
3337       new G4TwistedTubs(name, twistedangle, endinnerrad, endouterrad, zlen,
3338                         phi);
3339   }
3340   else
3341   {
3342     if(nseg != 0)
3343       new G4TwistedTubs(name, twistedangle, midinnerrad, midouterrad,
3344                         negativeEndz, positiveEndz, nseg, totphi);
3345     else
3346       new G4TwistedTubs(name, twistedangle, midinnerrad, midouterrad,
3347                         negativeEndz, positiveEndz, phi);
3348   }
3349 }
3350 
3351 // --------------------------------------------------------------------
3352 G4TwoVector G4GDMLReadSolids::TwoDimVertexRead(
3353   const xercesc::DOMElement* const element, G4double lunit)
3354 {
3355   G4TwoVector vec;
3356 
3357   const xercesc::DOMNamedNodeMap* const attributes = element->getAttributes();
3358   XMLSize_t attributeCount                         = attributes->getLength();
3359 
3360   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3361       ++attribute_index)
3362   {
3363     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3364 
3365     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3366     {
3367       continue;
3368     }
3369 
3370     const xercesc::DOMAttr* const attribute =
3371       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3372     if(attribute == nullptr)
3373     {
3374       G4Exception("G4GDMLReadSolids::TwoDimVertexRead()", "InvalidRead",
3375                   FatalException, "No attribute found!");
3376       return vec;
3377     }
3378     const G4String attName  = Transcode(attribute->getName());
3379     const G4String attValue = Transcode(attribute->getValue());
3380 
3381     if(attName == "x")
3382     {
3383       vec.setX(eval.Evaluate(attValue) * lunit);
3384     }
3385     else if(attName == "y")
3386     {
3387       vec.setY(eval.Evaluate(attValue) * lunit);
3388     }
3389   }
3390 
3391   return vec;
3392 }
3393 
3394 // --------------------------------------------------------------------
3395 G4GDMLReadSolids::zplaneType G4GDMLReadSolids::ZplaneRead(
3396   const xercesc::DOMElement* const zplaneElement)
3397 {
3398   zplaneType zplane = { 0., 0., 0. };
3399 
3400   const xercesc::DOMNamedNodeMap* const attributes =
3401     zplaneElement->getAttributes();
3402   XMLSize_t attributeCount = attributes->getLength();
3403 
3404   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3405       ++attribute_index)
3406   {
3407     xercesc::DOMNode* node = attributes->item(attribute_index);
3408 
3409     if(node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3410     {
3411       continue;
3412     }
3413 
3414     const xercesc::DOMAttr* const attribute =
3415       dynamic_cast<xercesc::DOMAttr*>(node);
3416     if(attribute == nullptr)
3417     {
3418       G4Exception("G4GDMLReadSolids::ZplaneRead()", "InvalidRead",
3419                   FatalException, "No attribute found!");
3420       return zplane;
3421     }
3422     const G4String attName  = Transcode(attribute->getName());
3423     const G4String attValue = Transcode(attribute->getValue());
3424 
3425     if(attName == "rmin")
3426     {
3427       zplane.rmin = eval.Evaluate(attValue);
3428     }
3429     else if(attName == "rmax")
3430     {
3431       zplane.rmax = eval.Evaluate(attValue);
3432     }
3433     else if(attName == "z")
3434     {
3435       zplane.z = eval.Evaluate(attValue);
3436     }
3437   }
3438 
3439   return zplane;
3440 }
3441 
3442 // --------------------------------------------------------------------
3443 G4GDMLReadSolids::rzPointType G4GDMLReadSolids::RZPointRead(
3444   const xercesc::DOMElement* const zplaneElement)
3445 {
3446   rzPointType rzpoint = { 0., 0. };
3447 
3448   const xercesc::DOMNamedNodeMap* const attributes =
3449     zplaneElement->getAttributes();
3450   XMLSize_t attributeCount = attributes->getLength();
3451 
3452   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3453       ++attribute_index)
3454   {
3455     xercesc::DOMNode* node = attributes->item(attribute_index);
3456 
3457     if(node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3458     {
3459       continue;
3460     }
3461 
3462     const xercesc::DOMAttr* const attribute =
3463       dynamic_cast<xercesc::DOMAttr*>(node);
3464     if(attribute == nullptr)
3465     {
3466       G4Exception("G4GDMLReadSolids::RZPointRead()", "InvalidRead",
3467                   FatalException, "No attribute found!");
3468       return rzpoint;
3469     }
3470     const G4String attName  = Transcode(attribute->getName());
3471     const G4String attValue = Transcode(attribute->getValue());
3472 
3473     if(attName == "r")
3474     {
3475       rzpoint.r = eval.Evaluate(attValue);
3476     }
3477     else if(attName == "z")
3478     {
3479       rzpoint.z = eval.Evaluate(attValue);
3480     }
3481   }
3482 
3483   return rzpoint;
3484 }
3485 
3486 // --------------------------------------------------------------------
3487 void G4GDMLReadSolids::PropertyRead(
3488   const xercesc::DOMElement* const propertyElement,
3489   G4OpticalSurface* opticalsurface)
3490 {
3491   G4String name;
3492   G4String ref;
3493   G4GDMLMatrix matrix;
3494 
3495   const xercesc::DOMNamedNodeMap* const attributes =
3496     propertyElement->getAttributes();
3497   XMLSize_t attributeCount = attributes->getLength();
3498 
3499   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3500       ++attribute_index)
3501   {
3502     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3503 
3504     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3505     {
3506       continue;
3507     }
3508 
3509     const xercesc::DOMAttr* const attribute =
3510       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3511     if(attribute == nullptr)
3512     {
3513       G4Exception("G4GDMLReadSolids::PropertyRead()", "InvalidRead",
3514                   FatalException, "No attribute found!");
3515       return;
3516     }
3517     const G4String attName  = Transcode(attribute->getName());
3518     const G4String attValue = Transcode(attribute->getValue());
3519 
3520     if(attName == "name")
3521     {
3522       name = GenerateName(attValue);
3523     }
3524     else if(attName == "ref")
3525     {
3526       matrix = GetMatrix(ref = attValue);
3527     }
3528   }
3529 
3530   /*
3531   if (matrix.GetCols() != 2)
3532   {
3533     G4String error_msg = "Referenced matrix '" + ref
3534            + "' should have \n two columns as a property table for
3535   opticalsurface: "
3536            + opticalsurface->GetName();
3537     G4Exception("G4GDMLReadSolids::PropertyRead()", "InvalidRead",
3538                 FatalException, error_msg);
3539   }
3540   */
3541 
3542   if(matrix.GetRows() == 0)
3543   {
3544     return;
3545   }
3546 
3547   G4MaterialPropertiesTable* matprop =
3548     opticalsurface->GetMaterialPropertiesTable();
3549   if(matprop == nullptr)
3550   {
3551     matprop = new G4MaterialPropertiesTable();
3552     opticalsurface->SetMaterialPropertiesTable(matprop);
3553   }
3554   if(matrix.GetCols() == 1)  // constant property assumed
3555   {
3556     matprop->AddConstProperty(Strip(name), matrix.Get(0, 0), true);
3557   }
3558   else  // build the material properties vector
3559   {
3560     G4MaterialPropertyVector* propvect;
3561     G4String temp = name + ref;
3562     // first check if it was already built
3563     if(mapOfMatPropVects.find(temp) == mapOfMatPropVects.end())
3564     {
3565       // if not create a new one
3566       propvect = new G4MaterialPropertyVector();
3567       for(size_t i = 0; i < matrix.GetRows(); i++)
3568       {
3569         propvect->InsertValues(matrix.Get(i, 0), matrix.Get(i, 1));
3570       }
3571       // and add it to the list for potential future reuse
3572       mapOfMatPropVects[temp] = propvect;
3573     }
3574     else
3575     {
3576       propvect = mapOfMatPropVects[temp];
3577     }
3578 
3579     matprop->AddProperty(Strip(name), propvect, true);
3580   }
3581 }
3582 
3583 // --------------------------------------------------------------------
3584 void G4GDMLReadSolids::OpticalSurfaceRead(
3585   const xercesc::DOMElement* const opticalsurfaceElement)
3586 {
3587   G4String name;
3588   G4String smodel;
3589   G4String sfinish;
3590   G4String stype;
3591   G4double value = 0.0;
3592 
3593   const xercesc::DOMNamedNodeMap* const attributes =
3594     opticalsurfaceElement->getAttributes();
3595   XMLSize_t attributeCount = attributes->getLength();
3596 
3597   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
3598       ++attribute_index)
3599   {
3600     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
3601 
3602     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
3603     {
3604       continue;
3605     }
3606 
3607     const xercesc::DOMAttr* const attribute =
3608       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
3609     if(attribute == nullptr)
3610     {
3611       G4Exception("G4GDMLReadSolids::OpticalSurfaceRead()", "InvalidRead",
3612                   FatalException, "No attribute found!");
3613       return;
3614     }
3615     const G4String attName  = Transcode(attribute->getName());
3616     const G4String attValue = Transcode(attribute->getValue());
3617 
3618     if(attName == "name")
3619     {
3620       name = GenerateName(attValue);
3621     }
3622     else if(attName == "model")
3623     {
3624       smodel = attValue;
3625     }
3626     else if(attName == "finish")
3627     {
3628       sfinish = attValue;
3629     }
3630     else if(attName == "type")
3631     {
3632       stype = attValue;
3633     }
3634     else if(attName == "value")
3635     {
3636       value = eval.Evaluate(attValue);
3637     }
3638   }
3639 
3640   G4OpticalSurfaceModel model;
3641   G4OpticalSurfaceFinish finish;
3642   G4SurfaceType type;
3643 
3644   if((smodel == "glisur") || (smodel == "0"))
3645   {
3646     model = glisur;
3647   }
3648   else if((smodel == "unified") || (smodel == "1"))
3649   {
3650     model = unified;
3651   }
3652   else if((smodel == "LUT") || (smodel == "2"))
3653   {
3654     model = LUT;
3655   }
3656   else if((smodel == "DAVIS") || (smodel == "3"))
3657   {
3658     model = DAVIS;
3659   }
3660   else
3661   {
3662     model = dichroic;
3663   }
3664 
3665   if((sfinish == "polished") || (sfinish == "0"))
3666   {
3667     finish = polished;
3668   }
3669   else if((sfinish == "polishedfrontpainted") || (sfinish == "1"))
3670   {
3671     finish = polishedfrontpainted;
3672   }
3673   else if((sfinish == "polishedbackpainted") || (sfinish == "2"))
3674   {
3675     finish = polishedbackpainted;
3676   }
3677   else if((sfinish == "ground") || (sfinish == "3"))
3678   {
3679     finish = ground;
3680   }
3681   else if((sfinish == "groundfrontpainted") || (sfinish == "4"))
3682   {
3683     finish = groundfrontpainted;
3684   }
3685   else if((sfinish == "groundbackpainted") || (sfinish == "5"))
3686   {
3687     finish = groundbackpainted;
3688   }
3689   else if((sfinish == "polishedlumirrorair") || (sfinish == "6"))
3690   {
3691     finish = polishedlumirrorair;
3692   }
3693   else if((sfinish == "polishedlumirrorglue") || (sfinish == "7"))
3694   {
3695     finish = polishedlumirrorglue;
3696   }
3697   else if((sfinish == "polishedair") || (sfinish == "8"))
3698   {
3699     finish = polishedair;
3700   }
3701   else if((sfinish == "polishedteflonair") || (sfinish == "9"))
3702   {
3703     finish = polishedteflonair;
3704   }
3705   else if((sfinish == "polishedtioair") || (sfinish == "10"))
3706   {
3707     finish = polishedtioair;
3708   }
3709   else if((sfinish == "polishedtyvekair") || (sfinish == "11"))
3710   {
3711     finish = polishedtyvekair;
3712   }
3713   else if((sfinish == "polishedvm2000air") || (sfinish == "12"))
3714   {
3715     finish = polishedvm2000air;
3716   }
3717   else if((sfinish == "polishedvm2000glue") || (sfinish == "13"))
3718   {
3719     finish = polishedvm2000glue;
3720   }
3721   else if((sfinish == "etchedlumirrorair") || (sfinish == "14"))
3722   {
3723     finish = etchedlumirrorair;
3724   }
3725   else if((sfinish == "etchedlumirrorglue") || (sfinish == "15"))
3726   {
3727     finish = etchedlumirrorglue;
3728   }
3729   else if((sfinish == "etchedair") || (sfinish == "16"))
3730   {
3731     finish = etchedair;
3732   }
3733   else if((sfinish == "etchedteflonair") || (sfinish == "17"))
3734   {
3735     finish = etchedteflonair;
3736   }
3737   else if((sfinish == "etchedtioair") || (sfinish == "18"))
3738   {
3739     finish = etchedtioair;
3740   }
3741   else if((sfinish == "etchedtyvekair") || (sfinish == "19"))
3742   {
3743     finish = etchedtyvekair;
3744   }
3745   else if((sfinish == "etchedvm2000air") || (sfinish == "20"))
3746   {
3747     finish = etchedvm2000air;
3748   }
3749   else if((sfinish == "etchedvm2000glue") || (sfinish == "21"))
3750   {
3751     finish = etchedvm2000glue;
3752   }
3753   else if((sfinish == "groundlumirrorair") || (sfinish == "22"))
3754   {
3755     finish = groundlumirrorair;
3756   }
3757   else if((sfinish == "groundlumirrorglue") || (sfinish == "23"))
3758   {
3759     finish = groundlumirrorglue;
3760   }
3761   else if((sfinish == "groundair") || (sfinish == "24"))
3762   {
3763     finish = groundair;
3764   }
3765   else if((sfinish == "groundteflonair") || (sfinish == "25"))
3766   {
3767     finish = groundteflonair;
3768   }
3769   else if((sfinish == "groundtioair") || (sfinish == "26"))
3770   {
3771     finish = groundtioair;
3772   }
3773   else if((sfinish == "groundtyvekair") || (sfinish == "27"))
3774   {
3775     finish = groundtyvekair;
3776   }
3777   else if((sfinish == "groundvm2000air") || (sfinish == "28"))
3778   {
3779     finish = groundvm2000air;
3780   }
3781   else if((sfinish == "groundvm2000glue") || (sfinish == "29"))
3782   {
3783     finish = groundvm2000glue;
3784   }
3785   else if((sfinish == "Rough_LUT") || (sfinish == "30"))
3786   {
3787     finish = Rough_LUT;
3788   }
3789   else if((sfinish == "RoughTeflon_LUT") || (sfinish == "31"))
3790   {
3791     finish = RoughTeflon_LUT;
3792   }
3793   else if((sfinish == "RoughESR_LUT") || (sfinish == "32"))
3794   {
3795     finish = RoughESR_LUT;
3796   }
3797   else if((sfinish == "RoughESRGrease_LUT") || (sfinish == "33"))
3798   {
3799     finish = RoughESRGrease_LUT;
3800   }
3801   else if((sfinish == "Polished_LUT") || (sfinish == "34"))
3802   {
3803     finish = Polished_LUT;
3804   }
3805   else if((sfinish == "PolishedTeflon_LUT") || (sfinish == "35"))
3806   {
3807     finish = PolishedTeflon_LUT;
3808   }
3809   else if((sfinish == "PolishedESR_LUT") || (sfinish == "36"))
3810   {
3811     finish = PolishedESR_LUT;
3812   }
3813   else if((sfinish == "PolishedESRGrease_LUT") || (sfinish == "37"))
3814   {
3815     finish = PolishedESRGrease_LUT;
3816   }
3817   else
3818   {
3819     finish = Detector_LUT;
3820   }
3821 
3822   if((stype == "dielectric_metal") || (stype == "0"))
3823   {
3824     type = dielectric_metal;
3825   }
3826   else if((stype == "dielectric_dielectric") || (stype == "1"))
3827   {
3828     type = dielectric_dielectric;
3829   }
3830   else if((stype == "dielectric_LUT") || (stype == "2"))
3831   {
3832     type = dielectric_LUT;
3833   }
3834   else if((stype == "dielectric_LUTDAVIS") || (stype == "3"))
3835   {
3836     type = dielectric_LUTDAVIS;
3837   }
3838   else if((stype == "dielectric_dichroic") || (stype == "4"))
3839   {
3840     type = dielectric_dichroic;
3841   }
3842   else if((stype == "firsov") || (stype == "5"))
3843   {
3844     type = firsov;
3845   }
3846   else
3847   {
3848     type = x_ray;
3849   }
3850 
3851   G4OpticalSurface* opticalsurface =
3852     new G4OpticalSurface(name, model, finish, type, value);
3853 
3854   for(xercesc::DOMNode* iter = opticalsurfaceElement->getFirstChild();
3855       iter != nullptr; iter = iter->getNextSibling())
3856   {
3857     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
3858     {
3859       continue;
3860     }
3861 
3862     const xercesc::DOMElement* const child =
3863       dynamic_cast<xercesc::DOMElement*>(iter);
3864     if(child == nullptr)
3865     {
3866       G4Exception("G4GDMLReadSolids::OpticalSurfaceRead()", "InvalidRead",
3867                   FatalException, "No child found!");
3868       return;
3869     }
3870     const G4String tag = Transcode(child->getTagName());
3871 
3872     if(tag == "property")
3873     {
3874       PropertyRead(child, opticalsurface);
3875     }
3876   }
3877 }
3878 
3879 // --------------------------------------------------------------------
3880 void G4GDMLReadSolids::SolidsRead(
3881   const xercesc::DOMElement* const solidsElement)
3882 {
3883 #ifdef G4VERBOSE
3884   G4cout << "G4GDML: Reading solids..." << G4endl;
3885 #endif
3886   for(xercesc::DOMNode* iter = solidsElement->getFirstChild(); iter != nullptr;
3887       iter                   = iter->getNextSibling())
3888   {
3889     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
3890     {
3891       continue;
3892     }
3893 
3894     const xercesc::DOMElement* const child =
3895       dynamic_cast<xercesc::DOMElement*>(iter);
3896     if(child == nullptr)
3897     {
3898       G4Exception("G4GDMLReadSolids::SolidsRead()", "InvalidRead",
3899                   FatalException, "No child found!");
3900       return;
3901     }
3902     const G4String tag = Transcode(child->getTagName());
3903     if(tag == "define")
3904     {
3905       DefineRead(child);
3906     }
3907     else if(tag == "box")
3908     {
3909       BoxRead(child);
3910     }
3911     else if(tag == "cone")
3912     {
3913       ConeRead(child);
3914     }
3915     else if(tag == "elcone")
3916     {
3917       ElconeRead(child);
3918     }
3919     else if(tag == "ellipsoid")
3920     {
3921       EllipsoidRead(child);
3922     }
3923     else if(tag == "eltube")
3924     {
3925       EltubeRead(child);
3926     }
3927     else if(tag == "xtru")
3928     {
3929       XtruRead(child);
3930     }
3931     else if(tag == "hype")
3932     {
3933       HypeRead(child);
3934     }
3935     else if(tag == "intersection")
3936     {
3937       BooleanRead(child, INTERSECTION);
3938     }
3939     else if(tag == "multiUnion")
3940     {
3941       MultiUnionRead(child);
3942     }
3943     else if(tag == "orb")
3944     {
3945       OrbRead(child);
3946     }
3947     else if(tag == "para")
3948     {
3949       ParaRead(child);
3950     }
3951     else if(tag == "paraboloid")
3952     {
3953       ParaboloidRead(child);
3954     }
3955     else if(tag == "polycone")
3956     {
3957       PolyconeRead(child);
3958     }
3959     else if(tag == "genericPolycone")
3960     {
3961       GenericPolyconeRead(child);
3962     }
3963     else if(tag == "polyhedra")
3964     {
3965       PolyhedraRead(child);
3966     }
3967     else if(tag == "genericPolyhedra")
3968     {
3969       GenericPolyhedraRead(child);
3970     }
3971     else if(tag == "reflectedSolid")
3972     {
3973       ReflectedSolidRead(child);
3974     }
3975     else if(tag == "scaledSolid")
3976     {
3977       ScaledSolidRead(child);
3978     }
3979     else if(tag == "sphere")
3980     {
3981       SphereRead(child);
3982     }
3983     else if(tag == "subtraction")
3984     {
3985       BooleanRead(child, SUBTRACTION);
3986     }
3987     else if(tag == "tessellated")
3988     {
3989       TessellatedRead(child);
3990     }
3991     else if(tag == "tet")
3992     {
3993       TetRead(child);
3994     }
3995     else if(tag == "torus")
3996     {
3997       TorusRead(child);
3998     }
3999     else if(tag == "arb8")
4000     {
4001       GenTrapRead(child);
4002     }
4003     else if(tag == "trap")
4004     {
4005       TrapRead(child);
4006     }
4007     else if(tag == "trd")
4008     {
4009       TrdRead(child);
4010     }
4011     else if(tag == "tube")
4012     {
4013       TubeRead(child);
4014     }
4015     else if(tag == "cutTube")
4016     {
4017       CutTubeRead(child);
4018     }
4019     else if(tag == "twistedbox")
4020     {
4021       TwistedboxRead(child);
4022     }
4023     else if(tag == "twistedtrap")
4024     {
4025       TwistedtrapRead(child);
4026     }
4027     else if(tag == "twistedtrd")
4028     {
4029       TwistedtrdRead(child);
4030     }
4031     else if(tag == "twistedtubs")
4032     {
4033       TwistedtubsRead(child);
4034     }
4035     else if(tag == "union")
4036     {
4037       BooleanRead(child, UNION);
4038     }
4039     else if(tag == "opticalsurface")
4040     {
4041       OpticalSurfaceRead(child);
4042     }
4043     else if(tag == "loop")
4044     {
4045       LoopRead(child, &G4GDMLRead::SolidsRead);
4046     }
4047     else
4048     {
4049       G4String error_msg = "Unknown tag in solids: " + tag;
4050       G4Exception("G4GDMLReadSolids::SolidsRead()", "ReadError", FatalException,
4051                   error_msg);
4052     }
4053   }
4054 }
4055 
4056 // --------------------------------------------------------------------
4057 G4VSolid* G4GDMLReadSolids::GetSolid(const G4String& ref) const
4058 {
4059   G4VSolid* solidPtr = G4SolidStore::GetInstance()
4060                                     ->GetSolid(ref,false,reverseSearch);
4061 
4062   if(solidPtr == nullptr)
4063   {
4064     G4String error_msg = "Referenced solid '" + ref + "' was not found!";
4065     G4Exception("G4GDMLReadSolids::GetSolid()", "ReadError", FatalException,
4066                 error_msg);
4067   }
4068 
4069   return solidPtr;
4070 }
4071 
4072 // --------------------------------------------------------------------
4073 G4SurfaceProperty* G4GDMLReadSolids::GetSurfaceProperty(
4074   const G4String& ref) const
4075 {
4076   const G4SurfacePropertyTable* surfaceList =
4077     G4SurfaceProperty::GetSurfacePropertyTable();
4078   const std::size_t surfaceCount = surfaceList->size();
4079 
4080   for(std::size_t i = 0; i < surfaceCount; ++i)
4081   {
4082     if((*surfaceList)[i]->GetName() == ref)
4083     {
4084       return (*surfaceList)[i];
4085     }
4086   }
4087 
4088   G4String error_msg =
4089     "Referenced optical surface '" + ref + "' was not found!";
4090   G4Exception("G4GDMLReadSolids::GetSurfaceProperty()", "ReadError",
4091               FatalException, error_msg);
4092 
4093   return nullptr;
4094 }
4095