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