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),
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
251{
252 fgNamingSpeed = naming;
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Ignore dummy material instance, which causes trouble reading GDML in Geant4
257
259{
260 fIgnoreDummyMaterial = (value ? 1 : 0);
261}
262
263////////////////////////////////////////////////////////////////////////////////
264// wrapper of all main methods for extraction
265void TGDMLWrite::WriteGDMLfile(TGeoManager *geomanager, const char *filename, TString option)
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();
274 fTopVolumeName = fTopVolume->GetName();
275 WriteGDMLfile(geomanager, node, materials, filename, option);
276}
277
278////////////////////////////////////////////////////////////////////////////////
279// Wrapper to only selectively write one branch of the volume hierarchy to file
280void TGDMLWrite::WriteGDMLfile(TGeoManager *geomanager, TGeoNode *node, const char *filename, TString option)
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
308void TGDMLWrite::WriteGDMLfile(TGeoManager *geomanager, TGeoNode *node, TList *materialsLst, const char *filename,
309 TString option)
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
332 auto def_units = gGeoManager->GetDefaultUnits();
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
342 Int_t outputLayout = 1;
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;
351 fGdmlE->SetSkipComments(kTRUE);
352
353 // create blank GDML file
354 fGdmlFile = fGdmlE->NewDoc();
355
356 // create root node and add it to blank GDML file
357 XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
358 fGdmlE->DocSetRootElement(fGdmlFile, rootNode);
359
360 // add namespaces to root node
361 fGdmlE->NewNS(rootNode, knsRefGeneral, knsNameGeneral);
362 fGdmlE->NewAttr(rootNode, nullptr, knsNameGdml, knsRefGdml);
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);
403 ExtractConstants(geomanager);
404 fMaterialsNode = ExtractMaterials(materialsLst);
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);
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>
422 Double_t tdiffI = difftime(endT, startT);
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
428 fGdmlE->SaveDoc(fGdmlFile, filename, outputLayout);
429 Info("WriteGDMLfile", "File %s saved", filename);
430 // cleaning
431 fGdmlE->FreeDoc(fGdmlFile);
432 // unset processing bits:
433 UnsetTemporaryBits(geomanager);
434 delete fGdmlE;
435}
436
437////////////////////////////////////////////////////////////////////////////////
438/// Method exporting GDML matrices
439
441{
442 if (!matrixList->GetEntriesFast())
443 return;
444 XMLNodePointer_t matrixN;
445 TIter next(matrixList);
446 TGDMLMatrix *matrix;
447 while ((matrix = (TGDMLMatrix *)next())) {
448 matrixN = CreateMatrixN(matrix);
449 fGdmlE->AddChild(fDefineNode, matrixN);
450 }
451}
452
453////////////////////////////////////////////////////////////////////////////////
454/// Method exporting GDML matrices
455
457{
458 if (!geom->GetNproperties())
459 return;
460 XMLNodePointer_t constantN;
461 TString property;
462 Double_t value;
463 for (Int_t i = 0; i < geom->GetNproperties(); ++i) {
464 value = geom->GetProperty(i, property);
465 constantN = CreateConstantN(property.Data(), value);
466 fGdmlE->AddChild(fDefineNode, constantN);
467 }
468}
469
470////////////////////////////////////////////////////////////////////////////////
471/// Method exporting optical surfaces
472
474{
475 if (!surfaces->GetEntriesFast())
476 return;
477 XMLNodePointer_t surfaceN;
478 TIter next(surfaces);
479 TGeoOpticalSurface *surf;
480 while ((surf = (TGeoOpticalSurface *)next())) {
481 if (fSurfaceList.find(surf) == fSurfaceList.end())
482 continue;
483 surfaceN = CreateOpticalSurfaceN(surf);
484 fGdmlE->AddChild(fSolidsNode, surfaceN);
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;
496 XMLNodePointer_t surfaceN;
497 TIter next(surfaces);
498 TGeoSkinSurface *surf;
499 while ((surf = (TGeoSkinSurface *)next())) {
500 if (fVolumeList.find(surf->GetVolume()) == fVolumeList.end())
501 continue;
502 surfaceN = CreateSkinSurfaceN(surf);
503 fGdmlE->AddChild(fStructureNode, surfaceN);
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;
516 XMLNodePointer_t surfaceN;
517 TIter next(surfaces);
518 TGeoBorderSurface *surf;
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 }
537 surfaceN = CreateBorderSurfaceN(surf);
538 fGdmlE->AddChild(fStructureNode, surfaceN);
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);
556 TGeoMaterial *lmaterial;
557 TGeoMedium *dummy_med = TGeoVolume::DummyMedium();
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();
564 if (fIgnoreDummyMaterial && dummy_mat && dummy_nam == mname) {
565 Info("ExtractMaterials", "Skip dummy material: %s", dummy_nam.c_str());
566 continue;
567 }
568 // generate uniq name
569 TString lname = GenName(lmaterial->GetName(), TString::Format("%p", lmaterial));
570
571 if (lmaterial->IsMixture()) {
572 TGeoMixture *lmixture = (TGeoMixture *)lmaterial;
573 XMLNodePointer_t mixtureN = CreateMixtureN(lmixture, materialsN, lname);
574 fGdmlE->AddChild(materialsN, mixtureN);
575 } else {
576 XMLNodePointer_t materialN = CreateMaterialN(lmaterial, lname);
577 fGdmlE->AddChild(materialsN, materialN);
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{
590 XMLNodePointer_t solidN;
591 TString solname = "";
592 solidN = ChooseObject(volShape); // volume->GetShape()
593 fGdmlE->AddChild(fSolidsNode, solidN);
594 if (solidN != nullptr)
595 fSolCnt++;
596 solname = fNameList->fLst[TString::Format("%p", volShape)];
597 if (solname.Contains("missing_")) {
598 solname = "-1";
599 }
600 return solname;
601}
602
603////////////////////////////////////////////////////////////////////////////////
604/// Method extracting geometry structure recursively
605
607{
608 XMLNodePointer_t volumeN, childN;
609 TGeoVolume *volume = node->GetVolume();
610 TString volname, matname, solname, pattClsName, nodeVolNameBak;
611 TGeoPatternFinder *pattFinder = nullptr;
612 Bool_t isPattern = kFALSE;
613 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
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();
621 fTopVolumeName = volname;
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()) {
630 volumeN = StartAssemblyN(volname);
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 }
643 volumeN = StartVolumeN(volname, solname, matname);
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)) {
653 isPattern = kTRUE;
654 }
655 }
656 }
657 // get all nodes in volume
658 TObjArray *nodeLst = volume->GetNodes();
659 TIter next(nodeLst);
660 TGeoNode *geoNode;
661 TString physvolname;
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);
670 ExtractVolumes(geoNode);
671 }
672
673 // volume of this node has to exist because it was processed recursively
674 TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
675 if (nodevolname.Contains("missing_")) {
676 continue;
677 }
678 if (nCnt == 0) { // save name of the first node for divisionvol
679 nodeVolNameBak = nodevolname;
680 }
681
682 if (isPattern == kFALSE) {
683 // create name for node
684 TString nodename, posname, rotname;
685 nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
686 nodename = nodename + "in" + volname;
687
688 // create name for position and clear rotation
689 posname = nodename + "pos";
690 rotname = "";
691
692 // position
693 const Double_t *pos = geoNode->GetMatrix()->GetTranslation();
694 Xyz nodPos;
695 nodPos.x = pos[0];
696 nodPos.y = pos[1];
697 nodPos.z = pos[2];
698 childN = CreatePositionN(posname.Data(), nodPos, "position", fDefault_lunit);
699 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
700 // Deal with reflection
701 XMLNodePointer_t scaleN = nullptr;
702 Double_t lx, ly, lz;
703 Double_t xangle = 0;
704 Double_t zangle = 0;
705 lx = geoNode->GetMatrix()->GetRotationMatrix()[0];
706 ly = geoNode->GetMatrix()->GetRotationMatrix()[4];
707 lz = geoNode->GetMatrix()->GetRotationMatrix()[8];
708 if (geoNode->GetMatrix()->IsReflection() && TMath::Abs(lx) == 1 && TMath::Abs(ly) == 1 &&
709 TMath::Abs(lz) == 1) {
710 scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
711 fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
712 fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
713 fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
714 fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
715 // experimentally found out, that rotation should be updated like this
716 if (lx == -1) {
717 zangle = 180;
718 }
719 if (lz == -1) {
720 xangle = 180;
721 }
722 }
723
724 // rotation
726 lxyz.x -= xangle;
727 lxyz.z -= zangle;
728 if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
729 rotname = nodename + "rot";
730 childN = CreateRotationN(rotname.Data(), lxyz);
731 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
732 }
733
734 // create physvol for main volume/assembly node
735 physvolname = fNameList->fLst[TString::Format("%p", geoNode)];
736 childN = CreatePhysVolN(physvolname, geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(),
737 scaleN);
738 fGdmlE->AddChild(volumeN, childN);
739 }
740 nCnt++;
741 }
742 // create only one divisionvol node
743 if (isPattern && pattFinder) {
744 // retrieve attributes of division
745 Int_t ndiv, divaxis;
746 Double_t offset, width, xlo, xhi;
747 TString axis, unit;
748
749 ndiv = pattFinder->GetNdiv();
750 width = pattFinder->GetStep();
751
752 divaxis = pattFinder->GetDivAxis();
753 volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
754
755 // compute relative start (not positional)
756 offset = pattFinder->GetStart() - xlo;
757 axis = GetPattAxis(divaxis, pattClsName, unit);
758
759 // create division node
760 childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
761 fGdmlE->AddChild(volumeN, childN);
762 }
763
764 // export auxiliary user-data if present (TMap of TObjString->TObjString)
765 {
766 TGeoRCExtension *rcext = dynamic_cast<TGeoRCExtension *>(volume->GetUserExtension());
767 if (rcext) {
768 TObject *userObj = rcext->GetUserObject();
769 if (userObj && userObj->InheritsFrom("TMap")) {
770 TMap *auxmap = (TMap *)userObj;
771 TIterator *it = auxmap->MakeIterator();
772 TObject *k = nullptr;
773 while ((k = it->Next())) {
774 TObject *valobj = auxmap->GetValue(k);
775 if (!valobj || !k->InheritsFrom("TObjString") || !valobj->InheritsFrom("TObjString"))
776 continue;
777 TObjString *key = (TObjString *)k;
778 TObjString *val = (TObjString *)valobj;
779 TString auxtype = key->GetString();
780 TString auxvalue = val->GetString();
781 TString auxunit = "";
782 Int_t pos = auxvalue.Index('*');
783 if (pos >= 0) {
784 auxunit = auxvalue(pos + 1, auxvalue.Length());
785 auxvalue = auxvalue(0, pos);
786 }
787 XMLNodePointer_t auxN = fGdmlE->NewChild(nullptr, nullptr, "auxiliary", nullptr);
788 fGdmlE->NewAttr(auxN, nullptr, "auxtype", auxtype.Data());
789 fGdmlE->NewAttr(auxN, nullptr, "auxvalue", auxvalue.Data());
790 if (!auxunit.IsNull())
791 fGdmlE->NewAttr(auxN, nullptr, "auxunit", auxunit.Data());
792 fGdmlE->AddChild(volumeN, auxN);
793 }
794 }
795 }
796 }
797
798 fVolCnt++;
799 // add volume/assembly node into the <structure> node
800 fGdmlE->AddChild(fStructureNode, volumeN);
801}
802
803////////////////////////////////////////////////////////////////////////////////
804/// Creates "atom" node for GDML
805
807{
808 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
809 XMLNodePointer_t atomN = fGdmlE->NewChild(nullptr, nullptr, "atom", nullptr);
810 fGdmlE->NewAttr(atomN, nullptr, "unit", unit);
811 fGdmlE->NewAttr(atomN, nullptr, "value", TString::Format(fltPrecision.Data(), atom));
812 return atomN;
813}
814
815////////////////////////////////////////////////////////////////////////////////
816/// Creates "D" density node for GDML
817
819{
820 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
821 XMLNodePointer_t densN = fGdmlE->NewChild(nullptr, nullptr, "D", nullptr);
822 fGdmlE->NewAttr(densN, nullptr, "unit", unit);
823 fGdmlE->NewAttr(densN, nullptr, "value", TString::Format(fltPrecision.Data(), density));
824 return densN;
825}
826
827////////////////////////////////////////////////////////////////////////////////
828/// Creates "fraction" node for GDML
829
831{
832 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
833 XMLNodePointer_t fractN = fGdmlE->NewChild(nullptr, nullptr, "fraction", nullptr);
834 fGdmlE->NewAttr(fractN, nullptr, "n", TString::Format(fltPrecision.Data(), percentage));
835 fGdmlE->NewAttr(fractN, nullptr, "ref", refName);
836 return fractN;
837}
838
839////////////////////////////////////////////////////////////////////////////////
840/// Creates "property" node for GDML
841
843{
844 XMLNodePointer_t propertyN = fGdmlE->NewChild(nullptr, nullptr, "property", nullptr);
845 fGdmlE->NewAttr(propertyN, nullptr, "name", property.GetName());
846 fGdmlE->NewAttr(propertyN, nullptr, "ref", property.GetTitle());
847 return propertyN;
848}
849
850////////////////////////////////////////////////////////////////////////////////
851/// Creates "isotope" node for GDML
852
854{
855 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "isotope", nullptr);
856 fGdmlE->NewAttr(mainN, nullptr, "name", name);
857 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", isotope->GetN()));
858 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", isotope->GetZ()));
859 fGdmlE->AddChild(mainN, CreateAtomN(isotope->GetA()));
860 return mainN;
861}
862
863////////////////////////////////////////////////////////////////////////////////
864/// Creates "element" node for GDML
865/// element node and attribute
866
868{
869 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "element", nullptr);
870 fGdmlE->NewAttr(mainN, nullptr, "name", name);
871 // local associative arrays for saving isotopes and their weight
872 // inside element
873 NameListF wPercentage;
874 NameListI wCounter;
875
876 if (element->HasIsotopes()) {
877 Int_t nOfIso = element->GetNisotopes();
878 // go through isotopes
879 for (Int_t idx = 0; idx < nOfIso; idx++) {
880 TGeoIsotope *myIsotope = element->GetIsotope(idx);
881 if (!myIsotope) {
882 Fatal("CreateElementN", "Missing isotopes for element %s", element->GetName());
883 return mainN;
884 }
885
886 // Get name of the Isotope (
887 TString lname = myIsotope->GetName();
888 //_iso suffix is added to avoid problems with same names
889 // for material, element and isotopes
890 lname = TString::Format("%s_iso", lname.Data());
891
892 // cumulates abundance, in case 2 isotopes with same names
893 // within one element
894 wPercentage[lname] += element->GetRelativeAbundance(idx);
895 wCounter[lname]++;
896
897 // check whether isotope name is not in list of isotopes
898 if (IsInList(fIsotopeList->fLst, lname)) {
899 continue;
900 }
901 // add isotope to list of isotopes and to main <materials> node
902 fIsotopeList->fLst[lname] = kTRUE;
903 XMLNodePointer_t isoNode = CreateIsotopN(myIsotope, lname);
904 fGdmlE->AddChild(materials, isoNode);
905 }
906 // loop through asoc array of isotopes
907 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
908 if (itr->second > 1) {
909 Info("CreateMixtureN", "WARNING! 2 equal isotopes in one element. Check: %s isotope of %s element",
910 itr->first.Data(), name);
911 }
912 // add fraction child to element with reference to isotope
913 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
914 }
915 } else {
916 fGdmlE->NewAttr(mainN, nullptr, "formula", element->GetName());
917 Int_t valZ = element->Z();
918 // Z can't be <1 in Geant4 and Z is optional parameter
919 if (valZ >= 1) {
920 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format("%i", valZ));
921 }
922 Int_t valN = element->N();
923 fGdmlE->NewAttr(mainN, nullptr, "N", TString::Format("%i", valN));
924 fGdmlE->AddChild(mainN, CreateAtomN(element->A()));
925 }
926 return mainN;
927}
928
929////////////////////////////////////////////////////////////////////////////////
930/// Creates "material" node for GDML with references to other sub elements
931
933{
934 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
935 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
936
937 // Write properties
938 TList const &properties = mixture->GetProperties();
939 if (properties.GetSize()) {
940 TIter next(&properties);
941 TNamed *property;
942 while ((property = (TNamed *)next()))
943 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
944 }
945 // Write CONST properties
946 TList const &const_properties = mixture->GetConstProperties();
947 if (const_properties.GetSize()) {
948 TIter next(&const_properties);
949 TNamed *property;
950 while ((property = (TNamed *)next()))
951 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
952 }
953
954 fGdmlE->AddChild(mainN, CreateDN(mixture->GetDensity()));
955 // local associative arrays for saving elements and their weight
956 // inside mixture
957 NameListF wPercentage;
958 NameListI wCounter;
959
960 Int_t nOfElm = mixture->GetNelements();
961 // go through elements
962 for (Int_t idx = 0; idx < nOfElm; idx++) {
963 TGeoElement *myElement = mixture->GetElement(idx);
964
965 // Get name of the element
966 // NOTE: that for element - GetTitle() returns the "name" tag
967 // and GetName() returns "formula" tag (see createElementN)
968 TString lname = myElement->GetTitle();
969 //_elm suffix is added to avoid problems with same names
970 // for material and element
971 lname = TString::Format("%s_elm", lname.Data());
972
973 // cumulates percentage, in case 2 elements with same names within one mixture
974 wPercentage[lname] += mixture->GetWmixt()[idx];
975 wCounter[lname]++;
976
977 // check whether element name is not in list of elements already created
978 if (IsInList(fElementList->fLst, lname)) {
979 continue;
980 }
981
982 // add element to list of elements and to main <materials> node
983 fElementList->fLst[lname] = kTRUE;
984 XMLNodePointer_t elmNode = CreateElementN(myElement, materials, lname);
985 fGdmlE->AddChild(materials, elmNode);
986 }
987 // loop through asoc array
988 for (NameListI::iterator itr = wCounter.begin(); itr != wCounter.end(); ++itr) {
989 if (itr->second > 1) {
990 Info("CreateMixtureN", "WARNING! 2 equal elements in one material. Check: %s element of %s material",
991 itr->first.Data(), mname.Data());
992 }
993 // add fraction child to material with reference to element
994 fGdmlE->AddChild(mainN, CreateFractionN(wPercentage[itr->first], itr->first.Data()));
995 }
996
997 return mainN;
998}
999
1000////////////////////////////////////////////////////////////////////////////////
1001/// Creates "material" node for GDML
1002
1004{
1005 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "material", nullptr);
1006 fGdmlE->NewAttr(mainN, nullptr, "name", mname);
1007 Double_t valZ = material->GetZ();
1008 // Z can't be zero in Geant4 so this is workaround for vacuum
1009 TString tmpname = mname;
1010 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1011 tmpname.ToLower();
1012 if (valZ < 1) {
1013 if (tmpname == "vacuum") {
1014 valZ = 1;
1015 } else {
1016 if (fgG4Compatibility == kTRUE) {
1017 Info("CreateMaterialN",
1018 "WARNING! value of Z in %s material can't be < 1 in Geant4, that is why it was changed to 1, please "
1019 "check it manually! ",
1020 mname.Data());
1021 valZ = 1;
1022 } else {
1023 Info("CreateMaterialN", "WARNING! value of Z in %s material can't be < 1 in Geant4", mname.Data());
1024 }
1025 }
1026 }
1027 fGdmlE->NewAttr(mainN, nullptr, "Z", TString::Format(fltPrecision.Data(), valZ)); // material->GetZ()));
1028
1029 // Create properties if any: Properties according to the GDML schema MUST come first!
1030 TList const &properties = material->GetProperties();
1031 if (properties.GetSize()) {
1032 TIter next(&properties);
1033 TNamed *property;
1034 while ((property = (TNamed *)next()))
1035 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
1036 }
1037 // Write CONST properties
1038 TList const &const_properties = material->GetConstProperties();
1039 if (const_properties.GetSize()) {
1040 TIter next(&const_properties);
1041 TNamed *property;
1042 while ((property = (TNamed *)next()))
1043 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
1044 }
1045
1046 // Now add the other children
1047 fGdmlE->AddChild(mainN, CreateDN(material->GetDensity()));
1048 fGdmlE->AddChild(mainN, CreateAtomN(material->GetA()));
1049 return mainN;
1050}
1051
1052////////////////////////////////////////////////////////////////////////////////
1053/// Creates "box" node for GDML
1054
1056{
1057 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "box", nullptr);
1058 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1059 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1060 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1061 if (IsNullParam(geoShape->GetDX(), "DX", lname) || IsNullParam(geoShape->GetDY(), "DY", lname) ||
1062 IsNullParam(geoShape->GetDZ(), "DZ", lname)) {
1063 return nullptr;
1064 }
1065 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDX()));
1066 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDY()));
1067 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDZ()));
1068
1069 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1070 return mainN;
1071}
1072
1073////////////////////////////////////////////////////////////////////////////////
1074/// Creates "paraboloid" node for GDML
1075
1077{
1078 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "paraboloid", nullptr);
1079 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1080 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1081 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1082 if (IsNullParam(geoShape->GetRhi(), "Rhi", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1083 return nullptr;
1084 }
1085 fGdmlE->NewAttr(mainN, nullptr, "rlo", TString::Format(fltPrecision.Data(), geoShape->GetRlo()));
1086 fGdmlE->NewAttr(mainN, nullptr, "rhi", TString::Format(fltPrecision.Data(), geoShape->GetRhi()));
1087 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1088
1089 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1090 return mainN;
1091}
1092
1093////////////////////////////////////////////////////////////////////////////////
1094/// Creates "sphere" node for GDML
1095
1097{
1098 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "sphere", nullptr);
1099 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1100 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1101 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1102 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1103 return nullptr;
1104 }
1105
1106 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1107 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1108 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1109 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1110 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1111 fGdmlE->NewAttr(mainN, nullptr, "starttheta", TString::Format(fltPrecision.Data(), geoShape->GetTheta1()));
1112 fGdmlE->NewAttr(mainN, nullptr, "deltatheta",
1113 TString::Format(fltPrecision.Data(), geoShape->GetTheta2() - geoShape->GetTheta1()));
1114
1115 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1116 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1117 return mainN;
1118}
1119
1120////////////////////////////////////////////////////////////////////////////////
1121/// Creates "arb8" node for GDML
1122
1124{
1125 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "arb8", nullptr);
1126 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1127 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1128 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1129 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1130 return nullptr;
1131 }
1132
1133 fGdmlE->NewAttr(mainN, nullptr, "v1x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[0]));
1134 fGdmlE->NewAttr(mainN, nullptr, "v1y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[1]));
1135 fGdmlE->NewAttr(mainN, nullptr, "v2x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[2]));
1136 fGdmlE->NewAttr(mainN, nullptr, "v2y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[3]));
1137 fGdmlE->NewAttr(mainN, nullptr, "v3x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[4]));
1138 fGdmlE->NewAttr(mainN, nullptr, "v3y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[5]));
1139 fGdmlE->NewAttr(mainN, nullptr, "v4x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[6]));
1140 fGdmlE->NewAttr(mainN, nullptr, "v4y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[7]));
1141 fGdmlE->NewAttr(mainN, nullptr, "v5x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[8]));
1142 fGdmlE->NewAttr(mainN, nullptr, "v5y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[9]));
1143 fGdmlE->NewAttr(mainN, nullptr, "v6x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[10]));
1144 fGdmlE->NewAttr(mainN, nullptr, "v6y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[11]));
1145 fGdmlE->NewAttr(mainN, nullptr, "v7x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[12]));
1146 fGdmlE->NewAttr(mainN, nullptr, "v7y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[13]));
1147 fGdmlE->NewAttr(mainN, nullptr, "v8x", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[14]));
1148 fGdmlE->NewAttr(mainN, nullptr, "v8y", TString::Format(fltPrecision.Data(), geoShape->GetVertices()[15]));
1149 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1150
1151 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1152 return mainN;
1153}
1154
1155////////////////////////////////////////////////////////////////////////////////
1156/// Creates "cone" node for GDML from TGeoConeSeg object
1157
1159{
1160 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1161 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1162 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1163 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1164 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1165 return nullptr;
1166 }
1167
1168 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1169 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1170 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1171 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1172 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1173 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1174 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1175 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1176
1177 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1178 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1179 return mainN;
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// Creates "cone" node for GDML from TGeoCone object
1184
1186{
1187 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "cone", nullptr);
1188 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1189 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1190 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1191 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1192 return nullptr;
1193 }
1194
1195 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1196 fGdmlE->NewAttr(mainN, nullptr, "rmin1", TString::Format(fltPrecision.Data(), geoShape->GetRmin1()));
1197 fGdmlE->NewAttr(mainN, nullptr, "rmin2", TString::Format(fltPrecision.Data(), geoShape->GetRmin2()));
1198 fGdmlE->NewAttr(mainN, nullptr, "rmax1", TString::Format(fltPrecision.Data(), geoShape->GetRmax1()));
1199 fGdmlE->NewAttr(mainN, nullptr, "rmax2", TString::Format(fltPrecision.Data(), geoShape->GetRmax2()));
1200 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1201 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1202
1203 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1204 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1205 return mainN;
1206}
1207
1208////////////////////////////////////////////////////////////////////////////////
1209/// Creates "para" node for GDML
1210
1212{
1213 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "para", nullptr);
1214 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1215 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1216
1217 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), 2 * geoShape->GetX()));
1218 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), 2 * geoShape->GetY()));
1219 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetZ()));
1220 fGdmlE->NewAttr(mainN, nullptr, "alpha", TString::Format(fltPrecision.Data(), geoShape->GetAlpha()));
1221 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1222 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1223
1224 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1225 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1226 return mainN;
1227}
1228
1229////////////////////////////////////////////////////////////////////////////////
1230/// Creates "trap" node for GDML
1231
1233{
1234 XMLNodePointer_t mainN;
1235 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1236
1237 // if one base equals 0 create Arb8 instead of trap
1238 if ((geoShape->GetBl1() == 0 || geoShape->GetTl1() == 0 || geoShape->GetH1() == 0) ||
1239 (geoShape->GetBl2() == 0 || geoShape->GetTl2() == 0 || geoShape->GetH2() == 0)) {
1240 mainN = CreateArb8N(geoShape);
1241 return mainN;
1242 }
1243
1244 // if is twisted then create arb8
1245 if (geoShape->IsTwisted()) {
1246 mainN = CreateArb8N((TGeoArb8 *)geoShape);
1247 return mainN;
1248 }
1249
1250 mainN = fGdmlE->NewChild(nullptr, nullptr, "trap", nullptr);
1251 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1252 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1253 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1254 return nullptr;
1255 }
1256
1257 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1258 fGdmlE->NewAttr(mainN, nullptr, "theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1259 fGdmlE->NewAttr(mainN, nullptr, "phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1260 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1261 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1262 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1263 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1264 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1265 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1266
1267 fGdmlE->NewAttr(mainN, nullptr, "alpha1", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1268 fGdmlE->NewAttr(mainN, nullptr, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1269
1270 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1271 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1272 return mainN;
1273}
1274
1275////////////////////////////////////////////////////////////////////////////////
1276/// Creates "twistedtrap" node for GDML
1277
1279{
1280 XMLNodePointer_t mainN;
1281 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1282
1283 // if one base equals 0 create Arb8 instead of twisted trap
1284 if ((geoShape->GetBl1() == 0 && geoShape->GetTl1() == 0 && geoShape->GetH1() == 0) ||
1285 (geoShape->GetBl2() == 0 && geoShape->GetTl2() == 0 && geoShape->GetH2() == 0)) {
1286 mainN = CreateArb8N((TGeoArb8 *)geoShape);
1287 return mainN;
1288 }
1289
1290 // if is twisted then create arb8
1291 if (geoShape->IsTwisted()) {
1292 mainN = CreateArb8N((TGeoArb8 *)geoShape);
1293 return mainN;
1294 }
1295
1296 // if parameter twistAngle (PhiTwist) equals zero create trap node
1297 if (geoShape->GetTwistAngle() == 0) {
1298 mainN = CreateTrapN((TGeoTrap *)geoShape);
1299 return mainN;
1300 }
1301
1302 mainN = fGdmlE->NewChild(nullptr, nullptr, "twistedtrap", nullptr);
1303 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1304 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1305 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1306 return nullptr;
1307 }
1308
1309 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1310 fGdmlE->NewAttr(mainN, nullptr, "Theta", TString::Format(fltPrecision.Data(), geoShape->GetTheta()));
1311 fGdmlE->NewAttr(mainN, nullptr, "Phi", TString::Format(fltPrecision.Data(), geoShape->GetPhi()));
1312 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl1()));
1313 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl1()));
1314 fGdmlE->NewAttr(mainN, nullptr, "x3", TString::Format(fltPrecision.Data(), 2 * geoShape->GetBl2()));
1315 fGdmlE->NewAttr(mainN, nullptr, "x4", TString::Format(fltPrecision.Data(), 2 * geoShape->GetTl2()));
1316 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH1()));
1317 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetH2()));
1318
1319 fGdmlE->NewAttr(mainN, nullptr, "Alph", TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()));
1320
1321 // check if alpha1 equals to alpha2 (converting to string - to avoid problems with floats)
1322 if (TString::Format(fltPrecision.Data(), geoShape->GetAlpha1()) !=
1323 TString::Format(fltPrecision.Data(), geoShape->GetAlpha2())) {
1324 Info("CreateTwistedTrapN",
1325 "ERROR! Object %s is not exported correctly because parameter Alpha2 is not declared in GDML schema",
1326 lname.Data());
1327 }
1328 // fGdmlE->NewAttr(mainN,0, "alpha2", TString::Format(fltPrecision.Data(), geoShape->GetAlpha2()));
1329 fGdmlE->NewAttr(mainN, nullptr, "PhiTwist", TString::Format(fltPrecision.Data(), geoShape->GetTwistAngle()));
1330
1331 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1332 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1333 return mainN;
1334}
1335
1336////////////////////////////////////////////////////////////////////////////////
1337/// Creates "trd" node for GDML from object TGeoTrd1
1338
1340{
1341 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1342 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1343 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1344 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1345 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1346 return nullptr;
1347 }
1348
1349 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1350 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1351 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1352 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy()));
1353 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1354
1355 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1356 return mainN;
1357}
1358
1359////////////////////////////////////////////////////////////////////////////////
1360/// Creates "trd" node for GDML from object TGeoTrd2
1361
1363{
1364 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "trd", nullptr);
1365 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1366 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1367 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1368 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1369 return nullptr;
1370 }
1371
1372 fGdmlE->NewAttr(mainN, nullptr, "x1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx1()));
1373 fGdmlE->NewAttr(mainN, nullptr, "x2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDx2()));
1374 fGdmlE->NewAttr(mainN, nullptr, "y1", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy1()));
1375 fGdmlE->NewAttr(mainN, nullptr, "y2", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDy2()));
1376 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1377
1378 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1379 return mainN;
1380}
1381
1382////////////////////////////////////////////////////////////////////////////////
1383/// Creates "tube" node for GDML from object TGeoTubeSeg
1384
1386{
1387 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1388 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1389 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1390 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1391 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1392 return nullptr;
1393 }
1394
1395 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1396 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1397 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1398 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1399 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1400 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1401
1402 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1403 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1404 return mainN;
1405}
1406
1407////////////////////////////////////////////////////////////////////////////////
1408/// Creates "cutTube" node for GDML
1409
1411{
1412 XMLNodePointer_t mainN;
1413 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1414
1415 mainN = fGdmlE->NewChild(nullptr, nullptr, "cutTube", nullptr);
1416 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1417 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1418 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1419 return nullptr;
1420 }
1421 // This is not needed, because cutTube is already supported by Geant4 9.5
1422 if (fgG4Compatibility == kTRUE && kFALSE) {
1423 TGeoShape *fakeCtub = CreateFakeCtub(geoShape);
1424 mainN = ChooseObject(fakeCtub);
1425
1426 // register name for cuttube shape (so it will be found during volume export)
1427 lname = fNameList->fLst[TString::Format("%p", fakeCtub)];
1428 fNameList->fLst[TString::Format("%p", geoShape)] = lname;
1429 Info("CreateCutTubeN", "WARNING! %s - CutTube was replaced by intersection of TGeoTubSeg and two TGeoBBoxes",
1430 lname.Data());
1431 return mainN;
1432 }
1433 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1434 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1435 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1436 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1437 fGdmlE->NewAttr(mainN, nullptr, "deltaphi",
1438 TString::Format(fltPrecision.Data(), geoShape->GetPhi2() - geoShape->GetPhi1()));
1439 fGdmlE->NewAttr(mainN, nullptr, "lowX", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[0]));
1440 fGdmlE->NewAttr(mainN, nullptr, "lowY", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[1]));
1441 fGdmlE->NewAttr(mainN, nullptr, "lowZ", TString::Format(fltPrecision.Data(), geoShape->GetNlow()[2]));
1442 fGdmlE->NewAttr(mainN, nullptr, "highX", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[0]));
1443 fGdmlE->NewAttr(mainN, nullptr, "highY", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[1]));
1444 fGdmlE->NewAttr(mainN, nullptr, "highZ", TString::Format(fltPrecision.Data(), geoShape->GetNhigh()[2]));
1445
1446 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1447 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1448
1449 return mainN;
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// Creates "tube" node for GDML from object TGeoTube
1454
1456{
1457 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tube", nullptr);
1458 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1459 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1460 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1461 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname) || IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1462 return nullptr;
1463 }
1464
1465 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1466 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1467 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1468 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format("%i", 0));
1469 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format("%i", 360));
1470
1471 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1472 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1473 return mainN;
1474}
1475
1476////////////////////////////////////////////////////////////////////////////////
1477/// Creates "zplane" node for GDML
1478
1480{
1481 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "zplane", nullptr);
1482 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1483
1484 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), z));
1485 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), rmin));
1486 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), rmax));
1487
1488 return mainN;
1489}
1490
1491////////////////////////////////////////////////////////////////////////////////
1492/// Creates "polycone" node for GDML
1493
1495{
1496 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polycone", nullptr);
1497 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1498 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1499 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1500
1501 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1502 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1503
1504 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1505 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1506 Int_t nZPlns = geoShape->GetNz();
1507 for (Int_t it = 0; it < nZPlns; it++) {
1508 // add zplane child node
1509 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1510 // compare actual plane and next plane
1511 if ((it < nZPlns - 1) && (geoShape->GetZ(it) == geoShape->GetZ(it + 1))) {
1512 // rmin of actual is greater then rmax of next one
1513 // | |rmax next
1514 // __ ...| |... __ < rmin actual
1515 // | | | |
1516 if (geoShape->GetRmin(it) > geoShape->GetRmax(it + 1)) {
1517 // adding plane from rmax next to rmin actual at the same z position
1518 if (fgG4Compatibility == kTRUE) {
1519 fGdmlE->AddChild(mainN,
1520 CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it + 1), geoShape->GetRmin(it)));
1521 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4",
1522 lname.Data());
1523 } else {
1524 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4",
1525 lname.Data());
1526 }
1527 }
1528 // rmin of next is greater then rmax of actual
1529 // | | | |
1530 // | |...___...| | rmin next
1531 // | | > rmax act
1532 if (geoShape->GetRmin(it + 1) > geoShape->GetRmax(it)) {
1533 // adding plane from rmax act to rmin next at the same z position
1534 if (fgG4Compatibility == kTRUE) {
1535 fGdmlE->AddChild(mainN,
1536 CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmax(it), geoShape->GetRmin(it + 1)));
1537 Info("CreatePolyconeN", "WARNING! One plane was added to %s solid to be compatible with Geant4",
1538 lname.Data());
1539 } else {
1540 Info("CreatePolyconeN", "WARNING! Solid %s definition seems not contiguous may cause problems in Geant4",
1541 lname.Data());
1542 }
1543 }
1544 }
1545 }
1546 return mainN;
1547}
1548
1549////////////////////////////////////////////////////////////////////////////////
1550/// Creates "torus" node for GDML
1551
1553{
1554 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "torus", nullptr);
1555 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1556 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1557 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1558 if (IsNullParam(geoShape->GetRmax(), "Rmax", lname)) {
1559 return nullptr;
1560 }
1561
1562 fGdmlE->NewAttr(mainN, nullptr, "rtor", TString::Format(fltPrecision.Data(), geoShape->GetR()));
1563 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1564 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1565 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1566 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1567
1568 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1569 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1570
1571 return mainN;
1572}
1573
1574////////////////////////////////////////////////////////////////////////////////
1575/// Creates "polyhedra" node for GDML
1576
1578{
1579 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "polyhedra", nullptr);
1580 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1581 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1582
1583 fGdmlE->NewAttr(mainN, nullptr, "startphi", TString::Format(fltPrecision.Data(), geoShape->GetPhi1()));
1584 fGdmlE->NewAttr(mainN, nullptr, "deltaphi", TString::Format(fltPrecision.Data(), geoShape->GetDphi()));
1585 fGdmlE->NewAttr(mainN, nullptr, "numsides", TString::Format("%i", geoShape->GetNedges()));
1586
1587 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1588 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1589 for (Int_t it = 0; it < geoShape->GetNz(); it++) {
1590 // add zplane child node
1591 fGdmlE->AddChild(mainN, CreateZplaneN(geoShape->GetZ(it), geoShape->GetRmin(it), geoShape->GetRmax(it)));
1592 }
1593 return mainN;
1594}
1595
1596////////////////////////////////////////////////////////////////////////////////
1597/// Creates "eltube" node for GDML
1598
1600{
1601 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "eltube", nullptr);
1602 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1603 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1604 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1605 if (IsNullParam(geoShape->GetA(), "A", lname) || IsNullParam(geoShape->GetB(), "B", lname) ||
1606 IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1607 return nullptr;
1608 }
1609
1610 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(fltPrecision.Data(), geoShape->GetA()));
1611 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(fltPrecision.Data(), geoShape->GetB()));
1612 fGdmlE->NewAttr(mainN, nullptr, "dz", TString::Format(fltPrecision.Data(), geoShape->GetDz()));
1613
1614 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1615
1616 return mainN;
1617}
1618
1619////////////////////////////////////////////////////////////////////////////////
1620/// Creates "hype" node for GDML
1621
1623{
1624 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "hype", nullptr);
1625 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1626 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1627 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1628 if (IsNullParam(geoShape->GetDz(), "Dz", lname)) {
1629 return nullptr;
1630 }
1631
1632 fGdmlE->NewAttr(mainN, nullptr, "rmin", TString::Format(fltPrecision.Data(), geoShape->GetRmin()));
1633 fGdmlE->NewAttr(mainN, nullptr, "rmax", TString::Format(fltPrecision.Data(), geoShape->GetRmax()));
1634 fGdmlE->NewAttr(mainN, nullptr, "inst", TString::Format(fltPrecision.Data(), geoShape->GetStIn()));
1635 fGdmlE->NewAttr(mainN, nullptr, "outst", TString::Format(fltPrecision.Data(), geoShape->GetStOut()));
1636 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), 2 * geoShape->GetDz()));
1637
1638 fGdmlE->NewAttr(mainN, nullptr, "aunit", "deg");
1639 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1640
1641 return mainN;
1642}
1643
1644////////////////////////////////////////////////////////////////////////////////
1645/// Creates "xtru" node for GDML
1646
1648{
1649 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "xtru", nullptr);
1650 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1651 TString lname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1652 fGdmlE->NewAttr(mainN, nullptr, "name", lname);
1653
1654 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1655 XMLNodePointer_t childN;
1656 Int_t vertNum = geoShape->GetNvert();
1657 Int_t secNum = geoShape->GetNz();
1658 if (vertNum < 3 || secNum < 2) {
1659 Info("CreateXtrusionN", "ERROR! TGeoXtru %s has only %i vertices and %i sections. It was not exported",
1660 lname.Data(), vertNum, secNum);
1661 mainN = nullptr;
1662 return mainN;
1663 }
1664 for (Int_t it = 0; it < vertNum; it++) {
1665 // add twoDimVertex child node
1666 childN = fGdmlE->NewChild(nullptr, nullptr, "twoDimVertex", nullptr);
1667 fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), geoShape->GetX(it)));
1668 fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), geoShape->GetY(it)));
1669 fGdmlE->AddChild(mainN, childN);
1670 }
1671 for (Int_t it = 0; it < secNum; it++) {
1672 // add section child node
1673 childN = fGdmlE->NewChild(nullptr, nullptr, "section", nullptr);
1674 fGdmlE->NewAttr(childN, nullptr, "zOrder", TString::Format("%i", it));
1675 fGdmlE->NewAttr(childN, nullptr, "zPosition", TString::Format(fltPrecision.Data(), geoShape->GetZ(it)));
1676 fGdmlE->NewAttr(childN, nullptr, "xOffset", TString::Format(fltPrecision.Data(), geoShape->GetXOffset(it)));
1677 fGdmlE->NewAttr(childN, nullptr, "yOffset", TString::Format(fltPrecision.Data(), geoShape->GetYOffset(it)));
1678 fGdmlE->NewAttr(childN, nullptr, "scalingFactor", TString::Format(fltPrecision.Data(), geoShape->GetScale(it)));
1679 fGdmlE->AddChild(mainN, childN);
1680 }
1681 return mainN;
1682}
1683
1684////////////////////////////////////////////////////////////////////////////////
1685/// Creates "ellipsoid" node for GDML
1686/// this is a special case, because ellipsoid is not defined in ROOT
1687/// so when intersection of scaled sphere and TGeoBBox is found,
1688/// it is considered as an ellipsoid
1689
1691{
1692 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "ellipsoid", nullptr);
1693 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1694 TGeoScaledShape *leftS = (TGeoScaledShape *)geoShape->GetBoolNode()->GetLeftShape(); // ScaledShape
1695 TGeoBBox *rightS = (TGeoBBox *)geoShape->GetBoolNode()->GetRightShape(); // BBox
1696
1697 fGdmlE->NewAttr(mainN, nullptr, "name", elName.Data());
1698 Double_t sx = leftS->GetScale()->GetScale()[0];
1699 Double_t sy = leftS->GetScale()->GetScale()[1];
1700 Double_t radius = ((TGeoSphere *)leftS->GetShape())->GetRmax();
1701
1702 Double_t ax, by, cz;
1703 cz = radius;
1704 ax = sx * radius;
1705 by = sy * radius;
1706
1707 Double_t dz = rightS->GetDZ();
1708 Double_t zorig = rightS->GetOrigin()[2];
1709 Double_t zcut2 = dz + zorig;
1710 Double_t zcut1 = 2 * zorig - zcut2;
1711
1712 fGdmlE->NewAttr(mainN, nullptr, "ax", TString::Format(fltPrecision.Data(), ax));
1713 fGdmlE->NewAttr(mainN, nullptr, "by", TString::Format(fltPrecision.Data(), by));
1714 fGdmlE->NewAttr(mainN, nullptr, "cz", TString::Format(fltPrecision.Data(), cz));
1715 fGdmlE->NewAttr(mainN, nullptr, "zcut1", TString::Format(fltPrecision.Data(), zcut1));
1716 fGdmlE->NewAttr(mainN, nullptr, "zcut2", TString::Format(fltPrecision.Data(), zcut2));
1717 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1718
1719 return mainN;
1720}
1721
1722////////////////////////////////////////////////////////////////////////////////
1723/// Creates "elcone" (elliptical cone) node for GDML
1724/// this is a special case, because elliptical cone is not defined in ROOT
1725/// so when scaled cone is found, it is considered as a elliptical cone
1726
1728{
1729 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "elcone", nullptr);
1730 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1731 fGdmlE->NewAttr(mainN, nullptr, "name", GenName(geoShape->GetName(), TString::Format("%p", geoShape)));
1732 Double_t zcut = ((TGeoCone *)geoShape->GetShape())->GetDz();
1733 Double_t rx1 = ((TGeoCone *)geoShape->GetShape())->GetRmax1();
1734 Double_t rx2 = ((TGeoCone *)geoShape->GetShape())->GetRmax2();
1735 Double_t zmax = zcut * ((rx1 + rx2) / (rx1 - rx2));
1736 Double_t z = zcut + zmax;
1737
1738 Double_t sy = geoShape->GetScale()->GetScale()[1];
1739 Double_t ry1 = sy * rx1;
1740
1741 std::string format(TString::Format("%s/%s", fltPrecision.Data(), fltPrecision.Data()).Data());
1742 fGdmlE->NewAttr(mainN, nullptr, "dx", TString::Format(format.c_str(), rx1, z));
1743 fGdmlE->NewAttr(mainN, nullptr, "dy", TString::Format(format.c_str(), ry1, z));
1744 fGdmlE->NewAttr(mainN, nullptr, "zmax", TString::Format(fltPrecision.Data(), zmax));
1745 fGdmlE->NewAttr(mainN, nullptr, "zcut", TString::Format(fltPrecision.Data(), zcut));
1746 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1747
1748 return mainN;
1749}
1750
1751////////////////////////////////////////////////////////////////////////////////
1752/// Creates "tessellated" (tessellated shape) node for GDML
1753
1755{
1756 // add all vertices to the define section
1757 TString genname = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1758 for (int i = 0; i < geoShape->GetNvertices(); ++i) {
1759 auto vertex = geoShape->GetVertex(i);
1760 TString posName = TString::Format("%s_%d", genname.Data(), i);
1761 Xyz nodPos;
1762 nodPos.x = vertex[0];
1763 nodPos.y = vertex[1];
1764 nodPos.z = vertex[2];
1765 auto childN = CreatePositionN(posName.Data(), nodPos, "position", fDefault_lunit);
1766 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
1767 }
1768 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "tessellated", nullptr);
1769 fGdmlE->NewAttr(mainN, nullptr, "name", genname.Data());
1770 fGdmlE->NewAttr(mainN, nullptr, "lunit", fDefault_lunit);
1771
1772 XMLNodePointer_t childN;
1773 for (Int_t it = 0; it < geoShape->GetNfacets(); it++) {
1774 // add section child node
1775 auto facet = geoShape->GetFacet(it);
1776 bool triangular = facet.GetNvert() == 3;
1777 TString ntype = (triangular) ? "triangular" : "quadrangular";
1778 childN = fGdmlE->NewChild(nullptr, nullptr, ntype.Data(), nullptr);
1779 fGdmlE->NewAttr(childN, nullptr, "vertex1", TString::Format("%s_%d", genname.Data(), facet[0]));
1780 fGdmlE->NewAttr(childN, nullptr, "vertex2", TString::Format("%s_%d", genname.Data(), facet[1]));
1781 fGdmlE->NewAttr(childN, nullptr, "vertex3", TString::Format("%s_%d", genname.Data(), facet[2]));
1782 if (!triangular)
1783 fGdmlE->NewAttr(childN, nullptr, "vertex4", TString::Format("%s_%d", genname.Data(), facet[3]));
1784 fGdmlE->NewAttr(childN, nullptr, "type", "ABSOLUTE");
1785 fGdmlE->AddChild(mainN, childN);
1786 }
1787 return mainN;
1788}
1789
1790////////////////////////////////////////////////////////////////////////////////
1791/// Creates a scaled node for GDML
1792
1794{
1795 XMLNodePointer_t mainN, childN, unscaledN;
1796 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1797 TString nodeName = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1798 auto const scale = geoShape->GetScale()->GetScale();
1799 TGeoShape *unscaled = geoShape->GetShape();
1800 // Create the unscaled shape record
1801 unscaledN = ChooseObject(unscaled);
1802 // retrieve node name by their pointer to make reference
1803 TString uname = fNameList->fLst[TString::Format("%p", unscaled)];
1804
1805 // the unplaced node appended to main structure of nodes (if they are not already there)
1806 if (unscaledN != nullptr) {
1807 fGdmlE->AddChild(fSolidsNode, unscaledN);
1808 fSolCnt++;
1809 } else {
1810 if (uname.Contains("missing_") || uname == "") {
1811 Info("CreateScaledN", "ERROR! Unscaled node is NULL - Scaled shape will be skipped");
1812 return nullptr;
1813 }
1814 }
1815
1816 // create union node and its child nodes (or intersection or subtraction)
1817 /* <scaledSolid name="...">
1818 * <solidref ref="unscaled solid name" />
1819 * <scale name="scale name" x="sx" y="sy" z="sz">
1820 * </scaledSolid>
1821 */
1822 mainN = fGdmlE->NewChild(nullptr, nullptr, "scaledSolid", nullptr);
1823 fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1824
1825 //<solidref> (solid)
1826 childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
1827 fGdmlE->NewAttr(childN, nullptr, "ref", uname);
1828 fGdmlE->AddChild(mainN, childN);
1829
1830 //<scale ame="scale name" x="sx" y="sy" z="sz">
1831 childN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
1832 fGdmlE->NewAttr(childN, nullptr, "name", (nodeName + "scl").Data());
1833 fGdmlE->NewAttr(childN, nullptr, "x", TString::Format(fltPrecision.Data(), scale[0]));
1834 fGdmlE->NewAttr(childN, nullptr, "y", TString::Format(fltPrecision.Data(), scale[1]));
1835 fGdmlE->NewAttr(childN, nullptr, "z", TString::Format(fltPrecision.Data(), scale[2]));
1836 fGdmlE->AddChild(mainN, childN);
1837
1838 return mainN;
1839}
1840
1841////////////////////////////////////////////////////////////////////////////////
1842/// Creates common part of union intersection and subtraction nodes
1843
1845{
1846 XMLNodePointer_t mainN, ndR, ndL, childN;
1847 TString nodeName = GenName(geoShape->GetName(), TString::Format("%p", geoShape));
1848 TString lboolType;
1850 switch (boolType) {
1851 case TGeoBoolNode::kGeoUnion: lboolType = "union"; break;
1852 case TGeoBoolNode::kGeoSubtraction: lboolType = "subtraction"; break;
1853 case TGeoBoolNode::kGeoIntersection: lboolType = "intersection"; break;
1854 }
1855
1857 const Double_t *ltr = geoShape->GetBoolNode()->GetLeftMatrix()->GetTranslation();
1859 const Double_t *rtr = geoShape->GetBoolNode()->GetRightMatrix()->GetTranslation();
1860
1861 // specific case!
1862 // Ellipsoid tag preparing
1863 // if left == TGeoScaledShape AND right == TGeoBBox
1864 // AND if TGeoScaledShape->GetShape == TGeoSphere
1865 TGeoShape *leftS = geoShape->GetBoolNode()->GetLeftShape();
1866 TGeoShape *rightS = geoShape->GetBoolNode()->GetRightShape();
1867 if (strcmp(leftS->ClassName(), "TGeoScaledShape") == 0 && strcmp(rightS->ClassName(), "TGeoBBox") == 0) {
1868 if (strcmp(((TGeoScaledShape *)leftS)->GetShape()->ClassName(), "TGeoSphere") == 0) {
1869 if (lboolType == "intersection") {
1870 mainN = CreateEllipsoidN(geoShape, nodeName);
1871 return mainN;
1872 }
1873 }
1874 }
1875
1876 Xyz translL, translR;
1877 // translation
1878 translL.x = ltr[0];
1879 translL.y = ltr[1];
1880 translL.z = ltr[2];
1881 translR.x = rtr[0];
1882 translR.y = rtr[1];
1883 translR.z = rtr[2];
1884
1885 // left and right nodes are created here also their names are created
1886 ndL = ChooseObject(geoShape->GetBoolNode()->GetLeftShape());
1887 ndR = ChooseObject(geoShape->GetBoolNode()->GetRightShape());
1888
1889 // retrieve left and right node names by their pointer to make reference
1890 TString lname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetLeftShape())];
1891 TString rname = fNameList->fLst[TString::Format("%p", geoShape->GetBoolNode()->GetRightShape())];
1892
1893 // left and right nodes appended to main structure of nodes (if they are not already there)
1894 if (ndL != nullptr) {
1895 fGdmlE->AddChild(fSolidsNode, ndL);
1896 fSolCnt++;
1897 } else {
1898 if (lname.Contains("missing_") || lname == "") {
1899 Info("CreateCommonBoolN", "ERROR! Left node is NULL - Boolean Shape will be skipped");
1900 return nullptr;
1901 }
1902 }
1903 if (ndR != nullptr) {
1904 fGdmlE->AddChild(fSolidsNode, ndR);
1905 fSolCnt++;
1906 } else {
1907 if (rname.Contains("missing_") || rname == "") {
1908 Info("CreateCommonBoolN", "ERROR! Right node is NULL - Boolean Shape will be skipped");
1909 return nullptr;
1910 }
1911 }
1912
1913 // create union node and its child nodes (or intersection or subtraction)
1914 /* <union name="...">
1915 * <first ref="left name" />
1916 * <second ref="right name" />
1917 * <firstposition .../>
1918 * <firstrotation .../>
1919 * <position .../>
1920 * <rotation .../>
1921 * </union>
1922 */
1923 mainN = fGdmlE->NewChild(nullptr, nullptr, lboolType.Data(), nullptr);
1924 fGdmlE->NewAttr(mainN, nullptr, "name", nodeName);
1925
1926 //<first> (left)
1927 childN = fGdmlE->NewChild(nullptr, nullptr, "first", nullptr);
1928 fGdmlE->NewAttr(childN, nullptr, "ref", lname);
1929 fGdmlE->AddChild(mainN, childN);
1930
1931 //<second> (right)
1932 childN = fGdmlE->NewChild(nullptr, nullptr, "second", nullptr);
1933 fGdmlE->NewAttr(childN, nullptr, "ref", rname);
1934 fGdmlE->AddChild(mainN, childN);
1935
1936 //<firstposition> (left)
1937 if ((translL.x != 0.0) || (translL.y != 0.0) || (translL.z != 0.0)) {
1938 childN = CreatePositionN((nodeName + lname + "pos").Data(), translL, "firstposition", fDefault_lunit);
1939 fGdmlE->AddChild(mainN, childN);
1940 }
1941 //<firstrotation> (left)
1942 if ((lrot.x != 0.0) || (lrot.y != 0.0) || (lrot.z != 0.0)) {
1943 childN = CreateRotationN((nodeName + lname + "rot").Data(), lrot, "firstrotation");
1944 fGdmlE->AddChild(mainN, childN);
1945 }
1946 //<position> (right)
1947 if ((translR.x != 0.0) || (translR.y != 0.0) || (translR.z != 0.0)) {
1948 childN = CreatePositionN((nodeName + rname + "pos").Data(), translR, "position", fDefault_lunit);
1949 fGdmlE->AddChild(mainN, childN);
1950 }
1951 //<rotation> (right)
1952 if ((rrot.x != 0.0) || (rrot.y != 0.0) || (rrot.z != 0.0)) {
1953 childN = CreateRotationN((nodeName + rname + "rot").Data(), rrot, "rotation");
1954 fGdmlE->AddChild(mainN, childN);
1955 }
1956
1957 return mainN;
1958}
1959
1960////////////////////////////////////////////////////////////////////////////////
1961/// Creates "opticalsurface" node for GDML
1962
1964{
1965 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "opticalsurface", nullptr);
1966 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
1967 std::string name = make_NCName(geoSurf->GetName());
1968 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
1969 fGdmlE->NewAttr(mainN, nullptr, "model", TGeoOpticalSurface::ModelToString(geoSurf->GetModel()));
1970 fGdmlE->NewAttr(mainN, nullptr, "finish", TGeoOpticalSurface::FinishToString(geoSurf->GetFinish()));
1971 fGdmlE->NewAttr(mainN, nullptr, "type", TGeoOpticalSurface::TypeToString(geoSurf->GetType()));
1972 fGdmlE->NewAttr(mainN, nullptr, "value", TString::Format(fltPrecision.Data(), geoSurf->GetValue()));
1973
1974 // Write properties
1975 TList const &properties = geoSurf->GetProperties();
1976 if (properties.GetSize()) {
1977 TIter next(&properties);
1978 TNamed *property;
1979 while ((property = (TNamed *)next()))
1980 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
1981 }
1982 // Write CONST properties
1983 TList const &const_properties = geoSurf->GetConstProperties();
1984 if (const_properties.GetSize()) {
1985 TIter next(&const_properties);
1986 TNamed *property;
1987 while ((property = (TNamed *)next()))
1988 fGdmlE->AddChild(mainN, CreatePropertyN(*property));
1989 }
1990 return mainN;
1991}
1992
1993////////////////////////////////////////////////////////////////////////////////
1994/// Creates "skinsurface" node for GDML
1995
1997{
1998 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "skinsurface", nullptr);
1999 std::string name = make_NCName(geoSurf->GetName());
2000 std::string prop = make_NCName(geoSurf->GetTitle());
2001
2002 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
2003 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
2004
2005 // Cretate the logical volume reference node
2006 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2007 const TString &volname = fNameList->fLst[TString::Format("%p", geoSurf->GetVolume())];
2008 fGdmlE->NewAttr(childN, nullptr, "ref", volname.Data());
2009 fGdmlE->AddChild(mainN, childN);
2010 return mainN;
2011}
2012
2013////////////////////////////////////////////////////////////////////////////////
2014/// Creates "bordersurface" node for GDML
2015
2017{
2018 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "bordersurface", nullptr);
2019 std::string name = make_NCName(geoSurf->GetName());
2020 std::string prop = make_NCName(geoSurf->GetTitle());
2021
2022 fGdmlE->NewAttr(mainN, nullptr, "name", name.c_str());
2023 fGdmlE->NewAttr(mainN, nullptr, "surfaceproperty", prop.c_str());
2024
2025 // Cretate the logical volume reference nodes
2026 XMLNodePointer_t childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
2027 TString physvolname = fNameList->fLst[TString::Format("%p", geoSurf->GetNode1())];
2028 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
2029 fGdmlE->AddChild(mainN, childN);
2030
2031 childN = fGdmlE->NewChild(nullptr, nullptr, "physvolref", nullptr);
2032 physvolname = fNameList->fLst[TString::Format("%p", geoSurf->GetNode2())];
2033 fGdmlE->NewAttr(childN, nullptr, "ref", physvolname);
2034 fGdmlE->AddChild(mainN, childN);
2035 return mainN;
2036}
2037
2038////////////////////////////////////////////////////////////////////////////////
2039/// Creates "position" kind of node for GDML
2040
2041XMLNodePointer_t TGDMLWrite::CreatePositionN(const char *name, Xyz position, const char *type, const char *unit)
2042{
2043 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
2044 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2045 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2046 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), position.x));
2047 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), position.y));
2048 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), position.z));
2049 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2050 return mainN;
2051}
2052
2053////////////////////////////////////////////////////////////////////////////////
2054/// Creates "rotation" kind of node for GDML
2055
2056XMLNodePointer_t TGDMLWrite::CreateRotationN(const char *name, Xyz rotation, const char *type, const char *unit)
2057{
2058 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, type, nullptr);
2059 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2060 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2061 fGdmlE->NewAttr(mainN, nullptr, "x", TString::Format(fltPrecision.Data(), rotation.x));
2062 fGdmlE->NewAttr(mainN, nullptr, "y", TString::Format(fltPrecision.Data(), rotation.y));
2063 fGdmlE->NewAttr(mainN, nullptr, "z", TString::Format(fltPrecision.Data(), rotation.z));
2064 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2065 return mainN;
2066}
2067
2068////////////////////////////////////////////////////////////////////////////////
2069/// Creates "matrix" kind of node for GDML
2070
2072{
2073 std::stringstream vals;
2074 size_t cols = matrix->GetCols();
2075 size_t rows = matrix->GetRows();
2076 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
2077 fGdmlE->NewAttr(mainN, nullptr, "name", matrix->GetName());
2078 fGdmlE->NewAttr(mainN, nullptr, "coldim", TString::Format("%zu", cols));
2079 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2080 for (size_t i = 0; i < rows; ++i) {
2081 for (size_t j = 0; j < cols; ++j) {
2082 vals << TString::Format(fltPrecision.Data(), matrix->Get(i, j));
2083 if (j < cols - 1)
2084 vals << ' ';
2085 }
2086 if (i < rows - 1)
2087 vals << '\n';
2088 }
2089 fGdmlE->NewAttr(mainN, nullptr, "values", vals.str().c_str());
2090 return mainN;
2091}
2092
2093////////////////////////////////////////////////////////////////////////////////
2094/// Creates "constant" kind of node for GDML
2095
2097{
2098 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "matrix", nullptr);
2099 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2100 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2101 fGdmlE->NewAttr(mainN, nullptr, "coldim", "1");
2102 fGdmlE->NewAttr(mainN, nullptr, "values", TString::Format(fltPrecision.Data(), value));
2103 return mainN;
2104}
2105
2106////////////////////////////////////////////////////////////////////////////////
2107/// Creates "setup" node for GDML
2108
2109XMLNodePointer_t TGDMLWrite::CreateSetupN(const char *topVolName, const char *name, const char *version)
2110{
2111 XMLNodePointer_t setupN = fGdmlE->NewChild(nullptr, nullptr, "setup", nullptr);
2112 fGdmlE->NewAttr(setupN, nullptr, "name", name);
2113 fGdmlE->NewAttr(setupN, nullptr, "version", version);
2114 XMLNodePointer_t fworldN = fGdmlE->NewChild(setupN, nullptr, "world", nullptr);
2115 fGdmlE->NewAttr(fworldN, nullptr, "ref", topVolName);
2116 return setupN;
2117}
2118
2119////////////////////////////////////////////////////////////////////////////////
2120/// Creates "volume" node for GDML
2121
2122XMLNodePointer_t TGDMLWrite::StartVolumeN(const char *name, const char *solid, const char *material)
2123{
2124 XMLNodePointer_t childN;
2125 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "volume", nullptr);
2126 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2127
2128 childN = fGdmlE->NewChild(nullptr, nullptr, "materialref", nullptr);
2129 fGdmlE->NewAttr(childN, nullptr, "ref", material);
2130 fGdmlE->AddChild(mainN, childN);
2131
2132 childN = fGdmlE->NewChild(nullptr, nullptr, "solidref", nullptr);
2133 fGdmlE->NewAttr(childN, nullptr, "ref", solid);
2134 fGdmlE->AddChild(mainN, childN);
2135
2136 return mainN;
2137}
2138
2139////////////////////////////////////////////////////////////////////////////////
2140/// Creates "assembly" node for GDML
2141
2143{
2144 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "assembly", nullptr);
2145 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2146
2147 return mainN;
2148}
2149
2150////////////////////////////////////////////////////////////////////////////////
2151/// Creates "physvol" node for GDML
2152
2153XMLNodePointer_t TGDMLWrite::CreatePhysVolN(const char *name, Int_t copyno, const char *volref, const char *posref,
2154 const char *rotref, XMLNodePointer_t scaleN)
2155{
2156 fPhysVolCnt++;
2157 XMLNodePointer_t childN;
2158 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "physvol", nullptr);
2159 fGdmlE->NewAttr(mainN, nullptr, "name", name);
2160 fGdmlE->NewAttr(mainN, nullptr, "copynumber", TString::Format("%d", copyno));
2161
2162 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2163 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2164 fGdmlE->AddChild(mainN, childN);
2165
2166 childN = fGdmlE->NewChild(nullptr, nullptr, "positionref", nullptr);
2167 fGdmlE->NewAttr(childN, nullptr, "ref", posref);
2168 fGdmlE->AddChild(mainN, childN);
2169
2170 // if is not empty string add this node
2171 if (strcmp(rotref, "") != 0) {
2172 childN = fGdmlE->NewChild(nullptr, nullptr, "rotationref", nullptr);
2173 fGdmlE->NewAttr(childN, nullptr, "ref", rotref);
2174 fGdmlE->AddChild(mainN, childN);
2175 }
2176 if (scaleN != nullptr) {
2177 fGdmlE->AddChild(mainN, scaleN);
2178 }
2179
2180 return mainN;
2181}
2182
2183////////////////////////////////////////////////////////////////////////////////
2184/// Creates "divisionvol" node for GDML
2185
2187 const char *unit, const char *volref)
2188{
2189 XMLNodePointer_t childN = nullptr;
2190 XMLNodePointer_t mainN = fGdmlE->NewChild(nullptr, nullptr, "divisionvol", nullptr);
2191 fGdmlE->NewAttr(mainN, nullptr, "axis", axis);
2192 fGdmlE->NewAttr(mainN, nullptr, "number", TString::Format("%i", number));
2193 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2194 if (fgG4Compatibility == kTRUE) {
2195 // if eg. full length is 20 and width * number = 20,0001 problem in geant4
2196 // unit is either in cm or degrees nothing else
2197 width = (floor(width * 1E4)) * 1E-4;
2198 if ((offset >= 0.) && (strcmp(axis, "kPhi") == 0)) {
2199 Int_t offsetI = (Int_t)offset;
2200 Double_t decimals = offset - offsetI;
2201 // put to range from 0 to 360 add decimals and then put to range 0 -> -360
2202 offset = (offsetI % 360) + decimals - 360;
2203 }
2204 }
2205 fGdmlE->NewAttr(mainN, nullptr, "width", TString::Format(fltPrecision.Data(), width));
2206
2207 fGdmlE->NewAttr(mainN, nullptr, "offset", TString::Format(fltPrecision.Data(), offset));
2208 fGdmlE->NewAttr(mainN, nullptr, "unit", unit);
2209 if (strcmp(volref, "") != 0) {
2210 childN = fGdmlE->NewChild(nullptr, nullptr, "volumeref", nullptr);
2211 fGdmlE->NewAttr(childN, nullptr, "ref", volref);
2212 }
2213 fGdmlE->AddChild(mainN, childN);
2214
2215 return mainN;
2216}
2217
2218////////////////////////////////////////////////////////////////////////////////
2219/// Chooses the object and method that should be used for processing object
2220
2222{
2223 const char *clsname = geoShape->ClassName();
2224 XMLNodePointer_t solidN;
2225
2226 if (CanProcess((TObject *)geoShape) == kFALSE) {
2227 return nullptr;
2228 }
2229
2230 // process different shapes
2231 if (strcmp(clsname, "TGeoBBox") == 0) {
2232 solidN = CreateBoxN((TGeoBBox *)geoShape);
2233 } else if (strcmp(clsname, "TGeoParaboloid") == 0) {
2234 solidN = CreateParaboloidN((TGeoParaboloid *)geoShape);
2235 } else if (strcmp(clsname, "TGeoSphere") == 0) {
2236 solidN = CreateSphereN((TGeoSphere *)geoShape);
2237 } else if (strcmp(clsname, "TGeoArb8") == 0) {
2238 solidN = CreateArb8N((TGeoArb8 *)geoShape);
2239 } else if (strcmp(clsname, "TGeoConeSeg") == 0) {
2240 solidN = CreateConeN((TGeoConeSeg *)geoShape);
2241 } else if (strcmp(clsname, "TGeoCone") == 0) {
2242 solidN = CreateConeN((TGeoCone *)geoShape);
2243 } else if (strcmp(clsname, "TGeoPara") == 0) {
2244 solidN = CreateParaN((TGeoPara *)geoShape);
2245 } else if (strcmp(clsname, "TGeoTrap") == 0) {
2246 solidN = CreateTrapN((TGeoTrap *)geoShape);
2247 } else if (strcmp(clsname, "TGeoGtra") == 0) {
2248 solidN = CreateTwistedTrapN((TGeoGtra *)geoShape);
2249 } else if (strcmp(clsname, "TGeoTrd1") == 0) {
2250 solidN = CreateTrdN((TGeoTrd1 *)geoShape);
2251 } else if (strcmp(clsname, "TGeoTrd2") == 0) {
2252 solidN = CreateTrdN((TGeoTrd2 *)geoShape);
2253 } else if (strcmp(clsname, "TGeoTubeSeg") == 0) {
2254 solidN = CreateTubeN((TGeoTubeSeg *)geoShape);
2255 } else if (strcmp(clsname, "TGeoCtub") == 0) {
2256 solidN = CreateCutTubeN((TGeoCtub *)geoShape);
2257 } else if (strcmp(clsname, "TGeoTube") == 0) {
2258 solidN = CreateTubeN((TGeoTube *)geoShape);
2259 } else if (strcmp(clsname, "TGeoPcon") == 0) {
2260 solidN = CreatePolyconeN((TGeoPcon *)geoShape);
2261 } else if (strcmp(clsname, "TGeoTorus") == 0) {
2262 solidN = CreateTorusN((TGeoTorus *)geoShape);
2263 } else if (strcmp(clsname, "TGeoPgon") == 0) {
2264 solidN = CreatePolyhedraN((TGeoPgon *)geoShape);
2265 } else if (strcmp(clsname, "TGeoEltu") == 0) {
2266 solidN = CreateEltubeN((TGeoEltu *)geoShape);
2267 } else if (strcmp(clsname, "TGeoHype") == 0) {
2268 solidN = CreateHypeN((TGeoHype *)geoShape);
2269 } else if (strcmp(clsname, "TGeoXtru") == 0) {
2270 solidN = CreateXtrusionN((TGeoXtru *)geoShape);
2271 } else if (strcmp(clsname, "TGeoTessellated") == 0) {
2272 solidN = CreateTessellatedN((TGeoTessellated *)geoShape);
2273 } else if (strcmp(clsname, "TGeoScaledShape") == 0) {
2274 solidN = CreateScaledN((TGeoScaledShape *)geoShape);
2275 } else if (strcmp(clsname, "TGeoCompositeShape") == 0) {
2276 solidN = CreateCommonBoolN((TGeoCompositeShape *)geoShape);
2277 } else if (strcmp(clsname, "TGeoUnion") == 0) {
2278 solidN = CreateCommonBoolN((TGeoCompositeShape *)geoShape);
2279 } else if (strcmp(clsname, "TGeoIntersection") == 0) {
2280 solidN = CreateCommonBoolN((TGeoCompositeShape *)geoShape);
2281 } else if (strcmp(clsname, "TGeoSubtraction") == 0) {
2282 solidN = CreateCommonBoolN((TGeoCompositeShape *)geoShape);
2283 } else {
2284 Info("ChooseObject", "ERROR! %s Solid CANNOT be processed, solid is NOT supported", clsname);
2285 solidN = nullptr;
2286 }
2287 if (solidN == nullptr) {
2288 if (fNameList->fLst[TString::Format("%p", geoShape)] == "") {
2289 TString missingName = geoShape->GetName();
2290 GenName("missing_" + missingName, TString::Format("%p", geoShape));
2291 } else {
2292 fNameList->fLst[TString::Format("%p", geoShape)] =
2293 "missing_" + fNameList->fLst[TString::Format("%p", geoShape)];
2294 }
2295 }
2296
2297 return solidN;
2298}
2299
2300////////////////////////////////////////////////////////////////////////////////
2301/// Retrieves X Y Z angles from rotation matrix
2302
2304{
2305 TGDMLWrite::Xyz lxyz;
2306 Double_t a, b, c;
2307 Double_t rad = 180.0 / TMath::ACos(-1.0);
2308 const Double_t *r = rotationMatrix;
2309 Double_t cosb = TMath::Sqrt(r[0] * r[0] + r[1] * r[1]);
2310 if (cosb > 0.00001) {
2311 a = TMath::ATan2(r[5], r[8]) * rad;
2312 b = TMath::ATan2(-r[2], cosb) * rad;
2313 c = TMath::ATan2(r[1], r[0]) * rad;
2314 } else {
2315 a = TMath::ATan2(-r[7], r[4]) * rad;
2316 b = TMath::ATan2(-r[2], cosb) * rad;
2317 c = 0;
2318 }
2319 lxyz.x = a;
2320 lxyz.y = b;
2321 lxyz.z = c;
2322 return lxyz;
2323}
2324
2325////////////////////////////////////////////////////////////////////////////////
2326/// Method creating cutTube as an intersection of tube and two boxes
2327/// - not used anymore because cutube is supported in Geant4 9.5
2328
2330{
2331 Double_t rmin = geoShape->GetRmin();
2332 Double_t rmax = geoShape->GetRmax();
2333 Double_t z = geoShape->GetDz();
2334 Double_t startphi = geoShape->GetPhi1();
2335 Double_t deltaphi = geoShape->GetPhi2();
2336 Double_t x1 = geoShape->GetNlow()[0];
2337 Double_t y1 = geoShape->GetNlow()[1];
2338 Double_t z1 = geoShape->GetNlow()[2];
2339 Double_t x2 = geoShape->GetNhigh()[0];
2340 Double_t y2 = geoShape->GetNhigh()[1];
2341 Double_t z2 = geoShape->GetNhigh()[2];
2342 TString xname = geoShape->GetName();
2343
2344 Double_t h0 = 2. * ((TGeoBBox *)geoShape)->GetDZ();
2345 Double_t h1 = 2 * z;
2346 Double_t h2 = 2 * z;
2347 Double_t boxdx = 1E8 * (2 * rmax) + (2 * z);
2348
2349 TGeoTubeSeg *T = new TGeoTubeSeg((xname + "T").Data(), rmin, rmax, h0, startphi, deltaphi);
2350 TGeoBBox *B1 = new TGeoBBox((xname + "B1").Data(), boxdx, boxdx, h1);
2351 TGeoBBox *B2 = new TGeoBBox((xname + "B2").Data(), boxdx, boxdx, h2);
2352
2353 // first box position parameters
2354 Double_t phi1 = 360 - TMath::ATan2(x1, y1) * TMath::RadToDeg();
2355 Double_t theta1 = 360 - TMath::ATan2(sqrt(x1 * x1 + y1 * y1), z1) * TMath::RadToDeg();
2356
2357 Double_t phi11 = TMath::ATan2(y1, x1) * TMath::RadToDeg();
2358 Double_t theta11 = TMath::ATan2(z1, sqrt(x1 * x1 + y1 * y1)) * TMath::RadToDeg();
2359
2360 Double_t xpos1 = h1 * TMath::Cos((theta11)*TMath::DegToRad()) * TMath::Cos((phi11)*TMath::DegToRad()) * (-1);
2361 Double_t ypos1 = h1 * TMath::Cos((theta11)*TMath::DegToRad()) * TMath::Sin((phi11)*TMath::DegToRad()) * (-1);
2362 Double_t zpos1 = h1 * TMath::Sin((theta11)*TMath::DegToRad()) * (-1);
2363
2364 // second box position parameters
2365 Double_t phi2 = 360 - TMath::ATan2(x2, y2) * TMath::RadToDeg();
2366 Double_t theta2 = 360 - TMath::ATan2(sqrt(x2 * x2 + y2 * y2), z2) * TMath::RadToDeg();
2367
2368 Double_t phi21 = TMath::ATan2(y2, x2) * TMath::RadToDeg();
2369 Double_t theta21 = TMath::ATan2(z2, sqrt(x2 * x2 + y2 * y2)) * TMath::RadToDeg();
2370
2371 Double_t xpos2 = h2 * TMath::Cos((theta21)*TMath::DegToRad()) * TMath::Cos((phi21)*TMath::DegToRad()) * (-1);
2372 Double_t ypos2 = h2 * TMath::Cos((theta21)*TMath::DegToRad()) * TMath::Sin((phi21)*TMath::DegToRad()) * (-1);
2373 Double_t zpos2 = h2 * TMath::Sin((theta21)*TMath::DegToRad()) * (-1);
2374
2375 // positioning
2376 TGeoTranslation *t0 = new TGeoTranslation(0, 0, 0);
2377 TGeoTranslation *t1 = new TGeoTranslation(0 + xpos1, 0 + ypos1, 0 + (zpos1 - z));
2378 TGeoTranslation *t2 = new TGeoTranslation(0 + xpos2, 0 + ypos2, 0 + (zpos2 + z));
2379 TGeoRotation *r0 = new TGeoRotation((xname + "r0").Data());
2380 TGeoRotation *r1 = new TGeoRotation((xname + "r1").Data());
2381 TGeoRotation *r2 = new TGeoRotation((xname + "r2").Data());
2382
2383 r1->SetAngles(phi1, theta1, 0);
2384 r2->SetAngles(phi2, theta2, 0);
2385
2386 TGeoMatrix *m0 = new TGeoCombiTrans(*t0, *r0);
2387 TGeoMatrix *m1 = new TGeoCombiTrans(*t1, *r1);
2388 TGeoMatrix *m2 = new TGeoCombiTrans(*t2, *r2);
2389
2390 TGeoCompositeShape *CS1 = new TGeoCompositeShape((xname + "CS1").Data(), new TGeoIntersection(T, B1, m0, m1));
2391 TGeoCompositeShape *cs = new TGeoCompositeShape((xname + "CS").Data(), new TGeoIntersection(CS1, B2, m0, m2));
2392 delete t0;
2393 delete t1;
2394 delete t2;
2395 delete r0;
2396 delete r1;
2397 delete r2;
2398 return cs;
2399}
2400
2401////////////////////////////////////////////////////////////////////////////////
2402/// Checks whether name2check is in (NameList) list
2403
2405{
2406 Bool_t isIN = list[name2check];
2407 return isIN;
2408}
2409
2410////////////////////////////////////////////////////////////////////////////////
2411/// NCNAME basic restrictions
2412/// Replace "$" character with empty character etc.
2413
2415{
2416 TString newname = oldname.ReplaceAll("$", "");
2417 newname = newname.ReplaceAll(" ", "_");
2418 // :, @, $, %, &, /, +, ,, ;, whitespace characters or different parenthesis
2419 newname = newname.ReplaceAll(":", "");
2420 newname = newname.ReplaceAll("@", "");
2421 newname = newname.ReplaceAll("%", "");
2422 newname = newname.ReplaceAll("&", "");
2423 newname = newname.ReplaceAll("/", "");
2424 newname = newname.ReplaceAll("+", "");
2425 newname = newname.ReplaceAll(";", "");
2426 newname = newname.ReplaceAll("{", "");
2427 newname = newname.ReplaceAll("}", "");
2428 newname = newname.ReplaceAll("(", "");
2429 newname = newname.ReplaceAll(")", "");
2430 newname = newname.ReplaceAll("[", "");
2431 newname = newname.ReplaceAll("]", "");
2432 newname = newname.ReplaceAll("_refl", "");
2433 // workaround if first letter is digit than replace it to "O" (ou character)
2434 TString fstLet = newname(0, 1);
2435 if (fstLet.IsDigit()) {
2436 newname = "O" + newname(1, newname.Length());
2437 }
2438 return newname;
2439}
2440
2441////////////////////////////////////////////////////////////////////////////////
2442/// Important function which is responsible for naming volumes, solids and materials
2443
2445{
2446 TString newname = GenName(oldname);
2447 if (newname != oldname) {
2448 if (fgkMaxNameErr > fActNameErr) {
2449 Info("GenName", "WARNING! Name of the object was changed because it failed to comply with NCNAME xml datatype "
2450 "restrictions.");
2451 } else if ((fgkMaxNameErr == fActNameErr)) {
2452 Info("GenName", "WARNING! Probably more names are going to be changed to comply with NCNAME xml datatype "
2453 "restriction, but it will not be displayed on the screen.");
2454 }
2455 fActNameErr++;
2456 }
2457 TString nameIter;
2458 Int_t iter = 0;
2459 switch (fgNamingSpeed) {
2460 case kfastButUglySufix: newname = newname + "0x" + objPointer; break;
2461 case kelegantButSlow:
2462 // 0 means not in the list
2463 iter = fNameList->fLstIter[newname];
2464 if (iter == 0) {
2465 nameIter = "";
2466 } else {
2467 nameIter = TString::Format("0x%i", iter);
2468 }
2469 fNameList->fLstIter[newname]++;
2470 newname = newname + nameIter;
2471 break;
2473 // no change
2474 break;
2475 }
2476 // store the name (mapped to pointer)
2477 fNameList->fLst[objPointer] = newname;
2478 return newname;
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Method which tests whether solids can be processed
2483
2485{
2486 Bool_t isProcessed = kFALSE;
2487 isProcessed = pointer->TestBit(fgkProcBit);
2488 pointer->SetBit(fgkProcBit, kTRUE);
2489 return !(isProcessed);
2490}
2491
2492////////////////////////////////////////////////////////////////////////////////
2493/// Method that retrieves axis and unit along which object is divided
2494
2495TString TGDMLWrite::GetPattAxis(Int_t divAxis, const char *pattName, TString &unit)
2496{
2497 TString resaxis;
2498 unit = fDefault_lunit;
2499 switch (divAxis) {
2500 case 1:
2501 if (strcmp(pattName, "TGeoPatternX") == 0) {
2502 return "kXAxis";
2503 } else if (strcmp(pattName, "TGeoPatternCylR") == 0) {
2504 return "kRho";
2505 }
2506 break;
2507 case 2:
2508 if (strcmp(pattName, "TGeoPatternY") == 0) {
2509 return "kYAxis";
2510 } else if (strcmp(pattName, "TGeoPatternCylPhi") == 0) {
2511 unit = "deg";
2512 return "kPhi";
2513 }
2514 break;
2515 case 3:
2516 if (strcmp(pattName, "TGeoPatternZ") == 0) {
2517 return "kZAxis";
2518 }
2519 break;
2520 default: return "kUndefined"; break;
2521 }
2522 return "kUndefined";
2523}
2524
2525////////////////////////////////////////////////////////////////////////////////
2526/// Check for null parameter to skip the NULL objects
2527
2529{
2530 if (parValue == 0.) {
2531 Info("IsNullParam", "ERROR! %s is NULL due to %s = %.12g, Volume based on this shape will be skipped",
2532 objName.Data(), parName.Data(), parValue);
2533 return kTRUE;
2534 }
2535 return kFALSE;
2536}
2537
2538////////////////////////////////////////////////////////////////////////////////
2539/// Unsetting bits that were changed in gGeoManager during export so that export
2540/// can be run more times with the same instance of gGeoManager.
2541
2543{
2544 TIter next(geoMng->GetListOfVolumes());
2545 TGeoVolume *vol;
2546 while ((vol = (TGeoVolume *)next())) {
2547 ((TObject *)vol->GetShape())->SetBit(fgkProcBit, kFALSE);
2549 }
2550}
2551
2552////////////////////////////////////////////////////////////////////////////////
2553//
2554// Backwards compatibility for old DD4hep version (to be removed in the future)
2555//
2556////////////////////////////////////////////////////////////////////////////////
2557
2558////////////////////////////////////////////////////////////////////////////////
2559// Backwards compatibility (to be removed in the future): Wrapper to only selectively write one branch
2560void TGDMLWrite::WriteGDMLfile(TGeoManager *geomanager, TGeoVolume *volume, const char *filename, TString option)
2561{
2562 TList materials, volumes, nodes;
2563 MaterialExtractor extract;
2564 if (!volume) {
2565 Info("WriteGDMLfile", "Invalid Volume reference to extract GDML information!");
2566 return;
2567 }
2568 extract(volume);
2569 for (TGeoMaterial *m : extract.materials)
2570 materials.Add(m);
2571 fTopVolumeName = volume->GetName();
2572 fTopVolume = volume;
2573 fSurfaceList.clear();
2574 fVolumeList.clear();
2575 fNodeList.clear();
2576 WriteGDMLfile(geomanager, volume, &materials, filename, option);
2577 materials.Clear("nodelete");
2578 volumes.Clear("nodelete");
2579 nodes.Clear("nodelete");
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Wrapper of all exporting methods
2584/// Creates blank GDML file and fills it with gGeoManager structure converted
2585/// to GDML structure of xml nodes
2586
2587void TGDMLWrite::WriteGDMLfile(TGeoManager *geomanager, TGeoVolume *volume, TList *materialsLst, const char *filename,
2588 TString option)
2589{
2590 // option processing
2591 option.ToLower();
2592 if (option.Contains("g")) {
2594 Info("WriteGDMLfile", "Geant4 compatibility mode set");
2595 } else {
2597 }
2598 if (option.Contains("f")) {
2600 Info("WriteGDMLfile", "Fast naming convention with pointer suffix set");
2601 } else if (option.Contains("n")) {
2603 Info("WriteGDMLfile", "Naming without prefix set - be careful uniqness of name is not ensured");
2604 } else {
2606 Info("WriteGDMLfile", "Potentially slow with incremental suffix naming convention set");
2607 }
2608
2609 // local variables
2610 Int_t outputLayout = 1;
2611 const char *krootNodeName = "gdml";
2612 const char *knsRefGeneral = "http://www.w3.org/2001/XMLSchema-instance";
2613 const char *knsNameGeneral = "xsi";
2614 const char *knsRefGdml = "http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd";
2615 const char *knsNameGdml = "xsi:noNamespaceSchemaLocation";
2616
2617 // First create engine
2618 fGdmlE = new TXMLEngine;
2619 fGdmlE->SetSkipComments(kTRUE);
2620
2621 // create blank GDML file
2622 fGdmlFile = fGdmlE->NewDoc();
2623
2624 // create root node and add it to blank GDML file
2625 XMLNodePointer_t rootNode = fGdmlE->NewChild(nullptr, nullptr, krootNodeName, nullptr);
2626 fGdmlE->DocSetRootElement(fGdmlFile, rootNode);
2627
2628 // add namespaces to root node
2629 fGdmlE->NewNS(rootNode, knsRefGeneral, knsNameGeneral);
2630 fGdmlE->NewAttr(rootNode, nullptr, knsNameGdml, knsRefGdml);
2631
2632 // initialize general lists and <define>, <solids>, <structure> nodes
2633 fIsotopeList = new StructLst;
2634 fElementList = new StructLst;
2635
2636 fNameList = new NameLst;
2637
2638 fDefineNode = fGdmlE->NewChild(nullptr, nullptr, "define", nullptr);
2639 fSolidsNode = fGdmlE->NewChild(nullptr, nullptr, "solids", nullptr);
2640 fStructureNode = fGdmlE->NewChild(nullptr, nullptr, "structure", nullptr);
2641 //========================
2642
2643 // initialize list of accepted patterns for divisions (in ExtractVolumes)
2644 fAccPatt = new StructLst;
2645 fAccPatt->fLst["TGeoPatternX"] = kTRUE;
2646 fAccPatt->fLst["TGeoPatternY"] = kTRUE;
2647 fAccPatt->fLst["TGeoPatternZ"] = kTRUE;
2648 fAccPatt->fLst["TGeoPatternCylR"] = kTRUE;
2649 fAccPatt->fLst["TGeoPatternCylPhi"] = kTRUE;
2650 //========================
2651
2652 // initialize list of rejected shapes for divisions (in ExtractVolumes)
2653 fRejShape = new StructLst;
2654 // this shapes are rejected because, it is not possible to divide trd2
2655 // in Y axis and while only trd2 object is imported from GDML
2656 // it causes a problem when TGeoTrd1 is divided in Y axis
2657 fRejShape->fLst["TGeoTrd1"] = kTRUE;
2658 fRejShape->fLst["TGeoTrd2"] = kTRUE;
2659 //=========================
2660
2661 // Initialize global counters
2662 fActNameErr = 0;
2663 fVolCnt = 0;
2664 fPhysVolCnt = 0;
2665 fSolCnt = 0;
2666
2667 // calling main extraction functions (with measuring time)
2668 time_t startT, endT;
2669 startT = time(nullptr);
2671 ExtractConstants(geomanager);
2672 fMaterialsNode = ExtractMaterials(materialsLst);
2673
2674 Info("WriteGDMLfile", "Extracting volumes");
2675 ExtractVolumes(volume);
2676 Info("WriteGDMLfile", "%i solids added", fSolCnt);
2677 Info("WriteGDMLfile", "%i volumes added", fVolCnt);
2678 Info("WriteGDMLfile", "%i physvolumes added", fPhysVolCnt);
2682 endT = time(nullptr);
2683 //<gdml>
2684 fGdmlE->AddChild(rootNode, fDefineNode); // <define>...</define>
2685 fGdmlE->AddChild(rootNode, fMaterialsNode); // <materials>...</materials>
2686 fGdmlE->AddChild(rootNode, fSolidsNode); // <solids>...</solids>
2687 fGdmlE->AddChild(rootNode, fStructureNode); // <structure>...</structure>
2688 fGdmlE->AddChild(rootNode, CreateSetupN(fTopVolumeName.Data())); // <setup>...</setup>
2689 //</gdml>
2690 Double_t tdiffI = difftime(endT, startT);
2691 TString tdiffS = (tdiffI == 0 ? TString("< 1 s") : TString::Format("%.0lf s", tdiffI));
2692 Info("WriteGDMLfile", "Exporting time: %s", tdiffS.Data());
2693 //=========================
2694
2695 // Saving document
2696 fGdmlE->SaveDoc(fGdmlFile, filename, outputLayout);
2697 Info("WriteGDMLfile", "File %s saved", filename);
2698 // cleaning
2699 fGdmlE->FreeDoc(fGdmlFile);
2700 // unset processing bits:
2701 UnsetTemporaryBits(geomanager);
2702 delete fGdmlE;
2703}
2704
2705////////////////////////////////////////////////////////////////////////////////
2706/// Method extracting geometry structure recursively
2707
2709{
2710 XMLNodePointer_t volumeN, childN;
2711 TString volname, matname, solname, pattClsName, nodeVolNameBak;
2712 TGeoPatternFinder *pattFinder = nullptr;
2713 Bool_t isPattern = kFALSE;
2714 const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision);
2715
2716 // create the name for volume/assembly
2717 if (volume == fTopVolume) {
2718 // not needed a special function for generating name
2719 volname = volume->GetName();
2720 fTopVolumeName = volname;
2721 // register name to the pointer
2722 fNameList->fLst[TString::Format("%p", volume)] = volname;
2723 } else {
2724 volname = GenName(volume->GetName(), TString::Format("%p", volume));
2725 }
2726
2727 // start to create main volume/assembly node
2728 if (volume->IsAssembly()) {
2729 volumeN = StartAssemblyN(volname);
2730 } else {
2731 // get reference material and add solid to <solids> + get name
2732 matname = fNameList->fLst[TString::Format("%p", volume->GetMaterial())];
2733 solname = ExtractSolid(volume->GetShape());
2734 // If solid is not supported or corrupted
2735 if (solname == "-1") {
2736 Info("ExtractVolumes", "ERROR! %s volume was not added, because solid is either not supported or corrupted",
2737 volname.Data());
2738 // set volume as missing volume
2739 fNameList->fLst[TString::Format("%p", volume)] = "missing_" + volname;
2740 return;
2741 }
2742 volumeN = StartVolumeN(volname, solname, matname);
2743
2744 // divisionvol can't be in assembly
2745 pattFinder = volume->GetFinder();
2746 // if found pattern
2747 if (pattFinder) {
2748 pattClsName = TString::Format("%s", pattFinder->ClassName());
2749 TString shapeCls = TString::Format("%s", volume->GetShape()->ClassName());
2750 // if pattern in accepted pattern list and not in shape rejected list
2751 if ((fAccPatt->fLst[pattClsName] == kTRUE) && (fRejShape->fLst[shapeCls] != kTRUE)) {
2752 isPattern = kTRUE;
2753 }
2754 }
2755 }
2756 // get all nodes in volume
2757 TObjArray *nodeLst = volume->GetNodes();
2758 TIter next(nodeLst);
2759 TString physvolname;
2760 TGeoNode *geoNode;
2761 Int_t nCnt = 0;
2762 // loop through all nodes
2763 while ((geoNode = (TGeoNode *)next())) {
2764 // get volume of current node and if not processed then process it
2765 TGeoVolume *subvol = geoNode->GetVolume();
2766 if (subvol->TestAttBit(fgkProcBitVol) == kFALSE) {
2767 subvol->SetAttBit(fgkProcBitVol);
2768 ExtractVolumes(subvol);
2769 }
2770
2771 // volume of this node has to exist because it was processed recursively
2772 TString nodevolname = fNameList->fLst[TString::Format("%p", geoNode->GetVolume())];
2773 if (nodevolname.Contains("missing_")) {
2774 continue;
2775 }
2776 if (nCnt == 0) { // save name of the first node for divisionvol
2777 nodeVolNameBak = nodevolname;
2778 }
2779
2780 if (isPattern == kFALSE) {
2781 // create name for node
2782 TString nodename, posname, rotname;
2783 nodename = GenName(geoNode->GetName(), TString::Format("%p", geoNode));
2784 nodename = nodename + "in" + volname;
2785
2786 // create name for position and clear rotation
2787 posname = nodename + "pos";
2788 rotname = "";
2789
2790 // position
2791 const Double_t *pos = geoNode->GetMatrix()->GetTranslation();
2792 Xyz nodPos;
2793 nodPos.x = pos[0];
2794 nodPos.y = pos[1];
2795 nodPos.z = pos[2];
2796 childN = CreatePositionN(posname.Data(), nodPos, "position", fDefault_lunit);
2797 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
2798 // Deal with reflection
2799 XMLNodePointer_t scaleN = nullptr;
2800 Double_t lx, ly, lz;
2801 Double_t xangle = 0;
2802 Double_t zangle = 0;
2803 lx = geoNode->GetMatrix()->GetRotationMatrix()[0];
2804 ly = geoNode->GetMatrix()->GetRotationMatrix()[4];
2805 lz = geoNode->GetMatrix()->GetRotationMatrix()[8];
2806 if (geoNode->GetMatrix()->IsReflection() && TMath::Abs(lx) == 1 && TMath::Abs(ly) == 1 &&
2807 TMath::Abs(lz) == 1) {
2808 scaleN = fGdmlE->NewChild(nullptr, nullptr, "scale", nullptr);
2809 fGdmlE->NewAttr(scaleN, nullptr, "name", (nodename + "scl").Data());
2810 fGdmlE->NewAttr(scaleN, nullptr, "x", TString::Format(fltPrecision.Data(), lx));
2811 fGdmlE->NewAttr(scaleN, nullptr, "y", TString::Format(fltPrecision.Data(), ly));
2812 fGdmlE->NewAttr(scaleN, nullptr, "z", TString::Format(fltPrecision.Data(), lz));
2813 // experimentally found out, that rotation should be updated like this
2814 if (lx == -1) {
2815 zangle = 180;
2816 }
2817 if (lz == -1) {
2818 xangle = 180;
2819 }
2820 }
2821
2822 // rotation
2824 lxyz.x -= xangle;
2825 lxyz.z -= zangle;
2826 if ((lxyz.x != 0.0) || (lxyz.y != 0.0) || (lxyz.z != 0.0)) {
2827 rotname = nodename + "rot";
2828 childN = CreateRotationN(rotname.Data(), lxyz);
2829 fGdmlE->AddChild(fDefineNode, childN); // adding node to <define> node
2830 }
2831
2832 // create physvol for main volume/assembly node
2833 physvolname = fNameList->fLst[TString::Format("%p", geoNode)];
2834 childN = CreatePhysVolN(physvolname, geoNode->GetNumber(), nodevolname.Data(), posname.Data(), rotname.Data(),
2835 scaleN);
2836 fGdmlE->AddChild(volumeN, childN);
2837 }
2838 nCnt++;
2839 }
2840 // create only one divisionvol node
2841 if (isPattern && pattFinder) {
2842 // retrieve attributes of division
2843 Int_t ndiv, divaxis;
2844 Double_t offset, width, xlo, xhi;
2845 TString axis, unit;
2846
2847 ndiv = pattFinder->GetNdiv();
2848 width = pattFinder->GetStep();
2849
2850 divaxis = pattFinder->GetDivAxis();
2851 volume->GetShape()->GetAxisRange(divaxis, xlo, xhi);
2852
2853 // compute relative start (not positional)
2854 offset = pattFinder->GetStart() - xlo;
2855 axis = GetPattAxis(divaxis, pattClsName, unit);
2856
2857 // create division node
2858 childN = CreateDivisionN(offset, width, ndiv, axis.Data(), unit.Data(), nodeVolNameBak.Data());
2859 fGdmlE->AddChild(volumeN, childN);
2860 }
2861
2862 fVolCnt++;
2863 // add volume/assembly node into the <structure> node
2864 fGdmlE->AddChild(fStructureNode, volumeN);
2865}
ROOT::R::TRInterface & r
Definition Object.C:4
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
char name[80]
Definition TGX11.cxx:148
externTGeoManager * gGeoManager
TRObject operator()(const T1 &t1) const
void * XMLNodePointer_t
Definition TXMLEngine.h:17
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
This class is used in the process of reading and writing the GDML "matrix" tag.
Definition TGDMLMatrix.h:33
Double_t Get(size_t r, size_t c) const
size_t GetRows() const
Definition TGDMLMatrix.h:43
size_t GetCols() const
Definition TGDMLMatrix.h:44
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.
Double_t GetDz() const
Definition TGeoArb8.h:68
Bool_t IsTwisted() const
Definition TGeoArb8.h:83
Double_t * GetVertices()
Definition TGeoArb8.h:73
Bool_t TestAttBit(UInt_t f) const
Definition TGeoAtt.h:64
void SetAttBit(UInt_t f)
Definition TGeoAtt.h:61
virtual const Double_t * GetOrigin() const
Definition TGeoBBox.h:81
virtual Double_t GetDX() const
Definition TGeoBBox.h:78
virtual Double_t GetDZ() const
Definition TGeoBBox.h:80
virtual Double_t GetDY() const
Definition TGeoBBox.h:79
virtual EGeoBoolType GetBooleanOperator() const =0
TGeoMatrix * GetRightMatrix() const
TGeoShape * GetLeftShape() const
TGeoMatrix * GetLeftMatrix() const
TGeoShape * GetRightShape() const
TGeoNode const * GetNode2() const
TGeoOpticalSurface const * GetSurface() const
TGeoNode const * GetNode1() const
Class describing rotation + translation.
Definition TGeoMatrix.h:318
Composite shapes are Boolean combinations of two or more shape components.
TGeoBoolNode * GetBoolNode() const
Double_t GetPhi1() const
Definition TGeoCone.h:166
Double_t GetPhi2() const
Definition TGeoCone.h:167
virtual Double_t GetRmax2() const
Definition TGeoCone.h:79
virtual Double_t GetDz() const
Definition TGeoCone.h:71
virtual Double_t GetRmin2() const
Definition TGeoCone.h:78
virtual Double_t GetRmin1() const
Definition TGeoCone.h:76
virtual Double_t GetRmax1() const
Definition TGeoCone.h:77
const Double_t * GetNlow() const
Definition TGeoTube.h:212
const Double_t * GetNhigh() const
Definition TGeoTube.h:213
Base class for chemical elements.
Definition TGeoElement.h:31
Int_t N() const
Definition TGeoElement.h:64
Double_t A() const
Definition TGeoElement.h:66
Int_t Z() const
Definition TGeoElement.h:63
Int_t GetNisotopes() const
Definition TGeoElement.h:68
Bool_t HasIsotopes() const
Definition TGeoElement.h:75
Double_t GetRelativeAbundance(Int_t i) const
Return relative abundance of i-th isotope in this element.
TGeoIsotope * GetIsotope(Int_t i) const
Return i-th isotope in the element.
virtual Double_t GetA() const
Definition TGeoEltu.h:47
virtual Double_t GetB() const
Definition TGeoEltu.h:48
int GetNvert() const
Double_t GetTwistAngle() const
Definition TGeoArb8.h:175
const Double_t * GetRotationMatrix() const override
Definition TGeoMatrix.h:529
Double_t GetStIn() const
Definition TGeoHype.h:72
Double_t GetStOut() const
Definition TGeoHype.h:73
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
Int_t GetZ() const
Int_t GetN() const
Double_t GetA() const
The manager class for any TGeo geometry.
Definition TGeoManager.h:46
TObjArray * GetListOfVolumes() const
TObjArray * GetListOfSkinSurfaces() const
TObjArray * GetListOfGDMLMatrices() const
Int_t GetNproperties() const
TObjArray * GetListOfBorderSurfaces() const
TGeoNode * GetTopNode() const
Double_t GetProperty(const char *name, Bool_t *error=nullptr) const
Get a user-defined property.
static UInt_t GetExportPrecision()
TObjArray * GetListOfOpticalSurfaces() const
TList * GetListOfMaterials() const
Base class describing materials.
virtual Bool_t IsMixture() const
TList const & GetConstProperties() const
TList const & GetProperties() const
virtual Double_t GetA() const
virtual Double_t GetDensity() const
virtual Double_t GetZ() const
Geometrical transformation package.
Definition TGeoMatrix.h:39
virtual const Double_t * GetTranslation() const =0
Bool_t IsReflection() const
Definition TGeoMatrix.h:67
virtual const Double_t * GetRotationMatrix() const =0
virtual TGeoHMatrix Inverse() const =0
Media are used to store properties related to tracking and which are useful only when using geometry ...
Definition TGeoMedium.h:23
TGeoMaterial * GetMaterial() const
Definition TGeoMedium.h:49
Mixtures of elements.
Int_t GetNelements() const override
Double_t * GetWmixt() const
TGeoElement * GetElement(Int_t i=0) const override
Retrieve the pointer to the element corresponding to component I.
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
virtual TGeoMatrix * GetMatrix() const =0
Int_t GetNumber() const
Definition TGeoNode.h:94
This is a wrapper class to G4OpticalSurface.
TList const & GetProperties() const
static const char * ModelToString(ESurfaceModel model)
static const char * TypeToString(ESurfaceType type)
ESurfaceModel GetModel() const
TList const & GetConstProperties() const
ESurfaceFinish GetFinish() const
static const char * FinishToString(ESurfaceFinish finish)
Double_t GetValue() const
ESurfaceType GetType() const
Double_t GetZ() const
Definition TGeoPara.h:68
Double_t GetPhi() const
Definition TGeoPara.h:71
Double_t GetAlpha() const
Definition TGeoPara.h:69
Double_t GetX() const
Definition TGeoPara.h:66
Double_t GetY() const
Definition TGeoPara.h:67
Double_t GetTheta() const
Definition TGeoPara.h:70
A paraboloid is defined by the revolution surface generated by a parabola and is bounded by two plane...
Double_t GetDz() const
Double_t GetRhi() const
Double_t GetRlo() const
base finder class for patterns. A pattern is specifying a division type
virtual Int_t GetDivAxis()
Int_t GetNdiv() const
Double_t GetStep() const
Double_t GetStart() const
Double_t * GetRmax() const
Definition TGeoPcon.h:82
Double_t GetDphi() const
Definition TGeoPcon.h:77
Double_t * GetZ() const
Definition TGeoPcon.h:84
Int_t GetNz() const
Definition TGeoPcon.h:78
Double_t * GetRmin() const
Definition TGeoPcon.h:80
Double_t GetPhi1() const
Definition TGeoPcon.h:76
Int_t GetNedges() const
Definition TGeoPgon.h:93
Reference counted extension which has a pointer to and owns a user defined TObject.
TObject * GetUserObject() const
Class describing rotations.
Definition TGeoMatrix.h:169
void SetAngles(Double_t phi, Double_t theta, Double_t psi)
Set matrix elements according to Euler angles.
const Double_t * GetScale() const override
Definition TGeoMatrix.h:306
A shape scaled by a TGeoScale transformation.
TGeoShape * GetShape() const
TGeoScale * GetScale() const
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
const char * GetName() const override
Get the shape name.
TGeoVolume const * GetVolume() const
TGeoOpticalSurface const * GetSurface() const
Double_t GetPhi1() const
Definition TGeoSphere.h:76
Double_t GetPhi2() const
Definition TGeoSphere.h:77
virtual Double_t GetRmin() const
Definition TGeoSphere.h:72
Double_t GetTheta2() const
Definition TGeoSphere.h:75
virtual Double_t GetRmax() const
Definition TGeoSphere.h:73
Double_t GetTheta1() const
Definition TGeoSphere.h:74
Tessellated solid class.
const TGeoFacet & GetFacet(int i) const
const Vertex_t & GetVertex(int i) const
int GetNvertices() const
int GetNfacets() const
Double_t GetRmax() const
Definition TGeoTorus.h:75
Double_t GetRmin() const
Definition TGeoTorus.h:74
Double_t GetR() const
Definition TGeoTorus.h:73
Double_t GetPhi1() const
Definition TGeoTorus.h:76
Double_t GetDphi() const
Definition TGeoTorus.h:77
Class describing translations.
Definition TGeoMatrix.h:117
Double_t GetTl1() const
Definition TGeoArb8.h:137
Double_t GetPhi() const
Definition TGeoArb8.h:134
Double_t GetAlpha2() const
Definition TGeoArb8.h:142
Double_t GetTheta() const
Definition TGeoArb8.h:133
Double_t GetAlpha1() const
Definition TGeoArb8.h:138
Double_t GetBl2() const
Definition TGeoArb8.h:140
Double_t GetTl2() const
Definition TGeoArb8.h:141
Double_t GetH1() const
Definition TGeoArb8.h:135
Double_t GetH2() const
Definition TGeoArb8.h:139
Double_t GetBl1() const
Definition TGeoArb8.h:136
Double_t GetDy() const
Definition TGeoTrd1.h:60
Double_t GetDx2() const
Definition TGeoTrd1.h:59
Double_t GetDz() const
Definition TGeoTrd1.h:61
Double_t GetDx1() const
Definition TGeoTrd1.h:58
Double_t GetDy2() const
Definition TGeoTrd2.h:62
Double_t GetDy1() const
Definition TGeoTrd2.h:61
Double_t GetDx2() const
Definition TGeoTrd2.h:60
Double_t GetDz() const
Definition TGeoTrd2.h:63
Double_t GetDx1() const
Definition TGeoTrd2.h:59
Double_t GetPhi2() const
Definition TGeoTube.h:155
Double_t GetPhi1() const
Definition TGeoTube.h:154
virtual Double_t GetRmin() const
Definition TGeoTube.h:72
virtual Double_t GetDz() const
Definition TGeoTube.h:74
virtual Double_t GetRmax() const
Definition TGeoTube.h:73
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Definition TGeoVolume.h:43
TGeoExtension * GetUserExtension() const
Definition TGeoVolume.h:133
TGeoMaterial * GetMaterial() const
Definition TGeoVolume.h:175
TObjArray * GetNodes()
Definition TGeoVolume.h:170
TGeoPatternFinder * GetFinder() const
Definition TGeoVolume.h:178
static TGeoMedium * DummyMedium()
TGeoShape * GetShape() const
Definition TGeoVolume.h:191
virtual Bool_t IsAssembly() const
Returns true if the volume is an assembly or a scaled assembly.
A TGeoXtru shape is represented by the extrusion of an arbitrary polygon with fixed outline between s...
Definition TGeoXtru.h:22
Double_t GetYOffset(Int_t i) const
Definition TGeoXtru.h:100
Double_t * GetZ() const
Definition TGeoXtru.h:102
Int_t GetNvert() const
Definition TGeoXtru.h:96
Double_t GetY(Int_t i) const
Definition TGeoXtru.h:98
Double_t GetScale(Int_t i) const
Definition TGeoXtru.h:101
Double_t GetXOffset(Int_t i) const
Definition TGeoXtru.h:99
Int_t GetNz() const
Definition TGeoXtru.h:95
Double_t GetX(Int_t i) const
Definition TGeoXtru.h:97
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
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Create an iterator for TMap.
Definition TMap.cxx:257
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition TMap.cxx:235
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
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
Collectable string class.
Definition TObjString.h:28
const TString & GetString() const
Definition TObjString.h:46
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:227
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:549
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1126
TObject()
TObject constructor.
Definition TObject.h:259
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1072
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition TString.cxx:1836
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:713
Bool_t IsNull() const
Definition TString.h:422
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:2385
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
TH1F * h1
Definition legend1.C:5
Double_t ACos(Double_t)
Returns the principal value of the arc cosine of x, expressed in radians.
Definition TMath.h:643
Double_t ATan2(Double_t y, Double_t x)
Returns the principal value of the arc tangent of y/x, expressed in radians.
Definition TMath.h:657
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
TMarker m
Definition textangle.C:8
auto * t1
Definition textangle.C:20