Geant4 Cross Reference

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

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

Diff markup

Differences between /persistency/gdml/src/G4GDMLWriteStructure.cc (Version 11.3.0) and /persistency/gdml/src/G4GDMLWriteStructure.cc (Version 10.0.p2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // G4GDMLWriteStructure implementation         << 
 27 //                                                 26 //
 28 // Author: Zoltan Torzsok, November 2007       <<  27 // $Id: G4GDMLWriteStructure.cc 68053 2013-03-13 14:39:51Z gcosmo $
                                                   >>  28 //
                                                   >>  29 // class G4GDMLWriteStructure Implementation
                                                   >>  30 //
                                                   >>  31 // Original author: Zoltan Torzsok, November 2007
                                                   >>  32 //
 29 // -------------------------------------------     33 // --------------------------------------------------------------------
 30                                                    34 
 31 #include "G4GDMLWriteStructure.hh"                 35 #include "G4GDMLWriteStructure.hh"
 32 #include "G4GDMLEvaluator.hh"                  << 
 33                                                    36 
 34 #include "G4Material.hh"                           37 #include "G4Material.hh"
 35 #include "G4ReflectedSolid.hh"                     38 #include "G4ReflectedSolid.hh"
 36 #include "G4DisplacedSolid.hh"                     39 #include "G4DisplacedSolid.hh"
 37 #include "G4LogicalVolumeStore.hh"                 40 #include "G4LogicalVolumeStore.hh"
 38 #include "G4PhysicalVolumeStore.hh"                41 #include "G4PhysicalVolumeStore.hh"
 39 #include "G4ReflectionFactory.hh"              << 
 40 #include "G4PVDivision.hh"                         42 #include "G4PVDivision.hh"
 41 #include "G4PVReplica.hh"                          43 #include "G4PVReplica.hh"
 42 #include "G4Region.hh"                         << 
 43 #include "G4OpticalSurface.hh"                     44 #include "G4OpticalSurface.hh"
 44 #include "G4LogicalSkinSurface.hh"                 45 #include "G4LogicalSkinSurface.hh"
 45 #include "G4LogicalBorderSurface.hh"               46 #include "G4LogicalBorderSurface.hh"
 46                                                    47 
 47 #include "G4ProductionCuts.hh"                 << 
 48 #include "G4ProductionCutsTable.hh"            << 
 49 #include "G4Gamma.hh"                          << 
 50 #include "G4Electron.hh"                       << 
 51 #include "G4Positron.hh"                       << 
 52 #include "G4Proton.hh"                         << 
 53                                                << 
 54 #include "G4VSensitiveDetector.hh"             << 
 55 #include "G4AssemblyStore.hh"                  << 
 56 #include "G4AssemblyVolume.hh"                 << 
 57                                                << 
 58 G4int G4GDMLWriteStructure::levelNo = 0;  // C << 
 59                                                << 
 60 // ------------------------------------------- << 
 61 G4GDMLWriteStructure::G4GDMLWriteStructure()       48 G4GDMLWriteStructure::G4GDMLWriteStructure()
 62   : G4GDMLWriteParamvol()                          49   : G4GDMLWriteParamvol()
 63   , maxLevel(INT_MAX)                          << 
 64 {                                                  50 {
 65   reflFactory = G4ReflectionFactory::Instance( << 
 66 }                                                  51 }
 67                                                    52 
 68 // ------------------------------------------- << 
 69 G4GDMLWriteStructure::~G4GDMLWriteStructure()      53 G4GDMLWriteStructure::~G4GDMLWriteStructure()
 70 {                                                  54 {
 71 }                                                  55 }
 72                                                    56 
 73 // ------------------------------------------- <<  57 void
 74 void G4GDMLWriteStructure::DivisionvolWrite(   <<  58 G4GDMLWriteStructure::DivisionvolWrite(xercesc::DOMElement* volumeElement,
 75   xercesc::DOMElement* volumeElement, const G4 <<  59                                        const G4PVDivision* const divisionvol)
 76 {                                              <<  60 {
 77   EAxis axis       = kUndefined;               <<  61    EAxis axis = kUndefined;
 78   G4int number     = 0;                        <<  62    G4int number = 0;
 79   G4double width   = 0.0;                      <<  63    G4double width = 0.0;
 80   G4double offset  = 0.0;                      <<  64    G4double offset = 0.0;
 81   G4bool consuming = false;                    <<  65    G4bool consuming = false;
 82                                                <<  66 
 83   divisionvol->GetReplicationData(axis, number <<  67    divisionvol->GetReplicationData(axis,number,width,offset,consuming);
 84   axis = divisionvol->GetDivisionAxis();       <<  68    axis = divisionvol->GetDivisionAxis();
 85                                                <<  69 
 86   G4String unitString("mm");                   <<  70    G4String unitString("mm");
 87   G4String axisString("kUndefined");           <<  71    G4String axisString("kUndefined");
 88   if(axis == kXAxis)                           <<  72    if (axis==kXAxis) { axisString = "kXAxis"; }
 89   {                                            <<  73    else if (axis==kYAxis) { axisString = "kYAxis"; }
 90     axisString = "kXAxis";                     <<  74    else if (axis==kZAxis) { axisString = "kZAxis"; }
 91   }                                            <<  75    else if (axis==kRho)   { axisString = "kRho";     }
 92   else if(axis == kYAxis)                      <<  76    else if (axis==kPhi)   { axisString = "kPhi"; unitString = "rad"; }
 93   {                                            <<  77 
 94     axisString = "kYAxis";                     <<  78    const G4String name
 95   }                                            <<  79          = GenerateName(divisionvol->GetName(),divisionvol);
 96   else if(axis == kZAxis)                      <<  80    const G4String volumeref
 97   {                                            <<  81          = GenerateName(divisionvol->GetLogicalVolume()->GetName(),
 98     axisString = "kZAxis";                     <<  82                         divisionvol->GetLogicalVolume());
 99   }                                            <<  83 
100   else if(axis == kRho)                        <<  84    xercesc::DOMElement* divisionvolElement = NewElement("divisionvol");
101   {                                            <<  85    divisionvolElement->setAttributeNode(NewAttribute("axis",axisString));
102     axisString = "kRho";                       <<  86    divisionvolElement->setAttributeNode(NewAttribute("number",number));
103   }                                            <<  87    divisionvolElement->setAttributeNode(NewAttribute("width",width));
104   else if(axis == kPhi)                        <<  88    divisionvolElement->setAttributeNode(NewAttribute("offset",offset));
105   {                                            <<  89    divisionvolElement->setAttributeNode(NewAttribute("unit",unitString));
106     axisString = "kPhi";                       <<  90    xercesc::DOMElement* volumerefElement = NewElement("volumeref");
107     unitString = "rad";                        <<  91    volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
108   }                                            <<  92    divisionvolElement->appendChild(volumerefElement);
109                                                <<  93    volumeElement->appendChild(divisionvolElement);
110   const G4String name = GenerateName(divisionv << 
111   const G4String volumeref =                   << 
112     GenerateName(divisionvol->GetLogicalVolume << 
113                  divisionvol->GetLogicalVolume << 
114                                                << 
115   xercesc::DOMElement* divisionvolElement = Ne << 
116   divisionvolElement->setAttributeNode(NewAttr << 
117   divisionvolElement->setAttributeNode(NewAttr << 
118   divisionvolElement->setAttributeNode(NewAttr << 
119   divisionvolElement->setAttributeNode(NewAttr << 
120   divisionvolElement->setAttributeNode(NewAttr << 
121   xercesc::DOMElement* volumerefElement = NewE << 
122   volumerefElement->setAttributeNode(NewAttrib << 
123   divisionvolElement->appendChild(volumerefEle << 
124   volumeElement->appendChild(divisionvolElemen << 
125 }                                                  94 }
126                                                    95 
127 // ------------------------------------------- << 
128 void G4GDMLWriteStructure::PhysvolWrite(xerces     96 void G4GDMLWriteStructure::PhysvolWrite(xercesc::DOMElement* volumeElement,
129                                         const      97                                         const G4VPhysicalVolume* const physvol,
130                                         const      98                                         const G4Transform3D& T,
131                                         const      99                                         const G4String& ModuleName)
132 {                                                 100 {
133   HepGeom::Scale3D scale;                      << 101    HepGeom::Scale3D scale;
134   HepGeom::Rotate3D rotate;                    << 102    HepGeom::Rotate3D rotate;
135   HepGeom::Translate3D translate;              << 103    HepGeom::Translate3D translate;
136                                                << 104 
137   T.getDecomposition(scale, rotate, translate) << 105    T.getDecomposition(scale,rotate,translate);
138                                                << 106 
139   const G4ThreeVector scl(scale(0, 0), scale(1 << 107    const G4ThreeVector scl(scale(0,0),scale(1,1),scale(2,2));
140   const G4ThreeVector rot = GetAngles(rotate.g << 108    const G4ThreeVector rot = GetAngles(rotate.getRotation());
141   const G4ThreeVector pos = T.getTranslation() << 109    const G4ThreeVector pos = T.getTranslation();
142                                                << 110 
143   const G4String name    = GenerateName(physvo << 111    const G4String name = GenerateName(physvol->GetName(),physvol);
144   const G4int copynumber = physvol->GetCopyNo( << 112 
145                                                << 113    xercesc::DOMElement* physvolElement = NewElement("physvol");
146   xercesc::DOMElement* physvolElement = NewEle << 114    physvolElement->setAttributeNode(NewAttribute("name",name));
147   physvolElement->setAttributeNode(NewAttribut << 115    volumeElement->appendChild(physvolElement);
148   if(copynumber)                               << 116 
149   {                                            << 117    const G4String volumeref
150     physvolElement->setAttributeNode(NewAttrib << 118          = GenerateName(physvol->GetLogicalVolume()->GetName(),
151   }                                            << 119                         physvol->GetLogicalVolume());
152                                                << 120 
153   volumeElement->appendChild(physvolElement);  << 121    if (ModuleName.empty())
154                                                << 122    {
155   G4LogicalVolume* lv;                         << 123       xercesc::DOMElement* volumerefElement = NewElement("volumeref");
156   // Is it reflected?                          << 124       volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
157   if(reflFactory->IsReflected(physvol->GetLogi << 125       physvolElement->appendChild(volumerefElement);
158   {                                            << 126    }
159     lv = reflFactory->GetConstituentLV(physvol << 127    else
160   }                                            << 128    {
161   else                                         << 129       xercesc::DOMElement* fileElement = NewElement("file");
162   {                                            << 130       fileElement->setAttributeNode(NewAttribute("name",ModuleName));
163     lv = physvol->GetLogicalVolume();          << 131       fileElement->setAttributeNode(NewAttribute("volname",volumeref));
164   }                                            << 132       physvolElement->appendChild(fileElement);
165                                                << 133    }
166   const G4String volumeref = GenerateName(lv-> << 134 
167                                                << 135    if (std::fabs(pos.x()) > kLinearPrecision
168   if(ModuleName.empty())                       << 136     || std::fabs(pos.y()) > kLinearPrecision
169   {                                            << 137     || std::fabs(pos.z()) > kLinearPrecision)
170     xercesc::DOMElement* volumerefElement = Ne << 138    {
171     volumerefElement->setAttributeNode(NewAttr << 139      PositionWrite(physvolElement,name+"_pos",pos);
172     physvolElement->appendChild(volumerefEleme << 140    }
173   }                                            << 141    if (std::fabs(rot.x()) > kAngularPrecision
174   else                                         << 142     || std::fabs(rot.y()) > kAngularPrecision
175   {                                            << 143     || std::fabs(rot.z()) > kAngularPrecision)
176     xercesc::DOMElement* fileElement = NewElem << 144    {
177     fileElement->setAttributeNode(NewAttribute << 145      RotationWrite(physvolElement,name+"_rot",rot);
178     fileElement->setAttributeNode(NewAttribute << 146    }
179     physvolElement->appendChild(fileElement);  << 147    if (std::fabs(scl.x()-1.0) > kRelativePrecision
180   }                                            << 148     || std::fabs(scl.y()-1.0) > kRelativePrecision
181                                                << 149     || std::fabs(scl.z()-1.0) > kRelativePrecision)
182   if(std::fabs(pos.x()) > kLinearPrecision ||  << 150    {
183      std::fabs(pos.y()) > kLinearPrecision ||  << 151      ScaleWrite(physvolElement,name+"_scl",scl);
184      std::fabs(pos.z()) > kLinearPrecision)    << 152    }
185   {                                            << 153 }
186     PositionWrite(physvolElement, name + "_pos << 154 
187   }                                            << 155 void G4GDMLWriteStructure::ReplicavolWrite(xercesc::DOMElement* volumeElement,
188   if(std::fabs(rot.x()) > kAngularPrecision || << 156                                      const G4VPhysicalVolume* const replicavol)
189      std::fabs(rot.y()) > kAngularPrecision || << 157 {
190      std::fabs(rot.z()) > kAngularPrecision)   << 158    EAxis axis = kUndefined;
191   {                                            << 159    G4int number = 0;
192     RotationWrite(physvolElement, name + "_rot << 160    G4double width = 0.0;
193   }                                            << 161    G4double offset = 0.0;
194   if(std::fabs(scl.x() - 1.0) > kRelativePreci << 162    G4bool consuming = false;
195      std::fabs(scl.y() - 1.0) > kRelativePreci << 163    G4String unitString("mm");
196      std::fabs(scl.z() - 1.0) > kRelativePreci << 164 
197   {                                            << 165    replicavol->GetReplicationData(axis,number,width,offset,consuming);
198     ScaleWrite(physvolElement, name + "_scl",  << 166 
199   }                                            << 167    const G4String volumeref
200 }                                              << 168          = GenerateName(replicavol->GetLogicalVolume()->GetName(),
201                                                << 169                         replicavol->GetLogicalVolume());
202 // ------------------------------------------- << 170 
203 void G4GDMLWriteStructure::ReplicavolWrite(    << 171    xercesc::DOMElement* replicavolElement = NewElement("replicavol");
204   xercesc::DOMElement* volumeElement, const G4 << 172    replicavolElement->setAttributeNode(NewAttribute("number",number));
205 {                                              << 173    xercesc::DOMElement* volumerefElement = NewElement("volumeref");
206   EAxis axis       = kUndefined;               << 174    volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
207   G4int number     = 0;                        << 175    replicavolElement->appendChild(volumerefElement);
208   G4double width   = 0.0;                      << 176    xercesc::DOMElement* replicateElement = NewElement("replicate_along_axis");
209   G4double offset  = 0.0;                      << 177    replicavolElement->appendChild(replicateElement);
210   G4bool consuming = false;                    << 178 
211   G4String unitString("mm");                   << 179    xercesc::DOMElement* dirElement = NewElement("direction");
212                                                << 180    if(axis==kXAxis)
213   replicavol->GetReplicationData(axis, number, << 181      { dirElement->setAttributeNode(NewAttribute("x","1")); }
214                                                << 182    else if(axis==kYAxis)
215   const G4String volumeref = GenerateName(     << 183      { dirElement->setAttributeNode(NewAttribute("y","1")); }
216     replicavol->GetLogicalVolume()->GetName(), << 184    else if(axis==kZAxis)
217                                                << 185      { dirElement->setAttributeNode(NewAttribute("z","1")); }
218   xercesc::DOMElement* replicavolElement = New << 186    else if(axis==kRho)
219   replicavolElement->setAttributeNode(NewAttri << 187      { dirElement->setAttributeNode(NewAttribute("rho","1")); }
220   xercesc::DOMElement* volumerefElement = NewE << 188    else if(axis==kPhi)
221   volumerefElement->setAttributeNode(NewAttrib << 189      { dirElement->setAttributeNode(NewAttribute("phi","1"));
222   replicavolElement->appendChild(volumerefElem << 190        unitString="rad"; }
223   xercesc::DOMElement* replicateElement = NewE << 191    replicateElement->appendChild(dirElement);
224   replicavolElement->appendChild(replicateElem << 192 
                                                   >> 193    xercesc::DOMElement* widthElement = NewElement("width");
                                                   >> 194    widthElement->setAttributeNode(NewAttribute("value",width));
                                                   >> 195    widthElement->setAttributeNode(NewAttribute("unit",unitString));
                                                   >> 196    replicateElement->appendChild(widthElement);
                                                   >> 197 
                                                   >> 198    xercesc::DOMElement* offsetElement = NewElement("offset");
                                                   >> 199    offsetElement->setAttributeNode(NewAttribute("value",offset));
                                                   >> 200    offsetElement->setAttributeNode(NewAttribute("unit",unitString));
                                                   >> 201    replicateElement->appendChild(offsetElement);
                                                   >> 202 
                                                   >> 203    volumeElement->appendChild(replicavolElement);
                                                   >> 204 }
                                                   >> 205 
                                                   >> 206 void G4GDMLWriteStructure::
                                                   >> 207 BorderSurfaceCache(const G4LogicalBorderSurface* const bsurf)
                                                   >> 208 {
                                                   >> 209    if (!bsurf)  { return; }
                                                   >> 210 
                                                   >> 211    const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
                                                   >> 212 
                                                   >> 213    // Generate the new element for border-surface
                                                   >> 214    //
                                                   >> 215    xercesc::DOMElement* borderElement = NewElement("bordersurface");
                                                   >> 216    borderElement->setAttributeNode(NewAttribute("name", bsurf->GetName()));
                                                   >> 217    borderElement->setAttributeNode(NewAttribute("surfaceproperty",
                                                   >> 218                                                 psurf->GetName()));
                                                   >> 219 
                                                   >> 220    const G4String volumeref1 = GenerateName(bsurf->GetVolume1()->GetName(),
                                                   >> 221                                             bsurf->GetVolume1());
                                                   >> 222    const G4String volumeref2 = GenerateName(bsurf->GetVolume2()->GetName(),
                                                   >> 223                                             bsurf->GetVolume2());
                                                   >> 224    xercesc::DOMElement* volumerefElement1 = NewElement("physvolref");
                                                   >> 225    xercesc::DOMElement* volumerefElement2 = NewElement("physvolref");
                                                   >> 226    volumerefElement1->setAttributeNode(NewAttribute("ref",volumeref1));
                                                   >> 227    volumerefElement2->setAttributeNode(NewAttribute("ref",volumeref2));
                                                   >> 228    borderElement->appendChild(volumerefElement1);
                                                   >> 229    borderElement->appendChild(volumerefElement2);
                                                   >> 230 
                                                   >> 231    if (FindOpticalSurface(psurf))
                                                   >> 232    {
                                                   >> 233      const G4OpticalSurface* opsurf =
                                                   >> 234        dynamic_cast<const G4OpticalSurface*>(psurf);
                                                   >> 235      if (!opsurf)
                                                   >> 236      {
                                                   >> 237        G4Exception("G4GDMLWriteStructure::BorderSurfaceCache()",
                                                   >> 238                    "InvalidSetup", FatalException, "No optical surface found!");
                                                   >> 239        return;
                                                   >> 240      }
                                                   >> 241      OpticalSurfaceWrite(solidsElement, opsurf);
                                                   >> 242    }
                                                   >> 243 
                                                   >> 244    borderElementVec.push_back(borderElement);
                                                   >> 245 }
                                                   >> 246 
                                                   >> 247 void G4GDMLWriteStructure::
                                                   >> 248 SkinSurfaceCache(const G4LogicalSkinSurface* const ssurf)
                                                   >> 249 {
                                                   >> 250    if (!ssurf)  { return; }
                                                   >> 251 
                                                   >> 252    const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
                                                   >> 253 
                                                   >> 254    // Generate the new element for border-surface
                                                   >> 255    //
                                                   >> 256    xercesc::DOMElement* skinElement = NewElement("skinsurface");
                                                   >> 257    skinElement->setAttributeNode(NewAttribute("name", ssurf->GetName()));
                                                   >> 258    skinElement->setAttributeNode(NewAttribute("surfaceproperty",
                                                   >> 259                                               psurf->GetName()));
                                                   >> 260 
                                                   >> 261    const G4String volumeref = GenerateName(ssurf->GetLogicalVolume()->GetName(),
                                                   >> 262                                            ssurf->GetLogicalVolume());
                                                   >> 263    xercesc::DOMElement* volumerefElement = NewElement("volumeref");
                                                   >> 264    volumerefElement->setAttributeNode(NewAttribute("ref",volumeref));
                                                   >> 265    skinElement->appendChild(volumerefElement);
                                                   >> 266 
                                                   >> 267    if (FindOpticalSurface(psurf))
                                                   >> 268    {
                                                   >> 269      const G4OpticalSurface* opsurf =
                                                   >> 270        dynamic_cast<const G4OpticalSurface*>(psurf);
                                                   >> 271      if (!opsurf)
                                                   >> 272      {
                                                   >> 273        G4Exception("G4GDMLWriteStructure::SkinSurfaceCache()",
                                                   >> 274                    "InvalidSetup", FatalException, "No optical surface found!");
                                                   >> 275        return;
                                                   >> 276      }
                                                   >> 277      OpticalSurfaceWrite(solidsElement, opsurf);
                                                   >> 278    }
225                                                   279 
226   xercesc::DOMElement* dirElement = NewElement << 280    skinElementVec.push_back(skinElement);
227   if(axis == kXAxis)                           << 
228   {                                            << 
229     dirElement->setAttributeNode(NewAttribute( << 
230   }                                            << 
231   else if(axis == kYAxis)                      << 
232   {                                            << 
233     dirElement->setAttributeNode(NewAttribute( << 
234   }                                            << 
235   else if(axis == kZAxis)                      << 
236   {                                            << 
237     dirElement->setAttributeNode(NewAttribute( << 
238   }                                            << 
239   else if(axis == kRho)                        << 
240   {                                            << 
241     dirElement->setAttributeNode(NewAttribute( << 
242   }                                            << 
243   else if(axis == kPhi)                        << 
244   {                                            << 
245     dirElement->setAttributeNode(NewAttribute( << 
246     unitString = "rad";                        << 
247   }                                            << 
248   replicateElement->appendChild(dirElement);   << 
249                                                << 
250   xercesc::DOMElement* widthElement = NewEleme << 
251   widthElement->setAttributeNode(NewAttribute( << 
252   widthElement->setAttributeNode(NewAttribute( << 
253   replicateElement->appendChild(widthElement); << 
254                                                << 
255   xercesc::DOMElement* offsetElement = NewElem << 
256   offsetElement->setAttributeNode(NewAttribute << 
257   offsetElement->setAttributeNode(NewAttribute << 
258   replicateElement->appendChild(offsetElement) << 
259                                                << 
260   volumeElement->appendChild(replicavolElement << 
261 }                                                 281 }
262                                                   282 
263 // ------------------------------------------- << 
264 void G4GDMLWriteStructure::AssemblyWrite(xerce << 
265                                          const << 
266 {                                              << 
267   G4AssemblyStore* assemblies  = G4AssemblySto << 
268   G4AssemblyVolume* myassembly = assemblies->G << 
269                                                << 
270   xercesc::DOMElement* assemblyElement = NewEl << 
271   G4String name = "Assembly_" + std::to_string << 
272                                                << 
273   assemblyElement->setAttributeNode(NewAttribu << 
274                                                << 
275   auto vit = myassembly->GetTripletsIterator() << 
276                                                << 
277   G4int depth = 0;                             << 
278   const G4String ModuleName;                   << 
279                                                << 
280   for(std::size_t i5 = 0; i5 < myassembly->Tot << 
281   {                                            << 
282     G4LogicalVolume* lvol = (*vit).GetVolume() << 
283     if (lvol == nullptr)                       << 
284     {                                          << 
285       G4String message = "Nested assemblies no << 
286       G4Exception("G4GDMLWriteStructure::Assem << 
287                   FatalException, message);    << 
288       return;                                  << 
289     }                                          << 
290     TraverseVolumeTree(lvol, depth + 1);       << 
291                                                << 
292     const G4ThreeVector rot = GetAngles((*vit) << 
293     const G4ThreeVector pos = (*vit).GetTransl << 
294                                                << 
295     const G4String pname =                     << 
296       GenerateName((*vit).GetVolume()->GetName << 
297                                                << 
298     xercesc::DOMElement* physvolElement = NewE << 
299     physvolElement->setAttributeNode(NewAttrib << 
300                                                << 
301     assemblyElement->appendChild(physvolElemen << 
302                                                << 
303     const G4String volumeref =                 << 
304       GenerateName((*vit).GetVolume()->GetName << 
305                                                << 
306     xercesc::DOMElement* volumerefElement = Ne << 
307     volumerefElement->setAttributeNode(NewAttr << 
308     physvolElement->appendChild(volumerefEleme << 
309                                                << 
310     if(std::fabs(pos.x()) > kLinearPrecision | << 
311        std::fabs(pos.y()) > kLinearPrecision | << 
312        std::fabs(pos.z()) > kLinearPrecision)  << 
313     {                                          << 
314       PositionWrite(physvolElement,name+"_posi << 
315     }                                          << 
316                                                << 
317     if(std::fabs(rot.x()) > kAngularPrecision  << 
318        std::fabs(rot.y()) > kAngularPrecision  << 
319        std::fabs(rot.z()) > kAngularPrecision) << 
320     {                                          << 
321       RotationWrite(physvolElement,name+"_rota << 
322     }                                          << 
323     ++vit;                                     << 
324   }                                            << 
325                                                << 
326   volumeElement->appendChild(assemblyElement); << 
327 }                                              << 
328                                                << 
329 // ------------------------------------------- << 
330 void G4GDMLWriteStructure::BorderSurfaceCache( << 
331   const G4LogicalBorderSurface* const bsurf)   << 
332 {                                              << 
333   if(bsurf == nullptr)                         << 
334   {                                            << 
335     return;                                    << 
336   }                                            << 
337                                                << 
338   const G4SurfaceProperty* psurf = bsurf->GetS << 
339                                                << 
340   // Generate the new element for border-surfa << 
341   //                                           << 
342   const G4String& bsname             = Generat << 
343   const G4String& psname             = Generat << 
344   xercesc::DOMElement* borderElement = NewElem << 
345   borderElement->setAttributeNode(NewAttribute << 
346   borderElement->setAttributeNode(NewAttribute << 
347                                                << 
348   const G4String volumeref1 =                  << 
349     GenerateName(bsurf->GetVolume1()->GetName( << 
350   const G4String volumeref2 =                  << 
351     GenerateName(bsurf->GetVolume2()->GetName( << 
352   xercesc::DOMElement* volumerefElement1 = New << 
353   xercesc::DOMElement* volumerefElement2 = New << 
354   volumerefElement1->setAttributeNode(NewAttri << 
355   volumerefElement2->setAttributeNode(NewAttri << 
356   borderElement->appendChild(volumerefElement1 << 
357   borderElement->appendChild(volumerefElement2 << 
358                                                << 
359   if(FindOpticalSurface(psurf))                << 
360   {                                            << 
361     const G4OpticalSurface* opsurf =           << 
362       dynamic_cast<const G4OpticalSurface*>(ps << 
363     if(opsurf == nullptr)                      << 
364     {                                          << 
365       G4Exception("G4GDMLWriteStructure::Borde << 
366                   FatalException, "No optical  << 
367       return;                                  << 
368     }                                          << 
369     OpticalSurfaceWrite(solidsElement, opsurf) << 
370   }                                            << 
371                                                << 
372   borderElementVec.push_back(borderElement);   << 
373 }                                              << 
374                                                << 
375 // ------------------------------------------- << 
376 void G4GDMLWriteStructure::SkinSurfaceCache(   << 
377   const G4LogicalSkinSurface* const ssurf)     << 
378 {                                              << 
379   if(ssurf == nullptr)                         << 
380   {                                            << 
381     return;                                    << 
382   }                                            << 
383                                                << 
384   const G4SurfaceProperty* psurf = ssurf->GetS << 
385                                                << 
386   // Generate the new element for border-surfa << 
387   //                                           << 
388   const G4String& ssname           = GenerateN << 
389   const G4String& psname           = GenerateN << 
390   xercesc::DOMElement* skinElement = NewElemen << 
391   skinElement->setAttributeNode(NewAttribute(" << 
392   skinElement->setAttributeNode(NewAttribute(" << 
393                                                << 
394   const G4String volumeref = GenerateName(ssur << 
395                                           ssur << 
396   xercesc::DOMElement* volumerefElement = NewE << 
397   volumerefElement->setAttributeNode(NewAttrib << 
398   skinElement->appendChild(volumerefElement);  << 
399                                                << 
400   if(FindOpticalSurface(psurf))                << 
401   {                                            << 
402     const G4OpticalSurface* opsurf =           << 
403       dynamic_cast<const G4OpticalSurface*>(ps << 
404     if(opsurf == nullptr)                      << 
405     {                                          << 
406       G4Exception("G4GDMLWriteStructure::SkinS << 
407                   FatalException, "No optical  << 
408       return;                                  << 
409     }                                          << 
410     OpticalSurfaceWrite(solidsElement, opsurf) << 
411   }                                            << 
412                                                << 
413   skinElementVec.push_back(skinElement);       << 
414 }                                              << 
415                                                << 
416 // ------------------------------------------- << 
417 G4bool G4GDMLWriteStructure::FindOpticalSurfac    283 G4bool G4GDMLWriteStructure::FindOpticalSurface(const G4SurfaceProperty* psurf)
418 {                                                 284 {
419   const G4OpticalSurface* osurf = dynamic_cast << 285    const G4OpticalSurface* osurf = dynamic_cast<const G4OpticalSurface*>(psurf);
420   auto pos = std::find(opt_vec.cbegin(), opt_v << 286    std::vector<const G4OpticalSurface*>::const_iterator pos;
421   if(pos != opt_vec.cend())                    << 287    pos = std::find(opt_vec.begin(), opt_vec.end(), osurf);
422   {                                            << 288    if (pos != opt_vec.end()) { return false; }  // item already created!
423     return false;                              << 
424   }  // item already created!                  << 
425                                                   289 
426   opt_vec.push_back(osurf);  // cache it for f << 290    opt_vec.push_back(osurf);              // cache it for future reference
427   return true;                                 << 291    return true;
428 }                                                 292 }
429                                                   293 
430 // ------------------------------------------- << 294 const G4LogicalSkinSurface*
431 const G4LogicalSkinSurface* G4GDMLWriteStructu << 295 G4GDMLWriteStructure::GetSkinSurface(const G4LogicalVolume* const lvol)
432   const G4LogicalVolume* const lvol)           << 
433 {                                                 296 {
434   G4LogicalSkinSurface* surf = nullptr;        << 297   G4LogicalSkinSurface* surf = 0;
435   std::size_t nsurf = G4LogicalSkinSurface::Ge << 298   G4int nsurf = G4LogicalSkinSurface::GetNumberOfSkinSurfaces();
436   if(nsurf)                                    << 299   if (nsurf)
437   {                                               300   {
438     const G4LogicalSkinSurfaceTable* stable =     301     const G4LogicalSkinSurfaceTable* stable =
439       G4LogicalSkinSurface::GetSurfaceTable(); << 302           G4LogicalSkinSurface::GetSurfaceTable();
440     auto pos = stable->find(lvol);             << 303     std::vector<G4LogicalSkinSurface*>::const_iterator pos;
441     if(pos != stable->cend())                  << 304     for (pos = stable->begin(); pos != stable->end(); pos++)
442     {                                             305     {
443       surf = pos->second;                      << 306       if (lvol == (*pos)->GetLogicalVolume())
                                                   >> 307       {
                                                   >> 308         surf = *pos; break;
                                                   >> 309       }
444     }                                             310     }
445   }                                               311   }
446   return surf;                                    312   return surf;
447 }                                                 313 }
448                                                   314 
449 // ------------------------------------------- << 315 const G4LogicalBorderSurface*
450 const G4LogicalBorderSurface* G4GDMLWriteStruc << 316 G4GDMLWriteStructure::GetBorderSurface(const G4VPhysicalVolume* const pvol)
451   const G4VPhysicalVolume* const pvol)         << 
452 {                                                 317 {
453   G4LogicalBorderSurface* surf = nullptr;      << 318   G4LogicalBorderSurface* surf = 0;
454   std::size_t nsurf = G4LogicalBorderSurface:: << 319   G4int nsurf = G4LogicalBorderSurface::GetNumberOfBorderSurfaces();
455   if(nsurf)                                    << 320   if (nsurf)
456   {                                               321   {
457     const G4LogicalBorderSurfaceTable* btable     322     const G4LogicalBorderSurfaceTable* btable =
458       G4LogicalBorderSurface::GetSurfaceTable( << 323           G4LogicalBorderSurface::GetSurfaceTable();
459     for(auto pos = btable->cbegin(); pos != bt << 324     std::vector<G4LogicalBorderSurface*>::const_iterator pos;
460     {                                          << 325     for (pos = btable->begin(); pos != btable->end(); pos++)
461       if(pvol == pos->first.first)  // just th << 326     {
462       {                             // could b << 327       if (pvol == (*pos)->GetVolume1())  // just the first in the couple 
463         surf = pos->second;         // break;  << 328       {                                  // is enough
464         BorderSurfaceCache(surf);              << 329         surf = *pos; break;
465       }                                           330       }
466     }                                             331     }
467   }                                               332   }
468   return surf;                                    333   return surf;
469 }                                                 334 }
470                                                   335 
471 // ------------------------------------------- << 
472 void G4GDMLWriteStructure::SurfacesWrite()        336 void G4GDMLWriteStructure::SurfacesWrite()
473 {                                                 337 {
474 #ifdef G4VERBOSE                               << 338    G4cout << "G4GDML: Writing surfaces..." << G4endl;
475   G4cout << "G4GDML: Writing surfaces..." << G << 339 
476 #endif                                         << 340    std::vector<xercesc::DOMElement*>::const_iterator pos;
477   for(auto pos = skinElementVec.cbegin();      << 341    for (pos = skinElementVec.begin(); pos != skinElementVec.end(); pos++)
478            pos != skinElementVec.cend(); ++pos << 342    {
479   {                                            << 343      structureElement->appendChild(*pos);
480     structureElement->appendChild(*pos);       << 344    }
481   }                                            << 345    for (pos = borderElementVec.begin(); pos != borderElementVec.end(); pos++)
482   for(auto pos = borderElementVec.cbegin();    << 346    {
483            pos != borderElementVec.cend(); ++p << 347      structureElement->appendChild(*pos);
484   {                                            << 348    }
485     structureElement->appendChild(*pos);       << 
486   }                                            << 
487 }                                                 349 }
488                                                   350 
489 // ------------------------------------------- << 
490 void G4GDMLWriteStructure::StructureWrite(xerc    351 void G4GDMLWriteStructure::StructureWrite(xercesc::DOMElement* gdmlElement)
491 {                                                 352 {
492 #ifdef G4VERBOSE                               << 353    G4cout << "G4GDML: Writing structure..." << G4endl;
493   G4cout << "G4GDML: Writing structure..." <<  << 
494 #endif                                         << 
495                                                << 
496   // filling the list of phys volumes that are << 
497                                                << 
498   G4AssemblyStore* assemblies = G4AssemblyStor << 
499                                                << 
500   for(auto it = assemblies->cbegin(); it != as << 
501   {                                            << 
502     auto vit = (*it)->GetVolumesIterator();    << 
503                                                << 
504     for(std::size_t i5 = 0; i5 < (*it)->TotalI << 
505     {                                          << 
506       G4String pvname = (*vit)->GetName();     << 
507       std::size_t pos = pvname.find("_impr_")  << 
508       G4String impID  = pvname.substr(pos);    << 
509                                                << 
510       pos   = impID.find("_");                 << 
511       impID = impID.substr(0, pos);            << 
512                                                << 
513       assemblyVolMap[*vit] = (*it)->GetAssembl << 
514       imprintsMap[*vit]    = std::atoi(impID.c << 
515       ++vit;                                   << 
516     }                                          << 
517   }                                            << 
518                                                   354 
519   structureElement = NewElement("structure");  << 355    structureElement = NewElement("structure");
520   gdmlElement->appendChild(structureElement);  << 356    gdmlElement->appendChild(structureElement);
521 }                                                 357 }
522                                                   358 
523 // ------------------------------------------- << 359 G4Transform3D G4GDMLWriteStructure::
524 G4Transform3D G4GDMLWriteStructure::TraverseVo << 360 TraverseVolumeTree(const G4LogicalVolume* const volumePtr, const G4int depth)
525   const G4LogicalVolume* const volumePtr, cons << 
526 {                                                 361 {
527   if(VolumeMap().find(volumePtr) != VolumeMap( << 362    if (VolumeMap().find(volumePtr) != VolumeMap().end())
528   {                                            << 363    {
529     return VolumeMap()[volumePtr];  // Volume  << 364      return VolumeMap()[volumePtr]; // Volume is already processed
530   }                                            << 365    }
531                                                << 
532   G4VSolid* solidPtr = volumePtr->GetSolid();  << 
533   G4Transform3D R, invR;                       << 
534   G4int trans = 0;                             << 
535                                                << 
536   std::map<const G4LogicalVolume*, G4GDMLAuxLi << 
537                                                << 
538   ++levelNo;                                   << 
539                                                << 
540   while(true)  // Solve possible displacement/ << 
541   {            // of the referenced solid!     << 
542     if(trans > maxTransforms)                  << 
543     {                                          << 
544       G4String ErrorMessage = "Referenced soli << 
545                               volumePtr->GetNa << 
546                               "' was displaced << 
547       G4Exception("G4GDMLWriteStructure::Trave << 
548                   FatalException, ErrorMessage << 
549     }                                          << 
550                                                << 
551     if(G4ReflectedSolid* refl = dynamic_cast<G << 
552     {                                          << 
553       R        = R * refl->GetTransform3D();   << 
554       solidPtr = refl->GetConstituentMovedSoli << 
555       ++trans;                                 << 
556       continue;                                << 
557     }                                          << 
558                                                << 
559     if(G4DisplacedSolid* disp = dynamic_cast<G << 
560     {                                          << 
561       R        = R * G4Transform3D(disp->GetOb << 
562                             disp->GetObjectTra << 
563       solidPtr = disp->GetConstituentMovedSoli << 
564       ++trans;                                 << 
565       continue;                                << 
566     }                                          << 
567                                                << 
568     break;                                     << 
569   }                                            << 
570                                                << 
571   // check if it is a reflected volume         << 
572   G4LogicalVolume* tmplv = const_cast<G4Logica << 
573                                                << 
574   if(reflFactory->IsReflected(tmplv))          << 
575   {                                            << 
576     tmplv = reflFactory->GetConstituentLV(tmpl << 
577     if(VolumeMap().find(tmplv) != VolumeMap(). << 
578     {                                          << 
579       return R;  // Volume is already processe << 
580     }                                          << 
581   }                                            << 
582                                                << 
583   // Only compute the inverse when necessary!  << 
584   //                                           << 
585   if(trans > 0)                                << 
586   {                                            << 
587     invR = R.inverse();                        << 
588   }                                            << 
589                                                << 
590   const G4String name = GenerateName(tmplv->Ge << 
591                                                << 
592   G4String materialref = "NULL";               << 
593                                                   366 
594   if(volumePtr->GetMaterial())                 << 367    G4VSolid* solidPtr = volumePtr->GetSolid();
595   {                                            << 368    G4Transform3D R,invR;
596     materialref = GenerateName(volumePtr->GetM << 369    G4int trans=0;
597                                volumePtr->GetM << 
598   }                                            << 
599                                                << 
600   const G4String solidref = GenerateName(solid << 
601                                                << 
602   xercesc::DOMElement* volumeElement = NewElem << 
603   volumeElement->setAttributeNode(NewAttribute << 
604   xercesc::DOMElement* materialrefElement = Ne << 
605   materialrefElement->setAttributeNode(NewAttr << 
606   volumeElement->appendChild(materialrefElemen << 
607   xercesc::DOMElement* solidrefElement = NewEl << 
608   solidrefElement->setAttributeNode(NewAttribu << 
609   volumeElement->appendChild(solidrefElement); << 
610                                                << 
611   std::size_t daughterCount = volumePtr->GetNo << 
612                                                << 
613   if(levelNo == maxLevel)  // Stop exporting i << 
614   {                                            << 
615     daughterCount = 0;                         << 
616   }                                            << 
617                                                   370 
618   std::map<G4int, std::vector<G4int> > assembl << 371    while (true) // Solve possible displacement/reflection
619                                                << 372    {            // of the referenced solid!
620   for(std::size_t i = 0; i < daughterCount; ++ << 373       if (trans>maxTransforms)
621   {                                            << 
622     const G4VPhysicalVolume* const physvol = v << 
623     const G4String ModuleName              = M << 
624                                                << 
625     G4Transform3D daughterR;                   << 
626                                                << 
627     if(ModuleName.empty())  // Check if subtre << 
628     {                       // a separate modu << 
629       daughterR = TraverseVolumeTree(physvol-> << 
630     }                                          << 
631     else                                       << 
632     {                                          << 
633       G4GDMLWriteStructure writer;             << 
634       daughterR = writer.Write(ModuleName, phy << 
635                                SchemaLocation, << 
636     }                                          << 
637                                                << 
638     if(const G4PVDivision* const divisionvol = << 
639          dynamic_cast<const G4PVDivision*>(phy << 
640     {                                          << 
641       if(!G4Transform3D::Identity.isNear(invR  << 
642       {                                           374       {
643         G4String ErrorMessage = "Division volu << 375         G4String ErrorMessage = "Referenced solid in volume '"
644                                 "' can not be  << 376                               + volumePtr->GetName()
                                                   >> 377                               + "' was displaced/reflected too many times!";
645         G4Exception("G4GDMLWriteStructure::Tra    378         G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
646                     "InvalidSetup", FatalExcep    379                     "InvalidSetup", FatalException, ErrorMessage);
647       }                                           380       }
648       DivisionvolWrite(volumeElement, division << 381 
649     }                                          << 382       if (G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
650     else                                       << 
651     {                                          << 
652       if(physvol->IsParameterised())  // Is it << 
653       {                                           383       {
654         if(!G4Transform3D::Identity.isNear(inv << 384          R = R*refl->GetTransform3D();
655                                            kRe << 385          solidPtr = refl->GetConstituentMovedSolid();
656         {                                      << 386          trans++;
657           G4String ErrorMessage = "Parameteris << 387          continue;
658                                   "' can not b << 
659           G4Exception("G4GDMLWriteStructure::T << 
660                       "InvalidSetup", FatalExc << 
661         }                                      << 
662         ParamvolWrite(volumeElement, physvol); << 
663       }                                           388       }
664       else                                     << 389 
                                                   >> 390       if (G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
665       {                                           391       {
666         if(physvol->IsReplicated())  // Is it  << 392          R = R*G4Transform3D(disp->GetObjectRotation(),
667         {                                      << 393                              disp->GetObjectTranslation());
668           if(!G4Transform3D::Identity.isNear(i << 394          solidPtr = disp->GetConstituentMovedSolid();
669                                              k << 395          trans++;
670           {                                    << 396          continue;
671             G4String ErrorMessage = "Replica v << 
672                                     "' can not << 
673             G4Exception("G4GDMLWriteStructure: << 
674                         "InvalidSetup", FatalE << 
675           }                                    << 
676           ReplicavolWrite(volumeElement, physv << 
677         }                                      << 
678         else  // Is it a physvol or an assembl << 
679         {                                      << 
680           if(assemblyVolMap.find(physvol) != a << 
681           {                                    << 
682             G4int assemblyID = assemblyVolMap[ << 
683                                                << 
684             G4String assemblyref = "Assembly_" << 
685                                                << 
686             // here I need to retrieve the imp << 
687                                                << 
688             G4int imprintID = imprintsMap[phys << 
689                                                << 
690             // there are 2 steps:              << 
691             //                                 << 
692             // 1) add assembly to the structur << 
693             // (but after the constituents vol << 
694             //                                 << 
695                                                << 
696             if(std::find(addedAssemblies.cbegi << 
697                          assemblyID) == addedA << 
698             {                                  << 
699               AssemblyWrite(structureElement,  << 
700               addedAssemblies.push_back(assemb << 
701               assemblyIDToAddedImprints[assemb << 
702             }                                  << 
703                                                << 
704             // 2) add the assembly (as physica << 
705             // (but only once), using it's ori << 
706             //                                 << 
707                                                << 
708             // here I need a check if assembly << 
709             // mother volume                   << 
710             std::vector<G4int>& addedImprints  << 
711             if(std::find(addedImprints.cbegin( << 
712                          imprintID) == addedIm << 
713             {                                  << 
714               G4String imprintname = "Imprint_ << 
715               imprintname          = GenerateN << 
716                                                << 
717               // I need to get those two from  << 
718               // the assembly I have the impri << 
719               //                               << 
720               G4Transform3D& transf = G4Assemb << 
721                                         ->GetA << 
722                                         ->GetI << 
723                                                << 
724               HepGeom::Scale3D scale;          << 
725               HepGeom::Rotate3D rotate;        << 
726               HepGeom::Translate3D translate;  << 
727                                                << 
728               transf.getDecomposition(scale, r << 
729                                                << 
730               const G4ThreeVector scl(scale(0, << 
731               const G4ThreeVector rot = GetAng << 
732               const G4ThreeVector pos = transf << 
733                                                << 
734               // here I need a normal physvol  << 
735                                                << 
736               xercesc::DOMElement* physvolElem << 
737               physvolElement->setAttributeNode << 
738                                                << 
739               xercesc::DOMElement* volumerefEl << 
740               volumerefElement->setAttributeNo << 
741               physvolElement->appendChild(volu << 
742                                                << 
743               if(std::fabs(pos.x()) > kLinearP << 
744                  std::fabs(pos.y()) > kLinearP << 
745                  std::fabs(pos.z()) > kLinearP << 
746               {                                << 
747                 PositionWrite(physvolElement,  << 
748               }                                << 
749               if(std::fabs(rot.x()) > kAngular << 
750                  std::fabs(rot.y()) > kAngular << 
751                  std::fabs(rot.z()) > kAngular << 
752               {                                << 
753                 RotationWrite(physvolElement,  << 
754               }                                << 
755               if(std::fabs(scl.x() - 1.0) > kR << 
756                  std::fabs(scl.y() - 1.0) > kR << 
757                  std::fabs(scl.z() - 1.0) > kR << 
758               {                                << 
759                 ScaleWrite(physvolElement, nam << 
760               }                                << 
761                                                << 
762               volumeElement->appendChild(physv << 
763               //                               << 
764               addedImprints.push_back(imprintI << 
765             }                                  << 
766           }                                    << 
767           else  // not part of assembly, so a  << 
768           {                                    << 
769             G4RotationMatrix rot;              << 
770             if(physvol->GetFrameRotation() !=  << 
771             {                                  << 
772               rot = *(physvol->GetFrameRotatio << 
773             }                                  << 
774             G4Transform3D P(rot, physvol->GetO << 
775                                                << 
776             PhysvolWrite(volumeElement, physvo << 
777                          ModuleName);          << 
778           }                                    << 
779         }                                      << 
780       }                                           397       }
781     }                                          << 
782     // BorderSurfaceCache(GetBorderSurface(phy << 
783     GetBorderSurface(physvol);                 << 
784   }                                            << 
785                                                << 
786   if(cexport)                                  << 
787   {                                            << 
788     ExportEnergyCuts(volumePtr);               << 
789   }                                            << 
790   // Add optional energy cuts                  << 
791                                                << 
792   if(sdexport)                                 << 
793   {                                            << 
794     ExportSD(volumePtr);                       << 
795   }                                            << 
796   // Add optional SDs                          << 
797                                                << 
798   // Here write the auxiliary info             << 
799   //                                           << 
800   auxiter = auxmap.find(volumePtr);            << 
801   if(auxiter != auxmap.cend())                 << 
802   {                                            << 
803     AddAuxInfo(&(auxiter->second), volumeEleme << 
804   }                                            << 
805                                                << 
806   structureElement->appendChild(volumeElement) << 
807   // Append the volume AFTER traversing the ch << 
808   // the order of volumes will be correct!     << 
809                                                << 
810   VolumeMap()[tmplv] = R;                      << 
811                                                << 
812   AddExtension(volumeElement, volumePtr);      << 
813   // Add any possible user defined extension a << 
814                                                << 
815   AddMaterial(volumePtr->GetMaterial());       << 
816   // Add the involved materials and solids!    << 
817                                                   398 
818   AddSolid(solidPtr);                          << 399       break;
                                                   >> 400    }
819                                                   401 
820   SkinSurfaceCache(GetSkinSurface(volumePtr)); << 402    // Only compute the inverse when necessary!
821                                                << 403    //
822   return R;                                    << 404    if (trans>0) { invR = R.inverse(); }
823 }                                              << 405 
824                                                << 406    const G4String name
825 // ------------------------------------------- << 407          = GenerateName(volumePtr->GetName(),volumePtr);
826 void G4GDMLWriteStructure::AddVolumeAuxiliary( << 408    const G4String materialref
827                                                << 409          = GenerateName(volumePtr->GetMaterial()->GetName(),
828 {                                              << 410                         volumePtr->GetMaterial());
829   auto pos = auxmap.find(lvol);                << 411    const G4String solidref
830                                                << 412          = GenerateName(solidPtr->GetName(),solidPtr);
831   if(pos == auxmap.cend())                     << 413 
832   {                                            << 414    xercesc::DOMElement* volumeElement = NewElement("volume");
833     auxmap[lvol] = G4GDMLAuxListType();        << 415    volumeElement->setAttributeNode(NewAttribute("name",name));
834   }                                            << 416    xercesc::DOMElement* materialrefElement = NewElement("materialref");
                                                   >> 417    materialrefElement->setAttributeNode(NewAttribute("ref",materialref));
                                                   >> 418    volumeElement->appendChild(materialrefElement);
                                                   >> 419    xercesc::DOMElement* solidrefElement = NewElement("solidref");
                                                   >> 420    solidrefElement->setAttributeNode(NewAttribute("ref",solidref));
                                                   >> 421    volumeElement->appendChild(solidrefElement);
                                                   >> 422 
                                                   >> 423    const G4int daughterCount = volumePtr->GetNoDaughters();
                                                   >> 424 
                                                   >> 425    for (G4int i=0;i<daughterCount;i++)   // Traverse all the children!
                                                   >> 426    {
                                                   >> 427       const G4VPhysicalVolume* const physvol = volumePtr->GetDaughter(i);
                                                   >> 428       const G4String ModuleName = Modularize(physvol,depth);
                                                   >> 429 
                                                   >> 430       G4Transform3D daughterR;
                                                   >> 431 
                                                   >> 432       if (ModuleName.empty())   // Check if subtree requested to be 
                                                   >> 433       {                         // a separate module!
                                                   >> 434          daughterR = TraverseVolumeTree(physvol->GetLogicalVolume(),depth+1);
                                                   >> 435       }
                                                   >> 436       else
                                                   >> 437       {   
                                                   >> 438          G4GDMLWriteStructure writer;
                                                   >> 439          daughterR = writer.Write(ModuleName,physvol->GetLogicalVolume(),
                                                   >> 440                                   SchemaLocation,depth+1);
                                                   >> 441       }
835                                                   442 
836   auxmap[lvol].push_back(myaux);               << 443       if (const G4PVDivision* const divisionvol
837 }                                              << 444          = dynamic_cast<const G4PVDivision*>(physvol)) // Is it division?
                                                   >> 445       {
                                                   >> 446          if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
                                                   >> 447          {
                                                   >> 448             G4String ErrorMessage = "Division volume in '"
                                                   >> 449                                   + name
                                                   >> 450                                   + "' can not be related to reflected solid!";
                                                   >> 451             G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
                                                   >> 452                         "InvalidSetup", FatalException, ErrorMessage);
                                                   >> 453          }
                                                   >> 454          DivisionvolWrite(volumeElement,divisionvol); 
                                                   >> 455       } else 
                                                   >> 456       if (physvol->IsParameterised())   // Is it a paramvol?
                                                   >> 457       {
                                                   >> 458          if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
                                                   >> 459          {
                                                   >> 460             G4String ErrorMessage = "Parameterised volume in '"
                                                   >> 461                                   + name
                                                   >> 462                                   + "' can not be related to reflected solid!";
                                                   >> 463             G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
                                                   >> 464                         "InvalidSetup", FatalException, ErrorMessage);
                                                   >> 465          }
                                                   >> 466          ParamvolWrite(volumeElement,physvol);
                                                   >> 467       } else
                                                   >> 468       if (physvol->IsReplicated())   // Is it a replicavol?
                                                   >> 469       {
                                                   >> 470          if (!G4Transform3D::Identity.isNear(invR*daughterR,kRelativePrecision))
                                                   >> 471          {
                                                   >> 472             G4String ErrorMessage = "Replica volume in '"
                                                   >> 473                                   + name
                                                   >> 474                                   + "' can not be related to reflected solid!";
                                                   >> 475             G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
                                                   >> 476                         "InvalidSetup", FatalException, ErrorMessage);
                                                   >> 477          }
                                                   >> 478          ReplicavolWrite(volumeElement,physvol); 
                                                   >> 479       }
                                                   >> 480       else   // Is it a physvol?
                                                   >> 481       {
                                                   >> 482          G4RotationMatrix rot;
838                                                   483 
839 // ------------------------------------------- << 484          if (physvol->GetFrameRotation() != 0)
840 void G4GDMLWriteStructure::SetEnergyCutsExport << 485          {
841 {                                              << 486            rot = *(physvol->GetFrameRotation());
842   cexport = fcuts;                             << 487          }
843 }                                              << 488          G4Transform3D P(rot,physvol->GetObjectTranslation());
                                                   >> 489          PhysvolWrite(volumeElement,physvol,invR*P*daughterR,ModuleName);
                                                   >> 490       }
                                                   >> 491       BorderSurfaceCache(GetBorderSurface(physvol));
                                                   >> 492    }
844                                                   493 
845 // ------------------------------------------- << 494    structureElement->appendChild(volumeElement);
846 void G4GDMLWriteStructure::ExportEnergyCuts(co << 495      // Append the volume AFTER traversing the children so that
847 {                                              << 496      // the order of volumes will be correct!
848   G4GDMLEvaluator eval;                        << 
849   G4ProductionCuts* pcuts     = lvol->GetRegio << 
850   G4ProductionCutsTable* ctab = G4ProductionCu << 
851   G4Gamma* gamma              = G4Gamma::Gamma << 
852   G4Electron* eminus          = G4Electron::El << 
853   G4Positron* eplus           = G4Positron::Po << 
854   G4Proton* proton            = G4Proton::Prot << 
855                                                << 
856   G4double gamma_cut = ctab->ConvertRangeToEne << 
857     gamma, lvol->GetMaterial(), pcuts->GetProd << 
858   G4double eminus_cut = ctab->ConvertRangeToEn << 
859     eminus, lvol->GetMaterial(), pcuts->GetPro << 
860   G4double eplus_cut = ctab->ConvertRangeToEne << 
861     eplus, lvol->GetMaterial(), pcuts->GetProd << 
862   G4double proton_cut = ctab->ConvertRangeToEn << 
863     proton, lvol->GetMaterial(), pcuts->GetPro << 
864                                                << 
865   G4GDMLAuxStructType gammainfo  = { "gammaECu << 
866                                     eval.Conve << 
867   G4GDMLAuxStructType eminusinfo = { "electron << 
868                                      eval.Conv << 
869                                      0 };      << 
870   G4GDMLAuxStructType eplusinfo  = { "positron << 
871                                     eval.Conve << 
872   G4GDMLAuxStructType protinfo   = { "protonEC << 
873                                    eval.Conver << 
874                                                << 
875   AddVolumeAuxiliary(gammainfo, lvol);         << 
876   AddVolumeAuxiliary(eminusinfo, lvol);        << 
877   AddVolumeAuxiliary(eplusinfo, lvol);         << 
878   AddVolumeAuxiliary(protinfo, lvol);          << 
879 }                                              << 
880                                                   497 
881 // ------------------------------------------- << 498    VolumeMap()[volumePtr] = R;
882 void G4GDMLWriteStructure::SetSDExport(G4bool  << 
883 {                                              << 
884   sdexport = fsd;                              << 
885 }                                              << 
886                                                   499 
887 // ------------------------------------------- << 500    AddExtension(volumeElement, volumePtr);
888 void G4GDMLWriteStructure::ExportSD(const G4Lo << 501      // Add any possible user defined extension attached to a volume
889 {                                              << 
890   G4VSensitiveDetector* sd = lvol->GetMasterSe << 
891                                                   502 
892   if(sd != nullptr)                            << 503    AddMaterial(volumePtr->GetMaterial());
893   {                                            << 504      // Add the involved materials and solids!
894     G4String SDname = sd->GetName();           << 
895                                                   505 
896     G4GDMLAuxStructType SDinfo = { "SensDet",  << 506    AddSolid(solidPtr);
897     AddVolumeAuxiliary(SDinfo, lvol);          << 
898   }                                            << 
899 }                                              << 
900                                                   507 
901 // ------------------------------------------- << 508    SkinSurfaceCache(GetSkinSurface(volumePtr));
902 G4int G4GDMLWriteStructure::GetMaxExportLevel( << 
903 {                                              << 
904   return maxLevel;                             << 
905 }                                              << 
906                                                   509 
907 // ------------------------------------------- << 510    return R;
908 void G4GDMLWriteStructure::SetMaxExportLevel(G << 
909 {                                              << 
910   if(level <= 0)                               << 
911   {                                            << 
912     G4Exception("G4GDMLWriteStructure::Travers << 
913                 FatalException, "Levels to exp << 
914     return;                                    << 
915   }                                            << 
916   maxLevel = level;                            << 
917   levelNo  = 0;                                << 
918 }                                                 511 }
919                                                   512