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 rot3x3[9];
703 for (Int_t i = 0; i < 9; ++i) {
704 rot3x3[i] = geoNode->GetMatrix()->GetRotationMatrix()[i];
705 }
706 Double_t lx = rot3x3[0];
707 Double_t ly = rot3x3[4];
708 Double_t lz = rot3x3[8];
709 if (geoNode->GetMatrix()->IsReflection()) {
710 // A physvol is read back as translation * rotation * scale, so the reflection
711 // is carried by <scale> and <rotation> gets the matrix with the scale taken
712 // out again, which is a proper rotation. A matrix that is already diagonal
713 // keeps its own signs and leaves an identity rotation; every other reflection
714 // is written as a mirror on z plus a rotation.
715 if (TMath::Abs(lx) != 1 || TMath::Abs(ly) != 1 || TMath::Abs(lz) != 1) {
716 lx = 1.;
717 ly = 1.;
718 lz = -1.;
719 }
720 scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
721 fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
722 fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
723 fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
724 fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
725 // take the scale out column by column; the entries are +-1, so multiplying
726 // by them again is the same as dividing
727 for (Int_t i = 0; i < 3; ++i) {
728 rot3x3[3 * i] *= lx;
729 rot3x3[3 * i + 1] *= ly;
730 rot3x3[3 * i + 2] *= lz;
731 }
732 }
733
734 // rotation
736 if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
737 rotname = nodename + "rot";
738 childN = CreateRotationN(rotname.Data(), lxyz);
739 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
740 }
741
742 // create physvol for main volume/assembly node
744 childN = CreatePhysVolN(physvolname, geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(),
745 scaleN);
747 }
748 nCnt++;
749 }
750 // create only one divisionvol node
751 if (isPattern && pattFinder) {
752 // retrieve attributes of division
753 Int_t ndiv, divaxis;
754 Double_t offset, width, xlo, xhi;
755 TString axis, unit;
756
757 ndiv = pattFinder->GetNdiv();
758 width = pattFinder->GetStep();
759
760 divaxis = pattFinder->GetDivAxis();
761 volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
762
763 // compute relative start (not positional)
764 offset = pattFinder->GetStart() - xlo;
765 axis = GetPattAxis(divaxis, pattClsName, unit);
766
767 // create division node
768 childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
770 }
771
772 // export auxiliary user-data if present (TMap of TObjString->TObjString)
773 {
774 TGeoRCExtension *rcext = dynamic_cast<TGeoRCExtension *>(volume->GetUserExtension());
775 if (rcext) {
776 TObject *userObj = rcext->GetUserObject();
777 if (userObj && userObj->InheritsFrom("TMap")) {
778 TMap *auxmap = (TMap *)userObj;
779 TIterator *it = auxmap->MakeIterator();
780 TObject *k = nullptr;
781 while ((k = it->Next())) {
782 TObject *valobj = auxmap->GetValue(k);
783 if (!valobj || !k->InheritsFrom("TObjString") || !valobj->InheritsFrom("TObjString"))
784 continue;
785 TObjString *key = (TObjString *)k;
786 TObjString *val = (TObjString *)valobj;
787 TString auxtype = key->GetString();
788 TString auxvalue = val->GetString();
789 TString auxunit = "";
790 Int_t pos = auxvalue.Index('*');
791 if (pos >= 0) {
792 auxunit = auxvalue(pos + 1, auxvalue.Length());
793 auxvalue = auxvalue(0, pos);
794 }
795 XMLNodePointer_t auxN = fGdmlE->NewChild(nullptr, nullptr, "auxiliary", nullptr);
796 fGdmlE->NewAttr(auxN, nullptr, "auxtype", auxtype.Data());
797 fGdmlE->NewAttr(auxN, nullptr, "auxvalue", auxvalue.Data());
798 if (!auxunit.IsNull())
799 fGdmlE->NewAttr(auxN, nullptr, "auxunit", auxunit.Data());
801 }
802 }
803 }
804 }
805
806 fVolCnt++;
807 // add volume/assembly node into the <structure> node
809}
810
811////////////////////////////////////////////////////////////////////////////////
812/// Creates "atom" node for GDML
813
815{
817 XMLNodePointer_t atomN = fGdmlE->NewChild(nullptr, nullptr, "atom", nullptr);
818 fGdmlE->NewAttr(atomN, nullptr, "unit", unit);
819 fGdmlE->NewAttr(atomN, nullptr, "value", TString::Format(fltPrecision.Data(), atom));
820 return atomN;
821}
822
823////////////////////////////////////////////////////////////////////////////////
824/// Creates "D" density node for GDML
825
827{
829 XMLNodePointer_t densN = fGdmlE->NewChild(nullptr, nullptr, "D", nullptr);
830 fGdmlE->NewAttr(densN, nullptr, "unit", unit);
831 fGdmlE->NewAttr(densN, nullptr, "value", TString::Format(fltPrecision.Data(), density));
832 return densN;
833}
834
835////////////////////////////////////////////////////////////////////////////////
836/// Creates "fraction" node for GDML
837
839{
841 XMLNodePointer_t fractN = fGdmlE->NewChild(nullptr, nullptr, "fraction", nullptr);
843 fGdmlE->NewAttr(fractN, nullptr, "ref", refName);
844 return fractN;
845}
846
847////////////////////////////////////////////////////////////////////////////////
848/// Creates "property" node for GDML
849
851{
852 XMLNodePointer_t propertyN = fGdmlE->NewChild(nullptr, nullptr, "property", nullptr);
853 fGdmlE->NewAttr(propertyN, nullptr, "name", property.GetName());
854 fGdmlE->NewAttr(propertyN, nullptr, "ref", property.GetTitle());
855 return propertyN;
856}
857
858////////////////////////////////////////////////////////////////////////////////
859/// Creates "isotope" node for GDML
860
862{
863 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "isotope", nullptr);
864 fGdmlE->NewAttr(mainN, nullptr, "name", name);
865 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", isotope->GetN()));
866 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", isotope->GetZ()));
868 return mainN;
869}
870
871////////////////////////////////////////////////////////////////////////////////
872/// Creates "element" node for GDML
873/// element node and attribute
874
876{
877 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "element", nullptr);
878 fGdmlE->NewAttr(mainN, nullptr, "name", name);
879 // local associative arrays for saving isotopes and their weight
880 // inside element
883
884 if (element->HasIsotopes()) {
885 Int_t nOfIso = element->GetNisotopes();
886 // go through isotopes
887 for (Int_t idx = 0; idx < nOfIso; idx++) {
888 TGeoIsotope *myIsotope = element->GetIsotope(idx);
889 if (!myIsotope) {
890 Fatal("CreateElementN", "Missing isotopes for element %s", element->GetName());
891 return mainN;
892 }
893
894 // Get name of the Isotope (
895 TString lname = myIsotope->GetName();
896 //_iso suffix is added to avoid problems with same names
897 // for material, element and isotopes
898 lname = TString::Format("%s_iso", lname.Data());
899
900 // cumulates abundance, in case 2 isotopes with same names
901 // within one element
902 wPercentage[lname] += element->GetRelativeAbundance(idx);
903 wCounter[lname]++;
904
905 // check whether isotope name is not in list of isotopes
907 continue;
908 }
909 // add isotope to list of isotopes and to main <materials> node
912 fGdmlE->AddChild(materials, isoNode);
913 }
914 // loop through asoc array of isotopes
915 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
916 if (itr->second > 1) {
917 Info("CreateMixtureN", "WARNING! 2 equal isotopes in one element. Check: %s isotope of %s element",
918 itr->first.Data(), name);
919 }
920 // add fraction child to element with reference to isotope
921 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
922 }
923 } else {
924 fGdmlE->NewAttr(mainN, nullptr, "formula", element->GetName());
925 Int_t valZ = element->Z();
926 // Z can't be <1 in Geant4 and Z is optional parameter
927 if (valZ >= 1) {
928 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", valZ));
929 }
930 Int_t valN = element->N();
931 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", valN));
933 }
934 return mainN;
935}
936
937////////////////////////////////////////////////////////////////////////////////
938/// Creates "material" node for GDML with references to other sub elements
939
941{
942 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
943 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
944
945 // Write properties
946 TList const &properties = mixture->GetProperties();
947 if (properties.GetSize()) {
948 TIter next(&properties);
950 while ((property = (TNamed *)next()))
952 }
953 // Write CONST properties
954 TList const &const_properties = mixture->GetConstProperties();
955 if (const_properties.GetSize()) {
956 TIter next(&const_properties);
958 while ((property = (TNamed *)next()))
960 }
961
962 fGdmlE->AddChild(mainN, CreateDN(mixture->GetDensity()));
963 // local associative arrays for saving elements and their weight
964 // inside mixture
967
968 Int_t nOfElm = mixture->GetNelements();
969 // go through elements
970 for (Int_t idx = 0; idx < nOfElm; idx++) {
971 TGeoElement *myElement = mixture->GetElement(idx);
972
973 // Get name of the element
974 // NOTE: that for element - GetTitle() returns the "name" tag
975 // and GetName() returns "formula" tag (see createElementN)
976 TString lname = myElement->GetTitle();
977 //_elm suffix is added to avoid problems with same names
978 // for material and element
979 lname = TString::Format("%s_elm", lname.Data());
980
981 // cumulates percentage, in case 2 elements with same names within one mixture
982 wPercentage[lname] += mixture->GetWmixt()[idx];
983 wCounter[lname]++;
984
985 // check whether element name is not in list of elements already created
987 continue;
988 }
989
990 // add element to list of elements and to main <materials> node
993 fGdmlE->AddChild(materials, elmNode);
994 }
995 // loop through asoc array
996 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
997 if (itr->second > 1) {
998 Info("CreateMixtureN", "WARNING! 2 equal elements in one material. Check: %s element of %s material",
999 itr->first.Data(), mname.Data());
1000 }
1001 // add fraction child to material with reference to element
1002 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
1003 }
1004
1005 return mainN;
1006}
1007
1008////////////////////////////////////////////////////////////////////////////////
1009/// Creates "material" node for GDML
1010
1012{
1013 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
1014 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
1015 Double_t valZ = material->GetZ();
1016 // Z can't be zero in Geant4 so this is workaround for vacuum
1019 tmpname.ToLower();
1020 if (valZ < 1) {
1021 if (tmpname == "vacuum") {
1022 valZ = 1;
1023 } else {
1024 if (fgG4Compatibility == kTRUE) {
1025 Info("CreateMaterialN",
1026 "WARNING! value of Z in %s material can't be < 1 in Geant4, that is why it was changed to 1, please "
1027 "check it manually! ",
1028 mname.Data());
1029 valZ = 1;
1030 } else {
1031 Info("CreateMaterialN", "WARNING! value of Z in %s material can't be < 1 in Geant4", mname.Data());
1032 }
1033 }
1034 }
1035 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format(fltPrecision.Data(), valZ)); // material->GetZ()));
1036
1037 // Create properties if any: Properties according to the GDML schema MUST come first!
1038 TList const &properties = material->GetProperties();
1039 if (properties.GetSize()) {
1040 TIter next(&properties);
1042 while ((property = (TNamed *)next()))
1044 }
1045 // Write CONST properties
1046 TList const &const_properties = material->GetConstProperties();
1047 if (const_properties.GetSize()) {
1048 TIter next(&const_properties);
1050 while ((property = (TNamed *)next()))
1052 }
1053
1054 // Now add the other children
1055 fGdmlE->AddChild(mainN, CreateDN(material->GetDensity()));
1056 fGdmlE->AddChild(mainN, CreateAtomN(material->GetA()));
1057 return mainN;
1058}
1059
1060////////////////////////////////////////////////////////////////////////////////
1061/// Creates "box" node for GDML
1062
1064{
1065 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "box", nullptr);
1067 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1068 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1069 if (IsNullParam(geoShape->GetDX(), "DX", lname) || IsNullParam(geoShape->GetDY(), "DY", lname) ||
1070 IsNullParam(geoShape->GetDZ(), "DZ", lname)) {
1071 return nullptr;
1072 }
1073 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDX()));
1074 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDY()));
1075 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDZ()));
1076
1077 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1078 return mainN;
1079}
1080
1081////////////////////////////////////////////////////////////////////////////////
1082/// Creates "paraboloid" node for GDML
1083
1085{
1086 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "paraboloid", nullptr);
1088 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1089 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1090 if (IsNullParam(geoShape->GetRhi(), "Rhi", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1091 return nullptr;
1092 }
1093 fGdmlE->NewAttr(mainN, nullptr, "rlo", TString::Format(fltPrecision.Data(), geoShape->GetRlo()));
1094 fGdmlE->NewAttr(mainN, nullptr, "rhi", TString::Format(fltPrecision.Data(), geoShape->GetRhi()));
1095 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1096
1097 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1098 return mainN;
1099}
1100
1101////////////////////////////////////////////////////////////////////////////////
1102/// Creates "sphere" node for GDML
1103
1105{
1106 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "sphere", nullptr);
1108 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1109 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1110 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1111 return nullptr;
1112 }
1113
1114 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1115 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1116 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1117 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1118 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1119 fGdmlE->NewAttr(mainN, nullptr, "starttheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta1()));
1120 fGdmlE->NewAttr(mainN, nullptr, "deltatheta",
1121 TString::Format(fltPrecision.Data(), geoShape->GetTheta2() - geoShape->GetTheta1()));
1122
1123 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1124 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1125 return mainN;
1126}
1127
1128////////////////////////////////////////////////////////////////////////////////
1129/// Creates "arb8" node for GDML
1130
1132{
1133 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "arb8", nullptr);
1135 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1136 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1137 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1138 return nullptr;
1139 }
1140
1141 fGdmlE->NewAttr(mainN, nullptr, "v1x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[0]));
1142 fGdmlE->NewAttr(mainN, nullptr, "v1y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[1]));
1143 fGdmlE->NewAttr(mainN, nullptr, "v2x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[2]));
1144 fGdmlE->NewAttr(mainN, nullptr, "v2y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[3]));
1145 fGdmlE->NewAttr(mainN, nullptr, "v3x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[4]));
1146 fGdmlE->NewAttr(mainN, nullptr, "v3y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[5]));
1147 fGdmlE->NewAttr(mainN, nullptr, "v4x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[6]));
1148 fGdmlE->NewAttr(mainN, nullptr, "v4y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[7]));
1149 fGdmlE->NewAttr(mainN, nullptr, "v5x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[8]));
1150 fGdmlE->NewAttr(mainN, nullptr, "v5y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[9]));
1151 fGdmlE->NewAttr(mainN, nullptr, "v6x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[10]));
1152 fGdmlE->NewAttr(mainN, nullptr, "v6y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[11]));
1153 fGdmlE->NewAttr(mainN, nullptr, "v7x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[12]));
1154 fGdmlE->NewAttr(mainN, nullptr, "v7y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[13]));
1155 fGdmlE->NewAttr(mainN, nullptr, "v8x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[14]));
1156 fGdmlE->NewAttr(mainN, nullptr, "v8y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[15]));
1157 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1158
1159 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1160 return mainN;
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// Creates "cone" node for GDML from TGeoConeSeg object
1165
1167{
1168 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1170 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1171 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1172 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1173 return nullptr;
1174 }
1175
1176 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1177 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1178 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1179 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1180 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1181 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1182 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1183 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1184
1185 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1186 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1187 return mainN;
1188}
1189
1190////////////////////////////////////////////////////////////////////////////////
1191/// Creates "cone" node for GDML from TGeoCone object
1192
1194{
1195 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1197 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1198 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1199 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1200 return nullptr;
1201 }
1202
1203 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1204 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1205 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1206 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1207 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1208 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1209 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1210
1211 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1212 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1213 return mainN;
1214}
1215
1216////////////////////////////////////////////////////////////////////////////////
1217/// Creates "para" node for GDML
1218
1220{
1221 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "para", nullptr);
1223 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1224
1225 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetX()));
1226 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetY()));
1227 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetZ()));
1228 fGdmlE->NewAttr(mainN, nullptr, "alpha", TString::Format(fltPrecision.Data(), geoShape->GetAlpha()));
1229 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1230 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1231
1232 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1233 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1234 return mainN;
1235}
1236
1237////////////////////////////////////////////////////////////////////////////////
1238/// Creates "trap" node for GDML
1239
1241{
1244
1245 // if one base equals 0 create Arb8 instead of trap
1246 if ((geoShape->GetBl1() == 0 || geoShape->GetTl1() == 0 || geoShape->GetH1() == 0) ||
1247 (geoShape->GetBl2() == 0 || geoShape->GetTl2() == 0 || geoShape->GetH2() == 0)) {
1249 return mainN;
1250 }
1251
1252 // if is twisted then create arb8
1253 if (geoShape->IsTwisted()) {
1255 return mainN;
1256 }
1257
1258 mainN = fGdmlE->NewChild(nullptr, nullptr, "trap", nullptr);
1259 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1260 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1261 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1262 return nullptr;
1263 }
1264
1265 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1266 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1267 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1268 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1269 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1270 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1271 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1272 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1273 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1274
1275 fGdmlE->NewAttr(mainN, nullptr, "alpha1", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1276 fGdmlE->NewAttr(mainN, nullptr, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1277
1278 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1279 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1280 return mainN;
1281}
1282
1283////////////////////////////////////////////////////////////////////////////////
1284/// Creates "twistedtrap" node for GDML
1285
1287{
1290
1291 // if one base equals 0 create Arb8 instead of twisted trap
1292 if ((geoShape->GetBl1() == 0 && geoShape->GetTl1() == 0 && geoShape->GetH1() == 0) ||
1293 (geoShape->GetBl2() == 0 && geoShape->GetTl2() == 0 && geoShape->GetH2() == 0)) {
1295 return mainN;
1296 }
1297
1298 // if is twisted then create arb8
1299 if (geoShape->IsTwisted()) {
1301 return mainN;
1302 }
1303
1304 // if parameter twistAngle (PhiTwist) equals zero create trap node
1305 if (geoShape->GetTwistAngle() == 0) {
1307 return mainN;
1308 }
1309
1310 mainN = fGdmlE->NewChild(nullptr, nullptr, "twistedtrap", nullptr);
1311 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1312 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1313 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1314 return nullptr;
1315 }
1316
1317 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1318 fGdmlE->NewAttr(mainN, nullptr, "Theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1319 fGdmlE->NewAttr(mainN, nullptr, "Phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1320 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1321 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1322 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1323 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1324 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1325 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1326
1327 fGdmlE->NewAttr(mainN, nullptr, "Alph", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1328
1329 // check if alpha1 equals to alpha2 (converting to string - to avoid problems with floats)
1330 if (TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()) !=
1331 TString::Format(fltPrecision.Data(), geoShape->GetAlpha2())) {
1332 Info("CreateTwistedTrapN",
1333 "ERROR! Object %s is not exported correctly because parameter Alpha2 is not declared in GDML schema",
1334 lname.Data());
1335 }
1336 // fGdmlE->NewAttr(mainN,0, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1337 fGdmlE->NewAttr(mainN, nullptr, "PhiTwist", TString::Format(fltPrecision.Data(), geoShape->GetTwistAngle()));
1338
1339 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1340 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1341 return mainN;
1342}
1343
1344////////////////////////////////////////////////////////////////////////////////
1345/// Creates "trd" node for GDML from object TGeoTrd1
1346
1348{
1349 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1351 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1352 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1353 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1354 return nullptr;
1355 }
1356
1357 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1358 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1359 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1360 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1361 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1362
1363 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1364 return mainN;
1365}
1366
1367////////////////////////////////////////////////////////////////////////////////
1368/// Creates "trd" node for GDML from object TGeoTrd2
1369
1371{
1372 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1374 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1375 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1376 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1377 return nullptr;
1378 }
1379
1380 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1381 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1382 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy1()));
1383 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy2()));
1384 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1385
1386 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1387 return mainN;
1388}
1389
1390////////////////////////////////////////////////////////////////////////////////
1391/// Creates "tube" node for GDML from object TGeoTubeSeg
1392
1394{
1395 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1397 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1398 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1399 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1400 return nullptr;
1401 }
1402
1403 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1404 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1405 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1406 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1407 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1408 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1409
1410 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1411 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1412 return mainN;
1413}
1414
1415////////////////////////////////////////////////////////////////////////////////
1416/// Creates "cutTube" node for GDML
1417
1419{
1422
1423 mainN = fGdmlE->NewChild(nullptr, nullptr, "cutTube", nullptr);
1424 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1425 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1426 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1427 return nullptr;
1428 }
1429 // This is not needed, because cutTube is already supported by Geant4 9.5
1430 if (fgG4Compatibility == kTRUE && kFALSE) {
1433
1434 // register name for cuttube shape (so it will be found during volume export)
1437 Info("CreateCutTubeN", "WARNING! %s - CutTube was replaced by intersection of TGeoTubSeg and two TGeoBBoxes",
1438 lname.Data());
1439 return mainN;
1440 }
1441 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1442 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1443 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1444 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1445 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1446 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1447 fGdmlE->NewAttr(mainN, nullptr, "lowX", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[0]));
1448 fGdmlE->NewAttr(mainN, nullptr, "lowY", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[1]));
1449 fGdmlE->NewAttr(mainN, nullptr, "lowZ", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[2]));
1450 fGdmlE->NewAttr(mainN, nullptr, "highX", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[0]));
1451 fGdmlE->NewAttr(mainN, nullptr, "highY", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[1]));
1452 fGdmlE->NewAttr(mainN, nullptr, "highZ", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[2]));
1453
1454 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1455 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1456
1457 return mainN;
1458}
1459
1460////////////////////////////////////////////////////////////////////////////////
1461/// Creates "tube" node for GDML from object TGeoTube
1462
1464{
1465 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1467 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1468 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1469 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1470 return nullptr;
1471 }
1472
1473 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1474 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1475 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1476 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1477 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1478
1479 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1480 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1481 return mainN;
1482}
1483
1484////////////////////////////////////////////////////////////////////////////////
1485/// Creates "zplane" node for GDML
1486
1488{
1489 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "zplane", nullptr);
1491
1492 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), z));
1493 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), rmin));
1494 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), rmax));
1495
1496 return mainN;
1497}
1498
1499////////////////////////////////////////////////////////////////////////////////
1500/// Creates "polycone" node for GDML
1501
1503{
1504 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polycone", nullptr);
1506 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1507 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1508
1509 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1510 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1511
1512 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1513 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1514 Int_t nZPlns = geoShape->GetNz();
1515 for (Int_t it = 0; it < nZPlns; it++) {
1516 // add zplane child node
1517 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1518 // compare actual plane and next plane
1519 if ((it < nZPlns - 1) && (geoShape->GetZ(it) == geoShape->GetZ(it + 1))) {
1520 // rmin of actual is greater then rmax of next one
1521 // | |rmax next
1522 // __ ...| |... __ < rmin actual
1523 // | | | |
1524 if (geoShape->GetRmin(it) > geoShape->GetRmax(it + 1)) {
1525 // adding plane from rmax next to rmin actual at the same z position
1526 if (fgG4Compatibility == kTRUE) {
1528 CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it + 1), geoShape->GetRmin(it)));
1529 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4",
1530 lname.Data());
1531 } else {
1532 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4",
1533 lname.Data());
1534 }
1535 }
1536 // rmin of next is greater then rmax of actual
1537 // | | | |
1538 // | |...___...| | rmin next
1539 // | | > rmax act
1540 if (geoShape->GetRmin(it + 1) > geoShape->GetRmax(it)) {
1541 // adding plane from rmax act to rmin next at the same z position
1542 if (fgG4Compatibility == kTRUE) {
1544 CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it), geoShape->GetRmin(it + 1)));
1545 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4",
1546 lname.Data());
1547 } else {
1548 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4",
1549 lname.Data());
1550 }
1551 }
1552 }
1553 }
1554 return mainN;
1555}
1556
1557////////////////////////////////////////////////////////////////////////////////
1558/// Creates "torus" node for GDML
1559
1561{
1562 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "torus", nullptr);
1564 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1565 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1566 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1567 return nullptr;
1568 }
1569
1570 fGdmlE->NewAttr(mainN, nullptr, "rtor", TString::Format(fltPrecision.Data(), geoShape->GetR()));
1571 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1572 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1573 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1574 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1575
1576 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1577 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1578
1579 return mainN;
1580}
1581
1582////////////////////////////////////////////////////////////////////////////////
1583/// Creates "polyhedra" node for GDML
1584
1586{
1587 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polyhedra", nullptr);
1589 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1590
1591 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1592 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1593 fGdmlE->NewAttr(mainN, nullptr, "numsides", TString::Format("%i", geoShape->GetNedges()));
1594
1595 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1596 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1597 for (Int_t it = 0; it < geoShape->GetNz(); it++) {
1598 // add zplane child node
1599 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1600 }
1601 return mainN;
1602}
1603
1604////////////////////////////////////////////////////////////////////////////////
1605/// Creates "eltube" node for GDML
1606
1608{
1609 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "eltube", nullptr);
1611 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1612 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1613 if (IsNullParam(geoShape->GetA(), "A", lname) || IsNullParam(geoShape->GetB(), "B", lname) ||
1614 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1615 return nullptr;
1616 }
1617
1618 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(fltPrecision.Data(), geoShape->GetA()));
1619 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(fltPrecision.Data(), geoShape->GetB()));
1620 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1621
1622 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1623
1624 return mainN;
1625}
1626
1627////////////////////////////////////////////////////////////////////////////////
1628/// Creates "hype" node for GDML
1629
1631{
1632 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "hype", nullptr);
1634 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1635 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1636 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1637 return nullptr;
1638 }
1639
1640 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1641 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1642 fGdmlE->NewAttr(mainN, nullptr, "inst", TString::Format(fltPrecision.Data(), geoShape->GetStIn()));
1643 fGdmlE->NewAttr(mainN, nullptr, "outst", TString::Format(fltPrecision.Data(), geoShape->GetStOut()));
1644 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1645
1646 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1647 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1648
1649 return mainN;
1650}
1651
1652////////////////////////////////////////////////////////////////////////////////
1653/// Creates "xtru" node for GDML
1654
1656{
1657 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "xtru", nullptr);
1659 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1660 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1661
1662 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1664 Int_t vertNum = geoShape->GetNvert();
1665 Int_t secNum = geoShape->GetNz();
1666 if (vertNum < 3 || secNum < 2) {
1667 Info("CreateXtrusionN", "ERROR! TGeoXtru %s has only %i vertices and %i sections. It was not exported",
1668 lname.Data(), vertNum, secNum);
1669 mainN = nullptr;
1670 return mainN;
1671 }
1672 for (Int_t it = 0; it < vertNum; it++) {
1673 // add twoDimVertex child node
1674 childN = fGdmlE->NewChild(nullptr, nullptr, "twoDimVertex", nullptr);
1675 fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), geoShape->GetX(it)));
1676 fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), geoShape->GetY(it)));
1678 }
1679 for (Int_t it = 0; it < secNum; it++) {
1680 // add section child node
1681 childN = fGdmlE->NewChild(nullptr, nullptr, "section", nullptr);
1682 fGdmlE->NewAttr(childN, nullptr, "zOrder", TString::Format("%i", it));
1683 fGdmlE->NewAttr(childN, nullptr, "zPosition", TString::Format(fltPrecision.Data(), geoShape->GetZ(it)));
1684 fGdmlE->NewAttr(childN, nullptr, "xOffset", TString::Format(fltPrecision.Data(), geoShape->GetXOffset(it)));
1685 fGdmlE->NewAttr(childN, nullptr, "yOffset", TString::Format(fltPrecision.Data(), geoShape->GetYOffset(it)));
1686 fGdmlE->NewAttr(childN, nullptr, "scalingFactor", TString::Format(fltPrecision.Data(), geoShape->GetScale(it)));
1688 }
1689 return mainN;
1690}
1691
1692////////////////////////////////////////////////////////////////////////////////
1693/// Creates "ellipsoid" node for GDML
1694/// this is a special case, because ellipsoid is not defined in ROOT
1695/// so when intersection of scaled sphere and TGeoBBox is found,
1696/// it is considered as an ellipsoid
1697
1699{
1700 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "ellipsoid", nullptr);
1702 TGeoScaledShape *leftS = (TGeoScaledShape *)geoShape->GetBoolNode()->GetLeftShape(); // ScaledShape
1703 TGeoBBox *rightS = (TGeoBBox *)geoShape->GetBoolNode()->GetRightShape(); // BBox
1704
1705 fGdmlE->NewAttr(mainN, nullptr, "name", elName.Data());
1706 Double_t sx = leftS->GetScale()->GetScale()[0];
1707 Double_t sy = leftS->GetScale()->GetScale()[1];
1708 Double_t radius = ((TGeoSphere *)leftS->GetShape())->GetRmax();
1709
1710 Double_t ax, by, cz;
1711 cz = radius;
1712 ax = sx * radius;
1713 by = sy * radius;
1714
1715 Double_t dz = rightS->GetDZ();
1716 Double_t zorig = rightS->GetOrigin()[2];
1717 Double_t zcut2 = dz + zorig;
1718 Double_t zcut1 = 2 * zorig - zcut2;
1719
1720 fGdmlE->NewAttr(mainN, nullptr, "ax", TString::Format(fltPrecision.Data(), ax));
1721 fGdmlE->NewAttr(mainN, nullptr, "by", TString::Format(fltPrecision.Data(), by));
1722 fGdmlE->NewAttr(mainN, nullptr, "cz", TString::Format(fltPrecision.Data(), cz));
1723 fGdmlE->NewAttr(mainN, nullptr, "zcut1", TString::Format(fltPrecision.Data(), zcut1));
1724 fGdmlE->NewAttr(mainN, nullptr, "zcut2", TString::Format(fltPrecision.Data(), zcut2));
1725 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1726
1727 return mainN;
1728}
1729
1730////////////////////////////////////////////////////////////////////////////////
1731/// Creates "elcone" (elliptical cone) node for GDML
1732/// this is a special case, because elliptical cone is not defined in ROOT
1733/// so when scaled cone is found, it is considered as a elliptical cone
1734
1736{
1737 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "elcone", nullptr);
1739 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1740 Double_t zcut = ((TGeoCone *)geoShape->GetShape())->GetDz();
1741 Double_t rx1 = ((TGeoCone *)geoShape->GetShape())->GetRmax1();
1742 Double_t rx2 = ((TGeoCone *)geoShape->GetShape())->GetRmax2();
1743 Double_t zmax = zcut * ((rx1 + rx2) / (rx1 - rx2));
1744 Double_t z = zcut + zmax;
1745
1746 Double_t sy = geoShape->GetScale()->GetScale()[1];
1747 Double_t ry1 = sy * rx1;
1748
1749 std::string format(TString::Format("%s/%s", fltPrecision.Data(), fltPrecision.Data()).Data());
1750 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(format.c_str(), rx1, z));
1751 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(format.c_str(), ry1, z));
1752 fGdmlE->NewAttr(mainN, nullptr, "zmax", TString::Format(fltPrecision.Data(), zmax));
1753 fGdmlE->NewAttr(mainN, nullptr, "zcut", TString::Format(fltPrecision.Data(), zcut));
1754 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1755
1756 return mainN;
1757}
1758
1759////////////////////////////////////////////////////////////////////////////////
1760/// Creates "tessellated" (tessellated shape) node for GDML
1761
1763{
1764 // add all vertices to the define section
1766 for (int i = 0; i < geoShape->GetNvertices(); ++i) {
1767 auto vertex = geoShape->GetVertex(i);
1768 TString posName = TString::Format("%s_%d", genname.Data(), i);
1769 Xyz nodPos;
1770 nodPos.x = vertex[0];
1771 nodPos.y = vertex[1];
1772 nodPos.z = vertex[2];
1773 auto childN = CreatePositionN(posName.Data(), nodPos, "position", fDefault_lunit);
1774 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
1775 }
1776 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tessellated", nullptr);
1777 fGdmlE->NewAttr(mainN, nullptr, "name", genname.Data());
1778 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1779
1781 for (Int_t it = 0; it < geoShape->GetNfacets(); it++) {
1782 // add section child node
1783 auto facet = geoShape->GetFacet(it);
1784 bool triangular = facet.GetNvert() == 3;
1785 TString ntype = (triangular) ? "triangular" : "quadrangular";
1786 childN = fGdmlE->NewChild(nullptr, nullptr, ntype.Data(), nullptr);
1787 fGdmlE->NewAttr(childN, nullptr, "vertex1", TString::Format("%s_%d", genname.Data(), facet[0]));
1788 fGdmlE->NewAttr(childN, nullptr, "vertex2", TString::Format("%s_%d", genname.Data(), facet[1]));
1789 fGdmlE->NewAttr(childN, nullptr, "vertex3", TString::Format("%s_%d", genname.Data(), facet[2]));
1790 if (!triangular)
1791 fGdmlE->NewAttr(childN, nullptr, "vertex4", TString::Format("%s_%d", genname.Data(), facet[3]));
1792 fGdmlE->NewAttr(childN, nullptr, "type", "ABSOLUTE");
1794 }
1795 return mainN;
1796}
1797
1798////////////////////////////////////////////////////////////////////////////////
1799/// Creates a scaled node for GDML
1800
1802{
1806 auto const scale = geoShape->GetScale()->GetScale();
1807 TGeoShape *unscaled = geoShape->GetShape();
1808 // Create the unscaled shape record
1810 // retrieve node name by their pointer to make reference
1812
1813 // the unplaced node appended to main structure of nodes (if they are not already there)
1814 if (unscaledN != nullptr) {
1816 fSolCnt++;
1817 } else {
1818 if (uname.Contains("missing_") || uname == "") {
1819 Info("CreateScaledN", "ERROR! Unscaled node is NULL - Scaled shape will be skipped");
1820 return nullptr;
1821 }
1822 }
1823
1824 // create union node and its child nodes (or intersection or subtraction)
1825 /* <scaledSolid name="...">
1826 * <solidref ref="unscaled solid name" />
1827 * <scale name="scale name" x="sx" y="sy" z="sz">
1828 * </scaledSolid>
1829 */
1830 mainN = fGdmlE->NewChild(nullptr, nullptr, "scaledSolid", nullptr);
1831 fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1832
1833 //<solidref> (solid)
1834 childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
1835 fGdmlE->NewAttr(childN, nullptr, "ref", uname);
1837
1838 //<scale ame="scale name" x="sx" y="sy" z="sz">
1839 childN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
1840 fGdmlE->NewAttr(childN, nullptr, "name", (nodeName + "scl").Data());
1841 fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), scale[0]));
1842 fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), scale[1]));
1843 fGdmlE->NewAttr(childN, nullptr, "z", TString::Format(fltPrecision.Data(), scale[2]));
1845
1846 return mainN;
1847}
1848
1849////////////////////////////////////////////////////////////////////////////////
1850/// Creates common part of union intersection and subtraction nodes
1851
1853{
1857 TGeoBoolNode::EGeoBoolType boolType = geoShape->GetBoolNode()->GetBooleanOperator();
1858 switch (boolType) {
1859 case TGeoBoolNode::kGeoUnion: lboolType = "union"; break;
1860 case TGeoBoolNode::kGeoSubtraction: lboolType = "subtraction"; break;
1861 case TGeoBoolNode::kGeoIntersection: lboolType = "intersection"; break;
1862 }
1863
1864 TGDMLWrite::Xyz lrot = GetXYZangles(geoShape->GetBoolNode()->GetLeftMatrix()->Inverse().GetRotationMatrix());
1865 const Double_t *ltr = geoShape->GetBoolNode()->GetLeftMatrix()->GetTranslation();
1866 TGDMLWrite::Xyz rrot = GetXYZangles(geoShape->GetBoolNode()->GetRightMatrix()->Inverse().GetRotationMatrix());
1867 const Double_t *rtr = geoShape->GetBoolNode()->GetRightMatrix()->GetTranslation();
1868
1869 // specific case!
1870 // Ellipsoid tag preparing
1871 // if left == TGeoScaledShape AND right == TGeoBBox
1872 // AND if TGeoScaledShape->GetShape == TGeoSphere
1873 TGeoShape *leftS = geoShape->GetBoolNode()->GetLeftShape();
1874 TGeoShape *rightS = geoShape->GetBoolNode()->GetRightShape();
1875 if (strcmp(leftS->ClassName(), "TGeoScaledShape") == 0 && strcmp(rightS->ClassName(), "TGeoBBox") == 0) {
1876 if (strcmp(((TGeoScaledShape *)leftS)->GetShape()->ClassName(), "TGeoSphere") == 0) {
1877 if (lboolType == "intersection") {
1879 return mainN;
1880 }
1881 }
1882 }
1883
1885 // translation
1886 translL.x = ltr[0];
1887 translL.y = ltr[1];
1888 translL.z = ltr[2];
1889 translR.x = rtr[0];
1890 translR.y = rtr[1];
1891 translR.z = rtr[2];
1892
1893 // left and right nodes are created here also their names are created
1894 ndL = ChooseObject(geoShape->GetBoolNode()->GetLeftShape());
1895 ndR = ChooseObject(geoShape->GetBoolNode()->GetRightShape());
1896
1897 // retrieve left and right node names by their pointer to make reference
1898 TString lname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetLeftShape())];
1899 TString rname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetRightShape())];
1900
1901 // left and right nodes appended to main structure of nodes (if they are not already there)
1902 if (ndL != nullptr) {
1904 fSolCnt++;
1905 } else {
1906 if (lname.Contains("missing_") || lname == "") {
1907 Info("CreateCommonBoolN", "ERROR! Left node is NULL - Boolean Shape will be skipped");
1908 return nullptr;
1909 }
1910 }
1911 if (ndR != nullptr) {
1913 fSolCnt++;
1914 } else {
1915 if (rname.Contains("missing_") || rname == "") {
1916 Info("CreateCommonBoolN", "ERROR! Right node is NULL - Boolean Shape will be skipped");
1917 return nullptr;
1918 }
1919 }
1920
1921 // create union node and its child nodes (or intersection or subtraction)
1922 /* <union name="...">
1923 * <first ref="left name" />
1924 * <second ref="right name" />
1925 * <firstposition .../>
1926 * <firstrotation .../>
1927 * <position .../>
1928 * <rotation .../>
1929 * </union>
1930 */
1931 mainN = fGdmlE->NewChild(nullptr, nullptr, lboolType.Data(), nullptr);
1932 fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1933
1934 //<first> (left)
1935 childN = fGdmlE->NewChild(nullptr, nullptr, "first", nullptr);
1936 fGdmlE->NewAttr(childN, nullptr, "ref", lname);
1938
1939 //<second> (right)
1940 childN = fGdmlE->NewChild(nullptr, nullptr, "second", nullptr);
1941 fGdmlE->NewAttr(childN, nullptr, "ref", rname);
1943
1944 //<firstposition> (left)
1945 if ((translL.x != 0.0) || (translL.y != 0.0) || (translL.z != 0.0)) {
1946 childN = CreatePositionN((nodeName + lname + "pos").Data(), translL, "firstposition", fDefault_lunit);
1948 }
1949 //<firstrotation> (left)
1950 if ((lrot.x != 0.0) || (lrot.y != 0.0) || (lrot.z != 0.0)) {
1951 childN = CreateRotationN((nodeName + lname + "rot").Data(), lrot, "firstrotation");
1953 }
1954 //<position> (right)
1955 if ((translR.x != 0.0) || (translR.y != 0.0) || (translR.z != 0.0)) {
1956 childN = CreatePositionN((nodeName + rname + "pos").Data(), translR, "position", fDefault_lunit);
1958 }
1959 //<rotation> (right)
1960 if ((rrot.x != 0.0) || (rrot.y != 0.0) || (rrot.z != 0.0)) {
1961 childN = CreateRotationN((nodeName + rname + "rot").Data(), rrot, "rotation");
1963 }
1964
1965 return mainN;
1966}
1967
1968////////////////////////////////////////////////////////////////////////////////
1969/// Creates "opticalsurface" node for GDML
1970
1972{
1973 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "opticalsurface", nullptr);
1975 std::string name = make_NCName(geoSurf->GetName());
1976 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
1977 fGdmlE->NewAttr(mainN, nullptr, "model", TGeoOpticalSurface::ModelToString(geoSurf->GetModel()));
1978 fGdmlE->NewAttr(mainN, nullptr, "finish", TGeoOpticalSurface::FinishToString(geoSurf->GetFinish()));
1979 fGdmlE->NewAttr(mainN, nullptr, "type", TGeoOpticalSurface::TypeToString(geoSurf->GetType()));
1980 fGdmlE->NewAttr(mainN, nullptr, "value", TString::Format(fltPrecision.Data(), geoSurf->GetValue()));
1981
1982 // Write properties
1983 TList const &properties = geoSurf->GetProperties();
1984 if (properties.GetSize()) {
1985 TIter next(&properties);
1987 while ((property = (TNamed *)next()))
1989 }
1990 // Write CONST properties
1991 TList const &const_properties = geoSurf->GetConstProperties();
1992 if (const_properties.GetSize()) {
1993 TIter next(&const_properties);
1995 while ((property = (TNamed *)next()))
1997 }
1998 return mainN;
1999}
2000
2001////////////////////////////////////////////////////////////////////////////////
2002/// Creates "skinsurface" node for GDML
2003
2005{
2006 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "skinsurface", nullptr);
2007 std::string name = make_NCName(geoSurf->GetName());
2008 std::string prop = make_NCName(geoSurf->GetTitle());
2009
2010 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
2011 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
2012
2013 // Cretate the logical volume reference node
2014 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2015 const TString &volname = fNameList->fLst[TString::Format("%p", geoSurf->GetVolume())];
2016 fGdmlE->NewAttr(childN, nullptr, "ref", volname.Data());
2018 return mainN;
2019}
2020
2021////////////////////////////////////////////////////////////////////////////////
2022/// Creates "bordersurface" node for GDML
2023
2025{
2026 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "bordersurface", nullptr);
2027 std::string name = make_NCName(geoSurf->GetName());
2028 std::string prop = make_NCName(geoSurf->GetTitle());
2029
2030 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
2031 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
2032
2033 // Cretate the logical volume reference nodes
2034 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
2036 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
2038
2039 childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
2040 physvolname = fNameList->fLst[TString::Format("%p", geoSurf->GetNode2())];
2041 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
2043 return mainN;
2044}
2045
2046////////////////////////////////////////////////////////////////////////////////
2047/// Creates "position" kind of node for GDML
2048
2049XMLNodePointer_t TGDMLWrite::CreatePositionN(const char *name, Xyz position, const char *type, const char *unit)
2050{
2051 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
2053 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2054 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), position.x));
2055 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), position.y));
2056 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), position.z));
2057 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2058 return mainN;
2059}
2060
2061////////////////////////////////////////////////////////////////////////////////
2062/// Creates "rotation" kind of node for GDML
2063
2064XMLNodePointer_t TGDMLWrite::CreateRotationN(const char *name, Xyz rotation, const char *type, const char *unit)
2065{
2066 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
2068 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2069 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), rotation.x));
2070 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), rotation.y));
2071 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), rotation.z));
2072 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2073 return mainN;
2074}
2075
2076////////////////////////////////////////////////////////////////////////////////
2077/// Creates "matrix" kind of node for GDML
2078
2080{
2081 std::stringstream vals;
2082 size_t cols = matrix->GetCols();
2083 size_t rows = matrix->GetRows();
2084 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
2085 fGdmlE->NewAttr(mainN, nullptr, "name", matrix->GetName());
2086 fGdmlE->NewAttr(mainN, nullptr, "coldim", TString::Format("%zu", cols));
2088 for (size_t i = 0; i < rows; ++i) {
2089 for (size_t j = 0; j < cols; ++j) {
2090 vals << TString::Format(fltPrecision.Data(), matrix->Get(i, j));
2091 if (j < cols - 1)
2092 vals << ' ';
2093 }
2094 if (i < rows - 1)
2095 vals << '\n';
2096 }
2097 fGdmlE->NewAttr(mainN, nullptr, "values", vals.str().c_str());
2098 return mainN;
2099}
2100
2101////////////////////////////////////////////////////////////////////////////////
2102/// Creates "constant" kind of node for GDML
2103
2105{
2106 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
2108 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2109 fGdmlE->NewAttr(mainN, nullptr, "coldim", "1");
2110 fGdmlE->NewAttr(mainN, nullptr, "values", TString::Format(fltPrecision.Data(), value));
2111 return mainN;
2112}
2113
2114////////////////////////////////////////////////////////////////////////////////
2115/// Creates "setup" node for GDML
2116
2118{
2119 XMLNodePointer_t setupN = fGdmlE->NewChild(nullptr, nullptr, "setup", nullptr);
2120 fGdmlE->NewAttr(setupN, nullptr, "name", name);
2121 fGdmlE->NewAttr(setupN, nullptr, "version", version);
2122 XMLNodePointer_t fworldN = fGdmlE->NewChild(setupN, nullptr, "world", nullptr);
2123 fGdmlE->NewAttr(fworldN, nullptr, "ref", topVolName);
2124 return setupN;
2125}
2126
2127////////////////////////////////////////////////////////////////////////////////
2128/// Creates "volume" node for GDML
2129
2130XMLNodePointer_t TGDMLWrite::StartVolumeN(const char *name, const char *solid, const char *material)
2131{
2133 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "volume", nullptr);
2134 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2135
2136 childN = fGdmlE->NewChild(nullptr, nullptr, "materialref", nullptr);
2137 fGdmlE->NewAttr(childN, nullptr, "ref", material);
2139
2140 childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
2141 fGdmlE->NewAttr(childN, nullptr, "ref", solid);
2143
2144 return mainN;
2145}
2146
2147////////////////////////////////////////////////////////////////////////////////
2148/// Creates "assembly" node for GDML
2149
2151{
2152 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "assembly", nullptr);
2153 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2154
2155 return mainN;
2156}
2157
2158////////////////////////////////////////////////////////////////////////////////
2159/// Creates "physvol" node for GDML
2160
2162 const char *rotref, XMLNodePointer_t scaleN)
2163{
2164 fPhysVolCnt++;
2166 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "physvol", nullptr);
2167 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2168 fGdmlE->NewAttr(mainN, nullptr, "copynumber", TString::Format("%d", copyno));
2169
2170 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2171 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2173
2174 childN = fGdmlE->NewChild(nullptr, nullptr, "positionref", nullptr);
2175 fGdmlE->NewAttr(childN, nullptr, "ref", posref);
2177
2178 // if is not empty string add this node
2179 if (strcmp(rotref, "") != 0) {
2180 childN = fGdmlE->NewChild(nullptr, nullptr, "rotationref", nullptr);
2181 fGdmlE->NewAttr(childN, nullptr, "ref", rotref);
2183 }
2184 if (scaleN != nullptr) {
2186 }
2187
2188 return mainN;
2189}
2190
2191////////////////////////////////////////////////////////////////////////////////
2192/// Creates "divisionvol" node for GDML
2193
2195 const char *unit, const char *volref)
2196{
2197 XMLNodePointer_t childN = nullptr;
2198 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "divisionvol", nullptr);
2199 fGdmlE->NewAttr(mainN, nullptr, "axis", axis);
2200 fGdmlE->NewAttr(mainN, nullptr, "number", TString::Format("%i", number));
2202 if (fgG4Compatibility == kTRUE) {
2203 // if eg. full length is 20 and width * number = 20,0001 problem in geant4
2204 // unit is either in cm or degrees nothing else
2205 width = (floor(width * 1E4)) * 1E-4;
2206 if ((offset >= 0.) && (strcmp(axis, "kPhi") == 0)) {
2209 // put to range from 0 to 360 add decimals and then put to range 0 -> -360
2210 offset = (offsetI % 360) + decimals - 360;
2211 }
2212 }
2213 fGdmlE->NewAttr(mainN, nullptr, "width", TString::Format(fltPrecision.Data(), width));
2214
2215 fGdmlE->NewAttr(mainN, nullptr, "offset", TString::Format(fltPrecision.Data(), offset));
2216 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2217 if (strcmp(volref, "") != 0) {
2218 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2219 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2220 }
2222
2223 return mainN;
2224}
2225
2226////////////////////////////////////////////////////////////////////////////////
2227/// Chooses the object and method that should be used for processing object
2228
2230{
2231 const char *clsname = geoShape->ClassName();
2233
2234 if (CanProcess((TObject *)geoShape) == kFALSE) {
2235 return nullptr;
2236 }
2237
2238 // process different shapes
2239 if (strcmp(clsname, "TGeoBBox") == 0) {
2241 } else if (strcmp(clsname, "TGeoParaboloid") == 0) {
2243 } else if (strcmp(clsname, "TGeoSphere") == 0) {
2245 } else if (strcmp(clsname, "TGeoArb8") == 0) {
2247 } else if (strcmp(clsname, "TGeoConeSeg") == 0) {
2249 } else if (strcmp(clsname, "TGeoCone") == 0) {
2251 } else if (strcmp(clsname, "TGeoPara") == 0) {
2253 } else if (strcmp(clsname, "TGeoTrap") == 0) {
2255 } else if (strcmp(clsname, "TGeoGtra") == 0) {
2257 } else if (strcmp(clsname, "TGeoTrd1") == 0) {
2259 } else if (strcmp(clsname, "TGeoTrd2") == 0) {
2261 } else if (strcmp(clsname, "TGeoTubeSeg") == 0) {
2263 } else if (strcmp(clsname, "TGeoCtub") == 0) {
2265 } else if (strcmp(clsname, "TGeoTube") == 0) {
2267 } else if (strcmp(clsname, "TGeoPcon") == 0) {
2269 } else if (strcmp(clsname, "TGeoTorus") == 0) {
2271 } else if (strcmp(clsname, "TGeoPgon") == 0) {
2273 } else if (strcmp(clsname, "TGeoEltu") == 0) {
2275 } else if (strcmp(clsname, "TGeoHype") == 0) {
2277 } else if (strcmp(clsname, "TGeoXtru") == 0) {
2279 } else if (strcmp(clsname, "TGeoTessellated") == 0) {
2281 } else if (strcmp(clsname, "TGeoScaledShape") == 0) {
2283 } else if (strcmp(clsname, "TGeoCompositeShape") == 0) {
2285 } else if (strcmp(clsname, "TGeoUnion") == 0) {
2287 } else if (strcmp(clsname, "TGeoIntersection") == 0) {
2289 } else if (strcmp(clsname, "TGeoSubtraction") == 0) {
2291 } else {
2292 Info("ChooseObject", "ERROR! %s Solid CANNOT be processed, solid is NOT supported", clsname);
2293 solidN = nullptr;
2294 }
2295 if (solidN == nullptr) {
2296 if (fNameList->fLst[TString::Format("%p", geoShape)] == "") {
2297 TString missingName = geoShape->GetName();
2298 GenName("missing_" + missingName, TString::Format("%p", geoShape));
2299 } else {
2301 "missing_" + fNameList->fLst[TString::Format("%p", geoShape)];
2302 }
2303 }
2304
2305 return solidN;
2306}
2307
2308////////////////////////////////////////////////////////////////////////////////
2309/// Retrieves X Y Z angles from rotation matrix
2310
2312{
2314 Double_t a, b, c;
2315 Double_t rad = 180.0 / TMath::ACos(-1.0);
2316 const Double_t *r = rotationMatrix;
2317 Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
2318 if (cosb > 0.00001) {
2319 a = TMath::ATan2(r[5], r[8]) * rad;
2320 b = TMath::ATan2(-r[2], cosb) * rad;
2321 c = TMath::ATan2(r[1], r[0]) * rad;
2322 } else {
2323 a = TMath::ATan2(-r[7], r[4]) * rad;
2324 b = TMath::ATan2(-r[2], cosb) * rad;
2325 c = 0;
2326 }
2327 lxyz.x = a;
2328 lxyz.y = b;
2329 lxyz.z = c;
2330 return lxyz;
2331}
2332
2333////////////////////////////////////////////////////////////////////////////////
2334/// Method creating cutTube as an intersection of tube and two boxes
2335/// - not used anymore because cutube is supported in Geant4 9.5
2336
2338{
2339 Double_t rmin = geoShape->GetRmin();
2340 Double_t rmax = geoShape->GetRmax();
2341 Double_t z = geoShape->GetDz();
2342 Double_t startphi = geoShape->GetPhi1();
2343 Double_t deltaphi = geoShape->GetPhi2();
2344 Double_t x1 = geoShape->GetNlow()[0];
2345 Double_t y1 = geoShape->GetNlow()[1];
2346 Double_t z1 = geoShape->GetNlow()[2];
2347 Double_t x2 = geoShape->GetNhigh()[0];
2348 Double_t y2 = geoShape->GetNhigh()[1];
2349 Double_t z2 = geoShape->GetNhigh()[2];
2350 TString xname = geoShape->GetName();
2351
2352 Double_t h0 = 2. * ((TGeoBBox *)geoShape)->GetDZ();
2353 Double_t h1 = 2 * z;
2354 Double_t h2 = 2 * z;
2355 Double_t boxdx = 1E8 * (2 * rmax) + (2 * z);
2356
2357 TGeoTubeSeg *T = new TGeoTubeSeg((xname + "T").Data(), rmin, rmax, h0, startphi, deltaphi);
2358 TGeoBBox *B1 = new TGeoBBox((xname + "B1").Data(), boxdx, boxdx, h1);
2359 TGeoBBox *B2 = new TGeoBBox((xname + "B2").Data(), boxdx, boxdx, h2);
2360
2361 // first box position parameters
2363 Double_t theta1 = 360 - TMath::ATan2(sqrt(x1 * x1 + y1 * y1), z1) * TMath::RadToDeg();
2364
2366 Double_t theta11 = TMath::ATan2(z1, sqrt(x1 * x1 + y1 * y1)) * TMath::RadToDeg();
2367
2371
2372 // second box position parameters
2374 Double_t theta2 = 360 - TMath::ATan2(sqrt(x2 * x2 + y2 * y2), z2) * TMath::RadToDeg();
2375
2377 Double_t theta21 = TMath::ATan2(z2, sqrt(x2 * x2 + y2 * y2)) * TMath::RadToDeg();
2378
2381 Double_t zpos2 = h2 * TMath::Sin((theta21)*TMath::DegToRad()) * (-1);
2382
2383 // positioning
2384 TGeoTranslation *t0 = new TGeoTranslation(0, 0, 0);
2385 TGeoTranslation *t1 = new TGeoTranslation(0 + xpos1, 0 + ypos1, 0 + (zpos1 - z));
2386 TGeoTranslation *t2 = new TGeoTranslation(0 + xpos2, 0 + ypos2, 0 + (zpos2 + z));
2387 TGeoRotation *r0 = new TGeoRotation((xname + "r0").Data());
2388 TGeoRotation *r1 = new TGeoRotation((xname + "r1").Data());
2389 TGeoRotation *r2 = new TGeoRotation((xname + "r2").Data());
2390
2391 r1->SetAngles(phi1, theta1, 0);
2392 r2->SetAngles(phi2, theta2, 0);
2393
2394 TGeoMatrix *m0 = new TGeoCombiTrans(*t0, *r0);
2395 TGeoMatrix *m1 = new TGeoCombiTrans(*t1, *r1);
2396 TGeoMatrix *m2 = new TGeoCombiTrans(*t2, *r2);
2397
2398 TGeoCompositeShape *CS1 = new TGeoCompositeShape((xname + "CS1").Data(), new TGeoIntersection(T, B1, m0, m1));
2399 TGeoCompositeShape *cs = new TGeoCompositeShape((xname + "CS").Data(), new TGeoIntersection(CS1, B2, m0, m2));
2400 delete t0;
2401 delete t1;
2402 delete t2;
2403 delete r0;
2404 delete r1;
2405 delete r2;
2406 return cs;
2407}
2408
2409////////////////////////////////////////////////////////////////////////////////
2410/// Checks whether name2check is in (NameList) list
2411
2413{
2414 Bool_t isIN = list[name2check];
2415 return isIN;
2416}
2417
2418////////////////////////////////////////////////////////////////////////////////
2419/// NCNAME basic restrictions
2420/// Replace "$" character with empty character etc.
2421
2423{
2424 TString newname = oldname.ReplaceAll("$", "");
2425 newname = newname.ReplaceAll(" ", "_");
2426 // :, @, $, %, &, /, +, ,, ;, whitespace characters or different parenthesis
2427 newname = newname.ReplaceAll(":", "");
2428 newname = newname.ReplaceAll("@", "");
2429 newname = newname.ReplaceAll("%", "");
2430 newname = newname.ReplaceAll("&", "");
2431 newname = newname.ReplaceAll("/", "");
2432 newname = newname.ReplaceAll("+", "");
2433 newname = newname.ReplaceAll(";", "");
2434 newname = newname.ReplaceAll("{", "");
2435 newname = newname.ReplaceAll("}", "");
2436 newname = newname.ReplaceAll("(", "");
2437 newname = newname.ReplaceAll(")", "");
2438 newname = newname.ReplaceAll("[", "");
2439 newname = newname.ReplaceAll("]", "");
2440 newname = newname.ReplaceAll("_refl", "");
2441 // workaround if first letter is digit than replace it to "O" (ou character)
2442 TString fstLet = newname(0, 1);
2443 if (fstLet.IsDigit()) {
2444 newname = "O" + newname(1, newname.Length());
2445 }
2446 return newname;
2447}
2448
2449////////////////////////////////////////////////////////////////////////////////
2450/// Important function which is responsible for naming volumes, solids and materials
2451
2453{
2455 if (newname != oldname) {
2456 if (fgkMaxNameErr > fActNameErr) {
2457 Info("GenName", "WARNING! Name of the object was changed because it failed to comply with NCNAME xml datatype "
2458 "restrictions.");
2459 } else if ((fgkMaxNameErr == fActNameErr)) {
2460 Info("GenName", "WARNING! Probably more names are going to be changed to comply with NCNAME xml datatype "
2461 "restriction, but it will not be displayed on the screen.");
2462 }
2463 fActNameErr++;
2464 }
2466 Int_t iter = 0;
2467 switch (fgNamingSpeed) {
2468 case kfastButUglySufix: newname = newname + "0x" + objPointer; break;
2469 case kelegantButSlow:
2470 // 0 means not in the list
2471 iter = fNameList->fLstIter[newname];
2472 if (iter == 0) {
2473 nameIter = "";
2474 } else {
2475 nameIter = TString::Format("0x%i", iter);
2476 }
2479 break;
2481 // no change
2482 break;
2483 }
2484 // store the name (mapped to pointer)
2486 return newname;
2487}
2488
2489////////////////////////////////////////////////////////////////////////////////
2490/// Method which tests whether solids can be processed
2491
2493{
2495 isProcessed = pointer->TestBit(fgkProcBit);
2496 pointer->SetBit(fgkProcBit, kTRUE);
2497 return !(isProcessed);
2498}
2499
2500////////////////////////////////////////////////////////////////////////////////
2501/// Method that retrieves axis and unit along which object is divided
2502
2504{
2506 unit = fDefault_lunit;
2507 switch (divAxis) {
2508 case 1:
2509 if (strcmp(pattName, "TGeoPatternX") == 0) {
2510 return "kXAxis";
2511 } else if (strcmp(pattName, "TGeoPatternCylR") == 0) {
2512 return "kRho";
2513 }
2514 break;
2515 case 2:
2516 if (strcmp(pattName, "TGeoPatternY") == 0) {
2517 return "kYAxis";
2518 } else if (strcmp(pattName, "TGeoPatternCylPhi") == 0) {
2519 unit = "deg";
2520 return "kPhi";
2521 }
2522 break;
2523 case 3:
2524 if (strcmp(pattName, "TGeoPatternZ") == 0) {
2525 return "kZAxis";
2526 }
2527 break;
2528 default: return "kUndefined"; break;
2529 }
2530 return "kUndefined";
2531}
2532
2533////////////////////////////////////////////////////////////////////////////////
2534/// Check for null parameter to skip the NULL objects
2535
2537{
2538 if (parValue == 0.) {
2539 Info("IsNullParam", "ERROR! %s is NULL due to %s = %.12g, Volume based on this shape will be skipped",
2540 objName.Data(), parName.Data(), parValue);
2541 return kTRUE;
2542 }
2543 return kFALSE;
2544}
2545
2546////////////////////////////////////////////////////////////////////////////////
2547/// Unsetting bits that were changed in gGeoManager during export so that export
2548/// can be run more times with the same instance of gGeoManager.
2549
2551{
2552 TIter next(geoMng->GetListOfVolumes());
2553 TGeoVolume *vol;
2554 while ((vol = (TGeoVolume *)next())) {
2555 ((TObject *)vol->GetShape())->SetBit(fgkProcBit, kFALSE);
2557 }
2558}
2559
2560////////////////////////////////////////////////////////////////////////////////
2561//
2562// Backwards compatibility for old DD4hep version (to be removed in the future)
2563//
2564////////////////////////////////////////////////////////////////////////////////
2565
2566////////////////////////////////////////////////////////////////////////////////
2567// Backwards compatibility (to be removed in the future): Wrapper to only selectively write one branch
2569{
2570 TList materials, volumes, nodes;
2571 MaterialExtractor extract;
2572 if (!volume) {
2573 Info("WriteGDMLfile", "Invalid Volume reference to extract GDML information!");
2574 return;
2575 }
2576 extract(volume);
2577 for (TGeoMaterial *m : extract.materials)
2578 materials.Add(m);
2579 fTopVolumeName = volume->GetName();
2580 fTopVolume = volume;
2581 fSurfaceList.clear();
2582 fVolumeList.clear();
2583 fNodeList.clear();
2584 WriteGDMLfile(geomanager, volume, &materials, filename, option);
2585 materials.Clear("nodelete");
2586 volumes.Clear("nodelete");
2587 nodes.Clear("nodelete");
2588}
2589
2590////////////////////////////////////////////////////////////////////////////////
2591/// Wrapper of all exporting methods
2592/// Creates blank GDML file and fills it with gGeoManager structure converted
2593/// to GDML structure of xml nodes
2594
2597{
2598 // option processing
2599 option.ToLower();
2600 if (option.Contains("g")) {
2602 Info("WriteGDMLfile", "Geant4 compatibility mode set");
2603 } else {
2605 }
2606 if (option.Contains("f")) {
2608 Info("WriteGDMLfile", "Fast naming convention with pointer suffix set");
2609 } else if (option.Contains("n")) {
2611 Info("WriteGDMLfile", "Naming without prefix set - be careful uniqness of name is not ensured");
2612 } else {
2614 Info("WriteGDMLfile", "Potentially slow with incremental suffix naming convention set");
2615 }
2616
2617 // local variables
2618 Int_t outputLayout = 1;
2619 const char *krootNodeName = "gdml";
2620 const char *knsRefGeneral = "http://www.w3.org/2001/XMLSchema-instance";
2621 const char *knsNameGeneral = "xsi";
2622 const char *knsRefGdml = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
2623 const char *knsNameGdml = "xsi:noNamespaceSchemaLocation";
2624
2625 // First create engine
2626 fGdmlE = new TXMLEngine;
2628
2629 // create blank GDML file
2630 fGdmlFile = fGdmlE->NewDoc();
2631
2632 // create root node and add it to blank GDML file
2633 XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
2635
2636 // add namespaces to root node
2639
2640 // initialize general lists and <define>, <solids>, <structure> nodes
2641 fIsotopeList = new StructLst;
2642 fElementList = new StructLst;
2643
2644 fNameList = new NameLst;
2645
2646 fDefineNode = fGdmlE->NewChild(nullptr, nullptr, "define", nullptr);
2647 fSolidsNode = fGdmlE->NewChild(nullptr, nullptr, "solids", nullptr);
2648 fStructureNode = fGdmlE->NewChild(nullptr, nullptr, "structure", nullptr);
2649 //========================
2650
2651 // initialize list of accepted patterns for divisions (in ExtractVolumes)
2652 fAccPatt = new StructLst;
2653 fAccPatt->fLst["TGeoPatternX"] = kTRUE;
2654 fAccPatt->fLst["TGeoPatternY"] = kTRUE;
2655 fAccPatt->fLst["TGeoPatternZ"] = kTRUE;
2656 fAccPatt->fLst["TGeoPatternCylR"] = kTRUE;
2657 fAccPatt->fLst["TGeoPatternCylPhi"] = kTRUE;
2658 //========================
2659
2660 // initialize list of rejected shapes for divisions (in ExtractVolumes)
2661 fRejShape = new StructLst;
2662 // this shapes are rejected because, it is not possible to divide trd2
2663 // in Y axis and while only trd2 object is imported from GDML
2664 // it causes a problem when TGeoTrd1 is divided in Y axis
2665 fRejShape->fLst["TGeoTrd1"] = kTRUE;
2666 fRejShape->fLst["TGeoTrd2"] = kTRUE;
2667 //=========================
2668
2669 // Initialize global counters
2670 fActNameErr = 0;
2671 fVolCnt = 0;
2672 fPhysVolCnt = 0;
2673 fSolCnt = 0;
2674
2675 // calling main extraction functions (with measuring time)
2676 time_t startT, endT;
2677 startT = time(nullptr);
2678 ExtractMatrices(geomanager->GetListOfGDMLMatrices());
2681
2682 Info("WriteGDMLfile", "Extracting volumes");
2683 ExtractVolumes(volume);
2684 Info("WriteGDMLfile", "%i solids added", fSolCnt);
2685 Info("WriteGDMLfile", "%i volumes added", fVolCnt);
2686 Info("WriteGDMLfile", "%i physvolumes added", fPhysVolCnt);
2687 ExtractSkinSurfaces(geomanager->GetListOfSkinSurfaces());
2688 ExtractBorderSurfaces(geomanager->GetListOfBorderSurfaces());
2689 ExtractOpticalSurfaces(geomanager->GetListOfOpticalSurfaces());
2690 endT = time(nullptr);
2691 //<gdml>
2692 fGdmlE->AddChild(rootNode, fDefineNode); // <define>...</define>
2693 fGdmlE->AddChild(rootNode, fMaterialsNode); // <materials>...</materials>
2694 fGdmlE->AddChild(rootNode, fSolidsNode); // <solids>...</solids>
2695 fGdmlE->AddChild(rootNode, fStructureNode); // <structure>...</structure>
2696 fGdmlE->AddChild(rootNode, CreateSetupN(fTopVolumeName.Data())); // <setup>...</setup>
2697 //</gdml>
2699 TString tdiffS = (tdiffI == 0 ? TString("< 1 s") : TString::Format("%.0lf s", tdiffI));
2700 Info("WriteGDMLfile", "Exporting time: %s", tdiffS.Data());
2701 //=========================
2702
2703 // Saving document
2705 Info("WriteGDMLfile", "File %s saved", filename);
2706 // cleaning
2708 // unset processing bits:
2710 delete fGdmlE;
2711}
2712
2713////////////////////////////////////////////////////////////////////////////////
2714/// Method extracting geometry structure recursively
2715
2717{
2720 TGeoPatternFinder *pattFinder = nullptr;
2723
2724 // create the name for volume/assembly
2725 if (volume == fTopVolume) {
2726 // not needed a special function for generating name
2727 volname = volume->GetName();
2729 // register name to the pointer
2730 fNameList->fLst[TString::Format("%p", volume)] = volname;
2731 } else {
2732 volname = GenName(volume->GetName(), TString::Format("%p", volume));
2733 }
2734
2735 // start to create main volume/assembly node
2736 if (volume->IsAssembly()) {
2738 } else {
2739 // get reference material and add solid to <solids> + get name
2740 matname = fNameList->fLst[TString::Format("%p", volume->GetMaterial())];
2741 solname = ExtractSolid(volume->GetShape());
2742 // If solid is not supported or corrupted
2743 if (solname == "-1") {
2744 Info("ExtractVolumes", "ERROR! %s volume was not added, because solid is either not supported or corrupted",
2745 volname.Data());
2746 // set volume as missing volume
2747 fNameList->fLst[TString::Format("%p", volume)] = "missing_" + volname;
2748 return;
2749 }
2751
2752 // divisionvol can't be in assembly
2753 pattFinder = volume->GetFinder();
2754 // if found pattern
2755 if (pattFinder) {
2756 pattClsName = TString::Format("%s", pattFinder->ClassName());
2757 TString shapeCls = TString::Format("%s", volume->GetShape()->ClassName());
2758 // if pattern in accepted pattern list and not in shape rejected list
2759 if ((fAccPatt->fLst[pattClsName] == kTRUE) && (fRejShape->fLst[shapeCls] != kTRUE)) {
2760 isPattern = kTRUE;
2761 }
2762 }
2763 }
2764 // get all nodes in volume
2765 TObjArray *nodeLst = volume->GetNodes();
2766 TIter next(nodeLst);
2769 Int_t nCnt = 0;
2770 // loop through all nodes
2771 while ((geoNode = (TGeoNode *)next())) {
2772 // get volume of current node and if not processed then process it
2773 TGeoVolume *subvol = geoNode->GetVolume();
2774 if (subvol->TestAttBit(fgkProcBitVol) == kFALSE) {
2775 subvol->SetAttBit(fgkProcBitVol);
2777 }
2778
2779 // volume of this node has to exist because it was processed recursively
2780 TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
2781 if (nodevolname.Contains("missing_")) {
2782 continue;
2783 }
2784 if (nCnt == 0) { // save name of the first node for divisionvol
2786 }
2787
2788 if (isPattern == kFALSE) {
2789 // create name for node
2790 TString nodename, posname, rotname;
2791 nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
2792 nodename = nodename + "in" + volname;
2793
2794 // create name for position and clear rotation
2795 posname = nodename + "pos";
2796 rotname = "";
2797
2798 // position
2799 const Double_t *pos = geoNode->GetMatrix()->GetTranslation();
2800 Xyz nodPos;
2801 nodPos.x = pos[0];
2802 nodPos.y = pos[1];
2803 nodPos.z = pos[2];
2804 childN = CreatePositionN(posname.Data(), nodPos, "position", fDefault_lunit);
2805 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
2806 // Deal with reflection
2807 XMLNodePointer_t scaleN = nullptr;
2808 Double_t rot3x3[9];
2809 for (Int_t i = 0; i < 9; ++i) {
2810 rot3x3[i] = geoNode->GetMatrix()->GetRotationMatrix()[i];
2811 }
2812 Double_t lx = rot3x3[0];
2813 Double_t ly = rot3x3[4];
2814 Double_t lz = rot3x3[8];
2815 if (geoNode->GetMatrix()->IsReflection()) {
2816 // A physvol is read back as translation * rotation * scale, so the reflection
2817 // is carried by <scale> and <rotation> gets the matrix with the scale taken
2818 // out again, which is a proper rotation. A matrix that is already diagonal
2819 // keeps its own signs and leaves an identity rotation; every other reflection
2820 // is written as a mirror on z plus a rotation.
2821 if (TMath::Abs(lx) != 1 || TMath::Abs(ly) != 1 || TMath::Abs(lz) != 1) {
2822 lx = 1.;
2823 ly = 1.;
2824 lz = -1.;
2825 }
2826 scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
2827 fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
2828 fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
2829 fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
2830 fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
2831 // take the scale out column by column; the entries are +-1, so multiplying
2832 // by them again is the same as dividing
2833 for (Int_t i = 0; i < 3; ++i) {
2834 rot3x3[3 * i] *= lx;
2835 rot3x3[3 * i + 1] *= ly;
2836 rot3x3[3 * i + 2] *= lz;
2837 }
2838 }
2839
2840 // rotation
2842 if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
2843 rotname = nodename + "rot";
2844 childN = CreateRotationN(rotname.Data(), lxyz);
2845 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
2846 }
2847
2848 // create physvol for main volume/assembly node
2850 childN = CreatePhysVolN(physvolname, geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(),
2851 scaleN);
2853 }
2854 nCnt++;
2855 }
2856 // create only one divisionvol node
2857 if (isPattern && pattFinder) {
2858 // retrieve attributes of division
2859 Int_t ndiv, divaxis;
2860 Double_t offset, width, xlo, xhi;
2861 TString axis, unit;
2862
2863 ndiv = pattFinder->GetNdiv();
2864 width = pattFinder->GetStep();
2865
2866 divaxis = pattFinder->GetDivAxis();
2867 volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
2868
2869 // compute relative start (not positional)
2870 offset = pattFinder->GetStart() - xlo;
2871 axis = GetPattAxis(divaxis, pattClsName, unit);
2872
2873 // create division node
2874 childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
2876 }
2877
2878 fVolCnt++;
2879 // add volume/assembly node into the <structure> node
2881}
#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:60
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
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:142
R__EXTERN TGeoManager * gGeoManager
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
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
! floating point precision when writing
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:18
EGeoBoolType
non-reused index of this node into the per-thread vector
Class describing rotation + translation.
Definition TGeoMatrix.h:318
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:174
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:153
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:46
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:39
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:100
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:23
Reference counted extension which has a pointer to and owns a user defined TObject.
Class describing rotations.
Definition TGeoMatrix.h:169
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:117
A general trapezoid.
Definition TGeoArb8.h:99
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:45
TGeoExtension * GetUserExtension() const
Definition TGeoVolume.h:135
TGeoMaterial * GetMaterial() const
Definition TGeoVolume.h:177
TObjArray * GetNodes()
Definition TGeoVolume.h:172
TGeoPatternFinder * GetFinder() const
Definition TGeoVolume.h:180
static TGeoMedium * DummyMedium()
TGeoShape * GetShape() const
Definition TGeoVolume.h:193
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:25
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:42
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
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:1082
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1070
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:386
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:2459
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:49
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:645
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:659
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:675
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
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