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