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