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