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