Logo ROOT   6.21/01
Reference Guide
TGDMLWrite.cxx
Go to the documentation of this file.
1 // @(#)root/gdml:$Id$
2 // Author: Anton Pytel 15/9/2011
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TGDMLWrite
13 \ingroup Geometry_gdml
14 
15  This class contains implementation of converting ROOT's gGeoManager
16 geometry to GDML file. gGeoManager is the instance of TGeoManager class
17 containing tree of geometries creating resulting geometry. GDML is xml
18 based format of file mirroring the tree of geometries according to GDML
19 schema rules. For more information about GDML see http://gdml.web.cern.ch.
20 Each object in ROOT is represented by xml tag (=xml node/element) in GDML.
21 
22  This class is not needed to be instanciated. It should always be called
23 by gGeoManager->Export("xyz.gdml") method. Export is driven by extenstion
24 that is why ".gdml" is important in resulting name.
25 
26  Whenever a new ROOT geometry object is implemented or there is a change
27 in GDML schema this class is needed to be updated to ensure proper mapping
28 between ROOT objects and GDML elements.
29 
30  Current status of mapping ROOT -> GDML is implemented in method called
31 TGDMLWrite::ChooseObject and it contains following "map":
32 
33 #### Solids:
34 
35 ~~~
36 TGeoBBox -> <box ... >
37 TGeoParaboloid -> <paraboloid ...>
38 TGeoSphere -> <sphere ...>
39 TGeoArb8 -> <arb8 ...>
40 TGeoConeSeg -> <cone ...>
41 TGeoCone -> <cone ...>
42 TGeoPara -> <para ...>
43 TGeoTrap -> <trap ...> or
44 - -> <arb8 ...>
45 TGeoGtra -> <twistedtrap ...> or
46 - -> <trap ...> or
47 - -> <arb8 ...>
48 TGeoTrd1 -> <trd ...>
49 TGeoTrd2 -> <trd ...>
50 TGeoTubeSeg -> <tube ...>
51 TGeoCtub -> <cutTube ...>
52 TGeoTube -> <tube ...>
53 TGeoPcon -> <polycone ...>
54 TGeoTorus -> <torus ...>
55 TGeoPgon -> <polyhedra ...>
56 TGeoEltu -> <eltube ...>
57 TGeoHype -> <hype ...>
58 TGeoXtru -> <xtru ...>
59 TGeoTessellated -> <tessellated ...>
60 TGeoCompositeShape -> <union ...> or
61 - -> <subtraction ...> or
62 - -> <intersection ...>
63 
64 Special cases of solids:
65 TGeoScaledShape -> <elcone ...> if scaled TGeoCone or
66 - -> element without scale
67 TGeoCompositeShape -> <ellipsoid ...>
68 - intersection of:
69 - scaled TGeoSphere and TGeoBBox
70 ~~~
71 
72 #### Materials:
73 
74 ~~~
75 TGeoIsotope -> <isotope ...>
76 TGeoElement -> <element ...>
77 TGeoMaterial -> <material ...>
78 TGeoMixture -> <material ...>
79 ~~~
80 
81 #### Structure
82 
83 ~~~
84 TGeoVolume -> <volume ...> or
85 - -> <assembly ...>
86 TGeoNode -> <physvol ...>
87 TGeoPatternFinder -> <divisionvol ...>
88 ~~~
89 
90 There are options that can be set to change resulting document
91 
92 ##### Options:
93 
94 ~~~
95 g - is set by default in gGeoManager, this option ensures compatibility
96 - with Geant4. It means:
97 - -> atomic number of material will be changed if <1 to 1
98 - -> if polycone is set badly it will try to export it correctly
99 - -> if widht * ndiv + offset is more then width of object being divided
100 - (in divisions) then it will be rounded so it will not exceed or
101 - if kPhi divsion then it will keep range of offset in -360 -> 0
102 f - if this option is set then names of volumes and solids will have
103 - pointer as a suffix to ensure uniqness of names
104 n - if this option is set then names will not have suffix, but uniqness is
105 - of names is not secured
106 - - if none of this two options (f,n) is set then default behaviour is so
107 - that incremental suffix is added to the names.
108 - (eg. TGeoBBox_0x1, TGeoBBox_0x2 ...)
109 ~~~
110 
111 #### USAGE:
112 
113 ~~~
114 gGeoManager->Export("output.gdml");
115 gGeoManager->Export("output.gdml","","vg"); //the same as previous just
116  //options are set explicitly
117 gGeoManager->Export("output.gdml","","vgf");
118 gGeoManager->Export("output.gdml","","gn");
119 gGeoManager->Export("output.gdml","","f");
120 ...
121 ~~~
122 
123 #### Note:
124  Options discussed above are used only for TGDMLWrite class. There are
125 other options in the TGeoManager::Export(...) method that can be used.
126 See that function for details.
127 
128 */
129 
130 #include "TGDMLWrite.h"
131 
132 #include "TGeoManager.h"
133 #include "TGeoMaterial.h"
134 #include "TGeoMatrix.h"
135 #include "TXMLEngine.h"
136 #include "TGeoVolume.h"
137 #include "TGeoBBox.h"
138 #include "TGeoParaboloid.h"
139 #include "TGeoArb8.h"
140 #include "TGeoTube.h"
141 #include "TGeoCone.h"
142 #include "TGeoTrd1.h"
143 #include "TGeoTrd2.h"
144 #include "TGeoPcon.h"
145 #include "TGeoPgon.h"
146 #include "TGeoSphere.h"
147 #include "TGeoTorus.h"
148 #include "TGeoPara.h"
149 #include "TGeoHype.h"
150 #include "TGeoEltu.h"
151 #include "TGeoXtru.h"
152 #include "TGeoScaledShape.h"
153 #include "TGeoVolume.h"
154 #include "TROOT.h"
155 #include "TMath.h"
156 #include "TGeoBoolNode.h"
157 #include "TGeoMedium.h"
158 #include "TGeoElement.h"
159 #include "TGeoShape.h"
160 #include "TGeoCompositeShape.h"
161 #include "TGeoOpticalSurface.h"
162 #include <stdlib.h>
163 #include <string>
164 #include <map>
165 #include <set>
166 #include <ctime>
167 #include <sstream>
168 
170 
172 
173 namespace {
174  struct MaterialExtractor {
175  std::set<TGeoMaterial*> materials;
176  void operator() (const TGeoVolume* v) {
177  materials.insert(v->GetMaterial());
178  for(Int_t i=0; i<v->GetNdaughters(); ++i)
179  (*this)(v->GetNode(i)->GetVolume());
180  }
181  };
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Default constructor.
186 
188  : TObject(),
189  fIsotopeList(0),
190  fElementList(0),
191  fAccPatt(0),
192  fRejShape(0),
193  fNameList(0),
194  fgNamingSpeed(0),
195  fgG4Compatibility(0),
196  fGdmlFile(0),
197  fTopVolumeName(0),
198  fGdmlE(0),
199  fDefineNode(0),
200  fMaterialsNode(0),
201  fSolidsNode(0),
202  fStructureNode(0),
203  fVolCnt(0),
204  fPhysVolCnt(0),
205  fActNameErr(0),
206  fSolCnt(0),
207  fFltPrecision(17) // %.17g
208 {
209  if (fgGDMLWrite) delete fgGDMLWrite;
210  fgGDMLWrite = this;
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Destructor.
215 
217 {
218  delete fIsotopeList;
219  delete fElementList;
220  delete fAccPatt;
221  delete fRejShape;
222  delete fNameList;
223 
224  fgGDMLWrite = 0;
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 /// Set convention of naming solids and volumes
229 
231 {
232  fgNamingSpeed = naming;
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 //wrapper of all main methods for extraction
237 void TGDMLWrite::WriteGDMLfile(TGeoManager * geomanager, const char* filename, TString option)
238 {
239  TList* materials = geomanager->GetListOfMaterials();
240  TGeoNode* node = geomanager->GetTopNode();
241  if ( !node ) {
242  Info("WriteGDMLfile", "Top volume does not exist!");
243  return;
244  }
245  fTopVolumeName = "";
246  WriteGDMLfile(geomanager, node, materials, filename, option);
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 // Wrapper to only selectively write one branch of the volume hierarchy to file
251 void TGDMLWrite::WriteGDMLfile(TGeoManager * geomanager, TGeoNode* node, const char* filename, TString option)
252 {
253  TGeoVolume* volume = node->GetVolume();
254  TList materials, volumes, nodes;
255  MaterialExtractor extract;
256  if ( !volume ) {
257  Info("WriteGDMLfile", "Invalid Volume reference to extract GDML information!");
258  return;
259  }
260  extract(volume);
261  for(TGeoMaterial* m : extract.materials)
262  materials.Add(m);
263  fTopVolumeName = volume->GetName();
264  fSurfaceList.clear();
265  fVolumeList.clear();
266  fNodeList.clear();
267  WriteGDMLfile(geomanager, node, &materials, filename, option);
268  materials.Clear("nodelete");
269  volumes.Clear("nodelete");
270  nodes.Clear("nodelete");
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Wrapper of all exporting methods
275 /// Creates blank GDML file and fills it with gGeoManager structure converted
276 /// to GDML structure of xml nodes
277 
279  TGeoNode* node,
280  TList* materialsLst,
281  const char* filename,
282  TString option)
283 {
284  //option processing
285  option.ToLower();
286  if (option.Contains("g")) {
288  Info("WriteGDMLfile", "Geant4 compatibility mode set");
289  } else {
291  }
292  if (option.Contains("f")) {
294  Info("WriteGDMLfile", "Fast naming convention with pointer suffix set");
295  } else if (option.Contains("n")) {
297  Info("WriteGDMLfile", "Naming without prefix set - be careful uniqness of name is not ensured");
298  } else {
300  Info("WriteGDMLfile", "Potentially slow with incremental suffix naming convention set");
301  }
302 
303  //local variables
304  Int_t outputLayout = 1;
305  const char * krootNodeName = "gdml";
306  const char * knsRefGeneral = "http://www.w3.org/2001/XMLSchema-instance";
307  const char * knsNameGeneral = "xsi";
308  const char * knsRefGdml = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
309  const char * knsNameGdml = "xsi:noNamespaceSchemaLocation";
310 
311  // First create engine
312  fGdmlE = new TXMLEngine;
314 
315  //create blank GDML file
316  fGdmlFile = fGdmlE->NewDoc();
317 
318  //create root node and add it to blank GDML file
319  XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
320  fGdmlE->DocSetRootElement(fGdmlFile, rootNode);
321 
322  //add namespaces to root node
323  fGdmlE->NewNS(rootNode, knsRefGeneral, knsNameGeneral);
324  fGdmlE->NewAttr(rootNode, nullptr, knsNameGdml, knsRefGdml);
325 
326  //initialize general lists and <define>, <solids>, <structure> nodes
327  fIsotopeList = new StructLst;
328  fElementList = new StructLst;
329 
330  fNameList = new NameLst;
331 
332  fDefineNode = fGdmlE->NewChild(nullptr, nullptr, "define", nullptr);
333  fSolidsNode = fGdmlE->NewChild(nullptr, nullptr, "solids", nullptr);
334  fStructureNode = fGdmlE->NewChild(nullptr, nullptr, "structure", nullptr);
335  //========================
336 
337  //initialize list of accepted patterns for divisions (in ExtractVolumes)
338  fAccPatt = new StructLst;
339  fAccPatt->fLst["TGeoPatternX"] = kTRUE;
340  fAccPatt->fLst["TGeoPatternY"] = kTRUE;
341  fAccPatt->fLst["TGeoPatternZ"] = kTRUE;
342  fAccPatt->fLst["TGeoPatternCylR"] = kTRUE;
343  fAccPatt->fLst["TGeoPatternCylPhi"] = kTRUE;
344  //========================
345 
346  //initialize list of rejected shapes for divisions (in ExtractVolumes)
347  fRejShape = new StructLst;
348  //this shapes are rejected because, it is not possible to divide trd2
349  //in Y axis and while only trd2 object is imported from GDML
350  //it causes a problem when TGeoTrd1 is divided in Y axis
351  fRejShape->fLst["TGeoTrd1"] = kTRUE;
352  fRejShape->fLst["TGeoTrd2"] = kTRUE;
353  //=========================
354 
355  //Initialize global counters
356  fActNameErr = 0;
357  fVolCnt = 0;
358  fPhysVolCnt = 0;
359  fSolCnt = 0;
360 
361  //calling main extraction functions (with measuring time)
362  time_t startT, endT;
363  startT = time(nullptr);
364  ExtractMatrices(geomanager->GetListOfGDMLMatrices());
365  ExtractConstants(geomanager);
366  fMaterialsNode = ExtractMaterials(materialsLst);
367 
368  Info("WriteGDMLfile", "Extracting volumes");
369  ExtractVolumes(node);
370  Info("WriteGDMLfile", "%i solids added", fSolCnt);
371  Info("WriteGDMLfile", "%i volumes added", fVolCnt);
372  Info("WriteGDMLfile", "%i physvolumes added", fPhysVolCnt);
376  endT = time(nullptr);
377  //<gdml>
378  fGdmlE->AddChild(rootNode, fDefineNode); // <define>...</define>
379  fGdmlE->AddChild(rootNode, fMaterialsNode); // <materials>...</materials>
380  fGdmlE->AddChild(rootNode, fSolidsNode); // <solids>...</solids>
381  fGdmlE->AddChild(rootNode, fStructureNode); // <structure>...</structure>
382  fGdmlE->AddChild(rootNode, CreateSetupN(fTopVolumeName.Data())); // <setup>...</setup>
383  //</gdml>
384  Double_t tdiffI = difftime(endT, startT);
385  TString tdiffS = (tdiffI == 0 ? TString("< 1 s") : TString::Format("%.0lf s", tdiffI));
386  Info("WriteGDMLfile", "Exporting time: %s", tdiffS.Data());
387  //=========================
388 
389  //Saving document
390  fGdmlE->SaveDoc(fGdmlFile, filename, outputLayout);
391  Info("WriteGDMLfile", "File %s saved", filename);
392  //cleaning
394  //unset processing bits:
395  UnsetTemporaryBits(geomanager);
396  delete fGdmlE;
397 }
398 
399 ////////////////////////////////////////////////////////////////////////////////
400 /// Method exporting GDML matrices
401 
403 {
404  if (!matrixList->GetEntriesFast()) return;
405  XMLNodePointer_t matrixN;
406  TIter next(matrixList);
407  TGDMLMatrix *matrix;
408  while ((matrix = (TGDMLMatrix*)next())) {
409  matrixN = CreateMatrixN(matrix);
410  fGdmlE->AddChild(fDefineNode, matrixN);
411  }
412 }
413 
414 ////////////////////////////////////////////////////////////////////////////////
415 /// Method exporting GDML matrices
416 
418 {
419  if (!geom->GetNproperties()) return;
420  XMLNodePointer_t constantN;
421  TString property;
422  Double_t value;
423  for (Int_t i = 0; i < geom->GetNproperties(); ++i) {
424  value = geom->GetProperty(i, property);
425  constantN = CreateConstantN(property.Data(), value);
426  fGdmlE->AddChild(fDefineNode, constantN);
427  }
428 }
429 
430 ////////////////////////////////////////////////////////////////////////////////
431 /// Method exporting optical surfaces
432 
434 {
435  if (!surfaces->GetEntriesFast()) return;
436  XMLNodePointer_t surfaceN;
437  TIter next(surfaces);
438  TGeoOpticalSurface *surf;
439  while ((surf = (TGeoOpticalSurface*)next())) {
440  if ( fSurfaceList.find(surf) == fSurfaceList.end() ) continue;
441  surfaceN = CreateOpticalSurfaceN(surf);
442  fGdmlE->AddChild(fSolidsNode, surfaceN);
443  // Info("ExtractSkinSurfaces", "Extracted optical surface: %s",surf->GetName());
444  }
445 }
446 
447 ////////////////////////////////////////////////////////////////////////////////
448 /// Method exporting skin surfaces
449 
451 {
452  if (!surfaces->GetEntriesFast()) return;
453  XMLNodePointer_t surfaceN;
454  TIter next(surfaces);
455  TGeoSkinSurface *surf;
456  while ((surf = (TGeoSkinSurface*)next())) {
457  if ( fVolumeList.find(surf->GetVolume()) == fVolumeList.end() ) continue;
458  surfaceN = CreateSkinSurfaceN(surf);
459  fGdmlE->AddChild(fStructureNode, surfaceN);
460  fSurfaceList.insert(surf->GetSurface());
461  // Info("ExtractSkinSurfaces", "Extracted skin surface: %s",surf->GetName());
462  }
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Method exporting border surfaces
467 
469 {
470  if (!surfaces->GetEntriesFast()) return;
471  XMLNodePointer_t surfaceN;
472  TIter next(surfaces);
473  TGeoBorderSurface *surf;
474  while ((surf = (TGeoBorderSurface*)next())) {
475  auto ia = fNodeList.find(surf->GetNode1());
476  auto ib = fNodeList.find(surf->GetNode2());
477  if ( ia == fNodeList.end() && ib == fNodeList.end() ) {
478  continue;
479  }
480  else if ( ia == fNodeList.end() && ib != fNodeList.end() ) {
481  Warning("ExtractBorderSurfaces", "Inconsistent border surface extraction %s: Node %s"
482  " is not part of GDML!",surf->GetName(), surf->GetNode1()->GetName());
483  continue;
484  }
485  else if ( ia != fNodeList.end() && ib == fNodeList.end() ) {
486  Warning("ExtractBorderSurfaces", "Inconsistent border surface extraction %s: Node %s"
487  " is not part of GDML!",surf->GetName(), surf->GetNode2()->GetName());
488  continue;
489  }
490  surfaceN = CreateBorderSurfaceN(surf);
491  fGdmlE->AddChild(fStructureNode, surfaceN);
492  fSurfaceList.insert(surf->GetSurface());
493  // Info("ExtractBorderSurfaces", "Extracted border surface: %s",surf->GetName());
494  }
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// Method exporting materials
499 
501 {
502  Info("ExtractMaterials", "Extracting materials");
503  //crate main <materials> node
504  XMLNodePointer_t materialsN = fGdmlE->NewChild(nullptr, nullptr, "materials", nullptr);
505  Int_t matcnt = 0;
506 
507  //go through materials - iterator and object declaration
508  TIter next(materialsLst);
509  TGeoMaterial *lmaterial;
510 
511  while ((lmaterial = (TGeoMaterial *)next())) {
512  //generate uniq name
513  TString lname = GenName(lmaterial->GetName(), TString::Format("%p", lmaterial));
514 
515  if (lmaterial->IsMixture()) {
516  TGeoMixture *lmixture = (TGeoMixture *)lmaterial;
517  XMLNodePointer_t mixtureN = CreateMixtureN(lmixture, materialsN, lname);
518  fGdmlE->AddChild(materialsN, mixtureN);
519  } else {
520  XMLNodePointer_t materialN = CreateMaterialN(lmaterial, lname);
521  fGdmlE->AddChild(materialsN, materialN);
522  }
523  matcnt++;
524  }
525  Info("ExtractMaterials", "%i materials added", matcnt);
526  return materialsN;
527 }
528 
529 ////////////////////////////////////////////////////////////////////////////////
530 /// Method creating solid to xml file and returning its name
531 
533 {
534  XMLNodePointer_t solidN;
535  TString solname = "";
536  solidN = ChooseObject(volShape); //volume->GetShape()
537  fGdmlE->AddChild(fSolidsNode, solidN);
538  if (solidN != nullptr) fSolCnt++;
539  solname = fNameList->fLst[TString::Format("%p", volShape)];
540  if (solname.Contains("missing_")) {
541  solname = "-1";
542  }
543  return solname;
544 }
545 
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Method extracting geometry structure recursively
549 
551 {
552  XMLNodePointer_t volumeN, childN;
553  TGeoVolume * volume = node->GetVolume();
554  TString volname, matname, solname, pattClsName, nodeVolNameBak;
555  TGeoPatternFinder *pattFinder = 0;
556  Bool_t isPattern = kFALSE;
557  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
558 
559  fNodeList.insert(node);
560  fVolumeList.insert(volume);
561  //create the name for volume/assembly
562  if (volume->IsTopVolume()) {
563  //not needed a special function for generating name
564  volname = volume->GetName();
565  fTopVolumeName = volname;
566  //register name to the pointer
567  fNameList->fLst[TString::Format("%p", volume)] = volname;
568  } else {
569  volname = GenName(volume->GetName(), TString::Format("%p", volume));
570  }
571 
572  //start to create main volume/assembly node
573  if (volume->IsAssembly()) {
574  volumeN = StartAssemblyN(volname);
575  } else {
576  //get reference material and add solid to <solids> + get name
577  matname = fNameList->fLst[TString::Format("%p", volume->GetMaterial())];
578  solname = ExtractSolid(volume->GetShape());
579  //If solid is not supported or corrupted
580  if (solname == "-1") {
581  Info("ExtractVolumes", "ERROR! %s volume was not added, because solid is either not supported or corrupted",
582  volname.Data());
583  //set volume as missing volume
584  fNameList->fLst[TString::Format("%p", volume)] = "missing_" + volname;
585  return;
586  }
587  volumeN = StartVolumeN(volname, solname, matname);
588 
589  //divisionvol can't be in assembly
590  pattFinder = volume->GetFinder();
591  //if found pattern
592  if (pattFinder) {
593  pattClsName = TString::Format("%s", pattFinder->ClassName());
594  TString shapeCls = TString::Format("%s", volume->GetShape()->ClassName());
595  //if pattern in accepted pattern list and not in shape rejected list
596  if ((fAccPatt->fLst[pattClsName] == kTRUE) &&
597  (fRejShape->fLst[shapeCls] != kTRUE)) {
598  isPattern = kTRUE;
599  }
600  }
601  }
602  //get all nodes in volume
603  TObjArray *nodeLst = volume->GetNodes();
604  TIter next(nodeLst);
605  TGeoNode *geoNode;
606  Int_t nCnt = 0;
607  //loop through all nodes
608  while ((geoNode = (TGeoNode *) next())) {
609  //get volume of current node and if not processed then process it
610  TGeoVolume * subvol = geoNode->GetVolume();
611  fNodeList.insert(geoNode);
612  if (subvol->TestAttBit(fgkProcBitVol) == kFALSE) {
613  subvol->SetAttBit(fgkProcBitVol);
614  ExtractVolumes(geoNode);
615  }
616 
617  //volume of this node has to exist because it was processed recursively
618  TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
619  if (nodevolname.Contains("missing_")) {
620  continue;
621  }
622  if (nCnt == 0) { //save name of the first node for divisionvol
623  nodeVolNameBak = nodevolname;
624  }
625 
626  if (isPattern == kFALSE) {
627  //create name for node
628  TString nodename, posname, rotname;
629  nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
630  nodename = nodename + "in" + volname;
631 
632  //create name for position and clear rotation
633  posname = nodename + "pos";
634  rotname = "";
635 
636  //position
637  const Double_t * pos = geoNode->GetMatrix()->GetTranslation();
638  Xyz nodPos;
639  nodPos.x = pos[0];
640  nodPos.y = pos[1];
641  nodPos.z = pos[2];
642  childN = CreatePositionN(posname.Data(), nodPos);
643  fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
644  //Deal with reflection
645  XMLNodePointer_t scaleN = nullptr;
646  Double_t lx, ly, lz;
647  Double_t xangle = 0;
648  Double_t zangle = 0;
649  lx = geoNode->GetMatrix()->GetRotationMatrix()[0];
650  ly = geoNode->GetMatrix()->GetRotationMatrix()[4];
651  lz = geoNode->GetMatrix()->GetRotationMatrix()[8];
652  if (geoNode->GetMatrix()->IsReflection()
653  && TMath::Abs(lx) == 1 && TMath::Abs(ly) == 1 && TMath::Abs(lz) == 1) {
654  scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
655  fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
656  fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
657  fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
658  fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
659  //experimentally found out, that rotation should be updated like this
660  if (lx == -1) {
661  zangle = 180;
662  }
663  if (lz == -1) {
664  xangle = 180;
665  }
666  }
667 
668  //rotation
670  lxyz.x -= xangle;
671  lxyz.z -= zangle;
672  if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
673  rotname = nodename + "rot";
674  childN = CreateRotationN(rotname.Data(), lxyz);
675  fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
676  }
677 
678  //create physvol for main volume/assembly node
679  childN = CreatePhysVolN(geoNode->GetName(), geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(), scaleN);
680  fGdmlE->AddChild(volumeN, childN);
681  }
682  nCnt++;
683  }
684  //create only one divisionvol node
685  if (isPattern && pattFinder) {
686  //retrieve attributes of division
687  Int_t ndiv, divaxis;
688  Double_t offset, width, xlo, xhi;
689  TString axis, unit;
690 
691  ndiv = pattFinder->GetNdiv();
692  width = pattFinder->GetStep();
693 
694  divaxis = pattFinder->GetDivAxis();
695  volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
696 
697  //compute relative start (not positional)
698  offset = pattFinder->GetStart() - xlo;
699  axis = GetPattAxis(divaxis, pattClsName, unit);
700 
701  //create division node
702  childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
703  fGdmlE->AddChild(volumeN, childN);
704  }
705 
706  fVolCnt++;
707  //add volume/assembly node into the <structure> node
708  fGdmlE->AddChild(fStructureNode, volumeN);
709 
710 }
711 
712 ////////////////////////////////////////////////////////////////////////////////
713 /// Creates "atom" node for GDML
714 
716 {
717  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
718  XMLNodePointer_t atomN = fGdmlE->NewChild(nullptr, nullptr, "atom", nullptr);
719  fGdmlE->NewAttr(atomN, nullptr, "unit", unit);
720  fGdmlE->NewAttr(atomN, nullptr, "value", TString::Format(fltPrecision.Data(), atom));
721  return atomN;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 /// Creates "D" density node for GDML
726 
727 XMLNodePointer_t TGDMLWrite::CreateDN(Double_t density, const char * unit)
728 {
729  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
730  XMLNodePointer_t densN = fGdmlE->NewChild(nullptr, nullptr, "D", nullptr);
731  fGdmlE->NewAttr(densN, nullptr, "unit", unit);
732  fGdmlE->NewAttr(densN, nullptr, "value", TString::Format(fltPrecision.Data(), density));
733  return densN;
734 }
735 
736 ////////////////////////////////////////////////////////////////////////////////
737 /// Creates "fraction" node for GDML
738 
739 XMLNodePointer_t TGDMLWrite::CreateFractionN(Double_t percentage, const char * refName)
740 {
741  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
742  XMLNodePointer_t fractN = fGdmlE->NewChild(nullptr, nullptr, "fraction", nullptr);
743  fGdmlE->NewAttr(fractN, nullptr, "n", TString::Format(fltPrecision.Data(), percentage));
744  fGdmlE->NewAttr(fractN, nullptr, "ref", refName);
745  return fractN;
746 }
747 
748 ////////////////////////////////////////////////////////////////////////////////
749 /// Creates "property" node for GDML
750 
752 {
753  XMLNodePointer_t propertyN = fGdmlE->NewChild(nullptr, nullptr, "property", nullptr);
754  fGdmlE->NewAttr(propertyN, nullptr, "name", property.GetName());
755  fGdmlE->NewAttr(propertyN, nullptr, "ref", property.GetTitle());
756  return propertyN;
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// Creates "isotope" node for GDML
761 
763 {
764  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "isotope", nullptr);
765  fGdmlE->NewAttr(mainN, nullptr, "name", name);
766  fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", isotope->GetN()));
767  fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", isotope->GetZ()));
768  fGdmlE->AddChild(mainN, CreateAtomN(isotope->GetA()));
769  return mainN;
770 }
771 
772 ////////////////////////////////////////////////////////////////////////////////
773 /// Creates "element" node for GDML
774 ///element node and attribute
775 
777 {
778  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "element", nullptr);
779  fGdmlE->NewAttr(mainN, nullptr, "name", name);
780  //local associative arrays for saving isotopes and their weight
781  //inside element
782  NameListF wPercentage;
783  NameListI wCounter;
784 
785  if (element->HasIsotopes()) {
786  Int_t nOfIso = element->GetNisotopes();
787  //go through isotopes
788  for (Int_t idx = 0; idx < nOfIso; idx++) {
789  TGeoIsotope *myIsotope = element->GetIsotope(idx);
790  if (!myIsotope) {
791  Fatal("CreateElementN", "Missing isotopes for element %s", element->GetName());
792  return mainN;
793  }
794 
795  //Get name of the Isotope (
796  TString lname = myIsotope->GetName();
797  //_iso suffix is added to avoid problems with same names
798  //for material, element and isotopes
799  lname = TString::Format("%s_iso", lname.Data());
800 
801  //cumulates abundance, in case 2 isotopes with same names
802  //within one element
803  wPercentage[lname] += element->GetRelativeAbundance(idx);
804  wCounter[lname]++;
805 
806  //check whether isotope name is not in list of isotopes
807  if (IsInList(fIsotopeList->fLst, lname)) {
808  continue;
809  }
810  //add isotope to list of isotopes and to main <materials> node
811  fIsotopeList->fLst[lname] = kTRUE;
812  XMLNodePointer_t isoNode = CreateIsotopN(myIsotope, lname);
813  fGdmlE->AddChild(materials, isoNode);
814  }
815  //loop through asoc array of isotopes
816  for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
817  if (itr->second > 1) {
818  Info("CreateMixtureN", "WARNING! 2 equal isotopes in one element. Check: %s isotope of %s element",
819  itr->first.Data(), name);
820  }
821  //add fraction child to element with reference to isotope
822  fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
823  }
824  } else {
825  fGdmlE->NewAttr(mainN, nullptr, "formula", element->GetName());
826  Int_t valZ = element->Z();
827  // Z can't be <1 in Geant4 and Z is optional parameter
828  if (valZ >= 1) {
829  fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", valZ));
830  }
831  fGdmlE->AddChild(mainN, CreateAtomN(element->A()));
832  }
833  return mainN;
834 }
835 
836 ////////////////////////////////////////////////////////////////////////////////
837 /// Creates "material" node for GDML with references to other sub elements
838 
840 {
841  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
842  fGdmlE->NewAttr(mainN, nullptr, "name", mname);
843  fGdmlE->AddChild(mainN, CreateDN(mixture->GetDensity()));
844  //local associative arrays for saving elements and their weight
845  //inside mixture
846  NameListF wPercentage;
847  NameListI wCounter;
848 
849  Int_t nOfElm = mixture->GetNelements();
850  //go through elements
851  for (Int_t idx = 0; idx < nOfElm; idx++) {
852  TGeoElement *myElement = mixture->GetElement(idx);
853 
854  //Get name of the element
855  //NOTE: that for element - GetTitle() returns the "name" tag
856  //and GetName() returns "formula" tag (see createElementN)
857  TString lname = myElement->GetTitle();
858  //_elm suffix is added to avoid problems with same names
859  //for material and element
860  lname = TString::Format("%s_elm", lname.Data());
861 
862  //cumulates percentage, in case 2 elements with same names within one mixture
863  wPercentage[lname] += mixture->GetWmixt()[idx];
864  wCounter[lname]++;
865 
866  //check whether element name is not in list of elements already created
867  if (IsInList(fElementList->fLst, lname)) {
868  continue;
869  }
870 
871  //add element to list of elements and to main <materials> node
872  fElementList->fLst[lname] = kTRUE;
873  XMLNodePointer_t elmNode = CreateElementN(myElement, materials, lname);
874  fGdmlE->AddChild(materials, elmNode);
875  }
876  //loop through asoc array
877  for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
878  if (itr->second > 1) {
879  Info("CreateMixtureN", "WARNING! 2 equal elements in one material. Check: %s element of %s material",
880  itr->first.Data(), mname.Data());
881  }
882  //add fraction child to material with reference to element
883  fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
884  }
885 
886  // Write properties
887  TList const &properties = mixture->GetProperties();
888  if (properties.GetSize()) {
889  TIter next(&properties);
890  TNamed *property;
891  while ((property = (TNamed*)next()))
892  fGdmlE->AddChild(mainN, CreatePropertyN(*property));
893  }
894  // Write CONST properties
895  TList const &const_properties = mixture->GetConstProperties();
896  if (const_properties.GetSize()) {
897  TIter next(&const_properties);
898  TNamed *property;
899  while ((property = (TNamed*)next()))
900  fGdmlE->AddChild(mainN, CreatePropertyN(*property));
901  }
902 
903  return mainN;
904 }
905 
906 ////////////////////////////////////////////////////////////////////////////////
907 /// Creates "material" node for GDML
908 
910 {
911  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
912  fGdmlE->NewAttr(mainN, nullptr, "name", mname);
913  Double_t valZ = material->GetZ();
914  //Z can't be zero in Geant4 so this is workaround for vacuum
915  TString tmpname = mname;
916  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
917  tmpname.ToLower();
918  if (valZ < 1) {
919  if (tmpname == "vacuum") {
920  valZ = 1;
921  } else {
922  if (fgG4Compatibility == kTRUE) {
923  Info("CreateMaterialN", "WARNING! value of Z in %s material can't be < 1 in Geant4, that is why it was changed to 1, please check it manually! ",
924  mname.Data());
925  valZ = 1;
926  } else {
927  Info("CreateMaterialN", "WARNING! value of Z in %s material can't be < 1 in Geant4", mname.Data());
928  }
929  }
930  }
931  fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format(fltPrecision.Data(), valZ)); //material->GetZ()));
932  fGdmlE->AddChild(mainN, CreateDN(material->GetDensity()));
933  fGdmlE->AddChild(mainN, CreateAtomN(material->GetA()));
934  // Create properties if any
935  TList const &properties = material->GetProperties();
936  if (properties.GetSize()) {
937  TIter next(&properties);
938  TNamed *property;
939  while ((property = (TNamed*)next()))
940  fGdmlE->AddChild(mainN, CreatePropertyN(*property));
941  }
942  // Write CONST properties
943  TList const &const_properties = material->GetConstProperties();
944  if (const_properties.GetSize()) {
945  TIter next(&const_properties);
946  TNamed *property;
947  while ((property = (TNamed*)next()))
948  fGdmlE->AddChild(mainN, CreatePropertyN(*property));
949  }
950  return mainN;
951 }
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// Creates "box" node for GDML
955 
957 {
958  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "box", nullptr);
959  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
960  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
961  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
962  if (IsNullParam(geoShape->GetDX(), "DX", lname) ||
963  IsNullParam(geoShape->GetDY(), "DY", lname) ||
964  IsNullParam(geoShape->GetDZ(), "DZ", lname)) {
965  return nullptr;
966  }
967  fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDX()));
968  fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDY()));
969  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDZ()));
970 
971  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
972  return mainN;
973 }
974 
975 ////////////////////////////////////////////////////////////////////////////////
976 /// Creates "paraboloid" node for GDML
977 
979 {
980  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "paraboloid", nullptr);
981  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
982  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
983  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
984  if (IsNullParam(geoShape->GetRhi(), "Rhi", lname) ||
985  IsNullParam(geoShape->GetDz(), "Dz", lname)) {
986  return nullptr;
987  }
988  fGdmlE->NewAttr(mainN, nullptr, "rlo", TString::Format(fltPrecision.Data(), geoShape->GetRlo()));
989  fGdmlE->NewAttr(mainN, nullptr, "rhi", TString::Format(fltPrecision.Data(), geoShape->GetRhi()));
990  fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
991 
992  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
993  return mainN;
994 }
995 
996 ////////////////////////////////////////////////////////////////////////////////
997 /// Creates "sphere" node for GDML
998 
1000 {
1001  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "sphere", nullptr);
1002  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1003  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1004  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1005  if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1006  return nullptr;
1007  }
1008 
1009  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1010  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1011  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1012  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1013  fGdmlE->NewAttr(mainN, nullptr, "starttheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta1()));
1014  fGdmlE->NewAttr(mainN, nullptr, "deltatheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta2() - geoShape->GetTheta1()));
1015 
1016  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1017  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1018  return mainN;
1019 }
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Creates "arb8" node for GDML
1023 
1025 {
1026  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "arb8", nullptr);
1027  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1028  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1029  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1030  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1031  return nullptr;
1032  }
1033 
1034  fGdmlE->NewAttr(mainN, nullptr, "v1x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[0]));
1035  fGdmlE->NewAttr(mainN, nullptr, "v1y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[1]));
1036  fGdmlE->NewAttr(mainN, nullptr, "v2x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[2]));
1037  fGdmlE->NewAttr(mainN, nullptr, "v2y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[3]));
1038  fGdmlE->NewAttr(mainN, nullptr, "v3x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[4]));
1039  fGdmlE->NewAttr(mainN, nullptr, "v3y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[5]));
1040  fGdmlE->NewAttr(mainN, nullptr, "v4x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[6]));
1041  fGdmlE->NewAttr(mainN, nullptr, "v4y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[7]));
1042  fGdmlE->NewAttr(mainN, nullptr, "v5x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[8]));
1043  fGdmlE->NewAttr(mainN, nullptr, "v5y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[9]));
1044  fGdmlE->NewAttr(mainN, nullptr, "v6x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[10]));
1045  fGdmlE->NewAttr(mainN, nullptr, "v6y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[11]));
1046  fGdmlE->NewAttr(mainN, nullptr, "v7x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[12]));
1047  fGdmlE->NewAttr(mainN, nullptr, "v7y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[13]));
1048  fGdmlE->NewAttr(mainN, nullptr, "v8x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[14]));
1049  fGdmlE->NewAttr(mainN, nullptr, "v8y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[15]));
1050  fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1051 
1052  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1053  return mainN;
1054 }
1055 
1056 ////////////////////////////////////////////////////////////////////////////////
1057 /// Creates "cone" node for GDML from TGeoConeSeg object
1058 
1060 {
1061  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1062  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1063  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1064  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1065  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1066  return nullptr;
1067  }
1068 
1069  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1070  fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1071  fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1072  fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1073  fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1074  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1075  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1076 
1077  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1078  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1079  return mainN;
1080 }
1081 
1082 ////////////////////////////////////////////////////////////////////////////////
1083 /// Creates "cone" node for GDML from TGeoCone object
1084 
1086 {
1087  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1088  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1089  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1090  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1091  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1092  return nullptr;
1093  }
1094 
1095  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1096  fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1097  fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1098  fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1099  fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1100  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1101  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1102 
1103  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1104  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1105  return mainN;
1106 }
1107 
1108 ////////////////////////////////////////////////////////////////////////////////
1109 /// Creates "para" node for GDML
1110 
1112 {
1113  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "para", nullptr);
1114  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1115  fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1116 
1117  fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetX()));
1118  fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetY()));
1119  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetZ()));
1120  fGdmlE->NewAttr(mainN, nullptr, "alpha", TString::Format(fltPrecision.Data(), geoShape->GetAlpha()));
1121  fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1122  fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1123 
1124  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1125  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1126  return mainN;
1127 }
1128 
1129 ////////////////////////////////////////////////////////////////////////////////
1130 /// Creates "trap" node for GDML
1131 
1133 {
1134  XMLNodePointer_t mainN;
1135  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1136 
1137  //if one base equals 0 create Arb8 instead of trap
1138  if ((geoShape->GetBl1() == 0 || geoShape->GetTl1() == 0 || geoShape->GetH1() == 0) ||
1139  (geoShape->GetBl2() == 0 || geoShape->GetTl2() == 0 || geoShape->GetH2() == 0)) {
1140  mainN = CreateArb8N(geoShape);
1141  return mainN;
1142  }
1143 
1144  //if is twisted then create arb8
1145  if (geoShape->IsTwisted()) {
1146  mainN = CreateArb8N((TGeoArb8 *) geoShape);
1147  return mainN;
1148  }
1149 
1150  mainN = fGdmlE->NewChild(nullptr, nullptr, "trap", nullptr);
1151  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1152  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1153  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1154  return nullptr;
1155  }
1156 
1157  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1158  fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1159  fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1160  fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1161  fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1162  fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1163  fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1164  fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1165  fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1166 
1167  fGdmlE->NewAttr(mainN, nullptr, "alpha1", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1168  fGdmlE->NewAttr(mainN, nullptr, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1169 
1170  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1171  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1172  return mainN;
1173 }
1174 
1175 ////////////////////////////////////////////////////////////////////////////////
1176 /// Creates "twistedtrap" node for GDML
1177 
1179 {
1180  XMLNodePointer_t mainN;
1181  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1182 
1183  //if one base equals 0 create Arb8 instead of twisted trap
1184  if ((geoShape->GetBl1() == 0 && geoShape->GetTl1() == 0 && geoShape->GetH1() == 0) ||
1185  (geoShape->GetBl2() == 0 && geoShape->GetTl2() == 0 && geoShape->GetH2() == 0)) {
1186  mainN = CreateArb8N((TGeoArb8 *) geoShape);
1187  return mainN;
1188  }
1189 
1190  //if is twisted then create arb8
1191  if (geoShape->IsTwisted()) {
1192  mainN = CreateArb8N((TGeoArb8 *) geoShape);
1193  return mainN;
1194  }
1195 
1196  //if parameter twistAngle (PhiTwist) equals zero create trap node
1197  if (geoShape->GetTwistAngle() == 0) {
1198  mainN = CreateTrapN((TGeoTrap *) geoShape);
1199  return mainN;
1200  }
1201 
1202  mainN = fGdmlE->NewChild(nullptr, nullptr, "twistedtrap", nullptr);
1203  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1204  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1205  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1206  return nullptr;
1207  }
1208 
1209  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1210  fGdmlE->NewAttr(mainN, nullptr, "Theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1211  fGdmlE->NewAttr(mainN, nullptr, "Phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1212  fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1213  fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1214  fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1215  fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1216  fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1217  fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1218 
1219  fGdmlE->NewAttr(mainN, nullptr, "Alph", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1220 
1221  //check if alpha1 equals to alpha2 (converting to string - to avoid problems with floats)
1222  if (TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()) != TString::Format(fltPrecision.Data(), geoShape->GetAlpha2())) {
1223  Info("CreateTwistedTrapN",
1224  "ERROR! Object %s is not exported correctly because parameter Alpha2 is not declared in GDML schema",
1225  lname.Data());
1226  }
1227  //fGdmlE->NewAttr(mainN,0, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1228  fGdmlE->NewAttr(mainN, nullptr, "PhiTwist", TString::Format(fltPrecision.Data(), geoShape->GetTwistAngle()));
1229 
1230  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1231  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1232  return mainN;
1233 }
1234 
1235 ////////////////////////////////////////////////////////////////////////////////
1236 /// Creates "trd" node for GDML from object TGeoTrd1
1237 
1239 {
1240  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1241  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1242  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1243  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1244  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1245  return nullptr;
1246  }
1247 
1248  fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1249  fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1250  fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1251  fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1252  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1253 
1254  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1255  return mainN;
1256 }
1257 
1258 ////////////////////////////////////////////////////////////////////////////////
1259 /// Creates "trd" node for GDML from object TGeoTrd2
1260 
1262 {
1263  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1264  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1265  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1266  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1267  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1268  return nullptr;
1269  }
1270 
1271  fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1272  fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1273  fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy1()));
1274  fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy2()));
1275  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1276 
1277  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1278  return mainN;
1279 }
1280 
1281 ////////////////////////////////////////////////////////////////////////////////
1282 /// Creates "tube" node for GDML from object TGeoTubeSeg
1283 
1285 {
1286  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1287  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1288  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1289  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1290  if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1291  IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1292  return nullptr;
1293  }
1294 
1295  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1296  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1297  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1298  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1299  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1300 
1301  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1302  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1303  return mainN;
1304 }
1305 
1306 ////////////////////////////////////////////////////////////////////////////////
1307 /// Creates "cutTube" node for GDML
1308 
1310 {
1311  XMLNodePointer_t mainN;
1312  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1313 
1314  mainN = fGdmlE->NewChild(nullptr, nullptr, "cutTube", nullptr);
1315  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1316  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1317  if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1318  IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1319  return nullptr;
1320  }
1321  //This is not needed, because cutTube is already supported by Geant4 9.5
1322  if (fgG4Compatibility == kTRUE && kFALSE) {
1323  TGeoShape * fakeCtub = CreateFakeCtub(geoShape);
1324  mainN = ChooseObject(fakeCtub);
1325 
1326  //register name for cuttube shape (so it will be found during volume export)
1327  lname = fNameList->fLst[TString::Format("%p", fakeCtub)];
1328  fNameList->fLst[TString::Format("%p", geoShape)] = lname;
1329  Info("CreateCutTubeN", "WARNING! %s - CutTube was replaced by intersection of TGeoTubSeg and two TGeoBBoxes",
1330  lname.Data());
1331  return mainN;
1332  }
1333  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1334  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1335  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1336  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1337  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1338  fGdmlE->NewAttr(mainN, nullptr, "lowX", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[0]));
1339  fGdmlE->NewAttr(mainN, nullptr, "lowY", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[1]));
1340  fGdmlE->NewAttr(mainN, nullptr, "lowZ", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[2]));
1341  fGdmlE->NewAttr(mainN, nullptr, "highX", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[0]));
1342  fGdmlE->NewAttr(mainN, nullptr, "highY", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[1]));
1343  fGdmlE->NewAttr(mainN, nullptr, "highZ", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[2]));
1344 
1345  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1346  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1347 
1348  return mainN;
1349 }
1350 
1351 ////////////////////////////////////////////////////////////////////////////////
1352 /// Creates "tube" node for GDML from object TGeoTube
1353 
1355 {
1356  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1357  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1358  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1359  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1360  if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1361  IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1362  return nullptr;
1363  }
1364 
1365  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1366  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1367  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1368  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1369  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1370 
1371  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1372  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1373  return mainN;
1374 }
1375 
1376 ////////////////////////////////////////////////////////////////////////////////
1377 /// Creates "zplane" node for GDML
1378 
1380 {
1381  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "zplane", nullptr);
1382  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1383 
1384  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), z));
1385  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), rmin));
1386  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), rmax));
1387 
1388  return mainN;
1389 }
1390 
1391 ////////////////////////////////////////////////////////////////////////////////
1392 /// Creates "polycone" node for GDML
1393 
1395 {
1396  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polycone", nullptr);
1397  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1398  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1399  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1400 
1401  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1402  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1403 
1404  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1405  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1406  Int_t nZPlns = geoShape->GetNz();
1407  for (Int_t it = 0; it < nZPlns; it++) {
1408  //add zplane child node
1409  fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1410  //compare actual plane and next plane
1411  if ((it < nZPlns - 1) && (geoShape->GetZ(it) == geoShape->GetZ(it + 1))) {
1412  //rmin of actual is greater then rmax of next one
1413  // | |rmax next
1414  // __ ...| |... __ < rmin actual
1415  // | | | |
1416  if (geoShape->GetRmin(it) > geoShape->GetRmax(it + 1)) {
1417  //adding plane from rmax next to rmin actual at the same z position
1418  if (fgG4Compatibility == kTRUE) {
1419  fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it + 1), geoShape->GetRmin(it)));
1420  Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4", lname.Data());
1421  } else {
1422  Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4", lname.Data());
1423  }
1424 
1425  }
1426  //rmin of next is greater then rmax of actual
1427  // | | | |
1428  // | |...___...| | rmin next
1429  // | | > rmax act
1430  if (geoShape->GetRmin(it + 1) > geoShape->GetRmax(it)) {
1431  //adding plane from rmax act to rmin next at the same z position
1432  if (fgG4Compatibility == kTRUE) {
1433  fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it), geoShape->GetRmin(it + 1)));
1434  Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4", lname.Data());
1435  } else {
1436  Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4", lname.Data());
1437  }
1438  }
1439  }
1440  }
1441  return mainN;
1442 }
1443 
1444 ////////////////////////////////////////////////////////////////////////////////
1445 /// Creates "torus" node for GDML
1446 
1448 {
1449  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "torus", nullptr);
1450  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1451  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1452  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1453  if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1454  return nullptr;
1455  }
1456 
1457  fGdmlE->NewAttr(mainN, nullptr, "rtor", TString::Format(fltPrecision.Data(), geoShape->GetR()));
1458  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1459  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1460  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1461  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1462 
1463  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1464  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1465 
1466  return mainN;
1467 }
1468 
1469 ////////////////////////////////////////////////////////////////////////////////
1470 /// Creates "polyhedra" node for GDML
1471 
1473 {
1474  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polyhedra", nullptr);
1475  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1476  fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1477 
1478  fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1479  fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1480  fGdmlE->NewAttr(mainN, nullptr, "numsides", TString::Format("%i", geoShape->GetNedges()));
1481 
1482  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1483  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1484  for (Int_t it = 0; it < geoShape->GetNz(); it++) {
1485  //add zplane child node
1486  fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1487  }
1488  return mainN;
1489 }
1490 
1491 ////////////////////////////////////////////////////////////////////////////////
1492 /// Creates "eltube" node for GDML
1493 
1495 {
1496  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "eltube", nullptr);
1497  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1498  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1499  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1500  if (IsNullParam(geoShape->GetA(), "A", lname) ||
1501  IsNullParam(geoShape->GetB(), "B", lname) ||
1502  IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1503  return nullptr;
1504  }
1505 
1506  fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(fltPrecision.Data(), geoShape->GetA()));
1507  fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(fltPrecision.Data(), geoShape->GetB()));
1508  fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1509 
1510  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1511 
1512  return mainN;
1513 }
1514 
1515 ////////////////////////////////////////////////////////////////////////////////
1516 /// Creates "hype" node for GDML
1517 
1519 {
1520  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "hype", nullptr);
1521  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1522  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1523  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1524  if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1525  return nullptr;
1526  }
1527 
1528 
1529  fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1530  fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1531  fGdmlE->NewAttr(mainN, nullptr, "inst", TString::Format(fltPrecision.Data(), geoShape->GetStIn()));
1532  fGdmlE->NewAttr(mainN, nullptr, "outst", TString::Format(fltPrecision.Data(), geoShape->GetStOut()));
1533  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1534 
1535  fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1536  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1537 
1538  return mainN;
1539 }
1540 
1541 ////////////////////////////////////////////////////////////////////////////////
1542 /// Creates "xtru" node for GDML
1543 
1545 {
1546  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "xtru", nullptr);
1547  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1548  TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1549  fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1550 
1551  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1552  XMLNodePointer_t childN;
1553  Int_t vertNum = geoShape->GetNvert();
1554  Int_t secNum = geoShape->GetNz();
1555  if (vertNum < 3 || secNum < 2) {
1556  Info("CreateXtrusionN", "ERROR! TGeoXtru %s has only %i vertices and %i sections. It was not exported",
1557  lname.Data(), vertNum, secNum);
1558  mainN = nullptr;
1559  return mainN;
1560  }
1561  for (Int_t it = 0; it < vertNum; it++) {
1562  //add twoDimVertex child node
1563  childN = fGdmlE->NewChild(nullptr, nullptr, "twoDimVertex", nullptr);
1564  fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), geoShape->GetX(it)));
1565  fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), geoShape->GetY(it)));
1566  fGdmlE->AddChild(mainN, childN);
1567  }
1568  for (Int_t it = 0; it < secNum; it++) {
1569  //add section child node
1570  childN = fGdmlE->NewChild(nullptr, nullptr, "section", nullptr);
1571  fGdmlE->NewAttr(childN, nullptr, "zOrder", TString::Format("%i", it));
1572  fGdmlE->NewAttr(childN, nullptr, "zPosition", TString::Format(fltPrecision.Data(), geoShape->GetZ(it)));
1573  fGdmlE->NewAttr(childN, nullptr, "xOffset", TString::Format(fltPrecision.Data(), geoShape->GetXOffset(it)));
1574  fGdmlE->NewAttr(childN, nullptr, "yOffset", TString::Format(fltPrecision.Data(), geoShape->GetYOffset(it)));
1575  fGdmlE->NewAttr(childN, nullptr, "scalingFactor", TString::Format(fltPrecision.Data(), geoShape->GetScale(it)));
1576  fGdmlE->AddChild(mainN, childN);
1577  }
1578  return mainN;
1579 }
1580 
1581 ////////////////////////////////////////////////////////////////////////////////
1582 /// Creates "ellipsoid" node for GDML
1583 /// this is a special case, because ellipsoid is not defined in ROOT
1584 /// so when intersection of scaled sphere and TGeoBBox is found,
1585 /// it is considered as an ellipsoid
1586 
1588 {
1589  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "ellipsoid", nullptr);
1590  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1591  TGeoScaledShape *leftS = (TGeoScaledShape *)geoShape->GetBoolNode()->GetLeftShape(); //ScaledShape
1592  TGeoBBox *rightS = (TGeoBBox *)geoShape->GetBoolNode()->GetRightShape(); //BBox
1593 
1594 
1595  fGdmlE->NewAttr(mainN, nullptr, "name", elName.Data());
1596  Double_t sx = leftS->GetScale()->GetScale()[0];
1597  Double_t sy = leftS->GetScale()->GetScale()[1];
1598  Double_t radius = ((TGeoSphere *) leftS->GetShape())->GetRmax();
1599 
1600  Double_t ax, by, cz;
1601  cz = radius;
1602  ax = sx * radius;
1603  by = sy * radius;
1604 
1605  Double_t dz = rightS->GetDZ();
1606  Double_t zorig = rightS->GetOrigin()[2];
1607  Double_t zcut2 = dz + zorig;
1608  Double_t zcut1 = 2 * zorig - zcut2;
1609 
1610 
1611  fGdmlE->NewAttr(mainN, nullptr, "ax", TString::Format(fltPrecision.Data(), ax));
1612  fGdmlE->NewAttr(mainN, nullptr, "by", TString::Format(fltPrecision.Data(), by));
1613  fGdmlE->NewAttr(mainN, nullptr, "cz", TString::Format(fltPrecision.Data(), cz));
1614  fGdmlE->NewAttr(mainN, nullptr, "zcut1", TString::Format(fltPrecision.Data(), zcut1));
1615  fGdmlE->NewAttr(mainN, nullptr, "zcut2", TString::Format(fltPrecision.Data(), zcut2));
1616  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1617 
1618  return mainN;
1619 }
1620 
1621 ////////////////////////////////////////////////////////////////////////////////
1622 /// Creates "elcone" (elliptical cone) node for GDML
1623 /// this is a special case, because elliptical cone is not defined in ROOT
1624 /// so when scaled cone is found, it is considered as a elliptical cone
1625 
1627 {
1628  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "elcone", nullptr);
1629  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1630  fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1631  Double_t zcut = ((TGeoCone *) geoShape->GetShape())->GetDz();
1632  Double_t rx1 = ((TGeoCone *) geoShape->GetShape())->GetRmax1();
1633  Double_t rx2 = ((TGeoCone *) geoShape->GetShape())->GetRmax2();
1634  Double_t zmax = zcut * ((rx1 + rx2) / (rx1 - rx2));
1635  Double_t z = zcut + zmax;
1636 
1637  Double_t sy = geoShape->GetScale()->GetScale()[1];
1638  Double_t ry1 = sy * rx1;
1639 
1640  std::string format(TString::Format("%s/%s", fltPrecision.Data(), fltPrecision.Data()).Data());
1641  fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(format.c_str(), rx1, z));
1642  fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(format.c_str(), ry1, z));
1643  fGdmlE->NewAttr(mainN, nullptr, "zmax", TString::Format(fltPrecision.Data(), zmax));
1644  fGdmlE->NewAttr(mainN, nullptr, "zcut", TString::Format(fltPrecision.Data(), zcut));
1645  fGdmlE->NewAttr(mainN, nullptr, "lunit", "cm");
1646 
1647  return mainN;
1648 }
1649 
1650 ////////////////////////////////////////////////////////////////////////////////
1651 /// Creates "tessellated" (tessellated shape) node for GDML
1652 
1654 {
1655  // add all vertices to the define section
1656  TString genname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1657  for (int i = 0; i < geoShape->GetNvertices(); ++i) {
1658  auto vertex = geoShape->GetVertex(i);
1659  TString posName = TString::Format("%s_%d", genname.Data(), i);
1660  Xyz nodPos;
1661  nodPos.x = vertex[0];
1662  nodPos.y = vertex[1];
1663  nodPos.z = vertex[2];
1664  auto childN = CreatePositionN(posName.Data(), nodPos);
1665  fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
1666  }
1667  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tessellated", nullptr);
1668  fGdmlE->NewAttr(mainN, nullptr, "name", genname.Data());
1669 
1670  XMLNodePointer_t childN;
1671  for (Int_t it = 0; it < geoShape->GetNfacets(); it++) {
1672  //add section child node
1673  auto facet = geoShape->GetFacet(it);
1674  bool triangular = facet.GetNvert() == 3;
1675  TString ntype = (triangular) ? "triangular" : "quadrangular";
1676  childN = fGdmlE->NewChild(nullptr, nullptr, ntype.Data(), nullptr);
1677  fGdmlE->NewAttr(childN, nullptr, "vertex1", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(0)));
1678  fGdmlE->NewAttr(childN, nullptr, "vertex2", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(1)));
1679  fGdmlE->NewAttr(childN, nullptr, "vertex3", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(2)));
1680  if (!triangular)
1681  fGdmlE->NewAttr(childN, nullptr, "vertex4", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(3)));
1682  fGdmlE->NewAttr(childN, nullptr, "type", "ABSOLUTE");
1683  fGdmlE->AddChild(mainN, childN);
1684  }
1685  return mainN;
1686 }
1687 
1688 ////////////////////////////////////////////////////////////////////////////////
1689 /// Creates common part of union intersection and subtraction nodes
1690 
1692 {
1693  XMLNodePointer_t mainN, ndR, ndL, childN;
1694  TString nodeName = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1695  TString lboolType;
1696  TGeoBoolNode::EGeoBoolType boolType = geoShape->GetBoolNode()->GetBooleanOperator();
1697  switch (boolType) {
1699  lboolType = "union";
1700  break;
1702  lboolType = "subtraction";
1703  break;
1705  lboolType = "intersection";
1706  break;
1707  }
1708 
1710  const Double_t *ltr = geoShape->GetBoolNode()->GetLeftMatrix()->GetTranslation();
1712  const Double_t *rtr = geoShape->GetBoolNode()->GetRightMatrix()->GetTranslation();
1713 
1714  //specific case!
1715  //Ellipsoid tag preparing
1716  //if left == TGeoScaledShape AND right == TGeoBBox
1717  // AND if TGeoScaledShape->GetShape == TGeoSphere
1718  TGeoShape *leftS = geoShape->GetBoolNode()->GetLeftShape();
1719  TGeoShape *rightS = geoShape->GetBoolNode()->GetRightShape();
1720  if (strcmp(leftS->ClassName(), "TGeoScaledShape") == 0 &&
1721  strcmp(rightS->ClassName(), "TGeoBBox") == 0) {
1722  if (strcmp(((TGeoScaledShape *)leftS)->GetShape()->ClassName(), "TGeoSphere") == 0) {
1723  if (lboolType == "intersection") {
1724  mainN = CreateEllipsoidN(geoShape, nodeName);
1725  return mainN;
1726  }
1727  }
1728  }
1729 
1730  Xyz translL, translR;
1731  //translation
1732  translL.x = ltr[0];
1733  translL.y = ltr[1];
1734  translL.z = ltr[2];
1735  translR.x = rtr[0];
1736  translR.y = rtr[1];
1737  translR.z = rtr[2];
1738 
1739  //left and right nodes are created here also their names are created
1740  ndL = ChooseObject(geoShape->GetBoolNode()->GetLeftShape());
1741  ndR = ChooseObject(geoShape->GetBoolNode()->GetRightShape());
1742 
1743  //retrieve left and right node names by their pointer to make reference
1744  TString lname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetLeftShape())];
1745  TString rname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetRightShape())];
1746 
1747  //left and right nodes appended to main structure of nodes (if they are not already there)
1748  if (ndL != nullptr) {
1749  fGdmlE->AddChild(fSolidsNode, ndL);
1750  fSolCnt++;
1751  } else {
1752  if (lname.Contains("missing_") || lname == "") {
1753  Info("CreateCommonBoolN", "ERROR! Left node is NULL - Boolean Shape will be skipped");
1754  return nullptr;
1755  }
1756  }
1757  if (ndR != nullptr) {
1758  fGdmlE->AddChild(fSolidsNode, ndR);
1759  fSolCnt++;
1760  } else {
1761  if (rname.Contains("missing_") || rname == "") {
1762  Info("CreateCommonBoolN", "ERROR! Right node is NULL - Boolean Shape will be skipped");
1763  return nullptr;
1764  }
1765  }
1766 
1767  //create union node and its child nodes (or intersection or subtraction)
1768  /* <union name="...">
1769  * <first ref="left name" />
1770  * <second ref="right name" />
1771  * <firstposition .../>
1772  * <firstrotation .../>
1773  * <position .../>
1774  * <rotation .../>
1775  * </union>
1776  */
1777  mainN = fGdmlE->NewChild(nullptr, nullptr, lboolType.Data(), nullptr);
1778  fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1779 
1780  //<first> (left)
1781  childN = fGdmlE->NewChild(nullptr, nullptr, "first", nullptr);
1782  fGdmlE->NewAttr(childN, nullptr, "ref", lname);
1783  fGdmlE->AddChild(mainN, childN);
1784 
1785  //<second> (right)
1786  childN = fGdmlE->NewChild(nullptr, nullptr, "second", nullptr);
1787  fGdmlE->NewAttr(childN, nullptr, "ref", rname);
1788  fGdmlE->AddChild(mainN, childN);
1789 
1790  //<firstposition> (left)
1791  if ((translL.x != 0.0) || (translL.y != 0.0) || (translL.z != 0.0)) {
1792  childN = CreatePositionN((nodeName + lname + "pos").Data(), translL, "firstposition");
1793  fGdmlE->AddChild(mainN, childN);
1794  }
1795  //<firstrotation> (left)
1796  if ((lrot.x != 0.0) || (lrot.y != 0.0) || (lrot.z != 0.0)) {
1797  childN = CreateRotationN((nodeName + lname + "rot").Data(), lrot, "firstrotation");
1798  fGdmlE->AddChild(mainN, childN);
1799  }
1800  //<position> (right)
1801  if ((translR.x != 0.0) || (translR.y != 0.0) || (translR.z != 0.0)) {
1802  childN = CreatePositionN((nodeName + rname + "pos").Data(), translR, "position");
1803  fGdmlE->AddChild(mainN, childN);
1804  }
1805  //<rotation> (right)
1806  if ((rrot.x != 0.0) || (rrot.y != 0.0) || (rrot.z != 0.0)) {
1807  childN = CreateRotationN((nodeName + rname + "rot").Data(), rrot, "rotation");
1808  fGdmlE->AddChild(mainN, childN);
1809  }
1810 
1811  return mainN;
1812 }
1813 
1814 ////////////////////////////////////////////////////////////////////////////////
1815 /// Creates "opticalsurface" node for GDML
1816 
1818 {
1819  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "opticalsurface", nullptr);
1820  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1821  fGdmlE->NewAttr(mainN, nullptr, "name", geoSurf->GetName());
1822  fGdmlE->NewAttr(mainN, nullptr, "model", TGeoOpticalSurface::ModelToString(geoSurf->GetModel()));
1823  fGdmlE->NewAttr(mainN, nullptr, "finish", TGeoOpticalSurface::FinishToString(geoSurf->GetFinish()));
1824  fGdmlE->NewAttr(mainN, nullptr, "type", TGeoOpticalSurface::TypeToString(geoSurf->GetType()));
1825  fGdmlE->NewAttr(mainN, nullptr, "value", TString::Format(fltPrecision.Data(), geoSurf->GetValue()));
1826 
1827  // Write properties
1828  TList const &properties = geoSurf->GetProperties();
1829  if (properties.GetSize()) {
1830  TIter next(&properties);
1831  TNamed *property;
1832  while ((property = (TNamed*)next()))
1833  fGdmlE->AddChild(mainN, CreatePropertyN(*property));
1834  }
1835  return mainN;
1836 }
1837 
1838 ////////////////////////////////////////////////////////////////////////////////
1839 /// Creates "skinsurface" node for GDML
1840 
1842 {
1843  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "skinsurface", nullptr);
1844  fGdmlE->NewAttr(mainN, nullptr, "name", geoSurf->GetName());
1845  fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", geoSurf->GetTitle());
1846  // Cretate the logical volume reference node
1847  auto childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
1848  fGdmlE->NewAttr(childN, nullptr, "ref", geoSurf->GetVolume()->GetName());
1849  fGdmlE->AddChild(mainN, childN);
1850  return mainN;
1851 }
1852 
1853 ////////////////////////////////////////////////////////////////////////////////
1854 /// Creates "bordersurface" node for GDML
1855 
1857 {
1858  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "bordersurface", nullptr);
1859  fGdmlE->NewAttr(mainN, nullptr, "name", geoSurf->GetName());
1860  fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", geoSurf->GetTitle());
1861  // Cretate the logical volume reference node
1862  auto childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
1863  fGdmlE->NewAttr(childN, nullptr, "ref", geoSurf->GetNode1()->GetName());
1864  fGdmlE->NewAttr(childN, nullptr, "ref", geoSurf->GetNode2()->GetName());
1865  fGdmlE->AddChild(mainN, childN);
1866  return mainN;
1867 }
1868 
1869 ////////////////////////////////////////////////////////////////////////////////
1870 /// Creates "position" kind of node for GDML
1871 
1872 XMLNodePointer_t TGDMLWrite::CreatePositionN(const char * name, Xyz position, const char * type, const char * unit)
1873 {
1874  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
1875  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1876  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1877  fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), position.x));
1878  fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), position.y));
1879  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), position.z));
1880  fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
1881  return mainN;
1882 }
1883 
1884 ////////////////////////////////////////////////////////////////////////////////
1885 /// Creates "rotation" kind of node for GDML
1886 
1887 XMLNodePointer_t TGDMLWrite::CreateRotationN(const char * name, Xyz rotation, const char * type, const char * unit)
1888 {
1889  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
1890  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1891  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1892  fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), rotation.x));
1893  fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), rotation.y));
1894  fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), rotation.z));
1895  fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
1896  return mainN;
1897 }
1898 
1899 ////////////////////////////////////////////////////////////////////////////////
1900 /// Creates "matrix" kind of node for GDML
1901 
1903 {
1904  std::stringstream vals;
1905  size_t cols = matrix->GetCols();
1906  size_t rows = matrix->GetRows();
1907  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
1908  fGdmlE->NewAttr(mainN, nullptr, "name", matrix->GetName());
1909  fGdmlE->NewAttr(mainN, nullptr, "coldim", TString::Format("%zu", cols));
1910  for(size_t i=0; i<rows; ++i) {
1911  for(size_t j=0; j<cols; ++j) {
1912  vals << matrix->Get(i,j);
1913  if ( j < cols-1 ) vals << ' ';
1914  }
1915  if ( i < rows-1 ) vals << '\n';
1916  }
1917  fGdmlE->NewAttr(mainN, nullptr, "values", vals.str().c_str());
1918  return mainN;
1919 }
1920 
1921 ////////////////////////////////////////////////////////////////////////////////
1922 /// Creates "constant" kind of node for GDML
1923 
1925 {
1926  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "constant", nullptr);
1927  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1928  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1929  fGdmlE->NewAttr(mainN, nullptr, "value", TString::Format(fltPrecision.Data(), value));
1930  return mainN;
1931 }
1932 
1933 ////////////////////////////////////////////////////////////////////////////////
1934 /// Creates "setup" node for GDML
1935 
1936 XMLNodePointer_t TGDMLWrite::CreateSetupN(const char * topVolName, const char * name, const char * version)
1937 {
1938  XMLNodePointer_t setupN = fGdmlE->NewChild(nullptr, nullptr, "setup", nullptr);
1939  fGdmlE->NewAttr(setupN, nullptr, "name", name);
1940  fGdmlE->NewAttr(setupN, nullptr, "version", version);
1941  XMLNodePointer_t fworldN = fGdmlE->NewChild(setupN, nullptr, "world", nullptr);
1942  fGdmlE->NewAttr(fworldN, nullptr, "ref", topVolName);
1943  return setupN;
1944 }
1945 
1946 ////////////////////////////////////////////////////////////////////////////////
1947 /// Creates "volume" node for GDML
1948 
1949 XMLNodePointer_t TGDMLWrite::StartVolumeN(const char * name, const char * solid, const char * material)
1950 {
1951  XMLNodePointer_t childN;
1952  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "volume", nullptr);
1953  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1954 
1955  childN = fGdmlE->NewChild(nullptr, nullptr, "materialref", nullptr);
1956  fGdmlE->NewAttr(childN, nullptr, "ref", material);
1957  fGdmlE->AddChild(mainN, childN);
1958 
1959  childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
1960  fGdmlE->NewAttr(childN, nullptr, "ref", solid);
1961  fGdmlE->AddChild(mainN, childN);
1962 
1963  return mainN;
1964 }
1965 
1966 ////////////////////////////////////////////////////////////////////////////////
1967 /// Creates "assembly" node for GDML
1968 
1970 {
1971  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "assembly", nullptr);
1972  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1973 
1974  return mainN;
1975 }
1976 
1977 ////////////////////////////////////////////////////////////////////////////////
1978 /// Creates "physvol" node for GDML
1979 
1980 XMLNodePointer_t TGDMLWrite::CreatePhysVolN(const char *name, Int_t copyno, const char * volref, const char * posref, const char * rotref, XMLNodePointer_t scaleN)
1981 {
1982  fPhysVolCnt++;
1983  XMLNodePointer_t childN;
1984  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "physvol", nullptr);
1985  fGdmlE->NewAttr(mainN, nullptr, "name", name);
1986  fGdmlE->NewAttr(mainN, nullptr, "copynumber", TString::Format("%d",copyno));
1987 
1988  childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
1989  fGdmlE->NewAttr(childN, nullptr, "ref", volref);
1990  fGdmlE->AddChild(mainN, childN);
1991 
1992  childN = fGdmlE->NewChild(nullptr, nullptr, "positionref", nullptr);
1993  fGdmlE->NewAttr(childN, nullptr, "ref", posref);
1994  fGdmlE->AddChild(mainN, childN);
1995 
1996  //if is not empty string add this node
1997  if (strcmp(rotref, "") != 0) {
1998  childN = fGdmlE->NewChild(nullptr, nullptr, "rotationref", nullptr);
1999  fGdmlE->NewAttr(childN, nullptr, "ref", rotref);
2000  fGdmlE->AddChild(mainN, childN);
2001  }
2002  if (scaleN != nullptr) {
2003  fGdmlE->AddChild(mainN, scaleN);
2004  }
2005 
2006  return mainN;
2007 }
2008 
2009 ////////////////////////////////////////////////////////////////////////////////
2010 /// Creates "divisionvol" node for GDML
2011 
2012 XMLNodePointer_t TGDMLWrite::CreateDivisionN(Double_t offset, Double_t width, Int_t number, const char * axis, const char * unit, const char * volref)
2013 {
2014  XMLNodePointer_t childN = 0;
2015  XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "divisionvol", nullptr);
2016  fGdmlE->NewAttr(mainN, nullptr, "axis", axis);
2017  fGdmlE->NewAttr(mainN, nullptr, "number", TString::Format("%i", number));
2018  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2019  if (fgG4Compatibility == kTRUE) {
2020  //if eg. full length is 20 and width * number = 20,0001 problem in geant4
2021  //unit is either in cm or degrees nothing else
2022  width = (floor(width * 1E4)) * 1E-4;
2023  if ((offset >= 0.) && (strcmp(axis, "kPhi") == 0)) {
2024  Int_t offsetI = (Int_t) offset;
2025  Double_t decimals = offset - offsetI;
2026  //put to range from 0 to 360 add decimals and then put to range 0 -> -360
2027  offset = (offsetI % 360) + decimals - 360;
2028  }
2029  }
2030  fGdmlE->NewAttr(mainN, nullptr, "width", TString::Format(fltPrecision.Data(), width));
2031 
2032  fGdmlE->NewAttr(mainN, nullptr, "offset", TString::Format(fltPrecision.Data(), offset));
2033  fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2034  if (strcmp(volref, "") != 0) {
2035  childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2036  fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2037  }
2038  fGdmlE->AddChild(mainN, childN);
2039 
2040 
2041  return mainN;
2042 }
2043 
2044 ////////////////////////////////////////////////////////////////////////////////
2045 /// Chooses the object and method that should be used for processing object
2046 
2048 {
2049  const char * clsname = geoShape->ClassName();
2050  XMLNodePointer_t solidN;
2051 
2052  if (CanProcess((TObject *)geoShape) == kFALSE) {
2053  return nullptr;
2054  }
2055 
2056  //process different shapes
2057  if (strcmp(clsname, "TGeoBBox") == 0) {
2058  solidN = CreateBoxN((TGeoBBox*) geoShape);
2059  } else if (strcmp(clsname, "TGeoParaboloid") == 0) {
2060  solidN = CreateParaboloidN((TGeoParaboloid*) geoShape);
2061  } else if (strcmp(clsname, "TGeoSphere") == 0) {
2062  solidN = CreateSphereN((TGeoSphere*) geoShape);
2063  } else if (strcmp(clsname, "TGeoArb8") == 0) {
2064  solidN = CreateArb8N((TGeoArb8*) geoShape);
2065  } else if (strcmp(clsname, "TGeoConeSeg") == 0) {
2066  solidN = CreateConeN((TGeoConeSeg*) geoShape);
2067  } else if (strcmp(clsname, "TGeoCone") == 0) {
2068  solidN = CreateConeN((TGeoCone*) geoShape);
2069  } else if (strcmp(clsname, "TGeoPara") == 0) {
2070  solidN = CreateParaN((TGeoPara*) geoShape);
2071  } else if (strcmp(clsname, "TGeoTrap") == 0) {
2072  solidN = CreateTrapN((TGeoTrap*) geoShape);
2073  } else if (strcmp(clsname, "TGeoGtra") == 0) {
2074  solidN = CreateTwistedTrapN((TGeoGtra*) geoShape);
2075  } else if (strcmp(clsname, "TGeoTrd1") == 0) {
2076  solidN = CreateTrdN((TGeoTrd1*) geoShape);
2077  } else if (strcmp(clsname, "TGeoTrd2") == 0) {
2078  solidN = CreateTrdN((TGeoTrd2*) geoShape);
2079  } else if (strcmp(clsname, "TGeoTubeSeg") == 0) {
2080  solidN = CreateTubeN((TGeoTubeSeg*) geoShape);
2081  } else if (strcmp(clsname, "TGeoCtub") == 0) {
2082  solidN = CreateCutTubeN((TGeoCtub*) geoShape);
2083  } else if (strcmp(clsname, "TGeoTube") == 0) {
2084  solidN = CreateTubeN((TGeoTube*) geoShape);
2085  } else if (strcmp(clsname, "TGeoPcon") == 0) {
2086  solidN = CreatePolyconeN((TGeoPcon*) geoShape);
2087  } else if (strcmp(clsname, "TGeoTorus") == 0) {
2088  solidN = CreateTorusN((TGeoTorus*) geoShape);
2089  } else if (strcmp(clsname, "TGeoPgon") == 0) {
2090  solidN = CreatePolyhedraN((TGeoPgon*) geoShape);
2091  } else if (strcmp(clsname, "TGeoEltu") == 0) {
2092  solidN = CreateEltubeN((TGeoEltu*) geoShape);
2093  } else if (strcmp(clsname, "TGeoHype") == 0) {
2094  solidN = CreateHypeN((TGeoHype*) geoShape);
2095  } else if (strcmp(clsname, "TGeoXtru") == 0) {
2096  solidN = CreateXtrusionN((TGeoXtru*) geoShape);
2097  } else if (strcmp(clsname, "TGeoTessellated") == 0) {
2098  solidN = CreateTessellatedN((TGeoTessellated*) geoShape);
2099  } else if (strcmp(clsname, "TGeoScaledShape") == 0) {
2100  TGeoScaledShape * geoscale = (TGeoScaledShape *) geoShape;
2101  TString scaleObjClsName = geoscale->GetShape()->ClassName();
2102  if (scaleObjClsName == "TGeoCone") {
2103  solidN = CreateElConeN((TGeoScaledShape*) geoShape);
2104  } else {
2105  Info("ChooseObject",
2106  "ERROR! TGeoScaledShape object is not possible to process correctly. %s object is processed without scale",
2107  scaleObjClsName.Data());
2108  solidN = ChooseObject(geoscale->GetShape());
2109  //Name has to be propagated to geoscale level pointer
2110  fNameList->fLst[TString::Format("%p", geoscale)] =
2111  fNameList->fLst[TString::Format("%p", geoscale->GetShape())];
2112  }
2113  } else if (strcmp(clsname, "TGeoCompositeShape") == 0) {
2114  solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2115  } else if (strcmp(clsname, "TGeoUnion") == 0) {
2116  solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2117  } else if (strcmp(clsname, "TGeoIntersection") == 0) {
2118  solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2119  } else if (strcmp(clsname, "TGeoSubtraction") == 0) {
2120  solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2121  } else {
2122  Info("ChooseObject", "ERROR! %s Solid CANNOT be processed, solid is NOT supported",
2123  clsname);
2124  solidN = nullptr;
2125  }
2126  if (solidN == nullptr) {
2127  if (fNameList->fLst[TString::Format("%p", geoShape)] == "") {
2128  TString missingName = geoShape->GetName();
2129  GenName("missing_" + missingName, TString::Format("%p", geoShape));
2130  } else {
2131  fNameList->fLst[TString::Format("%p", geoShape)] = "missing_" + fNameList->fLst[TString::Format("%p", geoShape)];
2132  }
2133  }
2134 
2135  return solidN;
2136 }
2137 
2138 ////////////////////////////////////////////////////////////////////////////////
2139 /// Retrieves X Y Z angles from rotation matrix
2140 
2142 {
2143  TGDMLWrite::Xyz lxyz;
2144  Double_t a, b, c;
2145  Double_t rad = 180.0 / TMath::ACos(-1.0);
2146  const Double_t *r = rotationMatrix;
2147  Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
2148  if (cosb > 0.00001) {
2149  a = TMath::ATan2(r[5], r[8]) * rad;
2150  b = TMath::ATan2(-r[2], cosb) * rad;
2151  c = TMath::ATan2(r[1], r[0]) * rad;
2152  } else {
2153  a = TMath::ATan2(-r[7], r[4]) * rad;
2154  b = TMath::ATan2(-r[2], cosb) * rad;
2155  c = 0;
2156  }
2157  lxyz.x = a;
2158  lxyz.y = b;
2159  lxyz.z = c;
2160  return lxyz;
2161 }
2162 
2163 ////////////////////////////////////////////////////////////////////////////////
2164 /// Method creating cutTube as an intersection of tube and two boxes
2165 /// - not used anymore because cutube is supported in Geant4 9.5
2166 
2168 {
2169  Double_t rmin = geoShape->GetRmin();
2170  Double_t rmax = geoShape->GetRmax();
2171  Double_t z = geoShape->GetDz();
2172  Double_t startphi = geoShape->GetPhi1();
2173  Double_t deltaphi = geoShape->GetPhi2();
2174  Double_t x1 = geoShape->GetNlow()[0];
2175  Double_t y1 = geoShape->GetNlow()[1];
2176  Double_t z1 = geoShape->GetNlow()[2];
2177  Double_t x2 = geoShape->GetNhigh()[0];
2178  Double_t y2 = geoShape->GetNhigh()[1];
2179  Double_t z2 = geoShape->GetNhigh()[2];
2180  TString xname = geoShape->GetName();
2181 
2182 
2183  Double_t h0 = 2.*((TGeoBBox*)geoShape)->GetDZ();
2184  Double_t h1 = 2 * z;
2185  Double_t h2 = 2 * z;
2186  Double_t boxdx = 1E8 * (2 * rmax) + (2 * z);
2187 
2188  TGeoTubeSeg *T = new TGeoTubeSeg((xname + "T").Data(), rmin, rmax, h0, startphi, deltaphi);
2189  TGeoBBox *B1 = new TGeoBBox((xname + "B1").Data(), boxdx, boxdx, h1);
2190  TGeoBBox *B2 = new TGeoBBox((xname + "B2").Data(), boxdx, boxdx, h2);
2191 
2192 
2193  //first box position parameters
2194  Double_t phi1 = 360 - TMath::ATan2(x1, y1) * TMath::RadToDeg();
2195  Double_t theta1 = 360 - TMath::ATan2(sqrt(x1 * x1 + y1 * y1), z1) * TMath::RadToDeg();
2196 
2197  Double_t phi11 = TMath::ATan2(y1, x1) * TMath::RadToDeg() ;
2198  Double_t theta11 = TMath::ATan2(z1, sqrt(x1 * x1 + y1 * y1)) * TMath::RadToDeg() ;
2199 
2200  Double_t xpos1 = h1 * TMath::Cos((theta11) * TMath::DegToRad()) * TMath::Cos((phi11) * TMath::DegToRad()) * (-1);
2201  Double_t ypos1 = h1 * TMath::Cos((theta11) * TMath::DegToRad()) * TMath::Sin((phi11) * TMath::DegToRad()) * (-1);
2202  Double_t zpos1 = h1 * TMath::Sin((theta11) * TMath::DegToRad()) * (-1);
2203 
2204  //second box position parameters
2205  Double_t phi2 = 360 - TMath::ATan2(x2, y2) * TMath::RadToDeg();
2206  Double_t theta2 = 360 - TMath::ATan2(sqrt(x2 * x2 + y2 * y2), z2) * TMath::RadToDeg();
2207 
2208  Double_t phi21 = TMath::ATan2(y2, x2) * TMath::RadToDeg() ;
2209  Double_t theta21 = TMath::ATan2(z2, sqrt(x2 * x2 + y2 * y2)) * TMath::RadToDeg() ;
2210 
2211  Double_t xpos2 = h2 * TMath::Cos((theta21) * TMath::DegToRad()) * TMath::Cos((phi21) * TMath::DegToRad()) * (-1);
2212  Double_t ypos2 = h2 * TMath::Cos((theta21) * TMath::DegToRad()) * TMath::Sin((phi21) * TMath::DegToRad()) * (-1);
2213  Double_t zpos2 = h2 * TMath::Sin((theta21) * TMath::DegToRad()) * (-1);
2214 
2215 
2216  //positioning
2217  TGeoTranslation *t0 = new TGeoTranslation(0, 0, 0);
2218  TGeoTranslation *t1 = new TGeoTranslation(0 + xpos1, 0 + ypos1, 0 + (zpos1 - z));
2219  TGeoTranslation *t2 = new TGeoTranslation(0 + xpos2, 0 + ypos2, 0 + (zpos2 + z));
2220  TGeoRotation *r0 = new TGeoRotation((xname + "r0").Data());
2221  TGeoRotation *r1 = new TGeoRotation((xname + "r1").Data());
2222  TGeoRotation *r2 = new TGeoRotation((xname + "r2").Data());
2223 
2224  r1->SetAngles(phi1, theta1, 0);
2225  r2->SetAngles(phi2, theta2, 0);
2226 
2227  TGeoMatrix* m0 = new TGeoCombiTrans(*t0, *r0);
2228  TGeoMatrix* m1 = new TGeoCombiTrans(*t1, *r1);
2229  TGeoMatrix* m2 = new TGeoCombiTrans(*t2, *r2);
2230 
2231  TGeoCompositeShape *CS1 = new TGeoCompositeShape((xname + "CS1").Data(), new TGeoIntersection(T, B1, m0, m1));
2232  TGeoCompositeShape *cs = new TGeoCompositeShape((xname + "CS").Data(), new TGeoIntersection(CS1, B2, m0, m2));
2233  delete t0;
2234  delete t1;
2235  delete t2;
2236  delete r0;
2237  delete r1;
2238  delete r2;
2239  return cs;
2240 }
2241 
2242 ////////////////////////////////////////////////////////////////////////////////
2243 /// Checks whether name2check is in (NameList) list
2244 
2246 {
2247  Bool_t isIN = list[name2check];
2248  return isIN;
2249 }
2250 
2251 ////////////////////////////////////////////////////////////////////////////////
2252 ///NCNAME basic restrictions
2253 ///Replace "$" character with empty character etc.
2254 
2256 {
2257  TString newname = oldname.ReplaceAll("$", "");
2258  newname = newname.ReplaceAll(" ", "_");
2259  // :, @, $, %, &, /, +, ,, ;, whitespace characters or different parenthesis
2260  newname = newname.ReplaceAll(":", "");
2261  newname = newname.ReplaceAll("@", "");
2262  newname = newname.ReplaceAll("%", "");
2263  newname = newname.ReplaceAll("&", "");
2264  newname = newname.ReplaceAll("/", "");
2265  newname = newname.ReplaceAll("+", "");
2266  newname = newname.ReplaceAll(";", "");
2267  newname = newname.ReplaceAll("{", "");
2268  newname = newname.ReplaceAll("}", "");
2269  newname = newname.ReplaceAll("(", "");
2270  newname = newname.ReplaceAll(")", "");
2271  newname = newname.ReplaceAll("[", "");
2272  newname = newname.ReplaceAll("]", "");
2273  newname = newname.ReplaceAll("_refl", "");
2274  //workaround if first letter is digit than replace it to "O" (ou character)
2275  TString fstLet = newname(0, 1);
2276  if (fstLet.IsDigit()) {
2277  newname = "O" + newname(1, newname.Length());
2278  }
2279  return newname;
2280 }
2281 
2282 ////////////////////////////////////////////////////////////////////////////////
2283 /// Important function which is responsible for naming volumes, solids and materials
2284 
2286 {
2287  TString newname = GenName(oldname);
2288  if (newname != oldname) {
2289  if (fgkMaxNameErr > fActNameErr) {
2290  Info("GenName",
2291  "WARNING! Name of the object was changed because it failed to comply with NCNAME xml datatype restrictions.");
2292  } else if ((fgkMaxNameErr == fActNameErr)) {
2293  Info("GenName",
2294  "WARNING! Probably more names are going to be changed to comply with NCNAME xml datatype restriction, but it will not be displayed on the screen.");
2295  }
2296  fActNameErr++;
2297  }
2298  TString nameIter;
2299  Int_t iter = 0;
2300  switch (fgNamingSpeed) {
2301  case kfastButUglySufix:
2302  newname = newname + "0x" + objPointer;
2303  break;
2304  case kelegantButSlow:
2305  //0 means not in the list
2306  iter = fNameList->fLstIter[newname];
2307  if (iter == 0) {
2308  nameIter = "";
2309  } else {
2310  nameIter = TString::Format("0x%i", iter);
2311  }
2312  fNameList->fLstIter[newname]++;
2313  newname = newname + nameIter;
2314  break;
2315  case kwithoutSufixNotUniq:
2316  //no change
2317  break;
2318  }
2319  //store the name (mapped to pointer)
2320  fNameList->fLst[objPointer] = newname;
2321  return newname;
2322 }
2323 
2324 
2325 ////////////////////////////////////////////////////////////////////////////////
2326 /// Method which tests whether solids can be processed
2327 
2329 {
2330  Bool_t isProcessed = kFALSE;
2331  isProcessed = pointer->TestBit(fgkProcBit);
2332  pointer->SetBit(fgkProcBit, kTRUE);
2333  return !(isProcessed);
2334 }
2335 
2336 ////////////////////////////////////////////////////////////////////////////////
2337 /// Method that retrieves axis and unit along which object is divided
2338 
2339 TString TGDMLWrite::GetPattAxis(Int_t divAxis, const char * pattName, TString& unit)
2340 {
2341  TString resaxis;
2342  unit = "cm";
2343  switch (divAxis) {
2344  case 1:
2345  if (strcmp(pattName, "TGeoPatternX") == 0) {
2346  return "kXAxis";
2347  } else if (strcmp(pattName, "TGeoPatternCylR") == 0) {
2348  return "kRho";
2349  }
2350  break;
2351  case 2:
2352  if (strcmp(pattName, "TGeoPatternY") == 0) {
2353  return "kYAxis";
2354  } else if (strcmp(pattName, "TGeoPatternCylPhi") == 0) {
2355  unit = "deg";
2356  return "kPhi";
2357  }
2358  break;
2359  case 3:
2360  if (strcmp(pattName, "TGeoPatternZ") == 0) {
2361  return "kZAxis";
2362  }
2363  break;
2364  default:
2365  return "kUndefined";
2366  break;
2367  }
2368  return "kUndefined";
2369 }
2370 
2371 ////////////////////////////////////////////////////////////////////////////////
2372 /// Check for null parameter to skip the NULL objects
2373 
2375 {
2376  if (parValue == 0.) {
2377  Info("IsNullParam", "ERROR! %s is NULL due to %s = %.12g, Volume based on this shape will be skipped",
2378  objName.Data(),
2379  parName.Data(),
2380  parValue);
2381  return kTRUE;
2382  }
2383  return kFALSE;
2384 }
2385 
2386 ////////////////////////////////////////////////////////////////////////////////
2387 /// Unsetting bits that were changed in gGeoManager during export so that export
2388 /// can be run more times with the same instance of gGeoManager.
2389 
2391 {
2392  TIter next(geoMng->GetListOfVolumes());
2393  TGeoVolume *vol;
2394  while ((vol = (TGeoVolume *)next())) {
2395  ((TObject *)vol->GetShape())->SetBit(fgkProcBit, kFALSE);
2396  vol->SetAttBit(fgkProcBitVol, kFALSE);
2397  }
2398 
2399 }
2400 
2401 
2402 ////////////////////////////////////////////////////////////////////////////////
2403 //
2404 // Backwards compatibility for old DD4hep version (to be removed in the future)
2405 //
2406 ////////////////////////////////////////////////////////////////////////////////
2407 
2408 ////////////////////////////////////////////////////////////////////////////////
2409 // Backwards compatibility (to be removed in the future): Wrapper to only selectively write one branch
2410 void TGDMLWrite::WriteGDMLfile(TGeoManager * geomanager, TGeoVolume* volume, const char* filename, TString option)
2411 {
2412  TList materials, volumes, nodes;
2413  MaterialExtractor extract;
2414  if ( !volume ) {
2415  Info("WriteGDMLfile", "Invalid Volume reference to extract GDML information!");
2416  return;
2417  }
2418  extract(volume);
2419  for(TGeoMaterial* m : extract.materials)
2420  materials.Add(m);
2421  fTopVolumeName = volume->GetName();
2422  fSurfaceList.clear();
2423  fVolumeList.clear();
2424  fNodeList.clear();
2425  WriteGDMLfile(geomanager, volume, &materials, filename, option);
2426  materials.Clear("nodelete");
2427  volumes.Clear("nodelete");
2428  nodes.Clear("nodelete");
2429 }
2430 
2431 
2432 ////////////////////////////////////////////////////////////////////////////////
2433 /// Wrapper of all exporting methods
2434 /// Creates blank GDML file and fills it with gGeoManager structure converted
2435 /// to GDML structure of xml nodes
2436 
2438  TGeoVolume* volume,
2439  TList* materialsLst,
2440  const char* filename,
2441  TString option)
2442 {
2443  //option processing
2444  option.ToLower();
2445  if (option.Contains("g")) {
2447  Info("WriteGDMLfile", "Geant4 compatibility mode set");
2448  } else {
2450  }
2451  if (option.Contains("f")) {
2453  Info("WriteGDMLfile", "Fast naming convention with pointer suffix set");
2454  } else if (option.Contains("n")) {
2456  Info("WriteGDMLfile", "Naming without prefix set - be careful uniqness of name is not ensured");
2457  } else {
2459  Info("WriteGDMLfile", "Potentially slow with incremental suffix naming convention set");
2460  }
2461 
2462  //local variables
2463  Int_t outputLayout = 1;
2464  const char * krootNodeName = "gdml";
2465  const char * knsRefGeneral = "http://www.w3.org/2001/XMLSchema-instance";
2466  const char * knsNameGeneral = "xsi";
2467  const char * knsRefGdml = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
2468  const char * knsNameGdml = "xsi:noNamespaceSchemaLocation";
2469 
2470  // First create engine
2471  fGdmlE = new TXMLEngine;
2473 
2474  //create blank GDML file
2475  fGdmlFile = fGdmlE->NewDoc();
2476 
2477  //create root node and add it to blank GDML file
2478  XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
2479  fGdmlE->DocSetRootElement(fGdmlFile, rootNode);
2480 
2481  //add namespaces to root node
2482  fGdmlE->NewNS(rootNode, knsRefGeneral, knsNameGeneral);
2483  fGdmlE->NewAttr(rootNode, nullptr, knsNameGdml, knsRefGdml);
2484 
2485  //initialize general lists and <define>, <solids>, <structure> nodes
2486  fIsotopeList = new StructLst;
2487  fElementList = new StructLst;
2488 
2489  fNameList = new NameLst;
2490 
2491  fDefineNode = fGdmlE->NewChild(nullptr, nullptr, "define", nullptr);
2492  fSolidsNode = fGdmlE->NewChild(nullptr, nullptr, "solids", nullptr);
2493  fStructureNode = fGdmlE->NewChild(nullptr, nullptr, "structure", nullptr);
2494  //========================
2495 
2496  //initialize list of accepted patterns for divisions (in ExtractVolumes)
2497  fAccPatt = new StructLst;
2498  fAccPatt->fLst["TGeoPatternX"] = kTRUE;
2499  fAccPatt->fLst["TGeoPatternY"] = kTRUE;
2500  fAccPatt->fLst["TGeoPatternZ"] = kTRUE;
2501  fAccPatt->fLst["TGeoPatternCylR"] = kTRUE;
2502  fAccPatt->fLst["TGeoPatternCylPhi"] = kTRUE;
2503  //========================
2504 
2505  //initialize list of rejected shapes for divisions (in ExtractVolumes)
2506  fRejShape = new StructLst;
2507  //this shapes are rejected because, it is not possible to divide trd2
2508  //in Y axis and while only trd2 object is imported from GDML
2509  //it causes a problem when TGeoTrd1 is divided in Y axis
2510  fRejShape->fLst["TGeoTrd1"] = kTRUE;
2511  fRejShape->fLst["TGeoTrd2"] = kTRUE;
2512  //=========================
2513 
2514  //Initialize global counters
2515  fActNameErr = 0;
2516  fVolCnt = 0;
2517  fPhysVolCnt = 0;
2518  fSolCnt = 0;
2519 
2520  //calling main extraction functions (with measuring time)
2521  time_t startT, endT;
2522  startT = time(nullptr);
2523  ExtractMatrices(geomanager->GetListOfGDMLMatrices());
2524  ExtractConstants(geomanager);
2525  fMaterialsNode = ExtractMaterials(materialsLst);
2526 
2527  Info("WriteGDMLfile", "Extracting volumes");
2528  ExtractVolumes(volume);
2529  Info("WriteGDMLfile", "%i solids added", fSolCnt);
2530  Info("WriteGDMLfile", "%i volumes added", fVolCnt);
2531  Info("WriteGDMLfile", "%i physvolumes added", fPhysVolCnt);
2535  endT = time(nullptr);
2536  //<gdml>
2537  fGdmlE->AddChild(rootNode, fDefineNode); // <define>...</define>
2538  fGdmlE->AddChild(rootNode, fMaterialsNode); // <materials>...</materials>
2539  fGdmlE->AddChild(rootNode, fSolidsNode); // <solids>...</solids>
2540  fGdmlE->AddChild(rootNode, fStructureNode); // <structure>...</structure>
2541  fGdmlE->AddChild(rootNode, CreateSetupN(fTopVolumeName.Data())); // <setup>...</setup>
2542  //</gdml>
2543  Double_t tdiffI = difftime(endT, startT);
2544  TString tdiffS = (tdiffI == 0 ? TString("< 1 s") : TString::Format("%.0lf s", tdiffI));
2545  Info("WriteGDMLfile", "Exporting time: %s", tdiffS.Data());
2546  //=========================
2547 
2548  //Saving document
2549  fGdmlE->SaveDoc(fGdmlFile, filename, outputLayout);
2550  Info("WriteGDMLfile", "File %s saved", filename);
2551  //cleaning
2553  //unset processing bits:
2554  UnsetTemporaryBits(geomanager);
2555  delete fGdmlE;
2556 }
2557 
2558 
2559 
2560 
2561 ////////////////////////////////////////////////////////////////////////////////
2562 /// Method extracting geometry structure recursively
2563 
2565 {
2566  XMLNodePointer_t volumeN, childN;
2567  TString volname, matname, solname, pattClsName, nodeVolNameBak;
2568  TGeoPatternFinder *pattFinder = nullptr;
2569  Bool_t isPattern = kFALSE;
2570  const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2571 
2572  //create the name for volume/assembly
2573  if (volume->IsTopVolume()) {
2574  //not needed a special function for generating name
2575  volname = volume->GetName();
2576  fTopVolumeName = volname;
2577  //register name to the pointer
2578  fNameList->fLst[TString::Format("%p", volume)] = volname;
2579  } else {
2580  volname = GenName(volume->GetName(), TString::Format("%p", volume));
2581  }
2582 
2583  //start to create main volume/assembly node
2584  if (volume->IsAssembly()) {
2585  volumeN = StartAssemblyN(volname);
2586  } else {
2587  //get reference material and add solid to <solids> + get name
2588  matname = fNameList->fLst[TString::Format("%p", volume->GetMaterial())];
2589  solname = ExtractSolid(volume->GetShape());
2590  //If solid is not supported or corrupted
2591  if (solname == "-1") {
2592  Info("ExtractVolumes", "ERROR! %s volume was not added, because solid is either not supported or corrupted",
2593  volname.Data());
2594  //set volume as missing volume
2595  fNameList->fLst[TString::Format("%p", volume)] = "missing_" + volname;
2596  return;
2597  }
2598  volumeN = StartVolumeN(volname, solname, matname);
2599 
2600  //divisionvol can't be in assembly
2601  pattFinder = volume->GetFinder();
2602  //if found pattern
2603  if (pattFinder) {
2604  pattClsName = TString::Format("%s", pattFinder->ClassName());
2605  TString shapeCls = TString::Format("%s", volume->GetShape()->ClassName());
2606  //if pattern in accepted pattern list and not in shape rejected list
2607  if ((fAccPatt->fLst[pattClsName] == kTRUE) &&
2608  (fRejShape->fLst[shapeCls] != kTRUE)) {
2609  isPattern = kTRUE;
2610  }
2611  }
2612  }
2613  //get all nodes in volume
2614  TObjArray *nodeLst = volume->GetNodes();
2615  TIter next(nodeLst);
2616  TGeoNode *geoNode;
2617  Int_t nCnt = 0;
2618  //loop through all nodes
2619  while ((geoNode = (TGeoNode *) next())) {
2620  //get volume of current node and if not processed then process it
2621  TGeoVolume * subvol = geoNode->GetVolume();
2622  if (subvol->TestAttBit(fgkProcBitVol) == kFALSE) {
2623  subvol->SetAttBit(fgkProcBitVol);
2624  ExtractVolumes(subvol);
2625  }
2626 
2627  //volume of this node has to exist because it was processed recursively
2628  TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
2629  if (nodevolname.Contains("missing_")) {
2630  continue;
2631  }
2632  if (nCnt == 0) { //save name of the first node for divisionvol
2633  nodeVolNameBak = nodevolname;
2634  }
2635 
2636  if (isPattern == kFALSE) {
2637  //create name for node
2638  TString nodename, posname, rotname;
2639  nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
2640  nodename = nodename + "in" + volname;
2641 
2642  //create name for position and clear rotation
2643  posname = nodename + "pos";
2644  rotname = "";
2645 
2646  //position
2647  const Double_t * pos = geoNode->GetMatrix()->GetTranslation();
2648  Xyz nodPos;
2649  nodPos.x = pos[0];
2650  nodPos.y = pos[1];
2651  nodPos.z = pos[2];
2652  childN = CreatePositionN(posname.Data(), nodPos);
2653  fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
2654  //Deal with reflection
2655  XMLNodePointer_t scaleN = nullptr;
2656  Double_t lx, ly, lz;
2657  Double_t xangle = 0;
2658  Double_t zangle = 0;
2659  lx = geoNode->GetMatrix()->GetRotationMatrix()[0];
2660  ly = geoNode->GetMatrix()->GetRotationMatrix()[4];
2661  lz = geoNode->GetMatrix()->GetRotationMatrix()[8];
2662  if (geoNode->GetMatrix()->IsReflection()
2663  && TMath::Abs(lx) == 1 && TMath::Abs(ly) == 1 && TMath::Abs(lz) == 1) {
2664  scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
2665  fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
2666  fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
2667  fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
2668  fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
2669  //experimentally found out, that rotation should be updated like this
2670  if (lx == -1) {
2671  zangle = 180;
2672  }
2673  if (lz == -1) {
2674  xangle = 180;
2675  }
2676  }
2677 
2678  //rotation
2680  lxyz.x -= xangle;
2681  lxyz.z -= zangle;
2682  if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
2683  rotname = nodename + "rot";
2684  childN = CreateRotationN(rotname.Data(), lxyz);
2685  fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
2686  }
2687 
2688  //create physvol for main volume/assembly node
2689  childN = CreatePhysVolN(geoNode->GetName(), geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(), scaleN);
2690  fGdmlE->AddChild(volumeN, childN);
2691  }
2692  nCnt++;
2693  }
2694  //create only one divisionvol node
2695  if (isPattern && pattFinder) {
2696  //retrieve attributes of division
2697  Int_t ndiv, divaxis;
2698  Double_t offset, width, xlo, xhi;
2699  TString axis, unit;
2700 
2701  ndiv = pattFinder->GetNdiv();
2702  width = pattFinder->GetStep();
2703 
2704  divaxis = pattFinder->GetDivAxis();
2705  volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
2706 
2707  //compute relative start (not positional)
2708  offset = pattFinder->GetStart() - xlo;
2709  axis = GetPattAxis(divaxis, pattClsName, unit);
2710 
2711  //create division node
2712  childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
2713  fGdmlE->AddChild(volumeN, childN);
2714  }
2715 
2716  fVolCnt++;
2717  //add volume/assembly node into the <structure> node
2718  fGdmlE->AddChild(fStructureNode, volumeN);
2719 }
Double_t GetPhi2() const
Definition: TGeoTube.h:149
Int_t GetZ() const
Definition: TGeoElement.h:120
Double_t GetDy2() const
Definition: TGeoTrd2.h:59
XMLNodePointer_t CreateMixtureN(TGeoMixture *mixture, XMLNodePointer_t materials, TString mname)
Creates "material" node for GDML with references to other sub elements.
Definition: TGDMLWrite.cxx:839
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TObjArray * GetListOfOpticalSurfaces() const
Definition: TGeoManager.h:498
Double_t GetTheta() const
Definition: TGeoArb8.h:126
Mixtures of elements.
Definition: TGeoMaterial.h:150
Spherical shell class.
Definition: TGeoSphere.h:17
Int_t GetNz() const
Definition: TGeoXtru.h:93
Cylindrical tube class.
Definition: TGeoTube.h:17
An array of TObjects.
Definition: TObjArray.h:37
Double_t GetDphi() const
Definition: TGeoTorus.h:73
Double_t GetAlpha2() const
Definition: TGeoArb8.h:135
Double_t * GetZ() const
Definition: TGeoPcon.h:82
XMLNodePointer_t CreateHypeN(TGeoHype *geoShape)
Creates "hype" node for GDML.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Bool_t TestAttBit(UInt_t f) const
Definition: TGeoAtt.h:68
Double_t GetXOffset(Int_t i) const
Definition: TGeoXtru.h:97
The manager class for any TGeo geometry.
Definition: TGeoManager.h:42
ESurfaceType GetType() const
size_t GetRows() const
Definition: TGDMLMatrix.h:44
This class contains implementation of converting ROOT&#39;s gGeoManager geometry to GDML file...
Definition: TGDMLWrite.h:57
Box class.
Definition: TGeoBBox.h:17
Double_t GetDphi() const
Definition: TGeoPcon.h:75
TGeoShape * GetLeftShape() const
Definition: TGeoBoolNode.h:82
auto * m
Definition: textangle.C:8
XMLNodePointer_t CreateFractionN(Double_t percentage, const char *refName)
Creates "fraction" node for GDML.
Definition: TGDMLWrite.cxx:739
Double_t z
Definition: TGDMLWrite.h:94
Double_t GetPhi1() const
Definition: TGeoTube.h:148
virtual Double_t GetDX() const
Definition: TGeoBBox.h:70
void ExtractBorderSurfaces(TObjArray *surfaces)
Method exporting border surfaces.
Definition: TGDMLWrite.cxx:468
static const char * TypeToString(ESurfaceType type)
XMLNodePointer_t CreateParaN(TGeoPara *geoShape)
Creates "para" node for GDML.
ESurfaceModel GetModel() const
void ExtractOpticalSurfaces(TObjArray *surfaces)
Method exporting optical surfaces.
Definition: TGDMLWrite.cxx:433
XMLNodePointer_t fStructureNode
Definition: TGDMLWrite.h:134
static TGDMLWrite * fgGDMLWrite
Definition: TGDMLWrite.h:124
virtual Double_t GetDensity() const
Definition: TGeoMaterial.h:103
Gtra is a twisted trapezoid.
Definition: TGeoArb8.h:145
Double_t GetDy() const
Definition: TGeoTrd1.h:57
XMLNodePointer_t StartVolumeN(const char *name, const char *solid, const char *material)
Creates "volume" node for GDML.
Geometrical transformation package.
Definition: TGeoMatrix.h:40
Double_t Get(size_t r, size_t c) const
Definition: TGDMLMatrix.cxx:78
StructLst * fRejShape
Definition: TGDMLWrite.h:116
virtual const Double_t * GetRotationMatrix() const
Definition: TGeoMatrix.h:468
double T(double x)
Definition: ChebyshevPol.h:34
static constexpr double rad
Int_t Z() const
Definition: TGeoElement.h:73
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
A polycone.
Definition: TGeoPcon.h:17
virtual const Double_t * GetRotationMatrix() const =0
A polygone.
Definition: TGeoPgon.h:19
Double_t GetR() const
Definition: TGeoTorus.h:69
Double_t GetYOffset(Int_t i) const
Definition: TGeoXtru.h:98
XMLDocPointer_t NewDoc(const char *version="1.0")
creates new xml document with provided version
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition: TGeoVolume.h:42
Double_t GetPhi() const
Definition: TGeoArb8.h:127
Double_t GetPhi() const
Definition: TGeoPara.h:66
TString ExtractSolid(TGeoShape *volShape)
Method creating solid to xml file and returning its name.
Definition: TGDMLWrite.cxx:532
Int_t GetNedges() const
Definition: TGeoPgon.h:82
Tessellated solid class.
virtual Double_t GetB() const
Definition: TGeoEltu.h:44
Double_t GetValue() const
TObjArray * GetListOfSkinSurfaces() const
Definition: TGeoManager.h:499
virtual Double_t GetRmax() const
Definition: TGeoSphere.h:68
Double_t * GetWmixt() const
Definition: TGeoMaterial.h:191
Double_t GetRmin() const
Definition: TGeoTorus.h:70
virtual TGeoElement * GetElement(Int_t i=0) const
Retrieve the pointer to the element corresponding to component I.
const Double_t * GetNlow() const
Definition: TGeoTube.h:207
Class describing translations.
Definition: TGeoMatrix.h:121
Torus segment class.
Definition: TGeoTorus.h:17
void UnsetTemporaryBits(TGeoManager *geoMng)
Unsetting bits that were changed in gGeoManager during export so that export can be run more times wi...
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
XMLNodePointer_t CreateMaterialN(TGeoMaterial *material, TString mname)
Creates "material" node for GDML.
Definition: TGDMLWrite.cxx:909
Bool_t CanProcess(TObject *pointer)
Method which tests whether solids can be processed.
Basic string class.
Definition: TString.h:131
Base class describing materials.
Definition: TGeoMaterial.h:29
Double_t GetA() const
Definition: TGeoElement.h:122
XMLNodePointer_t CreateBorderSurfaceN(TGeoBorderSurface *geoSurf)
Creates "bordersurface" node for GDML.
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
XMLNodePointer_t CreatePositionN(const char *name, Xyz position, const char *type="position", const char *unit="cm")
Creates "position" kind of node for GDML.
XMLNodePointer_t CreateOpticalSurfaceN(TGeoOpticalSurface *geoSurf)
Creates "opticalsurface" node for GDML.
Double_t GetPhi1() const
Definition: TGeoCone.h:160
void WriteGDMLfile(TGeoManager *geomanager, const char *filename="test.gdml", TString option="")
Definition: TGDMLWrite.cxx:237
void SetSkipComments(Bool_t on=kTRUE)
Definition: TXMLEngine.h:48
std::map< TString, Float_t > NameListF
Definition: TGDMLWrite.h:103
Int_t GetNdiv() const
int GetNfacets() const
NameListI fLstIter
Definition: TGDMLWrite.h:109
virtual Double_t GetRmin2() const
Definition: TGeoCone.h:75
Double_t GetDx2() const
Definition: TGeoTrd2.h:57
Int_t GetNvert() const
Definition: TGeoXtru.h:94
virtual EGeoBoolType GetBooleanOperator() const =0
XMLNodePointer_t CreateXtrusionN(TGeoXtru *geoShape)
Creates "xtru" node for GDML.
TObjArray * GetListOfBorderSurfaces() const
Definition: TGeoManager.h:500
TGeoIsotope * GetIsotope(Int_t i) const
Return i-th isotope in the element.
A shape scaled by a TGeoScale transformation.
XMLNodePointer_t CreateEllipsoidN(TGeoCompositeShape *geoShape, TString elName)
Creates "ellipsoid" node for GDML this is a special case, because ellipsoid is not defined in ROOT so...
virtual const Double_t * GetScale() const
Definition: TGeoMatrix.h:279
XMLNodePointer_t StartAssemblyN(const char *name)
Creates "assembly" node for GDML.
A trapezoid with only x length varying with z.
Definition: TGeoTrd1.h:17
TRObject operator()(const T1 &t1) const
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
void FreeDoc(XMLDocPointer_t xmldoc)
frees allocated document data and deletes document itself
Paraboloid class.
XMLNodePointer_t CreateTwistedTrapN(TGeoGtra *geoShape)
Creates "twistedtrap" node for GDML.
Double_t GetPhi2() const
Definition: TGeoSphere.h:72
void ExtractSkinSurfaces(TObjArray *surfaces)
Method exporting skin surfaces.
Definition: TGDMLWrite.cxx:450
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
TList * GetListOfMaterials() const
Definition: TGeoManager.h:489
Double_t GetDx2() const
Definition: TGeoTrd1.h:56
TList const & GetProperties() const
Definition: TGeoMaterial.h:95
XMLDocPointer_t fGdmlFile
Definition: TGDMLWrite.h:127
TObjArray * GetNodes()
Definition: TGeoVolume.h:165
Double_t GetPhi2() const
Definition: TGeoCone.h:161
Double_t GetPhi1() const
Definition: TGeoSphere.h:71
XMLNodePointer_t CreateElConeN(TGeoScaledShape *geoShape)
Creates "elcone" (elliptical cone) node for GDML this is a special case, because elliptical cone is n...
virtual Double_t GetRmax() const
Definition: TGeoTube.h:67
Double_t GetStOut() const
Definition: TGeoHype.h:69
Bool_t HasIsotopes() const
Definition: TGeoElement.h:85
XMLNodePointer_t CreateArb8N(TGeoArb8 *geoShape)
Creates "arb8" node for GDML.
double sqrt(double)
static const double x2[5]
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
XMLNodePointer_t CreateZplaneN(Double_t z, Double_t rmin, Double_t rmax)
Creates "zplane" node for GDML.
TGeoPatternFinder * GetFinder() const
Definition: TGeoVolume.h:173
ESurfaceFinish GetFinish() const
XMLNodePointer_t CreateConeN(TGeoConeSeg *geoShape)
Creates "cone" node for GDML from TGeoConeSeg object.
Bool_t IsTwisted() const
Definition: TGeoArb8.h:75
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2311
Int_t GetNisotopes() const
Definition: TGeoElement.h:78
A phi segment of a conical tube.
Definition: TGeoCone.h:98
XMLNodePointer_t CreateTrapN(TGeoTrap *geoShape)
Creates "trap" node for GDML.
Int_t GetN() const
Definition: TGeoElement.h:121
TGeoMatrix * GetLeftMatrix() const
Definition: TGeoBoolNode.h:80
Bool_t IsInList(NameList list, TString name2check)
Checks whether name2check is in (NameList) list.
XMLNodePointer_t CreateIsotopN(TGeoIsotope *isotope, const char *name)
Creates "isotope" node for GDML.
Definition: TGDMLWrite.cxx:762
static const char * ModelToString(ESurfaceModel model)
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
Double_t ATan2(Double_t y, Double_t x)
Definition: TMath.h:669
void DocSetRootElement(XMLDocPointer_t xmldoc, XMLNodePointer_t xmlnode)
set main (root) node for document
void ExtractVolumes(TGeoNode *topNode)
Method extracting geometry structure recursively.
Definition: TGDMLWrite.cxx:550
Int_t fPhysVolCnt
Definition: TGDMLWrite.h:136
XMLNodePointer_t ExtractMaterials(TList *materialsLst)
Method exporting materials.
Definition: TGDMLWrite.cxx:500
TXMLEngine * fGdmlE
Definition: TGDMLWrite.h:129
UInt_t fActNameErr
Definition: TGDMLWrite.h:137
This class is used in the process of reading and writing the GDML "matrix" tag.
Definition: TGDMLMatrix.h:34
virtual ~TGDMLWrite()
Destructor.
Definition: TGDMLWrite.cxx:216
Int_t GetNz() const
Definition: TGeoPcon.h:76
Base class for chemical elements.
Definition: TGeoElement.h:36
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition: TMath.h:82
TObjArray * GetListOfGDMLMatrices() const
Definition: TGeoManager.h:497
virtual Double_t GetA() const
Definition: TGeoMaterial.h:100
TGDMLWrite()
Default constructor.
Definition: TGDMLWrite.cxx:187
Double_t y
Definition: TGDMLWrite.h:93
TRAP is a general trapezoid, i.e.
Definition: TGeoArb8.h:91
virtual TGeoMatrix * GetMatrix() const =0
TGeoMaterial * GetMaterial() const
Definition: TGeoVolume.h:170
void SetG4Compatibility(Bool_t G4Compatible)
Definition: TGDMLWrite.h:86
Double_t GetY(Int_t i) const
Definition: TGeoXtru.h:96
TH1F * h1
Definition: legend1.C:5
static const char * FinishToString(ESurfaceFinish finish)
Double_t GetH2() const
Definition: TGeoArb8.h:132
XMLNodePointer_t CreateEltubeN(TGeoEltu *geoShape)
Creates "eltube" node for GDML.
VolList fVolumeList
Definition: TGDMLWrite.h:118
Double_t GetX(Int_t i) const
Definition: TGeoXtru.h:95
virtual Double_t GetZ() const
Definition: TGeoMaterial.h:101
REAL * vertex
Definition: triangle.c:512
Bool_t IsNullParam(Double_t parValue, TString parName, TString objName)
Check for null parameter to skip the NULL objects.
A doubly linked list.
Definition: TList.h:44
XMLNodePointer_t fDefineNode
Definition: TGDMLWrite.h:131
Base finder class for patterns.
XMLNodePointer_t fSolidsNode
Definition: TGDMLWrite.h:133
virtual Double_t GetDz() const
Definition: TGeoCone.h:68
Class handling Boolean composition of shapes.
Double_t GetStep() const
virtual const char * GetName() const
Get the shape name.
Definition: TGeoShape.cxx:248
A trapezoid with both x and y lengths varying with z.
Definition: TGeoTrd2.h:17
Double_t * GetRmax() const
Definition: TGeoPcon.h:80
XMLNodePointer_t CreateTessellatedN(TGeoTessellated *geoShape)
Creates "tessellated" (tessellated shape) node for GDML.
Int_t GetNumber() const
Definition: TGeoNode.h:95
Parallelepiped class.
Definition: TGeoPara.h:17
void SaveDoc(XMLDocPointer_t xmldoc, const char *filename, Int_t layout=1)
store document content to file if layout<=0, no any spaces or newlines will be placed between xmlnode...
Double_t GetX() const
Definition: TGeoPara.h:61
Double_t * GetRmin() const
Definition: TGeoPcon.h:78
virtual Double_t GetRmin1() const
Definition: TGeoCone.h:73
Xyz GetXYZangles(const Double_t *rotationMatrix)
Retrieves X Y Z angles from rotation matrix.
XMLNodePointer_t CreatePhysVolN(const char *name, Int_t copyno, const char *volref, const char *posref, const char *rotref, XMLNodePointer_t scaleN)
Creates "physvol" node for GDML.
Double_t GetTheta1() const
Definition: TGeoSphere.h:69
static constexpr double m2
void ExtractMatrices(TObjArray *matrices)
Method exporting GDML matrices.
Definition: TGDMLWrite.cxx:402
Base abstract class for all shapes.
Definition: TGeoShape.h:25
void AddChild(XMLNodePointer_t parent, XMLNodePointer_t child)
add child element to xmlnode
Definition: TXMLEngine.cxx:793
XMLNodePointer_t CreatePropertyN(TNamed const &property)
Creates "property" node for GDML.
Definition: TGDMLWrite.cxx:751
ROOT::R::TRInterface & r
Definition: Object.C:4
Class describing rotation + translation.
Definition: TGeoMatrix.h:291
void SetNamingSpeed(ENamingType naming)
Set convention of naming solids and volumes.
Definition: TGDMLWrite.cxx:230
XMLNodePointer_t CreateBoxN(TGeoBBox *geoShape)
Creates "box" node for GDML.
Definition: TGDMLWrite.cxx:956
auto * a
Definition: textangle.C:12
Double_t GetAlpha() const
Definition: TGeoPara.h:64
Double_t GetY() const
Definition: TGeoPara.h:62
Int_t GetNproperties() const
Definition: TGeoManager.h:180
std::map< TString, Bool_t > NameList
Definition: TGDMLWrite.h:100
XMLNodePointer_t CreatePolyconeN(TGeoPcon *geoShape)
Creates "polycone" node for GDML.
XMLNodePointer_t CreateParaboloidN(TGeoParaboloid *geoShape)
Creates "paraboloid" node for GDML.
Definition: TGDMLWrite.cxx:978
XMLNodePointer_t CreateTorusN(TGeoTorus *geoShape)
Creates "torus" node for GDML.
StructLst * fIsotopeList
Definition: TGDMLWrite.h:113
Double_t GetStart() const
virtual Double_t GetRmax1() const
Definition: TGeoCone.h:74
virtual Int_t GetNelements() const
Definition: TGeoMaterial.h:188
Double_t GetDz() const
Definition: TGeoTrd2.h:60
Double_t GetRhi() const
Hyperboloid class defined by 5 parameters.
Definition: TGeoHype.h:17
Double_t GetBl1() const
Definition: TGeoArb8.h:129
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
TGeoNode const * GetNode1() const
Ssiz_t Length() const
Definition: TString.h:405
virtual const Double_t * GetOrigin() const
Definition: TGeoBBox.h:73
double floor(double)
Double_t GetProperty(const char *name, Bool_t *error=nullptr) const
Get a user-defined property.
Double_t GetBl2() const
Definition: TGeoArb8.h:133
TGeoOpticalSurface const * GetSurface() const
TGeoNode * GetTopNode() const
Definition: TGeoManager.h:531
Double_t ACos(Double_t)
Definition: TMath.h:658
TGeoCompositeShape * CreateFakeCtub(TGeoCtub *geoShape)
Method creating cutTube as an intersection of tube and two boxes.
Double_t GetScale(Int_t i) const
Definition: TGeoXtru.h:99
TString fTopVolumeName
Definition: TGDMLWrite.h:128
void * XMLNodePointer_t
Definition: TXMLEngine.h:17
virtual Double_t GetDY() const
Definition: TGeoBBox.h:71
Double_t GetDz() const
Bool_t fgG4Compatibility
Definition: TGDMLWrite.h:126
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:97
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=nullptr)
create new child element for parent node
Definition: TXMLEngine.cxx:709
Double_t Cos(Double_t)
Definition: TMath.h:631
Class describing rotations.
Definition: TGeoMatrix.h:174
void ExtractConstants(TGeoManager *geom)
Method exporting GDML matrices.
Definition: TGDMLWrite.cxx:417
const Bool_t kFALSE
Definition: RtypesCore.h:88
Double_t GetRlo() const
TString GenName(TString oldname)
NCNAME basic restrictions Replace "$" character with empty character etc.
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
Double_t GetPhi1() const
Definition: TGeoPcon.h:74
UInt_t fFltPrecision
Definition: TGDMLWrite.h:139
NodeList fNodeList
Definition: TGDMLWrite.h:119
Bool_t IsTopVolume() const
True if this is the top volume of the geometry.
Definition: TGeoVolume.cxx:811
A tube segment cut with 2 planes.
Definition: TGeoTube.h:168
XMLNodePointer_t CreateDivisionN(Double_t offset, Double_t width, Int_t number, const char *axis, const char *unit, const char *volref)
Creates "divisionvol" node for GDML.
Double_t GetRmax() const
Definition: TGeoTorus.h:71
An extrusion with fixed outline shape in x-y and a sequence of z extents (segments).
Definition: TGeoXtru.h:21
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
creates new attribute for xmlnode, namespaces are not supported for attributes
Definition: TXMLEngine.cxx:580
static const double x1[5]
auto * t1
Definition: textangle.C:20
#define ClassImp(name)
Definition: Rtypes.h:365
virtual Bool_t IsMixture() const
Definition: TGeoMaterial.h:124
double Double_t
Definition: RtypesCore.h:55
XMLNodePointer_t CreateMatrixN(TGDMLMatrix const *matrix)
Creates "matrix" kind of node for GDML.
Int_t fVolCnt
Definition: TGDMLWrite.h:135
const Vertex_t & GetVertex(int i)
int type
Definition: TGX11.cxx:120
const Double_t * GetNhigh() const
Definition: TGeoTube.h:208
Conical tube class.
Definition: TGeoCone.h:17
TGeoVolume const * GetVolume() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Double_t GetDy1() const
Definition: TGeoTrd2.h:58
An arbitrary trapezoid with less than 8 vertices standing on two parallel planes perpendicular to Z a...
Definition: TGeoArb8.h:17
XMLNodePointer_t CreateTrdN(TGeoTrd1 *geoShape)
Creates "trd" node for GDML from object TGeoTrd1.
static const UInt_t fgkProcBitVol
Definition: TGDMLWrite.h:142
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
Double_t GetH1() const
Definition: TGeoArb8.h:128
Bool_t IsReflection() const
Definition: TGeoMatrix.h:69
XMLNodePointer_t CreatePolyhedraN(TGeoPgon *geoShape)
Creates "polyhedra" node for GDML.
virtual Double_t GetRmax2() const
Definition: TGeoCone.h:76
TGeoMatrix * GetRightMatrix() const
Definition: TGeoBoolNode.h:81
XMLNodePointer_t CreateAtomN(Double_t atom, const char *unit="g/mole")
Creates "atom" node for GDML.
Definition: TGDMLWrite.cxx:715
Double_t GetTwistAngle() const
Definition: TGeoArb8.h:168
TGeoScale * GetScale() const
virtual Int_t GetDivAxis()
Double_t * GetZ() const
Definition: TGeoXtru.h:100
Mother of all ROOT objects.
Definition: TObject.h:37
Double_t GetPhi1() const
Definition: TGeoTorus.h:72
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
Double_t GetDx1() const
Definition: TGeoTrd2.h:56
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition: TMath.h:74
void SetAttBit(UInt_t f)
Definition: TGeoAtt.h:65
virtual TGeoHMatrix Inverse() const =0
XMLNodePointer_t ChooseObject(TGeoShape *geoShape)
Chooses the object and method that should be used for processing object.
XMLNodePointer_t CreateSkinSurfaceN(TGeoSkinSurface *geoSurf)
Creates "skinsurface" node for GDML.
XMLNodePointer_t CreateSphereN(TGeoSphere *geoShape)
Creates "sphere" node for GDML.
Definition: TGDMLWrite.cxx:999
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
Definition: TGeoNode.h:39
TList const & GetConstProperties() const
Definition: TGeoMaterial.h:96
int GetNvertices() const
Double_t GetDz() const
Definition: TGeoArb8.h:65
Double_t GetTl1() const
Definition: TGeoArb8.h:130
XMLNodePointer_t fMaterialsNode
Definition: TGDMLWrite.h:132
virtual void Add(TObject *obj)
Definition: TList.h:87
Elliptical tube class.
Definition: TGeoEltu.h:17
virtual Double_t GetRmin() const
Definition: TGeoTube.h:66
NameLst * fNameList
Definition: TGDMLWrite.h:121
XMLNsPointer_t NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name=nullptr)
create namespace attribute for xmlnode.
Definition: TXMLEngine.cxx:735
XMLNodePointer_t CreateTubeN(TGeoTubeSeg *geoShape)
Creates "tube" node for GDML from object TGeoTubeSeg.
Int_t fgNamingSpeed
Definition: TGDMLWrite.h:125
StructLst * fElementList
Definition: TGDMLWrite.h:114
Double_t Sin(Double_t)
Definition: TMath.h:627
TObjArray * GetListOfVolumes() const
Definition: TGeoManager.h:491
Double_t GetAlpha1() const
Definition: TGeoArb8.h:131
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
XMLNodePointer_t CreateConstantN(const char *name, Double_t value)
Creates "constant" kind of node for GDML.
virtual Double_t GetA() const
Definition: TGeoEltu.h:43
XMLNodePointer_t CreateDN(Double_t density, const char *unit="g/cm3")
Creates "D" density node for GDML.
Definition: TGDMLWrite.cxx:727
static const UInt_t fgkMaxNameErr
Definition: TGDMLWrite.h:143
virtual Double_t GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const =0
XMLNodePointer_t CreateElementN(TGeoElement *element, XMLNodePointer_t materials, const char *name)
Creates "element" node for GDML element node and attribute.
Definition: TGDMLWrite.cxx:776
#define c(i)
Definition: RSha256.hxx:101
TGeoShape * GetShape() const
XMLNodePointer_t CreateCommonBoolN(TGeoCompositeShape *geoShape)
Creates common part of union intersection and subtraction nodes.
TList const & GetProperties() const
TGeoNode const * GetNode2() const
UInt_t fSolCnt
Definition: TGDMLWrite.h:138
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1763
const TGeoFacet & GetFacet(int i)
Double_t A() const
Definition: TGeoElement.h:76
Double_t GetDz() const
Definition: TGeoTrd1.h:58
void SetAngles(Double_t phi, Double_t theta, Double_t psi)
Set matrix elements according to Euler angles.
TGeoOpticalSurface const * GetSurface() const
Double_t GetTheta() const
Definition: TGeoPara.h:65
Double_t x
Definition: TGDMLWrite.h:92
Double_t Sqrt(Double_t x)
Definition: TMath.h:681
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
Double_t GetRelativeAbundance(Int_t i) const
Return relative abundance of i-th isotope in this element.
TGeoShape * GetShape() const
Definition: TGeoVolume.h:186
Double_t GetZ() const
Definition: TGeoPara.h:63
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Double_t GetDx1() const
Definition: TGeoTrd1.h:55
int GetNvert() const
const Bool_t kTRUE
Definition: RtypesCore.h:87
TGeoBoolNode * GetBoolNode() const
TGeoShape * GetRightShape() const
Definition: TGeoBoolNode.h:83
virtual const Double_t * GetTranslation() const =0
TGeoVolume * GetVolume() const
Definition: TGeoNode.h:97
std::map< TString, Int_t > NameListI
Definition: TGDMLWrite.h:102
XMLNodePointer_t CreateSetupN(const char *topVolName, const char *name="default", const char *version="1.0")
Creates "setup" node for GDML.
size_t GetCols() const
Definition: TGDMLMatrix.h:45
virtual Double_t GetRmin() const
Definition: TGeoSphere.h:67
TString GetPattAxis(Int_t divAxis, const char *pattName, TString &unit)
Method that retrieves axis and unit along which object is divided.
virtual Double_t GetDz() const
Definition: TGeoTube.h:68
char name[80]
Definition: TGX11.cxx:109
XMLNodePointer_t CreateRotationN(const char *name, Xyz rotation, const char *type="rotation", const char *unit="deg")
Creates "rotation" kind of node for GDML.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
StructLst * fAccPatt
Definition: TGDMLWrite.h:115
Double_t GetTl2() const
Definition: TGeoArb8.h:134
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
SurfaceList fSurfaceList
Definition: TGDMLWrite.h:117
static const UInt_t fgkProcBit
floating point precision when writing
Definition: TGDMLWrite.h:141
virtual Double_t GetDZ() const
Definition: TGeoBBox.h:72
Double_t * GetVertices()
Definition: TGeoArb8.h:69
const char * Data() const
Definition: TString.h:364
Double_t GetStIn() const
Definition: TGeoHype.h:68
Double_t GetTheta2() const
Definition: TGeoSphere.h:70
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
XMLNodePointer_t CreateCutTubeN(TGeoCtub *geoShape)
Creates "cutTube" node for GDML.
A phi segment of a tube.
Definition: TGeoTube.h:88