9#include <geometry/modules/vrmlWriter/VRMLWriterModule.h>
10#include <geometry/GeometryManager.h>
12#include "G4PhysicalVolumeStore.hh"
13#include "G4LogicalVolumeStore.hh"
14#include "G4SolidStore.hh"
15#include "G4VPhysicalVolume.hh"
16#include "G4LogicalVolume.hh"
18#include "G4VisAttributes.hh"
19#include "G4VisExtent.hh"
20#include "G4Material.hh"
21#include "G4ThreeVector.hh"
22#include "G4RotationMatrix.hh"
23#include "G4Transform3D.hh"
24#include "G4VPVParameterisation.hh"
27#include <G4Polyhedron.hh>
28#include <G4DisplacedSolid.hh>
39 setDescription(
"Write the detector geometry in a hierarchical VRML format.");
56 B2ERROR(
"No geometry found: add the Geometry module to the path before the VRMLWriter module.");
62 G4PhysicalVolumeStore* pvStore = G4PhysicalVolumeStore::GetInstance();
63 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
64 G4SolidStore* solidStore = G4SolidStore::GetInstance();
66 m_PVName =
new std::vector<std::string>(pvStore->size(),
"");
67 m_LVName =
new std::vector<std::string>(lvStore->size(),
"");
68 m_SolidName =
new std::vector<std::string>(solidStore->size(),
"");
71 for (G4VPhysicalVolume* physVol : *pvStore) {
72 int pvIndex = std::find(pvStore->begin(), pvStore->end(), physVol) - pvStore->begin();
73 if ((*
m_PVName)[pvIndex].length() == 0)
75 G4LogicalVolume* logVol = physVol->GetLogicalVolume();
76 int lvIndex = std::find(lvStore->begin(), lvStore->end(), logVol) - lvStore->begin();
77 if ((*
m_LVName)[lvIndex].length() == 0)
79 G4VSolid* solid = logVol->GetSolid();
80 int solidIndex = std::find(solidStore->begin(), solidStore->end(), solid) - solidStore->begin();
87 m_IsCylinder =
new std::vector<bool>(solidStore->size(),
false);
88 for (
unsigned int solidIndex = 0; solidIndex < solidStore->size(); ++solidIndex) {
90 if ((*solidStore)[solidIndex]->GetEntityType() ==
"G4Tubs") {
91 auto* tube = (G4Tubs*)((*solidStore)[solidIndex]);
92 (*m_IsCylinder)[solidIndex] = ((tube->GetInnerRadius() == 0.0) && (tube->GetDeltaPhiAngle() == 2.0 * M_PI));
101 m_PVIndex =
new std::vector<std::vector<int> >(lvStore->size(), std::vector<int>());
102 m_LVWritten =
new std::vector<bool>(lvStore->size(),
false);
103 m_PVWritten =
new std::vector<bool>(pvStore->size(),
false);
107 int pvIndex = std::find(pvStore->begin(), pvStore->end(), topVol) - pvStore->begin();
108 int lvIndex = std::find(lvStore->begin(), lvStore->end(), topVol->GetLogicalVolume()) - lvStore->begin();
109 m_File <<
"# PhysicalVolume " << topVol->GetName() << std::endl <<
110 "DEF " << (*m_PVName)[pvIndex] <<
" Transform {" << std::endl <<
111 " children lv_" << (*m_LVName)[lvIndex] <<
"{}" << std::endl <<
128 G4SolidStore* solidStore = G4SolidStore::GetInstance();
129 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
130 G4PhysicalVolumeStore* pvStore = G4PhysicalVolumeStore::GetInstance();
132 G4String name = originalName;
133 if (name.length() == 0) { name =
"anonymous"; }
135 for (
char c :
" .,:;?'\"*+-=|^!/@#$\\%{}[]()<>") std::replace(name.begin(), name.end(), c,
'_');
137 for (
int j = (
int)index - 1; j >= 0; --j) {
138 if ((*names)[j].length() == 0)
continue;
142 match = (*pvStore)[j]->GetName().compare((*pvStore)[index]->GetName());
break;
144 match = (*lvStore)[j]->GetName().compare((*lvStore)[index]->GetName());
break;
146 match = (*solidStore)[j]->GetName().compare((*solidStore)[index]->GetName());
break;
149 if (name.length() == (*names)[j].length()) {
150 (*names)[j].append(
"_1");
152 int n = std::stoi((*names)[j].substr(name.length() + 1),
nullptr);
154 name.append(std::to_string(n + 1));
158 (*names)[index] = name;
163 m_File <<
"# Solid " << solid->GetName() <<
" of type " << solid->GetEntityType() << std::endl;
165 auto* tube = (G4Tubs*)solid;
167 m_File <<
"PROTO solid_" << solidName <<
" [ ] {" << std::endl <<
168 " Cylinder {" << std::endl << std::setprecision(10) <<
169 " radius " << tube->GetOuterRadius() << std::endl <<
170 " height " << tube->GetZHalfLength() * 2.0 << std::endl <<
173 }
else if (solid->GetEntityType() ==
"G4Box") {
174 auto* box = (G4Box*)solid;
175 m_File <<
"PROTO solid_" << solidName <<
" [ ] {" << std::endl <<
176 " Box {" << std::endl << std::setprecision(10) <<
177 " size " << box->GetXHalfLength() * 2.0 <<
" " <<
178 box->GetYHalfLength() * 2.0 <<
" " <<
179 box->GetZHalfLength() * 2.0 << std::endl <<
182 }
else if ((solid->GetEntityType() ==
"G4IntersectionSolid") ||
183 (solid->GetEntityType() ==
"G4UnionSolid") ||
184 (solid->GetEntityType() ==
"G4SubtractionSolid") ||
185 (solid->GetEntityType() ==
"G4BooleanSolid")) {
187 auto* g4polyhedron =
new G4Polyhedron(*polyhedron);
199 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
200 int lvIndex = std::find(lvStore->begin(), lvStore->end(), logVol) - lvStore->begin();
202 (*m_LVWritten)[lvIndex] =
true;
203 G4Color color(0.0, 1.0, 0.0, 0.5);
204 if ((lvName.compare(0, 23,
"eclBarrelCrystalLogical") == 0) ||
205 (lvName.compare(0, 20,
"eclFwdCrystalLogical") == 0) ||
206 (lvName.compare(0, 20,
"eclBwdCrystalLogical") == 0)) {
207 color = G4Color(1.0, 0.25, 0.0, 0.7);
209 std::string visible =
"";
210 G4String materialName = logVol->GetMaterial()->GetName();
212 if (materialName ==
"Vacuum") visible =
"#";
213 if (materialName ==
"G4_AIR") visible =
"#";
214 if (materialName ==
"CDCGas") visible =
"#";
215 if (materialName ==
"ColdAir") visible =
"#";
216 if (materialName ==
"STR-DryAir") visible =
"#";
217 if (materialName ==
"TOPAir") visible =
"#";
218 if (materialName ==
"TOPVacuum") visible =
"#";
219 const G4VisAttributes* visAttr = logVol->GetVisAttributes();
221 color =
const_cast<G4Color&
>(logVol->GetVisAttributes()->GetColor());
222 if (!(visAttr->IsVisible())) visible =
"#";
226 bool hasDaughters = (visible.length() == 0) || ((*
m_PVIndex)[lvIndex].size() > 0);
227 if (logVol->GetSensitiveDetector() !=
nullptr) visible =
"";
228 m_File <<
"# LogicalVolume " << logVol->GetName() <<
" containing " << materialName << std::endl <<
229 "PROTO lv_" << lvName <<
" [ ] {" << std::endl <<
230 " Group {" << std::endl <<
231 " " << (hasDaughters ?
"" :
"#") <<
"children [" << std::endl;
234 m_File <<
" " << visible <<
"Transform {" << std::endl <<
235 " " << visible <<
" rotation 1 0 0 " << M_PI_2 << std::endl <<
236 " " << visible <<
" children [" << std::endl;
239 m_File <<
" " << visible <<
"Shape {" << std::endl <<
240 " " << visible <<
" appearance Appearance {" << std::endl <<
241 " " << visible <<
" material Material {" << std::endl <<
242 " " << visible <<
" diffuseColor " << color.GetRed() <<
" " <<
243 color.GetGreen() <<
" " <<
244 color.GetBlue() << std::endl <<
245 " " << visible <<
" " << (color.GetAlpha() == 1.0 ?
"#" :
"") <<
246 "transparency " << 1.0 - color.GetAlpha() << std::endl <<
247 " " << visible <<
" }" << std::endl <<
248 " " << visible <<
" }" << std::endl <<
249 " " << visible <<
" geometry solid_" << solidName <<
"{}" << std::endl <<
250 " " << visible <<
"}" << std::endl;
252 visible.resize(visible.length() - 2);
253 m_File <<
" " << visible <<
" ]" << std::endl <<
254 " " << visible <<
"}" << std::endl;
256 G4PhysicalVolumeStore* pvStore = G4PhysicalVolumeStore::GetInstance();
257 for (
int daughter : (*
m_PVIndex)[lvIndex]) {
258 G4VPhysicalVolume* physVol = (*pvStore)[daughter];
259 std::string pvNameDaughter = (*m_PVName)[daughter];
260 int lvDaughter = std::find(lvStore->begin(), lvStore->end(), physVol->GetLogicalVolume()) - lvStore->begin();
261 std::string lvNameDaughter = (*m_LVName)[lvDaughter];
262 if (physVol->IsReplicated()) {
263 G4VSolid* solid = logVol->GetSolid();
269 physVol->GetReplicationData(axis, nReplicas, width, offset, consuming);
270 G4VPVParameterisation* physParameterisation = physVol->GetParameterisation();
271 if (physParameterisation) {
272 for (
int replica = 0; replica < nReplicas; ++replica) {
273 std::string pvNameReplica = pvNameDaughter;
274 std::string lvNameReplica = lvNameDaughter;
275 pvNameReplica.append(
"_");
276 pvNameReplica.append(std::to_string(replica));
277 physVol->SetCopyNo(replica);
278 physParameterisation->ComputeTransformation(replica, physVol);
279 G4VSolid* solidReplica = physParameterisation->ComputeSolid(replica, physVol);
280 if (solidReplica != solid) {
281 lvNameReplica.append(
"_");
282 lvNameReplica.append(std::to_string(replica));
287 G4ThreeVector originalTranslation = physVol->GetTranslation();
288 G4RotationMatrix* originalRotation = physVol->GetRotation();
289 for (
int replica = 0; replica < nReplicas; ++replica) {
290 G4ThreeVector translation;
291 G4RotationMatrix rotation;
292 std::string pvNameReplica = pvNameDaughter;
293 std::string lvNameReplica = lvNameDaughter;
294 pvNameReplica.append(
"_");
295 pvNameReplica.append(std::to_string(replica));
296 physVol->SetCopyNo(replica);
300 translation.setX(width * (replica - 0.5 * (nReplicas - 1)));
301 physVol->SetTranslation(translation);
304 translation.setY(width * (replica - 0.5 * (nReplicas - 1)));
305 physVol->SetTranslation(translation);
308 translation.setZ(width * (replica - 0.5 * (nReplicas - 1)));
309 physVol->SetTranslation(translation);
312 if (solid->GetEntityType() ==
"G4Tubs") {
313 lvNameReplica.append(
"_");
314 lvNameReplica.append(std::to_string(replica));
316 B2WARNING(
"Built-in volumes replicated along radius for " << solid->GetEntityType() <<
317 " (solid " << solid->GetName() <<
") are not visualisable.");
321 physVol->SetRotation(&(rotation.rotateZ(-(offset + (replica + 0.5) * width))));
327 physVol->SetTranslation(originalTranslation);
328 physVol->SetRotation(originalRotation);
333 (*m_PVWritten)[daughter] =
true;
335 G4VisExtent extent = logVol->GetSolid()->GetExtent();
336 double xMin = extent.GetXmin();
337 double xMax = extent.GetXmax();
338 double yMin = extent.GetYmin();
339 double yMax = extent.GetYmax();
340 double zMin = extent.GetZmin();
341 double zMax = extent.GetZmax();
342 double xCenter = 0.5 * (xMin + xMax);
343 double yCenter = 0.5 * (yMin + yMax);
344 double zCenter = 0.5 * (zMin + zMax);
345 bool atOrigin = (std::fabs(xCenter) + std::fabs(yCenter) + std::fabs(zCenter) > 1.0e-12);
346 m_File <<
" " << (hasDaughters ?
"" :
"#") <<
"]" << std::endl <<
347 " " << (atOrigin ?
"" :
"#") <<
348 "bboxCenter " << xCenter <<
" " << yCenter <<
" " << zCenter << std::endl <<
349 " bboxSize " << xMax - xMin <<
" " <<
350 (isCylinder ? zMax - zMin : yMax - yMin) <<
" " <<
351 (isCylinder ? yMax - yMin : zMax - zMin) << std::endl <<
353 "} # end of " << lvName << std::endl;
358 G4LogicalVolume* logVol = physVol->GetLogicalVolume();
359 G4VSolid* solid = logVol->GetSolid();
360 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
361 int lvIndex = std::find(lvStore->begin(), lvStore->end(), logVol) - lvStore->begin();
362 std::string lvName = (*m_LVName)[lvIndex];
363 if (physVol->IsReplicated()) {
364 G4SolidStore* solidStore = G4SolidStore::GetInstance();
365 int solidIndex = std::find(solidStore->begin(), solidStore->end(), solid) - solidStore->begin();
366 std::string solidName = (*m_SolidName)[solidIndex];
372 physVol->GetReplicationData(axis, nReplicas, width, offset, consuming);
373 G4VPVParameterisation* physParameterisation = physVol->GetParameterisation();
374 if (physParameterisation) {
375 for (
int replica = 0; replica < nReplicas; ++replica) {
376 std::string lvNameReplica = lvName;
377 G4VSolid* solidReplica = physParameterisation->ComputeSolid(replica, physVol);
378 if (solidReplica != solid) {
379 solidReplica->ComputeDimensions(physParameterisation, replica, physVol);
380 std::string solidNameReplica = solidName;
381 solidNameReplica.append(
"_");
382 solidNameReplica.append(std::to_string(replica));
383 lvNameReplica.append(
"_");
384 lvNameReplica.append(std::to_string(replica));
391 for (
int replica = 0; replica < nReplicas; ++replica) {
393 if (solid->GetEntityType() ==
"G4Tubs") {
394 double originalRMin = ((G4Tubs*)solid)->GetInnerRadius();
395 double originalRMax = ((G4Tubs*)solid)->GetOuterRadius();
396 ((G4Tubs*)solid)->SetInnerRadius(offset + width * replica);
397 ((G4Tubs*)solid)->SetOuterRadius(offset + width * (replica + 1));
398 std::string solidNameReplica = solidName;
399 solidNameReplica.append(
"_");
400 solidNameReplica.append(std::to_string(replica));
401 std::string lvNameReplica = lvName;
402 lvNameReplica.append(
"_");
403 lvNameReplica.append(std::to_string(replica));
405 ((G4Tubs*)solid)->SetInnerRadius(originalRMin);
406 ((G4Tubs*)solid)->SetOuterRadius(originalRMax);
410 B2WARNING(
"Built-in volumes replicated along radius for " << solid->GetEntityType() <<
411 " (solid " << solid->GetName() <<
") are not visualisable.");
425 G4PhysicalVolumeStore* pvStore = G4PhysicalVolumeStore::GetInstance();
426 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance();
427 G4SolidStore* solidStore = G4SolidStore::GetInstance();
429 int pvIndex = std::find(pvStore->begin(), pvStore->end(), physVol) - pvStore->begin();
433 G4LogicalVolume* logVol = physVol->GetLogicalVolume();
434 int lvIndex = std::find(lvStore->begin(), lvStore->end(), logVol) - lvStore->begin();
435 for (
size_t daughter = 0; daughter < logVol->GetNoDaughters(); ++daughter) {
436 G4VPhysicalVolume* dPhysVol = logVol->GetDaughter(daughter);
437 (*m_PVIndex)[lvIndex].push_back(std::find(pvStore->begin(), pvStore->end(), dPhysVol) - pvStore->begin());
441 int solidIndex = std::find(solidStore->begin(), solidStore->end(), logVol->GetSolid()) - solidStore->begin();
447 m_File <<
"#VRML V2.0 utf8" << std::endl << std::endl <<
448 "WorldInfo {" << std::endl <<
449 " info [ \"(c) The Belle II Collaboration\" ]" << std::endl <<
450 " title \"The Belle II Detector\"" << std::endl <<
452 "Viewpoint {" << std::endl <<
453 " position 0 0 15000" << std::endl <<
454 " description \"front\"" << std::endl <<
456 "Viewpoint {" << std::endl <<
457 " position 0 0 -15000" << std::endl <<
458 " orientation 0 1 0 3.141593" << std::endl <<
459 " description \"back\"" << std::endl <<
461 "Viewpoint {" << std::endl <<
462 " position 0 15000 0" << std::endl <<
463 " orientation 1 0 0 -1.570796" << std::endl <<
464 " description \"top\"" << std::endl <<
466 "Viewpoint {" << std::endl <<
467 " position 0 -15000 0" << std::endl <<
468 " orientation 1 0 0 1.570796" << std::endl <<
469 " description \"bottom\"" << std::endl <<
471 "Viewpoint {" << std::endl <<
472 " position 15000 0 0" << std::endl <<
473 " orientation 0 1 0 1.570796" << std::endl <<
474 " description \"right\"" << std::endl <<
476 "Viewpoint {" << std::endl <<
477 " position -15000 0 0" << std::endl <<
478 " orientation 0 1 0 -1.570796" << std::endl <<
479 " description \"left\"" << std::endl <<
486 m_File <<
"PROTO solid_" << name <<
" [ ] {" << std::endl <<
487 " IndexedFaceSet {" << std::endl <<
488 " coord Coordinate {" << std::endl <<
489 " point [" << std::endl;
490 for (
int j = 1; j <= polyhedron->GetNoVertices(); ++j) {
491 m_File <<
" " << polyhedron->GetVertex(j).x() <<
" " <<
492 polyhedron->GetVertex(j).y() <<
" " <<
493 polyhedron->GetVertex(j).z() << std::endl;
495 m_File <<
" ]" << std::endl <<
497 " coordIndex [" << std::endl;
498 for (
int j = 0; j < polyhedron->GetNoFacets(); ++j) {
499 G4bool notLastEdge =
true;
500 G4int ndx = -1, edgeFlag = 1;
503 notLastEdge = polyhedron->GetNextVertexIndex(ndx, edgeFlag);
505 }
while (notLastEdge);
506 m_File <<
" -1" << std::endl;
508 m_File <<
" ]" << std::endl <<
512 B2INFO(
"Polyhedron representation of solid " << name <<
" cannot be created");
520 m_File <<
" USE " << pvName << std::endl;
522 m_File <<
" # PhysicalVolume " << physVol->GetName() <<
" copy " << physVol->GetCopyNo() << std::endl <<
523 " DEF " << pvName <<
" Transform {" << std::endl;
524 G4RotationMatrix* rot = physVol->GetObjectRotation();
525 G4ThreeVector move = physVol->GetObjectTranslation();
526 double yaw = std::atan2(rot->yx(), rot->xx());
527 double pitch = -std::asin(rot->zx());
528 double roll = std::atan2(rot->zy(), rot->zz());
529 std::cout << physVol->GetName() <<
" translation: " << move.x() <<
"," << move.y() <<
"," << move.z() << std::endl;
530 std::cout << physVol->GetName() <<
" rotation: " << yaw * 180.0 / M_PI <<
"," << pitch * 180.0 / M_PI <<
"," << roll * 180.0 / M_PI
532 if (move.mag2() != 0.0) {
533 m_File <<
" translation " << std::setprecision(10) <<
534 move.x() <<
" " << move.y() <<
" " << move.z() << std::endl;
536 if (!(rot->isIdentity())) {
537 double trace = std::max(-1.0, std::min(3.0, rot->xx() + rot->yy() + rot->zz()));
538 double angle = std::acos(0.5 * (trace - 1.0));
539 G4ThreeVector rotA(rot->zy() - rot->yz(), rot->xz() - rot->zx(), rot->yx() - rot->xy());
540 if ((rotA.x() == 0.0) && (rotA.y() == 0.0) && (rotA.z() == 0.0)) {
543 if (rot->xx() > 0.0) {
544 rotA.setX((rot->yy() - 1.0) * (rot->zz() - 1.0) - rot->yz() * rot->zy());
545 rotA.setY(rot->yz() * rot->zx() - rot->yx() * (rot->zz() - 1.0));
546 rotA.setZ(rot->yx() * rot->zy() - rot->zx() * (rot->yy() - 1.0));
547 }
else if (rot->yy() > 0.0) {
548 rotA.setX(rot->xy() * (rot->zz() - 1.0) - rot->xz() * rot->zy());
549 rotA.setY(rot->xz() * rot->zx() - (rot->xx() - 1.0) * (rot->zz() - 1.0));
550 rotA.setZ((rot->xx() - 1.0) * rot->zy() - rot->xy() * rot->zx());
552 rotA.setX(rot->xy() * rot->yz() - rot->xz() * (rot->yy() - 1.0));
553 rotA.setY(rot->xz() * rot->yx() - rot->yz() * (rot->xx() - 1.0));
554 rotA.setZ((rot->xx() - 1.0) * (rot->yy() - 1.0) - rot->xy() * rot->yx());
558 m_File <<
" rotation " << std::setprecision(10) <<
559 rotA.x() <<
" " << rotA.y() <<
" " << rotA.z() <<
" " << angle << std::endl;
561 m_File <<
" children lv_" << lvName <<
"{}" << std::endl <<
570 G4VSolid* solidA = solid->GetConstituentSolid(0);
571 G4VSolid* solidB = solid->GetConstituentSolid(1);
572 HepPolyhedron* polyhedronA =
nullptr;
573 if ((solidA->GetEntityType() ==
"G4IntersectionSolid") ||
574 (solidA->GetEntityType() ==
"G4UnionSolid") ||
575 (solidA->GetEntityType() ==
"G4SubtractionSolid") ||
576 (solidA->GetEntityType() ==
"G4BooleanSolid")) {
579 polyhedronA =
new HepPolyhedron(*(solidA->GetPolyhedron()));
581 HepPolyhedron* polyhedronB =
nullptr;
582 G4VSolid* solidB2 = solidB;
583 if (solidB->GetEntityType() ==
"G4DisplacedSolid") {
584 solidB2 = ((G4DisplacedSolid*)solidB)->GetConstituentMovedSolid();
586 if ((solidB2->GetEntityType() ==
"G4IntersectionSolid") ||
587 (solidB2->GetEntityType() ==
"G4UnionSolid") ||
588 (solidB2->GetEntityType() ==
"G4SubtractionSolid") ||
589 (solidB2->GetEntityType() ==
"G4BooleanSolid")) {
591 if (solidB != solidB2) {
592 polyhedronB->Transform(G4Transform3D(
593 ((G4DisplacedSolid*)solidB)->GetObjectRotation(),
594 ((G4DisplacedSolid*)solidB)->GetObjectTranslation()));
597 polyhedronB =
new HepPolyhedron(*(solidB->GetPolyhedron()));
599 auto* result =
new HepPolyhedron();
600 if (solid->GetEntityType() ==
"G4UnionSolid") {
601 *result = polyhedronA->add(*polyhedronB);
602 }
else if (solid->GetEntityType() ==
"G4SubtractionSolid") {
603 *result = polyhedronA->subtract(*polyhedronB);
604 }
else if (solid->GetEntityType() ==
"G4IntersectionSolid") {
605 *result = polyhedronA->intersect(*polyhedronB);
607 B2WARNING(
"getBooleanSolidPolyhedron(): Unrecognized boolean solid " << solid->GetName() <<
608 " of type " << solid->GetEntityType());
void setDescription(const std::string &description)
Sets the description of the module.
void describeSolid(G4VSolid *, const std::string &, bool)
Emit VRML for each solid.
VRMLWriterModule()
Constructor of the module.
void writePolyhedron(const G4Polyhedron *, const std::string &)
Emit VRML for the solid's polyhedron.
void initialize() override
Initialize at the start of a job.
void event() override
Called for each event: this runs the VRML writer only for the first event.
void writePhysicalVolume(const G4VPhysicalVolume *, const std::string &, const std::string &, bool)
Emit VRML for each daughter of a logical volume.
void descendAndDescribe(G4VPhysicalVolume *, const std::string &, int)
Emit VRML for a physical volume (recursive)
std::ofstream m_File
Output file.
void writePreamble(void)
Emit VRML for the start of the file.
bool m_First
Once-only flag to write VRML only on the first event.
std::vector< std::vector< int > > * m_PVIndex
Indices (in G4PhysicalVolumeStore) of the logical volume's physical-volume daughters.
void assignName(std::vector< std::string > *, unsigned int, const G4String &, int)
Create unique and legal name for each solid.
std::vector< bool > * m_IsCylinder
Flag to indicate that a solid can be rendered as a VMRL cylinder.
std::string m_Filename
User-specified output filename.
std::vector< bool > * m_PVWritten
Flag to indicate that the physical volume has already been written.
std::vector< std::string > * m_PVName
Modified (legal-character and unique) physical-volume name.
std::vector< std::string > * m_SolidName
Modified (legal-character and unique) solid name.
void describeLogicalVolume(G4LogicalVolume *, const std::string &, const std::string &, bool)
Emit VRML for each logical volume.
std::vector< bool > * m_LVWritten
Flag to indicate that the logical volume has already been written.
HepPolyhedron * getBooleanSolidPolyhedron(G4VSolid *)
Create polyhedron for a boolean solid (recursive)
std::vector< std::string > * m_LVName
Modified (legal-character and unique) logical-volume name.
void describePhysicalVolume(G4VPhysicalVolume *)
Access next physical volume in the tree (recursive)
G4VPhysicalVolume * getTopVolume()
Return a pointer to the top volume.
static GeometryManager & getInstance()
Return a reference to the instance.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.