Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-01 07:06:35

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // G4GDMLReadSolids implementation
0027 //
0028 // Author: Zoltan Torzsok, November 2007
0029 // --------------------------------------------------------------------
0030 
0031 #include "G4GDMLReadSolids.hh"
0032 #include "G4Box.hh"
0033 #include "G4Cons.hh"
0034 #include "G4Ellipsoid.hh"
0035 #include "G4EllipticalCone.hh"
0036 #include "G4EllipticalTube.hh"
0037 #include "G4Hype.hh"
0038 #include "G4IntersectionSolid.hh"
0039 #include "G4Orb.hh"
0040 #include "G4Para.hh"
0041 #include "G4Paraboloid.hh"
0042 #include "G4Polycone.hh"
0043 #include "G4GenericPolycone.hh"
0044 #include "G4Polyhedra.hh"
0045 #include "G4QuadrangularFacet.hh"
0046 #include "G4ReflectedSolid.hh"
0047 #include "G4ScaledSolid.hh"
0048 #include "G4Sphere.hh"
0049 #include "G4SolidStore.hh"
0050 #include "G4SubtractionSolid.hh"
0051 #include "G4GenericTrap.hh"
0052 #include "G4TessellatedSolid.hh"
0053 #include "G4Tet.hh"
0054 #include "G4Torus.hh"
0055 #include "G4Transform3D.hh"
0056 #include "G4Trap.hh"
0057 #include "G4Trd.hh"
0058 #include "G4TriangularFacet.hh"
0059 #include "G4Tubs.hh"
0060 #include "G4CutTubs.hh"
0061 #include "G4TwistedBox.hh"
0062 #include "G4TwistedTrap.hh"
0063 #include "G4TwistedTrd.hh"
0064 #include "G4TwistedTubs.hh"
0065 #include "G4UnionSolid.hh"
0066 #include "G4OpticalSurface.hh"
0067 #include "G4UnitsTable.hh"
0068 #include "G4SurfaceProperty.hh"
0069 
0070 // --------------------------------------------------------------------
0071 G4GDMLReadSolids::G4GDMLReadSolids()
0072   : G4GDMLReadMaterials()
0073 {
0074 }
0075 
0076 // --------------------------------------------------------------------
0077 G4GDMLReadSolids::~G4GDMLReadSolids()
0078 {
0079 }
0080 
0081 // --------------------------------------------------------------------
0082 void G4GDMLReadSolids::BooleanRead(
0083   const xercesc::DOMElement* const booleanElement, const BooleanOp op)
0084 {
0085   G4String name;
0086   G4String first;
0087   G4String scnd;
0088   G4ThreeVector position(0.0, 0.0, 0.0);
0089   G4ThreeVector rotation(0.0, 0.0, 0.0);
0090   G4ThreeVector firstposition(0.0, 0.0, 0.0);
0091   G4ThreeVector firstrotation(0.0, 0.0, 0.0);
0092 
0093   const xercesc::DOMNamedNodeMap* const attributes =
0094     booleanElement->getAttributes();
0095   XMLSize_t attributeCount = attributes->getLength();
0096 
0097   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0098       ++attribute_index)
0099   {
0100     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0101 
0102     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0103     {
0104       continue;
0105     }
0106 
0107     const xercesc::DOMAttr* const attribute =
0108       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0109     if(attribute == nullptr)
0110     {
0111       G4Exception("G4GDMLReadSolids::BooleanRead()", "InvalidRead",
0112                   FatalException, "No attribute found!");
0113       return;
0114     }
0115     const G4String attName  = Transcode(attribute->getName());
0116     const G4String attValue = Transcode(attribute->getValue());
0117 
0118     if(attName == "name")
0119     {
0120       name = GenerateName(attValue);
0121     }
0122   }
0123 
0124   for(xercesc::DOMNode* iter = booleanElement->getFirstChild(); iter != nullptr;
0125       iter                   = iter->getNextSibling())
0126   {
0127     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
0128     {
0129       continue;
0130     }
0131 
0132     const xercesc::DOMElement* const child =
0133       dynamic_cast<xercesc::DOMElement*>(iter);
0134     if(child == nullptr)
0135     {
0136       G4Exception("G4GDMLReadSolids::BooleanRead()", "InvalidRead",
0137                   FatalException, "No child found!");
0138       return;
0139     }
0140     const G4String tag = Transcode(child->getTagName());
0141 
0142     if(tag == "first")
0143     {
0144       first = RefRead(child);
0145     }
0146     else if(tag == "second")
0147     {
0148       scnd = RefRead(child);
0149     }
0150     else if(tag == "position")
0151     {
0152       VectorRead(child, position);
0153     }
0154     else if(tag == "rotation")
0155     {
0156       VectorRead(child, rotation);
0157     }
0158     else if(tag == "positionref")
0159     {
0160       position = GetPosition(GenerateName(RefRead(child)));
0161     }
0162     else if(tag == "rotationref")
0163     {
0164       rotation = GetRotation(GenerateName(RefRead(child)));
0165     }
0166     else if(tag == "firstposition")
0167     {
0168       VectorRead(child, firstposition);
0169     }
0170     else if(tag == "firstrotation")
0171     {
0172       VectorRead(child, firstrotation);
0173     }
0174     else if(tag == "firstpositionref")
0175     {
0176       firstposition = GetPosition(GenerateName(RefRead(child)));
0177     }
0178     else if(tag == "firstrotationref")
0179     {
0180       firstrotation = GetRotation(GenerateName(RefRead(child)));
0181     }
0182     else
0183     {
0184       G4String error_msg = "Unknown tag in boolean solid: " + tag;
0185       G4Exception("G4GDMLReadSolids::BooleanRead()", "ReadError",
0186                   FatalException, error_msg);
0187     }
0188   }
0189 
0190   G4VSolid* firstSolid  = GetSolid(GenerateName(first));
0191   G4VSolid* secondSolid = GetSolid(GenerateName(scnd));
0192 
0193   G4Transform3D transform(GetRotationMatrix(rotation), position);
0194 
0195   if(((firstrotation.x() != 0.0) || (firstrotation.y() != 0.0) ||
0196       (firstrotation.z() != 0.0)) ||
0197      ((firstposition.x() != 0.0) || (firstposition.y() != 0.0) ||
0198       (firstposition.z() != 0.0)))
0199   {
0200     G4Transform3D firsttransform(GetRotationMatrix(firstrotation),
0201                                  firstposition);
0202     firstSolid = new G4DisplacedSolid(GenerateName("displaced_" + first),
0203                                       firstSolid, firsttransform);
0204   }
0205 
0206   if(op == UNION)
0207   {
0208     new G4UnionSolid(name, firstSolid, secondSolid, transform);
0209   }
0210   else if(op == SUBTRACTION)
0211   {
0212     new G4SubtractionSolid(name, firstSolid, secondSolid, transform);
0213   }
0214   else if(op == INTERSECTION)
0215   {
0216     new G4IntersectionSolid(name, firstSolid, secondSolid, transform);
0217   }
0218 }
0219 
0220 // --------------------------------------------------------------------
0221 void G4GDMLReadSolids::BoxRead(const xercesc::DOMElement* const boxElement)
0222 {
0223   G4String name;
0224   G4double lunit = 1.0;
0225   G4double x     = 0.0;
0226   G4double y     = 0.0;
0227   G4double z     = 0.0;
0228 
0229   const xercesc::DOMNamedNodeMap* const attributes =
0230     boxElement->getAttributes();
0231   XMLSize_t attributeCount = attributes->getLength();
0232 
0233   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0234       ++attribute_index)
0235   {
0236     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0237 
0238     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0239     {
0240       continue;
0241     }
0242 
0243     const xercesc::DOMAttr* const attribute =
0244       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0245     if(attribute == nullptr)
0246     {
0247       G4Exception("G4GDMLReadSolids::BoxRead()", "InvalidRead", FatalException,
0248                   "No attribute found!");
0249       return;
0250     }
0251     const G4String attName  = Transcode(attribute->getName());
0252     const G4String attValue = Transcode(attribute->getValue());
0253 
0254     if(attName == "name")
0255     {
0256       name = GenerateName(attValue);
0257     }
0258     else if(attName == "lunit")
0259     {
0260       lunit = G4UnitDefinition::GetValueOf(attValue);
0261       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0262       {
0263         G4Exception("G4GDMLReadSolids::BoxRead()", "InvalidRead",
0264                     FatalException, "Invalid unit for length!");
0265       }
0266     }
0267     else if(attName == "x")
0268     {
0269       x = eval.Evaluate(attValue);
0270     }
0271     else if(attName == "y")
0272     {
0273       y = eval.Evaluate(attValue);
0274     }
0275     else if(attName == "z")
0276     {
0277       z = eval.Evaluate(attValue);
0278     }
0279   }
0280 
0281   x *= 0.5 * lunit;
0282   y *= 0.5 * lunit;
0283   z *= 0.5 * lunit;
0284 
0285   new G4Box(name, x, y, z);
0286 }
0287 
0288 // --------------------------------------------------------------------
0289 void G4GDMLReadSolids::ConeRead(const xercesc::DOMElement* const coneElement)
0290 {
0291   G4String name;
0292   G4double lunit    = 1.0;
0293   G4double aunit    = 1.0;
0294   G4double rmin1    = 0.0;
0295   G4double rmax1    = 0.0;
0296   G4double rmin2    = 0.0;
0297   G4double rmax2    = 0.0;
0298   G4double z        = 0.0;
0299   G4double startphi = 0.0;
0300   G4double deltaphi = 0.0;
0301 
0302   const xercesc::DOMNamedNodeMap* const attributes =
0303     coneElement->getAttributes();
0304   XMLSize_t attributeCount = attributes->getLength();
0305 
0306   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0307       ++attribute_index)
0308   {
0309     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0310 
0311     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0312     {
0313       continue;
0314     }
0315 
0316     const xercesc::DOMAttr* const attribute =
0317       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0318     if(attribute == nullptr)
0319     {
0320       G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead", FatalException,
0321                   "No attribute found!");
0322       return;
0323     }
0324     const G4String attName  = Transcode(attribute->getName());
0325     const G4String attValue = Transcode(attribute->getValue());
0326 
0327     if(attName == "name")
0328     {
0329       name = GenerateName(attValue);
0330     }
0331     else if(attName == "lunit")
0332     {
0333       lunit = G4UnitDefinition::GetValueOf(attValue);
0334       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0335       {
0336         G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead",
0337                     FatalException, "Invalid unit for length!");
0338       }
0339     }
0340     else if(attName == "aunit")
0341     {
0342       aunit = G4UnitDefinition::GetValueOf(attValue);
0343       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
0344       {
0345         G4Exception("G4GDMLReadSolids::ConeRead()", "InvalidRead",
0346                     FatalException, "Invalid unit for angle!");
0347       }
0348     }
0349     else if(attName == "rmin1")
0350     {
0351       rmin1 = eval.Evaluate(attValue);
0352     }
0353     else if(attName == "rmax1")
0354     {
0355       rmax1 = eval.Evaluate(attValue);
0356     }
0357     else if(attName == "rmin2")
0358     {
0359       rmin2 = eval.Evaluate(attValue);
0360     }
0361     else if(attName == "rmax2")
0362     {
0363       rmax2 = eval.Evaluate(attValue);
0364     }
0365     else if(attName == "z")
0366     {
0367       z = eval.Evaluate(attValue);
0368     }
0369     else if(attName == "startphi")
0370     {
0371       startphi = eval.Evaluate(attValue);
0372     }
0373     else if(attName == "deltaphi")
0374     {
0375       deltaphi = eval.Evaluate(attValue);
0376     }
0377   }
0378 
0379   rmin1 *= lunit;
0380   rmax1 *= lunit;
0381   rmin2 *= lunit;
0382   rmax2 *= lunit;
0383   z *= 0.5 * lunit;
0384   startphi *= aunit;
0385   deltaphi *= aunit;
0386 
0387   new G4Cons(name, rmin1, rmax1, rmin2, rmax2, z, startphi, deltaphi);
0388 }
0389 
0390 // --------------------------------------------------------------------
0391 void G4GDMLReadSolids::ElconeRead(
0392   const xercesc::DOMElement* const elconeElement)
0393 {
0394   G4String name;
0395   G4double lunit = 1.0;
0396   G4double dx    = 0.0;
0397   G4double dy    = 0.0;
0398   G4double zmax  = 0.0;
0399   G4double zcut  = 0.0;
0400 
0401   const xercesc::DOMNamedNodeMap* const attributes =
0402     elconeElement->getAttributes();
0403   XMLSize_t attributeCount = attributes->getLength();
0404 
0405   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0406       ++attribute_index)
0407   {
0408     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0409 
0410     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0411     {
0412       continue;
0413     }
0414 
0415     const xercesc::DOMAttr* const attribute =
0416       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0417     if(attribute == nullptr)
0418     {
0419       G4Exception("G4GDMLReadSolids::ElconeRead()", "InvalidRead",
0420                   FatalException, "No attribute found!");
0421       return;
0422     }
0423     const G4String attName  = Transcode(attribute->getName());
0424     const G4String attValue = Transcode(attribute->getValue());
0425 
0426     if(attName == "name")
0427     {
0428       name = GenerateName(attValue);
0429     }
0430     else if(attName == "lunit")
0431     {
0432       lunit = G4UnitDefinition::GetValueOf(attValue);
0433       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0434       {
0435         G4Exception("G4GDMLReadSolids::ElconeRead()", "InvalidRead",
0436                     FatalException, "Invalid unit for length!");
0437       }
0438     }
0439     else if(attName == "dx")
0440     {
0441       dx = eval.Evaluate(attValue);
0442     }
0443     else if(attName == "dy")
0444     {
0445       dy = eval.Evaluate(attValue);
0446     }
0447     else if(attName == "zmax")
0448     {
0449       zmax = eval.Evaluate(attValue);
0450     }
0451     else if(attName == "zcut")
0452     {
0453       zcut = eval.Evaluate(attValue);
0454     }
0455   }
0456 
0457   zmax *= lunit;
0458   zcut *= lunit;
0459 
0460   new G4EllipticalCone(name, dx, dy, zmax, zcut);
0461 }
0462 
0463 // --------------------------------------------------------------------
0464 void G4GDMLReadSolids::EllipsoidRead(
0465   const xercesc::DOMElement* const ellipsoidElement)
0466 {
0467   G4String name;
0468   G4double lunit = 1.0;
0469   G4double ax    = 0.0;
0470   G4double by    = 0.0;
0471   G4double cz    = 0.0;
0472   G4double zcut1 = 0.0;
0473   G4double zcut2 = 0.0;
0474 
0475   const xercesc::DOMNamedNodeMap* const attributes =
0476     ellipsoidElement->getAttributes();
0477   XMLSize_t attributeCount = attributes->getLength();
0478 
0479   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0480       ++attribute_index)
0481   {
0482     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0483 
0484     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0485     {
0486       continue;
0487     }
0488 
0489     const xercesc::DOMAttr* const attribute =
0490       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0491     if(attribute == nullptr)
0492     {
0493       G4Exception("G4GDMLReadSolids::EllipsoidRead()", "InvalidRead",
0494                   FatalException, "No attribute found!");
0495       return;
0496     }
0497     const G4String attName  = Transcode(attribute->getName());
0498     const G4String attValue = Transcode(attribute->getValue());
0499 
0500     if(attName == "name")
0501     {
0502       name = GenerateName(attValue);
0503     }
0504     else if(attName == "lunit")
0505     {
0506       lunit = G4UnitDefinition::GetValueOf(attValue);
0507       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0508       {
0509         G4Exception("G4GDMLReadSolids::EllipsoidRead()", "InvalidRead",
0510                     FatalException, "Invalid unit for length!");
0511       }
0512     }
0513     else if(attName == "ax")
0514     {
0515       ax = eval.Evaluate(attValue);
0516     }
0517     else if(attName == "by")
0518     {
0519       by = eval.Evaluate(attValue);
0520     }
0521     else if(attName == "cz")
0522     {
0523       cz = eval.Evaluate(attValue);
0524     }
0525     else if(attName == "zcut1")
0526     {
0527       zcut1 = eval.Evaluate(attValue);
0528     }
0529     else if(attName == "zcut2")
0530     {
0531       zcut2 = eval.Evaluate(attValue);
0532     }
0533   }
0534 
0535   ax *= lunit;
0536   by *= lunit;
0537   cz *= lunit;
0538   zcut1 *= lunit;
0539   zcut2 *= lunit;
0540 
0541   new G4Ellipsoid(name, ax, by, cz, zcut1, zcut2);
0542 }
0543 
0544 // --------------------------------------------------------------------
0545 void G4GDMLReadSolids::EltubeRead(
0546   const xercesc::DOMElement* const eltubeElement)
0547 {
0548   G4String name;
0549   G4double lunit = 1.0;
0550   G4double dx    = 0.0;
0551   G4double dy    = 0.0;
0552   G4double dz    = 0.0;
0553 
0554   const xercesc::DOMNamedNodeMap* const attributes =
0555     eltubeElement->getAttributes();
0556   XMLSize_t attributeCount = attributes->getLength();
0557 
0558   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0559       ++attribute_index)
0560   {
0561     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0562 
0563     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0564     {
0565       continue;
0566     }
0567 
0568     const xercesc::DOMAttr* const attribute =
0569       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0570     if(attribute == nullptr)
0571     {
0572       G4Exception("G4GDMLReadSolids::EltubeRead()", "InvalidRead",
0573                   FatalException, "No attribute found!");
0574       return;
0575     }
0576     const G4String attName  = Transcode(attribute->getName());
0577     const G4String attValue = Transcode(attribute->getValue());
0578 
0579     if(attName == "name")
0580     {
0581       name = GenerateName(attValue);
0582     }
0583     else if(attName == "lunit")
0584     {
0585       lunit = G4UnitDefinition::GetValueOf(attValue);
0586       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0587       {
0588         G4Exception("G4GDMLReadSolids::EltubeRead()", "InvalidRead",
0589                     FatalException, "Invalid unit for length!");
0590       }
0591     }
0592     else if(attName == "dx")
0593     {
0594       dx = eval.Evaluate(attValue);
0595     }
0596     else if(attName == "dy")
0597     {
0598       dy = eval.Evaluate(attValue);
0599     }
0600     else if(attName == "dz")
0601     {
0602       dz = eval.Evaluate(attValue);
0603     }
0604   }
0605 
0606   dx *= lunit;
0607   dy *= lunit;
0608   dz *= lunit;
0609 
0610   new G4EllipticalTube(name, dx, dy, dz);
0611 }
0612 
0613 // --------------------------------------------------------------------
0614 void G4GDMLReadSolids::XtruRead(const xercesc::DOMElement* const xtruElement)
0615 {
0616   G4String name;
0617   G4double lunit = 1.0;
0618 
0619   const xercesc::DOMNamedNodeMap* const attributes =
0620     xtruElement->getAttributes();
0621   XMLSize_t attributeCount = attributes->getLength();
0622 
0623   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0624       ++attribute_index)
0625   {
0626     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0627 
0628     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0629     {
0630       continue;
0631     }
0632 
0633     const xercesc::DOMAttr* const attribute =
0634       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0635     if(attribute == nullptr)
0636     {
0637       G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead", FatalException,
0638                   "No attribute found!");
0639       return;
0640     }
0641     const G4String attName  = Transcode(attribute->getName());
0642     const G4String attValue = Transcode(attribute->getValue());
0643 
0644     if(attName == "name")
0645     {
0646       name = GenerateName(attValue);
0647     }
0648     else if(attName == "lunit")
0649     {
0650       lunit = G4UnitDefinition::GetValueOf(attValue);
0651       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0652       {
0653         G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead",
0654                     FatalException, "Invalid unit for length!");
0655       }
0656     }
0657   }
0658 
0659   std::vector<G4TwoVector> twoDimVertexList;
0660   std::vector<G4ExtrudedSolid::ZSection> sectionList;
0661 
0662   for(xercesc::DOMNode* iter = xtruElement->getFirstChild(); iter != nullptr;
0663       iter                   = iter->getNextSibling())
0664   {
0665     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
0666     {
0667       continue;
0668     }
0669 
0670     const xercesc::DOMElement* const child =
0671       dynamic_cast<xercesc::DOMElement*>(iter);
0672     if(child == nullptr)
0673     {
0674       G4Exception("G4GDMLReadSolids::XtruRead()", "InvalidRead", FatalException,
0675                   "No child found!");
0676       return;
0677     }
0678     const G4String tag = Transcode(child->getTagName());
0679 
0680     if(tag == "twoDimVertex")
0681     {
0682       twoDimVertexList.push_back(TwoDimVertexRead(child, lunit));
0683     }
0684     else if(tag == "section")
0685     {
0686       sectionList.push_back(SectionRead(child, lunit));
0687     }
0688   }
0689 
0690   new G4ExtrudedSolid(name, twoDimVertexList, sectionList);
0691 }
0692 
0693 // --------------------------------------------------------------------
0694 void G4GDMLReadSolids::HypeRead(const xercesc::DOMElement* const hypeElement)
0695 {
0696   G4String name;
0697   G4double lunit = 1.0;
0698   G4double aunit = 1.0;
0699   G4double rmin  = 0.0;
0700   G4double rmax  = 0.0;
0701   G4double inst  = 0.0;
0702   G4double outst = 0.0;
0703   G4double z     = 0.0;
0704 
0705   const xercesc::DOMNamedNodeMap* const attributes =
0706     hypeElement->getAttributes();
0707   XMLSize_t attributeCount = attributes->getLength();
0708 
0709   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0710       ++attribute_index)
0711   {
0712     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0713 
0714     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0715     {
0716       continue;
0717     }
0718 
0719     const xercesc::DOMAttr* const attribute =
0720       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0721     if(attribute == nullptr)
0722     {
0723       G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead", FatalException,
0724                   "No attribute found!");
0725       return;
0726     }
0727     const G4String attName  = Transcode(attribute->getName());
0728     const G4String attValue = Transcode(attribute->getValue());
0729 
0730     if(attName == "name")
0731     {
0732       name = GenerateName(attValue);
0733     }
0734     else if(attName == "lunit")
0735     {
0736       lunit = G4UnitDefinition::GetValueOf(attValue);
0737       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0738       {
0739         G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead",
0740                     FatalException, "Invalid unit for length!");
0741       }
0742     }
0743     else if(attName == "aunit")
0744     {
0745       aunit = G4UnitDefinition::GetValueOf(attValue);
0746       if(G4UnitDefinition::GetCategory(attValue) != "Angle")
0747       {
0748         G4Exception("G4GDMLReadSolids::HypeRead()", "InvalidRead",
0749                     FatalException, "Invalid unit for angle!");
0750       }
0751     }
0752     else if(attName == "rmin")
0753     {
0754       rmin = eval.Evaluate(attValue);
0755     }
0756     else if(attName == "rmax")
0757     {
0758       rmax = eval.Evaluate(attValue);
0759     }
0760     else if(attName == "inst")
0761     {
0762       inst = eval.Evaluate(attValue);
0763     }
0764     else if(attName == "outst")
0765     {
0766       outst = eval.Evaluate(attValue);
0767     }
0768     else if(attName == "z")
0769     {
0770       z = eval.Evaluate(attValue);
0771     }
0772   }
0773 
0774   rmin *= lunit;
0775   rmax *= lunit;
0776   inst *= aunit;
0777   outst *= aunit;
0778   z *= 0.5 * lunit;
0779 
0780   new G4Hype(name, rmin, rmax, inst, outst, z);
0781 }
0782 
0783 // --------------------------------------------------------------------
0784 void G4GDMLReadSolids::MultiUnionNodeRead(
0785   const xercesc::DOMElement* const unionNodeElement,
0786   G4MultiUnion* const multiUnionSolid)
0787 {
0788   G4String name;
0789   G4String solid;
0790   G4ThreeVector position(0.0, 0.0, 0.0);
0791   G4ThreeVector rotation(0.0, 0.0, 0.0);
0792 
0793   const xercesc::DOMNamedNodeMap* const attributes =
0794     unionNodeElement->getAttributes();
0795   XMLSize_t attributeCount = attributes->getLength();
0796 
0797   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0798       ++attribute_index)
0799   {
0800     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0801 
0802     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0803     {
0804       continue;
0805     }
0806 
0807     const xercesc::DOMAttr* const attribute =
0808       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0809     if(attribute == nullptr)
0810     {
0811       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "InvalidRead",
0812                   FatalException, "No attribute found!");
0813       return;
0814     }
0815     const G4String attName  = Transcode(attribute->getName());
0816     const G4String attValue = Transcode(attribute->getValue());
0817 
0818     if(attName == "name")
0819     {
0820       name = GenerateName(attValue);
0821     }
0822   }
0823 
0824   for(xercesc::DOMNode* iter = unionNodeElement->getFirstChild();
0825                         iter != nullptr; iter = iter->getNextSibling())
0826   {
0827     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
0828     {
0829       continue;
0830     }
0831 
0832     const xercesc::DOMElement* const child =
0833       dynamic_cast<xercesc::DOMElement*>(iter);
0834     if(child == nullptr)
0835     {
0836       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "InvalidRead",
0837                   FatalException, "No child found!");
0838       return;
0839     }
0840     const G4String tag = Transcode(child->getTagName());
0841 
0842     if(tag == "position")
0843     {
0844       VectorRead(child, position);
0845     }
0846     else if(tag == "rotation")
0847     {
0848       VectorRead(child, rotation);
0849     }
0850     else if(tag == "positionref")
0851     {
0852       position = GetPosition(GenerateName(RefRead(child)));
0853     }
0854     else if(tag == "rotationref")
0855     {
0856       rotation = GetRotation(GenerateName(RefRead(child)));
0857     }
0858     else if(tag == "solid")
0859     {
0860       solid = RefRead(child);
0861     }
0862     else
0863     {
0864       G4String error_msg = "Unknown tag in MultiUnion structure: " + tag;
0865       G4Exception("G4GDMLReadSolids::MultiUnionNodeRead()", "ReadError",
0866                   FatalException, error_msg);
0867     }
0868   }
0869   G4VSolid* solidNode = GetSolid(GenerateName(solid));
0870   G4Transform3D transform(GetRotationMatrix(rotation), position);
0871   multiUnionSolid->AddNode(*solidNode, transform);
0872 }
0873 
0874 // --------------------------------------------------------------------
0875 void G4GDMLReadSolids::MultiUnionRead(
0876   const xercesc::DOMElement* const unionElement)
0877 {
0878   G4String name;
0879 
0880   const xercesc::DOMNamedNodeMap* const attributes =
0881     unionElement->getAttributes();
0882   XMLSize_t attributeCount = attributes->getLength();
0883 
0884   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0885       ++attribute_index)
0886   {
0887     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0888 
0889     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0890     {
0891       continue;
0892     }
0893 
0894     const xercesc::DOMAttr* const attribute =
0895       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0896     if(attribute == nullptr)
0897     {
0898       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "InvalidRead",
0899                   FatalException, "No attribute found!");
0900       return;
0901     }
0902     const G4String attName  = Transcode(attribute->getName());
0903     const G4String attValue = Transcode(attribute->getValue());
0904 
0905     if(attName == "name")
0906     {
0907       name = GenerateName(attValue);
0908     }
0909   }
0910 
0911   G4MultiUnion* multiUnion = new G4MultiUnion(name);
0912 
0913   for(xercesc::DOMNode* iter = unionElement->getFirstChild(); iter != nullptr;
0914       iter                   = iter->getNextSibling())
0915   {
0916     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
0917     {
0918       continue;
0919     }
0920 
0921     const xercesc::DOMElement* const child =
0922       dynamic_cast<xercesc::DOMElement*>(iter);
0923     if(child == nullptr)
0924     {
0925       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "InvalidRead",
0926                   FatalException, "No child found!");
0927       return;
0928     }
0929     const G4String tag = Transcode(child->getTagName());
0930 
0931     if(tag == "multiUnionNode")
0932     {
0933       MultiUnionNodeRead(child, multiUnion);
0934     }
0935     else
0936     {
0937       G4String error_msg = "Unknown tag in MultiUnion structure: " + tag;
0938       G4Exception("G4GDMLReadSolids::MultiUnionRead()", "ReadError",
0939                   FatalException, error_msg);
0940     }
0941   }
0942   multiUnion->Voxelize();
0943 }
0944 
0945 // --------------------------------------------------------------------
0946 void G4GDMLReadSolids::OrbRead(const xercesc::DOMElement* const orbElement)
0947 {
0948   G4String name;
0949   G4double lunit = 1.0;
0950   G4double r     = 0.0;
0951 
0952   const xercesc::DOMNamedNodeMap* const attributes =
0953     orbElement->getAttributes();
0954   XMLSize_t attributeCount = attributes->getLength();
0955 
0956   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
0957       ++attribute_index)
0958   {
0959     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
0960 
0961     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
0962     {
0963       continue;
0964     }
0965 
0966     const xercesc::DOMAttr* const attribute =
0967       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
0968     if(attribute == nullptr)
0969     {
0970       G4Exception("G4GDMLReadSolids::OrbRead()", "InvalidRead", FatalException,
0971                   "No attribute found!");
0972       return;
0973     }
0974     const G4String attName  = Transcode(attribute->getName());
0975     const G4String attValue = Transcode(attribute->getValue());
0976 
0977     if(attName == "name")
0978     {
0979       name = GenerateName(attValue);
0980     }
0981     else if(attName == "lunit")
0982     {
0983       lunit = G4UnitDefinition::GetValueOf(attValue);
0984       if(G4UnitDefinition::GetCategory(attValue) != "Length")
0985       {
0986         G4Exception("G4GDMLReadSolids::OrbRead()", "InvalidRead",
0987                     FatalException, "Invalid unit for length!");
0988       }
0989     }
0990     else if(attName == "r")
0991     {
0992       r = eval.Evaluate(attValue);
0993     }
0994   }
0995 
0996   r *= lunit;
0997 
0998   new G4Orb(name, r);
0999 }
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   G4int 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(G4int 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, numZPlanes, z_array, rmin_array,
1276                  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   G4int numRZPoints = rzPointList.size();
1380 
1381   G4double* r_array = new G4double[numRZPoints];
1382   G4double* z_array = new G4double[numRZPoints];
1383 
1384   for(G4int 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, numRZPoints, r_array,
1390                         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   G4int 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(G4int 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, numZPlanes, z_array,
1510                   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   G4int numRZPoints = rzpointList.size();
1619 
1620   G4double* r_array = new G4double[numRZPoints];
1621   G4double* z_array = new G4double[numRZPoints];
1622 
1623   for(G4int 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, numRZPoints, r_array,
1630                   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 }