Logo ROOT  
Reference Guide
TGDMLWrite.cxx
Go to the documentation of this file.
1// @(#)root/gdml:$Id$
2// Author: Anton Pytel 15/9/2011
3
4/*************************************************************************
5 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TGDMLWrite
13\ingroup Geometry_gdml
14
15 This class contains implementation of converting ROOT's gGeoManager
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 fGdmlE->NewAttr(atomN, nullptr, "unit", unit);
775 fGdmlE->NewAttr(atomN, nullptr, "value", TString::Format(fltPrecision.Data(), atom));
776 return atomN;
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// Creates "D" density node for GDML
781
783{
784 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
785 XMLNodePointer_t densN = fGdmlE->NewChild(nullptr, nullptr, "D", nullptr);
786 fGdmlE->NewAttr(densN, nullptr, "unit", unit);
787 fGdmlE->NewAttr(densN, nullptr, "value", TString::Format(fltPrecision.Data(), density));
788 return densN;
789}
790
791////////////////////////////////////////////////////////////////////////////////
792/// Creates "fraction" node for GDML
793
795{
796 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
797 XMLNodePointer_t fractN = fGdmlE->NewChild(nullptr, nullptr, "fraction", nullptr);
798 fGdmlE->NewAttr(fractN, nullptr, "n", TString::Format(fltPrecision.Data(), percentage));
799 fGdmlE->NewAttr(fractN, nullptr, "ref", refName);
800 return fractN;
801}
802
803////////////////////////////////////////////////////////////////////////////////
804/// Creates "property" node for GDML
805
807{
808 XMLNodePointer_t propertyN = fGdmlE->NewChild(nullptr, nullptr, "property", nullptr);
809 fGdmlE->NewAttr(propertyN, nullptr, "name", property.GetName());
810 fGdmlE->NewAttr(propertyN, nullptr, "ref", property.GetTitle());
811 return propertyN;
812}
813
814////////////////////////////////////////////////////////////////////////////////
815/// Creates "isotope" node for GDML
816
818{
819 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "isotope", nullptr);
820 fGdmlE->NewAttr(mainN, nullptr, "name", name);
821 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", isotope->GetN()));
822 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", isotope->GetZ()));
823 fGdmlE->AddChild(mainN, CreateAtomN(isotope->GetA()));
824 return mainN;
825}
826
827////////////////////////////////////////////////////////////////////////////////
828/// Creates "element" node for GDML
829///element node and attribute
830
832{
833 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "element", nullptr);
834 fGdmlE->NewAttr(mainN, nullptr, "name", name);
835 //local associative arrays for saving isotopes and their weight
836 //inside element
837 NameListF wPercentage;
838 NameListI wCounter;
839
840 if (element->HasIsotopes()) {
841 Int_t nOfIso = element->GetNisotopes();
842 //go through isotopes
843 for (Int_t idx = 0; idx < nOfIso; idx++) {
844 TGeoIsotope *myIsotope = element->GetIsotope(idx);
845 if (!myIsotope) {
846 Fatal("CreateElementN", "Missing isotopes for element %s", element->GetName());
847 return mainN;
848 }
849
850 //Get name of the Isotope (
851 TString lname = myIsotope->GetName();
852 //_iso suffix is added to avoid problems with same names
853 //for material, element and isotopes
854 lname = TString::Format("%s_iso", lname.Data());
855
856 //cumulates abundance, in case 2 isotopes with same names
857 //within one element
858 wPercentage[lname] += element->GetRelativeAbundance(idx);
859 wCounter[lname]++;
860
861 //check whether isotope name is not in list of isotopes
862 if (IsInList(fIsotopeList->fLst, lname)) {
863 continue;
864 }
865 //add isotope to list of isotopes and to main <materials> node
866 fIsotopeList->fLst[lname] = kTRUE;
867 XMLNodePointer_t isoNode = CreateIsotopN(myIsotope, lname);
868 fGdmlE->AddChild(materials, isoNode);
869 }
870 //loop through asoc array of isotopes
871 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
872 if (itr->second > 1) {
873 Info("CreateMixtureN", "WARNING! 2 equal isotopes in one element. Check: %s isotope of %s element",
874 itr->first.Data(), name);
875 }
876 //add fraction child to element with reference to isotope
877 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
878 }
879 } else {
880 fGdmlE->NewAttr(mainN, nullptr, "formula", element->GetName());
881 Int_t valZ = element->Z();
882 // Z can't be <1 in Geant4 and Z is optional parameter
883 if (valZ >= 1) {
884 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", valZ));
885 }
886 Int_t valN = element->N();
887 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", valN));
888 fGdmlE->AddChild(mainN, CreateAtomN(element->A()));
889 }
890 return mainN;
891}
892
893////////////////////////////////////////////////////////////////////////////////
894/// Creates "material" node for GDML with references to other sub elements
895
897{
898 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
899 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
900
901 // Write properties
902 TList const &properties = mixture->GetProperties();
903 if (properties.GetSize()) {
904 TIter next(&properties);
906 while ((property = (TNamed*)next()))
908 }
909 // Write CONST properties
910 TList const &const_properties = mixture->GetConstProperties();
911 if (const_properties.GetSize()) {
912 TIter next(&const_properties);
914 while ((property = (TNamed*)next()))
916 }
917
918 fGdmlE->AddChild(mainN, CreateDN(mixture->GetDensity()));
919 //local associative arrays for saving elements and their weight
920 //inside mixture
921 NameListF wPercentage;
922 NameListI wCounter;
923
924 Int_t nOfElm = mixture->GetNelements();
925 //go through elements
926 for (Int_t idx = 0; idx < nOfElm; idx++) {
927 TGeoElement *myElement = mixture->GetElement(idx);
928
929 //Get name of the element
930 //NOTE: that for element - GetTitle() returns the "name" tag
931 //and GetName() returns "formula" tag (see createElementN)
932 TString lname = myElement->GetTitle();
933 //_elm suffix is added to avoid problems with same names
934 //for material and element
935 lname = TString::Format("%s_elm", lname.Data());
936
937 //cumulates percentage, in case 2 elements with same names within one mixture
938 wPercentage[lname] += mixture->GetWmixt()[idx];
939 wCounter[lname]++;
940
941 //check whether element name is not in list of elements already created
942 if (IsInList(fElementList->fLst, lname)) {
943 continue;
944 }
945
946 //add element to list of elements and to main <materials> node
947 fElementList->fLst[lname] = kTRUE;
948 XMLNodePointer_t elmNode = CreateElementN(myElement, materials, lname);
949 fGdmlE->AddChild(materials, elmNode);
950 }
951 //loop through asoc array
952 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
953 if (itr->second > 1) {
954 Info("CreateMixtureN", "WARNING! 2 equal elements in one material. Check: %s element of %s material",
955 itr->first.Data(), mname.Data());
956 }
957 //add fraction child to material with reference to element
958 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
959 }
960
961 return mainN;
962}
963
964////////////////////////////////////////////////////////////////////////////////
965/// Creates "material" node for GDML
966
968{
969 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
970 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
971 Double_t valZ = material->GetZ();
972 //Z can't be zero in Geant4 so this is workaround for vacuum
973 TString tmpname = mname;
974 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
975 tmpname.ToLower();
976 if (valZ < 1) {
977 if (tmpname == "vacuum") {
978 valZ = 1;
979 } else {
980 if (fgG4Compatibility == kTRUE) {
981 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! ",
982 mname.Data());
983 valZ = 1;
984 } else {
985 Info("CreateMaterialN", "WARNING! value of Z in %s material can't be < 1 in Geant4", mname.Data());
986 }
987 }
988 }
989 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format(fltPrecision.Data(), valZ)); //material->GetZ()));
990
991 // Create properties if any: Properties according to the GDML schema MUST come first!
992 TList const &properties = material->GetProperties();
993 if (properties.GetSize()) {
994 TIter next(&properties);
996 while ((property = (TNamed *)next()))
998 }
999 // Write CONST properties
1000 TList const &const_properties = material->GetConstProperties();
1001 if (const_properties.GetSize()) {
1002 TIter next(&const_properties);
1004 while ((property = (TNamed *)next()))
1006 }
1007
1008 // Now add the other children
1009 fGdmlE->AddChild(mainN, CreateDN(material->GetDensity()));
1010 fGdmlE->AddChild(mainN, CreateAtomN(material->GetA()));
1011 return mainN;
1012}
1013
1014////////////////////////////////////////////////////////////////////////////////
1015/// Creates "box" node for GDML
1016
1018{
1019 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "box", nullptr);
1020 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1021 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1022 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1023 if (IsNullParam(geoShape->GetDX(), "DX", lname) ||
1024 IsNullParam(geoShape->GetDY(), "DY", lname) ||
1025 IsNullParam(geoShape->GetDZ(), "DZ", lname)) {
1026 return nullptr;
1027 }
1028 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDX()));
1029 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDY()));
1030 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDZ()));
1031
1032 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1033 return mainN;
1034}
1035
1036////////////////////////////////////////////////////////////////////////////////
1037/// Creates "paraboloid" node for GDML
1038
1040{
1041 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "paraboloid", nullptr);
1042 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1043 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1044 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1045 if (IsNullParam(geoShape->GetRhi(), "Rhi", lname) ||
1046 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1047 return nullptr;
1048 }
1049 fGdmlE->NewAttr(mainN, nullptr, "rlo", TString::Format(fltPrecision.Data(), geoShape->GetRlo()));
1050 fGdmlE->NewAttr(mainN, nullptr, "rhi", TString::Format(fltPrecision.Data(), geoShape->GetRhi()));
1051 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1052
1053 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1054 return mainN;
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Creates "sphere" node for GDML
1059
1061{
1062 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "sphere", nullptr);
1063 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1064 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1065 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1066 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1067 return nullptr;
1068 }
1069
1070 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1071 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1072 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1073 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1074 fGdmlE->NewAttr(mainN, nullptr, "starttheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta1()));
1075 fGdmlE->NewAttr(mainN, nullptr, "deltatheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta2() - geoShape->GetTheta1()));
1076
1077 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1078 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1079 return mainN;
1080}
1081
1082////////////////////////////////////////////////////////////////////////////////
1083/// Creates "arb8" node for GDML
1084
1086{
1087 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "arb8", nullptr);
1088 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1089 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1090 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1091 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1092 return nullptr;
1093 }
1094
1095 fGdmlE->NewAttr(mainN, nullptr, "v1x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[0]));
1096 fGdmlE->NewAttr(mainN, nullptr, "v1y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[1]));
1097 fGdmlE->NewAttr(mainN, nullptr, "v2x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[2]));
1098 fGdmlE->NewAttr(mainN, nullptr, "v2y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[3]));
1099 fGdmlE->NewAttr(mainN, nullptr, "v3x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[4]));
1100 fGdmlE->NewAttr(mainN, nullptr, "v3y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[5]));
1101 fGdmlE->NewAttr(mainN, nullptr, "v4x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[6]));
1102 fGdmlE->NewAttr(mainN, nullptr, "v4y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[7]));
1103 fGdmlE->NewAttr(mainN, nullptr, "v5x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[8]));
1104 fGdmlE->NewAttr(mainN, nullptr, "v5y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[9]));
1105 fGdmlE->NewAttr(mainN, nullptr, "v6x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[10]));
1106 fGdmlE->NewAttr(mainN, nullptr, "v6y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[11]));
1107 fGdmlE->NewAttr(mainN, nullptr, "v7x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[12]));
1108 fGdmlE->NewAttr(mainN, nullptr, "v7y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[13]));
1109 fGdmlE->NewAttr(mainN, nullptr, "v8x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[14]));
1110 fGdmlE->NewAttr(mainN, nullptr, "v8y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[15]));
1111 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1112
1113 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1114 return mainN;
1115}
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Creates "cone" node for GDML from TGeoConeSeg object
1119
1121{
1122 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1123 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1124 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1125 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1126 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1127 return nullptr;
1128 }
1129
1130 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1131 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1132 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1133 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1134 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1135 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1136 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1137
1138 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1139 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1140 return mainN;
1141}
1142
1143////////////////////////////////////////////////////////////////////////////////
1144/// Creates "cone" node for GDML from TGeoCone object
1145
1147{
1148 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1149 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1150 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1151 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1152 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1153 return nullptr;
1154 }
1155
1156 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1157 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1158 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1159 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1160 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1161 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1162 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1163
1164 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1165 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1166 return mainN;
1167}
1168
1169////////////////////////////////////////////////////////////////////////////////
1170/// Creates "para" node for GDML
1171
1173{
1174 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "para", nullptr);
1175 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1176 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1177
1178 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetX()));
1179 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetY()));
1180 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetZ()));
1181 fGdmlE->NewAttr(mainN, nullptr, "alpha", TString::Format(fltPrecision.Data(), geoShape->GetAlpha()));
1182 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1183 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1184
1185 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1186 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1187 return mainN;
1188}
1189
1190////////////////////////////////////////////////////////////////////////////////
1191/// Creates "trap" node for GDML
1192
1194{
1195 XMLNodePointer_t mainN;
1196 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1197
1198 //if one base equals 0 create Arb8 instead of trap
1199 if ((geoShape->GetBl1() == 0 || geoShape->GetTl1() == 0 || geoShape->GetH1() == 0) ||
1200 (geoShape->GetBl2() == 0 || geoShape->GetTl2() == 0 || geoShape->GetH2() == 0)) {
1201 mainN = CreateArb8N(geoShape);
1202 return mainN;
1203 }
1204
1205 //if is twisted then create arb8
1206 if (geoShape->IsTwisted()) {
1207 mainN = CreateArb8N((TGeoArb8 *) geoShape);
1208 return mainN;
1209 }
1210
1211 mainN = fGdmlE->NewChild(nullptr, nullptr, "trap", nullptr);
1212 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1213 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1214 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1215 return nullptr;
1216 }
1217
1218 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1219 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1220 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1221 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1222 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1223 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1224 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1225 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1226 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1227
1228 fGdmlE->NewAttr(mainN, nullptr, "alpha1", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1229 fGdmlE->NewAttr(mainN, nullptr, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1230
1231 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1232 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1233 return mainN;
1234}
1235
1236////////////////////////////////////////////////////////////////////////////////
1237/// Creates "twistedtrap" node for GDML
1238
1240{
1241 XMLNodePointer_t mainN;
1242 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1243
1244 //if one base equals 0 create Arb8 instead of twisted trap
1245 if ((geoShape->GetBl1() == 0 && geoShape->GetTl1() == 0 && geoShape->GetH1() == 0) ||
1246 (geoShape->GetBl2() == 0 && geoShape->GetTl2() == 0 && geoShape->GetH2() == 0)) {
1247 mainN = CreateArb8N((TGeoArb8 *) geoShape);
1248 return mainN;
1249 }
1250
1251 //if is twisted then create arb8
1252 if (geoShape->IsTwisted()) {
1253 mainN = CreateArb8N((TGeoArb8 *) geoShape);
1254 return mainN;
1255 }
1256
1257 //if parameter twistAngle (PhiTwist) equals zero create trap node
1258 if (geoShape->GetTwistAngle() == 0) {
1259 mainN = CreateTrapN((TGeoTrap *) geoShape);
1260 return mainN;
1261 }
1262
1263 mainN = fGdmlE->NewChild(nullptr, nullptr, "twistedtrap", nullptr);
1264 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1265 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1266 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1267 return nullptr;
1268 }
1269
1270 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1271 fGdmlE->NewAttr(mainN, nullptr, "Theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1272 fGdmlE->NewAttr(mainN, nullptr, "Phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1273 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1274 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1275 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1276 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1277 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1278 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1279
1280 fGdmlE->NewAttr(mainN, nullptr, "Alph", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1281
1282 //check if alpha1 equals to alpha2 (converting to string - to avoid problems with floats)
1283 if (TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()) != TString::Format(fltPrecision.Data(), geoShape->GetAlpha2())) {
1284 Info("CreateTwistedTrapN",
1285 "ERROR! Object %s is not exported correctly because parameter Alpha2 is not declared in GDML schema",
1286 lname.Data());
1287 }
1288 //fGdmlE->NewAttr(mainN,0, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1289 fGdmlE->NewAttr(mainN, nullptr, "PhiTwist", TString::Format(fltPrecision.Data(), geoShape->GetTwistAngle()));
1290
1291 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1292 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1293 return mainN;
1294}
1295
1296////////////////////////////////////////////////////////////////////////////////
1297/// Creates "trd" node for GDML from object TGeoTrd1
1298
1300{
1301 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1302 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1303 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1304 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1305 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1306 return nullptr;
1307 }
1308
1309 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1310 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1311 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1312 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1313 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1314
1315 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1316 return mainN;
1317}
1318
1319////////////////////////////////////////////////////////////////////////////////
1320/// Creates "trd" node for GDML from object TGeoTrd2
1321
1323{
1324 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1325 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1326 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1327 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1328 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1329 return nullptr;
1330 }
1331
1332 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1333 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1334 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy1()));
1335 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy2()));
1336 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1337
1338 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1339 return mainN;
1340}
1341
1342////////////////////////////////////////////////////////////////////////////////
1343/// Creates "tube" node for GDML from object TGeoTubeSeg
1344
1346{
1347 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1348 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1349 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1350 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1351 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1352 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1353 return nullptr;
1354 }
1355
1356 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1357 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1358 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1359 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1360 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1361
1362 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1363 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1364 return mainN;
1365}
1366
1367////////////////////////////////////////////////////////////////////////////////
1368/// Creates "cutTube" node for GDML
1369
1371{
1372 XMLNodePointer_t mainN;
1373 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1374
1375 mainN = fGdmlE->NewChild(nullptr, nullptr, "cutTube", nullptr);
1376 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1377 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1378 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1379 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1380 return nullptr;
1381 }
1382 //This is not needed, because cutTube is already supported by Geant4 9.5
1383 if (fgG4Compatibility == kTRUE && kFALSE) {
1384 TGeoShape * fakeCtub = CreateFakeCtub(geoShape);
1385 mainN = ChooseObject(fakeCtub);
1386
1387 //register name for cuttube shape (so it will be found during volume export)
1388 lname = fNameList->fLst[TString::Format("%p", fakeCtub)];
1389 fNameList->fLst[TString::Format("%p", geoShape)] = lname;
1390 Info("CreateCutTubeN", "WARNING! %s - CutTube was replaced by intersection of TGeoTubSeg and two TGeoBBoxes",
1391 lname.Data());
1392 return mainN;
1393 }
1394 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1395 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1396 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1397 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1398 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1399 fGdmlE->NewAttr(mainN, nullptr, "lowX", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[0]));
1400 fGdmlE->NewAttr(mainN, nullptr, "lowY", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[1]));
1401 fGdmlE->NewAttr(mainN, nullptr, "lowZ", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[2]));
1402 fGdmlE->NewAttr(mainN, nullptr, "highX", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[0]));
1403 fGdmlE->NewAttr(mainN, nullptr, "highY", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[1]));
1404 fGdmlE->NewAttr(mainN, nullptr, "highZ", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[2]));
1405
1406 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1407 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1408
1409 return mainN;
1410}
1411
1412////////////////////////////////////////////////////////////////////////////////
1413/// Creates "tube" node for GDML from object TGeoTube
1414
1416{
1417 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1418 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1419 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1420 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1421 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) ||
1422 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1423 return nullptr;
1424 }
1425
1426 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1427 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1428 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1429 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1430 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1431
1432 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1433 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1434 return mainN;
1435}
1436
1437////////////////////////////////////////////////////////////////////////////////
1438/// Creates "zplane" node for GDML
1439
1441{
1442 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "zplane", nullptr);
1443 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1444
1445 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), z));
1446 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), rmin));
1447 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), rmax));
1448
1449 return mainN;
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// Creates "polycone" node for GDML
1454
1456{
1457 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polycone", nullptr);
1458 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1459 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1460 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1461
1462 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1463 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1464
1465 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1466 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1467 Int_t nZPlns = geoShape->GetNz();
1468 for (Int_t it = 0; it < nZPlns; it++) {
1469 //add zplane child node
1470 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1471 //compare actual plane and next plane
1472 if ((it < nZPlns - 1) && (geoShape->GetZ(it) == geoShape->GetZ(it + 1))) {
1473 //rmin of actual is greater then rmax of next one
1474 // | |rmax next
1475 // __ ...| |... __ < rmin actual
1476 // | | | |
1477 if (geoShape->GetRmin(it) > geoShape->GetRmax(it + 1)) {
1478 //adding plane from rmax next to rmin actual at the same z position
1479 if (fgG4Compatibility == kTRUE) {
1480 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it + 1), geoShape->GetRmin(it)));
1481 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4", lname.Data());
1482 } else {
1483 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4", lname.Data());
1484 }
1485
1486 }
1487 //rmin of next is greater then rmax of actual
1488 // | | | |
1489 // | |...___...| | rmin next
1490 // | | > rmax act
1491 if (geoShape->GetRmin(it + 1) > geoShape->GetRmax(it)) {
1492 //adding plane from rmax act to rmin next at the same z position
1493 if (fgG4Compatibility == kTRUE) {
1494 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it), geoShape->GetRmin(it + 1)));
1495 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4", lname.Data());
1496 } else {
1497 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4", lname.Data());
1498 }
1499 }
1500 }
1501 }
1502 return mainN;
1503}
1504
1505////////////////////////////////////////////////////////////////////////////////
1506/// Creates "torus" node for GDML
1507
1509{
1510 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "torus", nullptr);
1511 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1512 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1513 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1514 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1515 return nullptr;
1516 }
1517
1518 fGdmlE->NewAttr(mainN, nullptr, "rtor", TString::Format(fltPrecision.Data(), geoShape->GetR()));
1519 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1520 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1521 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1522 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1523
1524 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1525 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1526
1527 return mainN;
1528}
1529
1530////////////////////////////////////////////////////////////////////////////////
1531/// Creates "polyhedra" node for GDML
1532
1534{
1535 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polyhedra", nullptr);
1536 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1537 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1538
1539 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1540 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1541 fGdmlE->NewAttr(mainN, nullptr, "numsides", TString::Format("%i", geoShape->GetNedges()));
1542
1543 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1544 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1545 for (Int_t it = 0; it < geoShape->GetNz(); it++) {
1546 //add zplane child node
1547 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1548 }
1549 return mainN;
1550}
1551
1552////////////////////////////////////////////////////////////////////////////////
1553/// Creates "eltube" node for GDML
1554
1556{
1557 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "eltube", nullptr);
1558 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1559 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1560 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1561 if (IsNullParam(geoShape->GetA(), "A", lname) ||
1562 IsNullParam(geoShape->GetB(), "B", lname) ||
1563 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1564 return nullptr;
1565 }
1566
1567 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(fltPrecision.Data(), geoShape->GetA()));
1568 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(fltPrecision.Data(), geoShape->GetB()));
1569 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1570
1571 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1572
1573 return mainN;
1574}
1575
1576////////////////////////////////////////////////////////////////////////////////
1577/// Creates "hype" node for GDML
1578
1580{
1581 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "hype", nullptr);
1582 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1583 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1584 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1585 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1586 return nullptr;
1587 }
1588
1589
1590 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1591 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1592 fGdmlE->NewAttr(mainN, nullptr, "inst", TString::Format(fltPrecision.Data(), geoShape->GetStIn()));
1593 fGdmlE->NewAttr(mainN, nullptr, "outst", TString::Format(fltPrecision.Data(), geoShape->GetStOut()));
1594 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1595
1596 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1597 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1598
1599 return mainN;
1600}
1601
1602////////////////////////////////////////////////////////////////////////////////
1603/// Creates "xtru" node for GDML
1604
1606{
1607 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "xtru", nullptr);
1608 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1609 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1610 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1611
1612 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1613 XMLNodePointer_t childN;
1614 Int_t vertNum = geoShape->GetNvert();
1615 Int_t secNum = geoShape->GetNz();
1616 if (vertNum < 3 || secNum < 2) {
1617 Info("CreateXtrusionN", "ERROR! TGeoXtru %s has only %i vertices and %i sections. It was not exported",
1618 lname.Data(), vertNum, secNum);
1619 mainN = nullptr;
1620 return mainN;
1621 }
1622 for (Int_t it = 0; it < vertNum; it++) {
1623 //add twoDimVertex child node
1624 childN = fGdmlE->NewChild(nullptr, nullptr, "twoDimVertex", nullptr);
1625 fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), geoShape->GetX(it)));
1626 fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), geoShape->GetY(it)));
1627 fGdmlE->AddChild(mainN, childN);
1628 }
1629 for (Int_t it = 0; it < secNum; it++) {
1630 //add section child node
1631 childN = fGdmlE->NewChild(nullptr, nullptr, "section", nullptr);
1632 fGdmlE->NewAttr(childN, nullptr, "zOrder", TString::Format("%i", it));
1633 fGdmlE->NewAttr(childN, nullptr, "zPosition", TString::Format(fltPrecision.Data(), geoShape->GetZ(it)));
1634 fGdmlE->NewAttr(childN, nullptr, "xOffset", TString::Format(fltPrecision.Data(), geoShape->GetXOffset(it)));
1635 fGdmlE->NewAttr(childN, nullptr, "yOffset", TString::Format(fltPrecision.Data(), geoShape->GetYOffset(it)));
1636 fGdmlE->NewAttr(childN, nullptr, "scalingFactor", TString::Format(fltPrecision.Data(), geoShape->GetScale(it)));
1637 fGdmlE->AddChild(mainN, childN);
1638 }
1639 return mainN;
1640}
1641
1642////////////////////////////////////////////////////////////////////////////////
1643/// Creates "ellipsoid" node for GDML
1644/// this is a special case, because ellipsoid is not defined in ROOT
1645/// so when intersection of scaled sphere and TGeoBBox is found,
1646/// it is considered as an ellipsoid
1647
1649{
1650 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "ellipsoid", nullptr);
1651 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1652 TGeoScaledShape *leftS = (TGeoScaledShape *)geoShape->GetBoolNode()->GetLeftShape(); //ScaledShape
1653 TGeoBBox *rightS = (TGeoBBox *)geoShape->GetBoolNode()->GetRightShape(); //BBox
1654
1655
1656 fGdmlE->NewAttr(mainN, nullptr, "name", elName.Data());
1657 Double_t sx = leftS->GetScale()->GetScale()[0];
1658 Double_t sy = leftS->GetScale()->GetScale()[1];
1659 Double_t radius = ((TGeoSphere *) leftS->GetShape())->GetRmax();
1660
1661 Double_t ax, by, cz;
1662 cz = radius;
1663 ax = sx * radius;
1664 by = sy * radius;
1665
1666 Double_t dz = rightS->GetDZ();
1667 Double_t zorig = rightS->GetOrigin()[2];
1668 Double_t zcut2 = dz + zorig;
1669 Double_t zcut1 = 2 * zorig - zcut2;
1670
1671
1672 fGdmlE->NewAttr(mainN, nullptr, "ax", TString::Format(fltPrecision.Data(), ax));
1673 fGdmlE->NewAttr(mainN, nullptr, "by", TString::Format(fltPrecision.Data(), by));
1674 fGdmlE->NewAttr(mainN, nullptr, "cz", TString::Format(fltPrecision.Data(), cz));
1675 fGdmlE->NewAttr(mainN, nullptr, "zcut1", TString::Format(fltPrecision.Data(), zcut1));
1676 fGdmlE->NewAttr(mainN, nullptr, "zcut2", TString::Format(fltPrecision.Data(), zcut2));
1677 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1678
1679 return mainN;
1680}
1681
1682////////////////////////////////////////////////////////////////////////////////
1683/// Creates "elcone" (elliptical cone) node for GDML
1684/// this is a special case, because elliptical cone is not defined in ROOT
1685/// so when scaled cone is found, it is considered as a elliptical cone
1686
1688{
1689 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "elcone", nullptr);
1690 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1691 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1692 Double_t zcut = ((TGeoCone *) geoShape->GetShape())->GetDz();
1693 Double_t rx1 = ((TGeoCone *) geoShape->GetShape())->GetRmax1();
1694 Double_t rx2 = ((TGeoCone *) geoShape->GetShape())->GetRmax2();
1695 Double_t zmax = zcut * ((rx1 + rx2) / (rx1 - rx2));
1696 Double_t z = zcut + zmax;
1697
1698 Double_t sy = geoShape->GetScale()->GetScale()[1];
1699 Double_t ry1 = sy * rx1;
1700
1701 std::string format(TString::Format("%s/%s", fltPrecision.Data(), fltPrecision.Data()).Data());
1702 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(format.c_str(), rx1, z));
1703 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(format.c_str(), ry1, z));
1704 fGdmlE->NewAttr(mainN, nullptr, "zmax", TString::Format(fltPrecision.Data(), zmax));
1705 fGdmlE->NewAttr(mainN, nullptr, "zcut", TString::Format(fltPrecision.Data(), zcut));
1706 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1707
1708 return mainN;
1709}
1710
1711////////////////////////////////////////////////////////////////////////////////
1712/// Creates "tessellated" (tessellated shape) node for GDML
1713
1715{
1716 // add all vertices to the define section
1717 TString genname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1718 for (int i = 0; i < geoShape->GetNvertices(); ++i) {
1719 auto vertex = geoShape->GetVertex(i);
1720 TString posName = TString::Format("%s_%d", genname.Data(), i);
1721 Xyz nodPos;
1722 nodPos.x = vertex[0];
1723 nodPos.y = vertex[1];
1724 nodPos.z = vertex[2];
1725 auto childN = CreatePositionN(posName.Data(), nodPos, "position", fDefault_lunit);
1726 fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
1727 }
1728 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tessellated", nullptr);
1729 fGdmlE->NewAttr(mainN, nullptr, "name", genname.Data());
1730 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1731
1732 XMLNodePointer_t childN;
1733 for (Int_t it = 0; it < geoShape->GetNfacets(); it++) {
1734 //add section child node
1735 auto facet = geoShape->GetFacet(it);
1736 bool triangular = facet.GetNvert() == 3;
1737 TString ntype = (triangular) ? "triangular" : "quadrangular";
1738 childN = fGdmlE->NewChild(nullptr, nullptr, ntype.Data(), nullptr);
1739 fGdmlE->NewAttr(childN, nullptr, "vertex1", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(0)));
1740 fGdmlE->NewAttr(childN, nullptr, "vertex2", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(1)));
1741 fGdmlE->NewAttr(childN, nullptr, "vertex3", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(2)));
1742 if (!triangular)
1743 fGdmlE->NewAttr(childN, nullptr, "vertex4", TString::Format("%s_%d", genname.Data(), facet.GetVertexIndex(3)));
1744 fGdmlE->NewAttr(childN, nullptr, "type", "ABSOLUTE");
1745 fGdmlE->AddChild(mainN, childN);
1746 }
1747 return mainN;
1748}
1749
1750////////////////////////////////////////////////////////////////////////////////
1751/// Creates common part of union intersection and subtraction nodes
1752
1754{
1755 XMLNodePointer_t mainN, ndR, ndL, childN;
1756 TString nodeName = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1757 TString lboolType;
1759 switch (boolType) {
1761 lboolType = "union";
1762 break;
1764 lboolType = "subtraction";
1765 break;
1767 lboolType = "intersection";
1768 break;
1769 }
1770
1772 const Double_t *ltr = geoShape->GetBoolNode()->GetLeftMatrix()->GetTranslation();
1774 const Double_t *rtr = geoShape->GetBoolNode()->GetRightMatrix()->GetTranslation();
1775
1776 //specific case!
1777 //Ellipsoid tag preparing
1778 //if left == TGeoScaledShape AND right == TGeoBBox
1779 // AND if TGeoScaledShape->GetShape == TGeoSphere
1780 TGeoShape *leftS = geoShape->GetBoolNode()->GetLeftShape();
1781 TGeoShape *rightS = geoShape->GetBoolNode()->GetRightShape();
1782 if (strcmp(leftS->ClassName(), "TGeoScaledShape") == 0 &&
1783 strcmp(rightS->ClassName(), "TGeoBBox") == 0) {
1784 if (strcmp(((TGeoScaledShape *)leftS)->GetShape()->ClassName(), "TGeoSphere") == 0) {
1785 if (lboolType == "intersection") {
1786 mainN = CreateEllipsoidN(geoShape, nodeName);
1787 return mainN;
1788 }
1789 }
1790 }
1791
1792 Xyz translL, translR;
1793 //translation
1794 translL.x = ltr[0];
1795 translL.y = ltr[1];
1796 translL.z = ltr[2];
1797 translR.x = rtr[0];
1798 translR.y = rtr[1];
1799 translR.z = rtr[2];
1800
1801 //left and right nodes are created here also their names are created
1802 ndL = ChooseObject(geoShape->GetBoolNode()->GetLeftShape());
1803 ndR = ChooseObject(geoShape->GetBoolNode()->GetRightShape());
1804
1805 //retrieve left and right node names by their pointer to make reference
1806 TString lname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetLeftShape())];
1807 TString rname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetRightShape())];
1808
1809 //left and right nodes appended to main structure of nodes (if they are not already there)
1810 if (ndL != nullptr) {
1812 fSolCnt++;
1813 } else {
1814 if (lname.Contains("missing_") || lname == "") {
1815 Info("CreateCommonBoolN", "ERROR! Left node is NULL - Boolean Shape will be skipped");
1816 return nullptr;
1817 }
1818 }
1819 if (ndR != nullptr) {
1821 fSolCnt++;
1822 } else {
1823 if (rname.Contains("missing_") || rname == "") {
1824 Info("CreateCommonBoolN", "ERROR! Right node is NULL - Boolean Shape will be skipped");
1825 return nullptr;
1826 }
1827 }
1828
1829 //create union node and its child nodes (or intersection or subtraction)
1830 /* <union name="...">
1831 * <first ref="left name" />
1832 * <second ref="right name" />
1833 * <firstposition .../>
1834 * <firstrotation .../>
1835 * <position .../>
1836 * <rotation .../>
1837 * </union>
1838 */
1839 mainN = fGdmlE->NewChild(nullptr, nullptr, lboolType.Data(), nullptr);
1840 fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1841
1842 //<first> (left)
1843 childN = fGdmlE->NewChild(nullptr, nullptr, "first", nullptr);
1844 fGdmlE->NewAttr(childN, nullptr, "ref", lname);
1845 fGdmlE->AddChild(mainN, childN);
1846
1847 //<second> (right)
1848 childN = fGdmlE->NewChild(nullptr, nullptr, "second", nullptr);
1849 fGdmlE->NewAttr(childN, nullptr, "ref", rname);
1850 fGdmlE->AddChild(mainN, childN);
1851
1852 //<firstposition> (left)
1853 if ((translL.x != 0.0) || (translL.y != 0.0) || (translL.z != 0.0)) {
1854 childN = CreatePositionN((nodeName + lname + "pos").Data(), translL, "firstposition", fDefault_lunit);
1855 fGdmlE->AddChild(mainN, childN);
1856 }
1857 //<firstrotation> (left)
1858 if ((lrot.x != 0.0) || (lrot.y != 0.0) || (lrot.z != 0.0)) {
1859 childN = CreateRotationN((nodeName + lname + "rot").Data(), lrot, "firstrotation");
1860 fGdmlE->AddChild(mainN, childN);
1861 }
1862 //<position> (right)
1863 if ((translR.x != 0.0) || (translR.y != 0.0) || (translR.z != 0.0)) {
1864 childN = CreatePositionN((nodeName + rname + "pos").Data(), translR, "position", fDefault_lunit);
1865 fGdmlE->AddChild(mainN, childN);
1866 }
1867 //<rotation> (right)
1868 if ((rrot.x != 0.0) || (rrot.y != 0.0) || (rrot.z != 0.0)) {
1869 childN = CreateRotationN((nodeName + rname + "rot").Data(), rrot, "rotation");
1870 fGdmlE->AddChild(mainN, childN);
1871 }
1872
1873 return mainN;
1874}
1875
1876////////////////////////////////////////////////////////////////////////////////
1877/// Creates "opticalsurface" node for GDML
1878
1880{
1881 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "opticalsurface", nullptr);
1882 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1883 std::string name = make_NCName(geoSurf->GetName());
1884 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
1885 fGdmlE->NewAttr(mainN, nullptr, "model", TGeoOpticalSurface::ModelToString(geoSurf->GetModel()));
1886 fGdmlE->NewAttr(mainN, nullptr, "finish", TGeoOpticalSurface::FinishToString(geoSurf->GetFinish()));
1887 fGdmlE->NewAttr(mainN, nullptr, "type", TGeoOpticalSurface::TypeToString(geoSurf->GetType()));
1888 fGdmlE->NewAttr(mainN, nullptr, "value", TString::Format(fltPrecision.Data(), geoSurf->GetValue()));
1889
1890 // Write properties
1891 TList const &properties = geoSurf->GetProperties();
1892 if (properties.GetSize()) {
1893 TIter next(&properties);
1895 while ((property = (TNamed*)next()))
1897 }
1898 return mainN;
1899}
1900
1901////////////////////////////////////////////////////////////////////////////////
1902/// Creates "skinsurface" node for GDML
1903
1905{
1906 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "skinsurface", nullptr);
1907 std::string name = make_NCName(geoSurf->GetName());
1908 std::string prop = make_NCName(geoSurf->GetTitle());
1909
1910 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
1911 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
1912
1913 // Cretate the logical volume reference node
1914 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
1915 const TString &volname = fNameList->fLst[TString::Format("%p", geoSurf->GetVolume())];
1916 fGdmlE->NewAttr(childN, nullptr, "ref", volname.Data());
1917 fGdmlE->AddChild(mainN, childN);
1918 return mainN;
1919}
1920
1921////////////////////////////////////////////////////////////////////////////////
1922/// Creates "bordersurface" node for GDML
1923
1925{
1926 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "bordersurface", nullptr);
1927 std::string name = make_NCName(geoSurf->GetName());
1928 std::string prop = make_NCName(geoSurf->GetTitle());
1929
1930 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
1931 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
1932
1933 // Cretate the logical volume reference nodes
1934 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
1935 TString physvolname = fNameList->fLst[TString::Format("%p", geoSurf->GetNode1())];
1936 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
1937 fGdmlE->AddChild(mainN, childN);
1938
1939 childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
1940 physvolname = fNameList->fLst[TString::Format("%p", geoSurf->GetNode2())];
1941 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
1942 fGdmlE->AddChild(mainN, childN);
1943 return mainN;
1944}
1945
1946////////////////////////////////////////////////////////////////////////////////
1947/// Creates "position" kind of node for GDML
1948
1949XMLNodePointer_t TGDMLWrite::CreatePositionN(const char * name, Xyz position, const char * type, const char * unit)
1950{
1951 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
1952 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1953 fGdmlE->NewAttr(mainN, nullptr, "name", name);
1954 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), position.x));
1955 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), position.y));
1956 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), position.z));
1957 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
1958 return mainN;
1959}
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Creates "rotation" kind of node for GDML
1963
1964XMLNodePointer_t TGDMLWrite::CreateRotationN(const char * name, Xyz rotation, const char * type, const char * unit)
1965{
1966 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
1967 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1968 fGdmlE->NewAttr(mainN, nullptr, "name", name);
1969 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), rotation.x));
1970 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), rotation.y));
1971 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), rotation.z));
1972 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
1973 return mainN;
1974}
1975
1976////////////////////////////////////////////////////////////////////////////////
1977/// Creates "matrix" kind of node for GDML
1978
1980{
1981 std::stringstream vals;
1982 size_t cols = matrix->GetCols();
1983 size_t rows = matrix->GetRows();
1984 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
1985 fGdmlE->NewAttr(mainN, nullptr, "name", matrix->GetName());
1986 fGdmlE->NewAttr(mainN, nullptr, "coldim", TString::Format("%zu", cols));
1987 for(size_t i=0; i<rows; ++i) {
1988 for(size_t j=0; j<cols; ++j) {
1989 vals << matrix->Get(i,j);
1990 if ( j < cols-1 ) vals << ' ';
1991 }
1992 if ( i < rows-1 ) vals << '\n';
1993 }
1994 fGdmlE->NewAttr(mainN, nullptr, "values", vals.str().c_str());
1995 return mainN;
1996}
1997
1998////////////////////////////////////////////////////////////////////////////////
1999/// Creates "constant" kind of node for GDML
2000
2002{
2003 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
2004 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2005 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2006 fGdmlE->NewAttr(mainN, nullptr, "coldim", "1");
2007 fGdmlE->NewAttr(mainN, nullptr, "values", TString::Format(fltPrecision.Data(), value));
2008 return mainN;
2009}
2010
2011////////////////////////////////////////////////////////////////////////////////
2012/// Creates "setup" node for GDML
2013
2014XMLNodePointer_t TGDMLWrite::CreateSetupN(const char * topVolName, const char * name, const char * version)
2015{
2016 XMLNodePointer_t setupN = fGdmlE->NewChild(nullptr, nullptr, "setup", nullptr);
2017 fGdmlE->NewAttr(setupN, nullptr, "name", name);
2018 fGdmlE->NewAttr(setupN, nullptr, "version", version);
2019 XMLNodePointer_t fworldN = fGdmlE->NewChild(setupN, nullptr, "world", nullptr);
2020 fGdmlE->NewAttr(fworldN, nullptr, "ref", topVolName);
2021 return setupN;
2022}
2023
2024////////////////////////////////////////////////////////////////////////////////
2025/// Creates "volume" node for GDML
2026
2027XMLNodePointer_t TGDMLWrite::StartVolumeN(const char * name, const char * solid, const char * material)
2028{
2029 XMLNodePointer_t childN;
2030 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "volume", nullptr);
2031 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2032
2033 childN = fGdmlE->NewChild(nullptr, nullptr, "materialref", nullptr);
2034 fGdmlE->NewAttr(childN, nullptr, "ref", material);
2035 fGdmlE->AddChild(mainN, childN);
2036
2037 childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
2038 fGdmlE->NewAttr(childN, nullptr, "ref", solid);
2039 fGdmlE->AddChild(mainN, childN);
2040
2041 return mainN;
2042}
2043
2044////////////////////////////////////////////////////////////////////////////////
2045/// Creates "assembly" node for GDML
2046
2048{
2049 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "assembly", nullptr);
2050 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2051
2052 return mainN;
2053}
2054
2055////////////////////////////////////////////////////////////////////////////////
2056/// Creates "physvol" node for GDML
2057
2058XMLNodePointer_t TGDMLWrite::CreatePhysVolN(const char *name, Int_t copyno, const char * volref, const char * posref, const char * rotref, XMLNodePointer_t scaleN)
2059{
2060 fPhysVolCnt++;
2061 XMLNodePointer_t childN;
2062 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "physvol", nullptr);
2063 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2064 fGdmlE->NewAttr(mainN, nullptr, "copynumber", TString::Format("%d",copyno));
2065
2066 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2067 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2068 fGdmlE->AddChild(mainN, childN);
2069
2070 childN = fGdmlE->NewChild(nullptr, nullptr, "positionref", nullptr);
2071 fGdmlE->NewAttr(childN, nullptr, "ref", posref);
2072 fGdmlE->AddChild(mainN, childN);
2073
2074 //if is not empty string add this node
2075 if (strcmp(rotref, "") != 0) {
2076 childN = fGdmlE->NewChild(nullptr, nullptr, "rotationref", nullptr);
2077 fGdmlE->NewAttr(childN, nullptr, "ref", rotref);
2078 fGdmlE->AddChild(mainN, childN);
2079 }
2080 if (scaleN != nullptr) {
2081 fGdmlE->AddChild(mainN, scaleN);
2082 }
2083
2084 return mainN;
2085}
2086
2087////////////////////////////////////////////////////////////////////////////////
2088/// Creates "divisionvol" node for GDML
2089
2090XMLNodePointer_t TGDMLWrite::CreateDivisionN(Double_t offset, Double_t width, Int_t number, const char * axis, const char * unit, const char * volref)
2091{
2092 XMLNodePointer_t childN = 0;
2093 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "divisionvol", nullptr);
2094 fGdmlE->NewAttr(mainN, nullptr, "axis", axis);
2095 fGdmlE->NewAttr(mainN, nullptr, "number", TString::Format("%i", number));
2096 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2097 if (fgG4Compatibility == kTRUE) {
2098 //if eg. full length is 20 and width * number = 20,0001 problem in geant4
2099 //unit is either in cm or degrees nothing else
2100 width = (floor(width * 1E4)) * 1E-4;
2101 if ((offset >= 0.) && (strcmp(axis, "kPhi") == 0)) {
2102 Int_t offsetI = (Int_t) offset;
2103 Double_t decimals = offset - offsetI;
2104 //put to range from 0 to 360 add decimals and then put to range 0 -> -360
2105 offset = (offsetI % 360) + decimals - 360;
2106 }
2107 }
2108 fGdmlE->NewAttr(mainN, nullptr, "width", TString::Format(fltPrecision.Data(), width));
2109
2110 fGdmlE->NewAttr(mainN, nullptr, "offset", TString::Format(fltPrecision.Data(), offset));
2111 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2112 if (strcmp(volref, "") != 0) {
2113 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2114 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2115 }
2116 fGdmlE->AddChild(mainN, childN);
2117
2118
2119 return mainN;
2120}
2121
2122////////////////////////////////////////////////////////////////////////////////
2123/// Chooses the object and method that should be used for processing object
2124
2126{
2127 const char * clsname = geoShape->ClassName();
2128 XMLNodePointer_t solidN;
2129
2130 if (CanProcess((TObject *)geoShape) == kFALSE) {
2131 return nullptr;
2132 }
2133
2134 //process different shapes
2135 if (strcmp(clsname, "TGeoBBox") == 0) {
2136 solidN = CreateBoxN((TGeoBBox*) geoShape);
2137 } else if (strcmp(clsname, "TGeoParaboloid") == 0) {
2138 solidN = CreateParaboloidN((TGeoParaboloid*) geoShape);
2139 } else if (strcmp(clsname, "TGeoSphere") == 0) {
2140 solidN = CreateSphereN((TGeoSphere*) geoShape);
2141 } else if (strcmp(clsname, "TGeoArb8") == 0) {
2142 solidN = CreateArb8N((TGeoArb8*) geoShape);
2143 } else if (strcmp(clsname, "TGeoConeSeg") == 0) {
2144 solidN = CreateConeN((TGeoConeSeg*) geoShape);
2145 } else if (strcmp(clsname, "TGeoCone") == 0) {
2146 solidN = CreateConeN((TGeoCone*) geoShape);
2147 } else if (strcmp(clsname, "TGeoPara") == 0) {
2148 solidN = CreateParaN((TGeoPara*) geoShape);
2149 } else if (strcmp(clsname, "TGeoTrap") == 0) {
2150 solidN = CreateTrapN((TGeoTrap*) geoShape);
2151 } else if (strcmp(clsname, "TGeoGtra") == 0) {
2152 solidN = CreateTwistedTrapN((TGeoGtra*) geoShape);
2153 } else if (strcmp(clsname, "TGeoTrd1") == 0) {
2154 solidN = CreateTrdN((TGeoTrd1*) geoShape);
2155 } else if (strcmp(clsname, "TGeoTrd2") == 0) {
2156 solidN = CreateTrdN((TGeoTrd2*) geoShape);
2157 } else if (strcmp(clsname, "TGeoTubeSeg") == 0) {
2158 solidN = CreateTubeN((TGeoTubeSeg*) geoShape);
2159 } else if (strcmp(clsname, "TGeoCtub") == 0) {
2160 solidN = CreateCutTubeN((TGeoCtub*) geoShape);
2161 } else if (strcmp(clsname, "TGeoTube") == 0) {
2162 solidN = CreateTubeN((TGeoTube*) geoShape);
2163 } else if (strcmp(clsname, "TGeoPcon") == 0) {
2164 solidN = CreatePolyconeN((TGeoPcon*) geoShape);
2165 } else if (strcmp(clsname, "TGeoTorus") == 0) {
2166 solidN = CreateTorusN((TGeoTorus*) geoShape);
2167 } else if (strcmp(clsname, "TGeoPgon") == 0) {
2168 solidN = CreatePolyhedraN((TGeoPgon*) geoShape);
2169 } else if (strcmp(clsname, "TGeoEltu") == 0) {
2170 solidN = CreateEltubeN((TGeoEltu*) geoShape);
2171 } else if (strcmp(clsname, "TGeoHype") == 0) {
2172 solidN = CreateHypeN((TGeoHype*) geoShape);
2173 } else if (strcmp(clsname, "TGeoXtru") == 0) {
2174 solidN = CreateXtrusionN((TGeoXtru*) geoShape);
2175 } else if (strcmp(clsname, "TGeoTessellated") == 0) {
2176 solidN = CreateTessellatedN((TGeoTessellated*) geoShape);
2177 } else if (strcmp(clsname, "TGeoScaledShape") == 0) {
2178 TGeoScaledShape * geoscale = (TGeoScaledShape *) geoShape;
2179 TString scaleObjClsName = geoscale->GetShape()->ClassName();
2180 if (scaleObjClsName == "TGeoCone") {
2181 solidN = CreateElConeN((TGeoScaledShape*) geoShape);
2182 } else {
2183 Info("ChooseObject",
2184 "ERROR! TGeoScaledShape object is not possible to process correctly. %s object is processed without scale",
2185 scaleObjClsName.Data());
2186 solidN = ChooseObject(geoscale->GetShape());
2187 //Name has to be propagated to geoscale level pointer
2188 fNameList->fLst[TString::Format("%p", geoscale)] =
2189 fNameList->fLst[TString::Format("%p", geoscale->GetShape())];
2190 }
2191 } else if (strcmp(clsname, "TGeoCompositeShape") == 0) {
2192 solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2193 } else if (strcmp(clsname, "TGeoUnion") == 0) {
2194 solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2195 } else if (strcmp(clsname, "TGeoIntersection") == 0) {
2196 solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2197 } else if (strcmp(clsname, "TGeoSubtraction") == 0) {
2198 solidN = CreateCommonBoolN((TGeoCompositeShape*) geoShape);
2199 } else {
2200 Info("ChooseObject", "ERROR! %s Solid CANNOT be processed, solid is NOT supported",
2201 clsname);
2202 solidN = nullptr;
2203 }
2204 if (solidN == nullptr) {
2205 if (fNameList->fLst[TString::Format("%p", geoShape)] == "") {
2206 TString missingName = geoShape->GetName();
2207 GenName("missing_" + missingName, TString::Format("%p", geoShape));
2208 } else {
2209 fNameList->fLst[TString::Format("%p", geoShape)] = "missing_" + fNameList->fLst[TString::Format("%p", geoShape)];
2210 }
2211 }
2212
2213 return solidN;
2214}
2215
2216////////////////////////////////////////////////////////////////////////////////
2217/// Retrieves X Y Z angles from rotation matrix
2218
2220{
2221 TGDMLWrite::Xyz lxyz;
2222 Double_t a, b, c;
2223 Double_t rad = 180.0 / TMath::ACos(-1.0);
2224 const Double_t *r = rotationMatrix;
2225 Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
2226 if (cosb > 0.00001) {
2227 a = TMath::ATan2(r[5], r[8]) * rad;
2228 b = TMath::ATan2(-r[2], cosb) * rad;
2229 c = TMath::ATan2(r[1], r[0]) * rad;
2230 } else {
2231 a = TMath::ATan2(-r[7], r[4]) * rad;
2232 b = TMath::ATan2(-r[2], cosb) * rad;
2233 c = 0;
2234 }
2235 lxyz.x = a;
2236 lxyz.y = b;
2237 lxyz.z = c;
2238 return lxyz;
2239}
2240
2241////////////////////////////////////////////////////////////////////////////////
2242/// Method creating cutTube as an intersection of tube and two boxes
2243/// - not used anymore because cutube is supported in Geant4 9.5
2244
2246{
2247 Double_t rmin = geoShape->GetRmin();
2248 Double_t rmax = geoShape->GetRmax();
2249 Double_t z = geoShape->GetDz();
2250 Double_t startphi = geoShape->GetPhi1();
2251 Double_t deltaphi = geoShape->GetPhi2();
2252 Double_t x1 = geoShape->GetNlow()[0];
2253 Double_t y1 = geoShape->GetNlow()[1];
2254 Double_t z1 = geoShape->GetNlow()[2];
2255 Double_t x2 = geoShape->GetNhigh()[0];
2256 Double_t y2 = geoShape->GetNhigh()[1];
2257 Double_t z2 = geoShape->GetNhigh()[2];
2258 TString xname = geoShape->GetName();
2259
2260
2261 Double_t h0 = 2.*((TGeoBBox*)geoShape)->GetDZ();
2262 Double_t h1 = 2 * z;
2263 Double_t h2 = 2 * z;
2264 Double_t boxdx = 1E8 * (2 * rmax) + (2 * z);
2265
2266 TGeoTubeSeg *T = new TGeoTubeSeg((xname + "T").Data(), rmin, rmax, h0, startphi, deltaphi);
2267 TGeoBBox *B1 = new TGeoBBox((xname + "B1").Data(), boxdx, boxdx, h1);
2268 TGeoBBox *B2 = new TGeoBBox((xname + "B2").Data(), boxdx, boxdx, h2);
2269
2270
2271 //first box position parameters
2272 Double_t phi1 = 360 - TMath::ATan2(x1, y1) * TMath::RadToDeg();
2273 Double_t theta1 = 360 - TMath::ATan2(sqrt(x1 * x1 + y1 * y1), z1) * TMath::RadToDeg();
2274
2275 Double_t phi11 = TMath::ATan2(y1, x1) * TMath::RadToDeg() ;
2276 Double_t theta11 = TMath::ATan2(z1, sqrt(x1 * x1 + y1 * y1)) * TMath::RadToDeg() ;
2277
2278 Double_t xpos1 = h1 * TMath::Cos((theta11) * TMath::DegToRad()) * TMath::Cos((phi11) * TMath::DegToRad()) * (-1);
2279 Double_t ypos1 = h1 * TMath::Cos((theta11) * TMath::DegToRad()) * TMath::Sin((phi11) * TMath::DegToRad()) * (-1);
2280 Double_t zpos1 = h1 * TMath::Sin((theta11) * TMath::DegToRad()) * (-1);
2281
2282 //second box position parameters
2283 Double_t phi2 = 360 - TMath::ATan2(x2, y2) * TMath::RadToDeg();
2284 Double_t theta2 = 360 - TMath::ATan2(sqrt(x2 * x2 + y2 * y2), z2) * TMath::RadToDeg();
2285
2286 Double_t phi21 = TMath::ATan2(y2, x2) * TMath::RadToDeg() ;
2287 Double_t theta21 = TMath::ATan2(z2, sqrt(x2 * x2 + y2 * y2)) * TMath::RadToDeg() ;
2288
2289 Double_t xpos2 = h2 * TMath::Cos((theta21) * TMath::DegToRad()) * TMath::Cos((phi21) * TMath::DegToRad()) * (-1);
2290 Double_t ypos2 = h2 * TMath::Cos((theta21) * TMath::DegToRad()) * TMath::Sin((phi21) * TMath::DegToRad()) * (-1);
2291 Double_t zpos2 = h2 * TMath::Sin((theta21) * TMath::DegToRad()) * (-1);
2292
2293
2294 //positioning
2295 TGeoTranslation *t0 = new TGeoTranslation(0, 0, 0);
2296 TGeoTranslation *t1 = new TGeoTranslation(0 + xpos1, 0 + ypos1, 0 + (zpos1 - z));
2297 TGeoTranslation *t2 = new TGeoTranslation(0 + xpos2, 0 + ypos2, 0 + (zpos2 + z));
2298 TGeoRotation *r0 = new TGeoRotation((xname + "r0").Data());
2299 TGeoRotation *r1 = new TGeoRotation((xname + "r1").Data());
2300 TGeoRotation *r2 = new TGeoRotation((xname + "r2").Data());
2301
2302 r1->SetAngles(phi1, theta1, 0);
2303 r2->SetAngles(phi2, theta2, 0);
2304
2305 TGeoMatrix* m0 = new TGeoCombiTrans(*t0, *r0);
2306 TGeoMatrix* m1 = new TGeoCombiTrans(*t1, *r1);
2307 TGeoMatrix* m2 = new TGeoCombiTrans(*t2, *r2);
2308
2309 TGeoCompositeShape *CS1 = new TGeoCompositeShape((xname + "CS1").Data(), new TGeoIntersection(T, B1, m0, m1));
2310 TGeoCompositeShape *cs = new TGeoCompositeShape((xname + "CS").Data(), new TGeoIntersection(CS1, B2, m0, m2));
2311 delete t0;
2312 delete t1;
2313 delete t2;
2314 delete r0;
2315 delete r1;
2316 delete r2;
2317 return cs;
2318}
2319
2320////////////////////////////////////////////////////////////////////////////////
2321/// Checks whether name2check is in (NameList) list
2322
2324{
2325 Bool_t isIN = list[name2check];
2326 return isIN;
2327}
2328
2329////////////////////////////////////////////////////////////////////////////////
2330///NCNAME basic restrictions
2331///Replace "$" character with empty character etc.
2332
2334{
2335 TString newname = oldname.ReplaceAll("$", "");
2336 newname = newname.ReplaceAll(" ", "_");
2337 // :, @, $, %, &, /, +, ,, ;, whitespace characters or different parenthesis
2338 newname = newname.ReplaceAll(":", "");
2339 newname = newname.ReplaceAll("@", "");
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("_refl", "");
2352 //workaround if first letter is digit than replace it to "O" (ou character)
2353 TString fstLet = newname(0, 1);
2354 if (fstLet.IsDigit()) {
2355 newname = "O" + newname(1, newname.Length());
2356 }
2357 return newname;
2358}
2359
2360////////////////////////////////////////////////////////////////////////////////
2361/// Important function which is responsible for naming volumes, solids and materials
2362
2364{
2365 TString newname = GenName(oldname);
2366 if (newname != oldname) {
2367 if (fgkMaxNameErr > fActNameErr) {
2368 Info("GenName",
2369 "WARNING! Name of the object was changed because it failed to comply with NCNAME xml datatype restrictions.");
2370 } else if ((fgkMaxNameErr == fActNameErr)) {
2371 Info("GenName",
2372 "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.");
2373 }
2374 fActNameErr++;
2375 }
2376 TString nameIter;
2377 Int_t iter = 0;
2378 switch (fgNamingSpeed) {
2379 case kfastButUglySufix:
2380 newname = newname + "0x" + objPointer;
2381 break;
2382 case kelegantButSlow:
2383 //0 means not in the list
2384 iter = fNameList->fLstIter[newname];
2385 if (iter == 0) {
2386 nameIter = "";
2387 } else {
2388 nameIter = TString::Format("0x%i", iter);
2389 }
2390 fNameList->fLstIter[newname]++;
2391 newname = newname + nameIter;
2392 break;
2394 //no change
2395 break;
2396 }
2397 //store the name (mapped to pointer)
2398 fNameList->fLst[objPointer] = newname;
2399 return newname;
2400}
2401
2402
2403////////////////////////////////////////////////////////////////////////////////
2404/// Method which tests whether solids can be processed
2405
2407{
2408 Bool_t isProcessed = kFALSE;
2409 isProcessed = pointer->TestBit(fgkProcBit);
2410 pointer->SetBit(fgkProcBit, kTRUE);
2411 return !(isProcessed);
2412}
2413
2414////////////////////////////////////////////////////////////////////////////////
2415/// Method that retrieves axis and unit along which object is divided
2416
2417TString TGDMLWrite::GetPattAxis(Int_t divAxis, const char * pattName, TString& unit)
2418{
2419 TString resaxis;
2420 unit = fDefault_lunit;
2421 switch (divAxis) {
2422 case 1:
2423 if (strcmp(pattName, "TGeoPatternX") == 0) {
2424 return "kXAxis";
2425 } else if (strcmp(pattName, "TGeoPatternCylR") == 0) {
2426 return "kRho";
2427 }
2428 break;
2429 case 2:
2430 if (strcmp(pattName, "TGeoPatternY") == 0) {
2431 return "kYAxis";
2432 } else if (strcmp(pattName, "TGeoPatternCylPhi") == 0) {
2433 unit = "deg";
2434 return "kPhi";
2435 }
2436 break;
2437 case 3:
2438 if (strcmp(pattName, "TGeoPatternZ") == 0) {
2439 return "kZAxis";
2440 }
2441 break;
2442 default:
2443 return "kUndefined";
2444 break;
2445 }
2446 return "kUndefined";
2447}
2448
2449////////////////////////////////////////////////////////////////////////////////
2450/// Check for null parameter to skip the NULL objects
2451
2453{
2454 if (parValue == 0.) {
2455 Info("IsNullParam", "ERROR! %s is NULL due to %s = %.12g, Volume based on this shape will be skipped",
2456 objName.Data(),
2457 parName.Data(),
2458 parValue);
2459 return kTRUE;
2460 }
2461 return kFALSE;
2462}
2463
2464////////////////////////////////////////////////////////////////////////////////
2465/// Unsetting bits that were changed in gGeoManager during export so that export
2466/// can be run more times with the same instance of gGeoManager.
2467
2469{
2470 TIter next(geoMng->GetListOfVolumes());
2471 TGeoVolume *vol;
2472 while ((vol = (TGeoVolume *)next())) {
2473 ((TObject *)vol->GetShape())->SetBit(fgkProcBit, kFALSE);
2475 }
2476
2477}
2478
2479
2480////////////////////////////////////////////////////////////////////////////////
2481//
2482// Backwards compatibility for old DD4hep version (to be removed in the future)
2483//
2484////////////////////////////////////////////////////////////////////////////////
2485
2486////////////////////////////////////////////////////////////////////////////////
2487// Backwards compatibility (to be removed in the future): Wrapper to only selectively write one branch
2489{
2490 TList materials, volumes, nodes;
2491 MaterialExtractor extract;
2492 if ( !volume ) {
2493 Info("WriteGDMLfile", "Invalid Volume reference to extract GDML information!");
2494 return;
2495 }
2496 extract(volume);
2497 for(TGeoMaterial* m : extract.materials)
2498 materials.Add(m);
2499 fTopVolumeName = volume->GetName();
2500 fTopVolume = volume;
2501 fSurfaceList.clear();
2502 fVolumeList.clear();
2503 fNodeList.clear();
2504 WriteGDMLfile(geomanager, volume, &materials, filename, option);
2505 materials.Clear("nodelete");
2506 volumes.Clear("nodelete");
2507 nodes.Clear("nodelete");
2508}
2509
2510
2511////////////////////////////////////////////////////////////////////////////////
2512/// Wrapper of all exporting methods
2513/// Creates blank GDML file and fills it with gGeoManager structure converted
2514/// to GDML structure of xml nodes
2515
2517 TGeoVolume* volume,
2518 TList* materialsLst,
2519 const char* filename,
2521{
2522 //option processing
2523 option.ToLower();
2524 if (option.Contains("g")) {
2526 Info("WriteGDMLfile", "Geant4 compatibility mode set");
2527 } else {
2529 }
2530 if (option.Contains("f")) {
2532 Info("WriteGDMLfile", "Fast naming convention with pointer suffix set");
2533 } else if (option.Contains("n")) {
2535 Info("WriteGDMLfile", "Naming without prefix set - be careful uniqness of name is not ensured");
2536 } else {
2538 Info("WriteGDMLfile", "Potentially slow with incremental suffix naming convention set");
2539 }
2540
2541 //local variables
2542 Int_t outputLayout = 1;
2543 const char * krootNodeName = "gdml";
2544 const char * knsRefGeneral = "http://www.w3.org/2001/XMLSchema-instance";
2545 const char * knsNameGeneral = "xsi";
2546 const char * knsRefGdml = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
2547 const char * knsNameGdml = "xsi:noNamespaceSchemaLocation";
2548
2549 // First create engine
2550 fGdmlE = new TXMLEngine;
2552
2553 //create blank GDML file
2554 fGdmlFile = fGdmlE->NewDoc();
2555
2556 //create root node and add it to blank GDML file
2557 XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
2559
2560 //add namespaces to root node
2561 fGdmlE->NewNS(rootNode, knsRefGeneral, knsNameGeneral);
2562 fGdmlE->NewAttr(rootNode, nullptr, knsNameGdml, knsRefGdml);
2563
2564 //initialize general lists and <define>, <solids>, <structure> nodes
2565 fIsotopeList = new StructLst;
2566 fElementList = new StructLst;
2567
2568 fNameList = new NameLst;
2569
2570 fDefineNode = fGdmlE->NewChild(nullptr, nullptr, "define", nullptr);
2571 fSolidsNode = fGdmlE->NewChild(nullptr, nullptr, "solids", nullptr);
2572 fStructureNode = fGdmlE->NewChild(nullptr, nullptr, "structure", nullptr);
2573 //========================
2574
2575 //initialize list of accepted patterns for divisions (in ExtractVolumes)
2576 fAccPatt = new StructLst;
2577 fAccPatt->fLst["TGeoPatternX"] = kTRUE;
2578 fAccPatt->fLst["TGeoPatternY"] = kTRUE;
2579 fAccPatt->fLst["TGeoPatternZ"] = kTRUE;
2580 fAccPatt->fLst["TGeoPatternCylR"] = kTRUE;
2581 fAccPatt->fLst["TGeoPatternCylPhi"] = kTRUE;
2582 //========================
2583
2584 //initialize list of rejected shapes for divisions (in ExtractVolumes)
2585 fRejShape = new StructLst;
2586 //this shapes are rejected because, it is not possible to divide trd2
2587 //in Y axis and while only trd2 object is imported from GDML
2588 //it causes a problem when TGeoTrd1 is divided in Y axis
2589 fRejShape->fLst["TGeoTrd1"] = kTRUE;
2590 fRejShape->fLst["TGeoTrd2"] = kTRUE;
2591 //=========================
2592
2593 //Initialize global counters
2594 fActNameErr = 0;
2595 fVolCnt = 0;
2596 fPhysVolCnt = 0;
2597 fSolCnt = 0;
2598
2599 //calling main extraction functions (with measuring time)
2600 time_t startT, endT;
2601 startT = time(nullptr);
2603 ExtractConstants(geomanager);
2604 fMaterialsNode = ExtractMaterials(materialsLst);
2605
2606 Info("WriteGDMLfile", "Extracting volumes");
2607 ExtractVolumes(volume);
2608 Info("WriteGDMLfile", "%i solids added", fSolCnt);
2609 Info("WriteGDMLfile", "%i volumes added", fVolCnt);
2610 Info("WriteGDMLfile", "%i physvolumes added", fPhysVolCnt);
2614 endT = time(nullptr);
2615 //<gdml>
2616 fGdmlE->AddChild(rootNode, fDefineNode); // <define>...</define>
2617 fGdmlE->AddChild(rootNode, fMaterialsNode); // <materials>...</materials>
2618 fGdmlE->AddChild(rootNode, fSolidsNode); // <solids>...</solids>
2619 fGdmlE->AddChild(rootNode, fStructureNode); // <structure>...</structure>
2620 fGdmlE->AddChild(rootNode, CreateSetupN(fTopVolumeName.Data())); // <setup>...</setup>
2621 //</gdml>
2622 Double_t tdiffI = difftime(endT, startT);
2623 TString tdiffS = (tdiffI == 0 ? TString("< 1 s") : TString::Format("%.0lf s", tdiffI));
2624 Info("WriteGDMLfile", "Exporting time: %s", tdiffS.Data());
2625 //=========================
2626
2627 //Saving document
2628 fGdmlE->SaveDoc(fGdmlFile, filename, outputLayout);
2629 Info("WriteGDMLfile", "File %s saved", filename);
2630 //cleaning
2632 //unset processing bits:
2633 UnsetTemporaryBits(geomanager);
2634 delete fGdmlE;
2635}
2636
2637
2638
2639
2640////////////////////////////////////////////////////////////////////////////////
2641/// Method extracting geometry structure recursively
2642
2644{
2645 XMLNodePointer_t volumeN, childN;
2646 TString volname, matname, solname, pattClsName, nodeVolNameBak;
2647 TGeoPatternFinder *pattFinder = nullptr;
2648 Bool_t isPattern = kFALSE;
2649 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2650
2651 //create the name for volume/assembly
2652 if (volume == fTopVolume) {
2653 //not needed a special function for generating name
2654 volname = volume->GetName();
2655 fTopVolumeName = volname;
2656 //register name to the pointer
2657 fNameList->fLst[TString::Format("%p", volume)] = volname;
2658 } else {
2659 volname = GenName(volume->GetName(), TString::Format("%p", volume));
2660 }
2661
2662 //start to create main volume/assembly node
2663 if (volume->IsAssembly()) {
2664 volumeN = StartAssemblyN(volname);
2665 } else {
2666 //get reference material and add solid to <solids> + get name
2667 matname = fNameList->fLst[TString::Format("%p", volume->GetMaterial())];
2668 solname = ExtractSolid(volume->GetShape());
2669 //If solid is not supported or corrupted
2670 if (solname == "-1") {
2671 Info("ExtractVolumes", "ERROR! %s volume was not added, because solid is either not supported or corrupted",
2672 volname.Data());
2673 //set volume as missing volume
2674 fNameList->fLst[TString::Format("%p", volume)] = "missing_" + volname;
2675 return;
2676 }
2677 volumeN = StartVolumeN(volname, solname, matname);
2678
2679 //divisionvol can't be in assembly
2680 pattFinder = volume->GetFinder();
2681 //if found pattern
2682 if (pattFinder) {
2683 pattClsName = TString::Format("%s", pattFinder->ClassName());
2684 TString shapeCls = TString::Format("%s", volume->GetShape()->ClassName());
2685 //if pattern in accepted pattern list and not in shape rejected list
2686 if ((fAccPatt->fLst[pattClsName] == kTRUE) &&
2687 (fRejShape->fLst[shapeCls] != kTRUE)) {
2688 isPattern = kTRUE;
2689 }
2690 }
2691 }
2692 //get all nodes in volume
2693 TObjArray *nodeLst = volume->GetNodes();
2694 TIter next(nodeLst);
2695 TString physvolname;
2696 TGeoNode *geoNode;
2697 Int_t nCnt = 0;
2698 //loop through all nodes
2699 while ((geoNode = (TGeoNode *) next())) {
2700 //get volume of current node and if not processed then process it
2701 TGeoVolume * subvol = geoNode->GetVolume();
2702 if (subvol->TestAttBit(fgkProcBitVol) == kFALSE) {
2703 subvol->SetAttBit(fgkProcBitVol);
2704 ExtractVolumes(subvol);
2705 }
2706
2707 //volume of this node has to exist because it was processed recursively
2708 TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
2709 if (nodevolname.Contains("missing_")) {
2710 continue;
2711 }
2712 if (nCnt == 0) { //save name of the first node for divisionvol
2713 nodeVolNameBak = nodevolname;
2714 }
2715
2716 if (isPattern == kFALSE) {
2717 //create name for node
2718 TString nodename, posname, rotname;
2719 nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
2720 nodename = nodename + "in" + volname;
2721
2722 //create name for position and clear rotation
2723 posname = nodename + "pos";
2724 rotname = "";
2725
2726 //position
2727 const Double_t * pos = geoNode->GetMatrix()->GetTranslation();
2728 Xyz nodPos;
2729 nodPos.x = pos[0];
2730 nodPos.y = pos[1];
2731 nodPos.z = pos[2];
2732 childN = CreatePositionN(posname.Data(), nodPos, "position", fDefault_lunit);
2733 fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
2734 //Deal with reflection
2735 XMLNodePointer_t scaleN = nullptr;
2736 Double_t lx, ly, lz;
2737 Double_t xangle = 0;
2738 Double_t zangle = 0;
2739 lx = geoNode->GetMatrix()->GetRotationMatrix()[0];
2740 ly = geoNode->GetMatrix()->GetRotationMatrix()[4];
2741 lz = geoNode->GetMatrix()->GetRotationMatrix()[8];
2742 if (geoNode->GetMatrix()->IsReflection()
2743 && TMath::Abs(lx) == 1 && TMath::Abs(ly) == 1 && TMath::Abs(lz) == 1) {
2744 scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
2745 fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
2746 fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
2747 fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
2748 fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
2749 //experimentally found out, that rotation should be updated like this
2750 if (lx == -1) {
2751 zangle = 180;
2752 }
2753 if (lz == -1) {
2754 xangle = 180;
2755 }
2756 }
2757
2758 //rotation
2760 lxyz.x -= xangle;
2761 lxyz.z -= zangle;
2762 if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
2763 rotname = nodename + "rot";
2764 childN = CreateRotationN(rotname.Data(), lxyz);
2765 fGdmlE->AddChild(fDefineNode, childN); //adding node to <define> node
2766 }
2767
2768 //create physvol for main volume/assembly node
2769 physvolname = fNameList->fLst[TString::Format("%p", geoNode)];
2770 childN = CreatePhysVolN(physvolname, geoNode->GetNumber(), nodevolname.Data(),
2771 posname.Data(), rotname.Data(), scaleN);
2772 fGdmlE->AddChild(volumeN, childN);
2773 }
2774 nCnt++;
2775 }
2776 //create only one divisionvol node
2777 if (isPattern && pattFinder) {
2778 //retrieve attributes of division
2779 Int_t ndiv, divaxis;
2780 Double_t offset, width, xlo, xhi;
2781 TString axis, unit;
2782
2783 ndiv = pattFinder->GetNdiv();
2784 width = pattFinder->GetStep();
2785
2786 divaxis = pattFinder->GetDivAxis();
2787 volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
2788
2789 //compute relative start (not positional)
2790 offset = pattFinder->GetStart() - xlo;
2791 axis = GetPattAxis(divaxis, pattClsName, unit);
2792
2793 //create division node
2794 childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
2795 fGdmlE->AddChild(volumeN, childN);
2796 }
2797
2798 fVolCnt++;
2799 //add volume/assembly node into the <structure> node
2800 fGdmlE->AddChild(fStructureNode, volumeN);
2801}
#define c(i)
Definition: RSha256.hxx:101
int Int_t
Definition: RtypesCore.h:45
const Bool_t kFALSE
Definition: RtypesCore.h:101
const Bool_t kTRUE
Definition: RtypesCore.h:100
ClassImp(TGDMLWrite)
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 Float_t Float_t b
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
Definition: TGeoManager.h:602
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.
Definition: TCollection.h:184
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
Definition: TGDMLMatrix.cxx:78
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.
Definition: TGDMLWrite.cxx:794
void ExtractMatrices(TObjArray *matrices)
Method exporting GDML matrices.
Definition: TGDMLWrite.cxx:445
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.
Definition: TGDMLWrite.cxx:205
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.
Definition: TGDMLWrite.cxx:967
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.
Definition: TGDMLWrite.cxx:584
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.
Definition: TGDMLWrite.cxx:896
std::map< TString, Int_t > NameListI
Definition: TGDMLWrite.h:102
void ExtractBorderSurfaces(TObjArray *surfaces)
Method exporting border surfaces.
Definition: TGDMLWrite.cxx:511
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="")
Definition: TGDMLWrite.cxx:263
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.
Definition: TGDMLWrite.cxx:806
XMLNodePointer_t CreateElementN(TGeoElement *element, XMLNodePointer_t materials, const char *name)
Creates "element" node for GDML element node and attribute.
Definition: TGDMLWrite.cxx:831
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.
Definition: TGDMLWrite.cxx:493
XMLNodePointer_t fDefineNode
Definition: TGDMLWrite.h:134
virtual ~TGDMLWrite()
Destructor.
Definition: TGDMLWrite.cxx:234
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.
Definition: TGDMLWrite.cxx:543
XMLNodePointer_t fMaterialsNode
Definition: TGDMLWrite.h:135
void ExtractOpticalSurfaces(TObjArray *surfaces)
Method exporting optical surfaces.
Definition: TGDMLWrite.cxx:476
XMLNodePointer_t CreateDN(Double_t density, const char *unit="g/cm3")
Creates "D" density node for GDML.
Definition: TGDMLWrite.cxx:782
void ExtractConstants(TGeoManager *geom)
Method exporting GDML matrices.
Definition: TGDMLWrite.cxx:460
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.
Definition: TGDMLWrite.cxx:248
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.
Definition: TGDMLWrite.cxx:256
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.
Definition: TGDMLWrite.cxx:770
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.
Definition: TGDMLWrite.cxx:602
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.
Definition: TGDMLWrite.cxx:817
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
Definition: TGeoBoolNode.h:82
TGeoShape * GetLeftShape() const
Definition: TGeoBoolNode.h:83
TGeoMatrix * GetLeftMatrix() const
Definition: TGeoBoolNode.h:81
TGeoShape * GetRightShape() const
Definition: TGeoBoolNode.h:84
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
Definition: TGeoElement.h:120
Int_t GetN() const
Definition: TGeoElement.h:121
Double_t GetA() const
Definition: TGeoElement.h:122
The manager class for any TGeo geometry.
Definition: TGeoManager.h:45
static EDefaultUnits GetDefaultUnits()
TObjArray * GetListOfVolumes() const
Definition: TGeoManager.h:493
TObjArray * GetListOfSkinSurfaces() const
Definition: TGeoManager.h:501
TObjArray * GetListOfGDMLMatrices() const
Definition: TGeoManager.h:499
Int_t GetNproperties() const
Definition: TGeoManager.h:182
TObjArray * GetListOfBorderSurfaces() const
Definition: TGeoManager.h:502
TGeoNode * GetTopNode() const
Definition: TGeoManager.h:533
Double_t GetProperty(const char *name, Bool_t *error=nullptr) const
Get a user-defined property.
static UInt_t GetExportPrecision()
TObjArray * GetListOfOpticalSurfaces() const
Definition: TGeoManager.h:500
TList * GetListOfMaterials() const
Definition: TGeoManager.h:491
Base class describing materials.
Definition: TGeoMaterial.h:36
virtual Bool_t IsMixture() const
Definition: TGeoMaterial.h:130
TList const & GetConstProperties() const
Definition: TGeoMaterial.h:101
TList const & GetProperties() const
Definition: TGeoMaterial.h:100
virtual Double_t GetA() const
Definition: TGeoMaterial.h:105
virtual Double_t GetDensity() const
Definition: TGeoMaterial.h:108
virtual Double_t GetZ() const
Definition: TGeoMaterial.h:106
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.
Definition: TGeoMaterial.h:157
virtual TGeoElement * GetElement(Int_t i=0) const
Retrieve the pointer to the element corresponding to component I.
Double_t * GetWmixt() const
Definition: TGeoMaterial.h:197
virtual Int_t GetNelements() const
Definition: TGeoMaterial.h:194
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.
Definition: TGeoShape.cxx:248
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.
const TGeoFacet & GetFacet(int i) const
const Vertex_t & GetVertex(int i) const
int GetNvertices() const
int GetNfacets() const
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()
Definition: TGeoVolume.cxx:440
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:136
Ssiz_t Length() const
Definition: TString.h:410
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1171
const char * Data() const
Definition: TString.h:369
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1809
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:693
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:2357
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:625
XMLNodePointer_t NewChild(XMLNodePointer_t parent, XMLNsPointer_t ns, const char *name, const char *content=nullptr)
create new child element for parent node
Definition: TXMLEngine.cxx:715
XMLAttrPointer_t NewAttr(XMLNodePointer_t xmlnode, XMLNsPointer_t, const char *name, const char *value)
creates new attribute for xmlnode, namespaces are not supported for attributes
Definition: TXMLEngine.cxx:586
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
Definition: TXMLEngine.cxx:799
XMLNsPointer_t NewNS(XMLNodePointer_t xmlnode, const char *reference, const char *name=nullptr)
create namespace attribute for xmlnode.
Definition: TXMLEngine.cxx:741
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
RVec< PromoteType< T > > floor(const RVec< T > &v)
Definition: RVec.hxx:1814
TH1F * h1
Definition: legend1.C:5
double T(double x)
Definition: ChebyshevPol.h:34
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
static const std::string pattern("pattern")
static constexpr double rad
static constexpr double m2
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition: TMath.h:632
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:646
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:93
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:662
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition: TMath.h:594
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition: TMath.h:588
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
NameListI fLstIter
Definition: TGDMLWrite.h:109
Double_t z
Definition: TGDMLWrite.h:94
Double_t y
Definition: TGDMLWrite.h:93
Double_t x
Definition: TGDMLWrite.h:92
TMarker m
Definition: textangle.C:8
TArc a
Definition: textangle.C:12
auto * t1
Definition: textangle.C:20