Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VSceneHandler.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27//
28//
29// John Allison 19th July 1996
30// Abstract interface class for graphics scenes.
31
32#include "G4VSceneHandler.hh"
33
34#include "G4ios.hh"
35#include <sstream>
36
37#include "G4VisManager.hh"
38#include "G4VGraphicsSystem.hh"
39#include "G4VViewer.hh"
40#include "G4VSolid.hh"
41#include "G4RotationMatrix.hh"
42#include "G4ThreeVector.hh"
43#include "G4VPhysicalVolume.hh"
44#include "G4Material.hh"
45#include "G4Polyline.hh"
46#include "G4Text.hh"
47#include "G4Circle.hh"
48#include "G4Square.hh"
49#include "G4Polymarker.hh"
50#include "G4Polyhedron.hh"
51#include "G4Visible.hh"
52#include "G4VisAttributes.hh"
53#include "G4VModel.hh"
55#include "G4Box.hh"
56#include "G4Cons.hh"
57#include "G4Orb.hh"
58#include "G4Para.hh"
59#include "G4Sphere.hh"
60#include "G4Torus.hh"
61#include "G4Trap.hh"
62#include "G4Trd.hh"
63#include "G4Tubs.hh"
64#include "G4Ellipsoid.hh"
65#include "G4Polycone.hh"
66#include "G4Polyhedra.hh"
67#include "G4Tet.hh"
68#include "G4DisplacedSolid.hh"
69#include "G4UnionSolid.hh"
71#include "G4SubtractionSolid.hh"
72#include "G4LogicalVolume.hh"
75#include "G4VTrajectory.hh"
76#include "G4VTrajectoryPoint.hh"
77#include "G4HitsModel.hh"
78#include "G4VHit.hh"
79#include "G4VDigi.hh"
80#include "G4ScoringManager.hh"
81#include "G4VScoringMesh.hh"
82#include "G4Mesh.hh"
84#include "G4QuickRand.hh"
85#include "G4StateManager.hh"
86#include "G4RunManager.hh"
88#include "G4Run.hh"
89#include "G4Transform3D.hh"
90#include "G4AttHolder.hh"
91#include "G4AttDef.hh"
92#include "G4SceneTreeItem.hh"
93#include "G4VVisCommand.hh"
95#include "G4SystemOfUnits.hh"
96
97#define G4warn G4cout
98
100 fSystem (system),
101 fSceneHandlerId (id),
105 fMarkForClearingTransientStore (true), // Ready for first
106 // ClearTransientStoreIfMarked(),
107 // e.g., at end of run (see
108 // G4VisManager.cc).
109 fReadyForTransients (true), // Only false while processing scene.
110 fProcessingSolid (false),
111 fProcessing2D (false),
117 fpScene = pVMan -> GetCurrentScene ();
118 if (name == "") {
119 std::ostringstream ost;
120 ost << fSystem.GetName () << '-' << fSceneHandlerId;
121 fName = ost.str();
122 }
123 else {
124 fName = name;
125 }
126 fTransientsDrawnThisEvent = pVMan->GetTransientsDrawnThisEvent();
127 fTransientsDrawnThisRun = pVMan->GetTransientsDrawnThisRun();
128}
129
132 while( ! fViewerList.empty() ) {
133 last = fViewerList.back();
134 fViewerList.pop_back();
135 delete last;
136 }
137}
138
140{
141 if (fpScene) {
142 return fpScene->GetExtent();
143 } else {
144 static const G4VisExtent defaultExtent = G4VisExtent();
145 return defaultExtent;
146 }
147}
148
149void G4VSceneHandler::PreAddSolid (const G4Transform3D& objectTransformation,
150 const G4VisAttributes& visAttribs) {
151 fObjectTransformation = objectTransformation;
152 fpVisAttribs = &visAttribs;
153 fProcessingSolid = true;
154}
155
164
166(const G4Transform3D& objectTransformation) {
167 //static G4int count = 0;
168 //G4cout << "G4VSceneHandler::BeginPrimitives: " << count++ << G4endl;
170 if (fNestingDepth > 1)
172 ("G4VSceneHandler::BeginPrimitives",
173 "visman0101", FatalException,
174 "Nesting detected. It is illegal to nest Begin/EndPrimitives.");
175 fObjectTransformation = objectTransformation;
176}
177
179 if (fNestingDepth <= 0)
180 G4Exception("G4VSceneHandler::EndPrimitives",
181 "visman0102", FatalException, "Nesting error.");
186 }
187}
188
190(const G4Transform3D& objectTransformation) {
192 if (fNestingDepth > 1)
194 ("G4VSceneHandler::BeginPrimitives2D",
195 "visman0103", FatalException,
196 "Nesting detected. It is illegal to nest Begin/EndPrimitives.");
197 fObjectTransformation = objectTransformation;
198 fProcessing2D = true;
199}
200
202 if (fNestingDepth <= 0)
203 G4Exception("G4VSceneHandler::EndPrimitives2D",
204 "visman0104", FatalException, "Nesting error.");
209 }
210 fProcessing2D = false;
211}
212
215
217{
218 fpModel = 0;
219}
220
222
224
225template <class T> void G4VSceneHandler::AddSolidT
226(const T& solid)
227{
228 // Get and check applicable vis attributes.
229 fpVisAttribs = fpViewer->GetApplicableVisAttributes(fpVisAttribs);
230 RequestPrimitives (solid);
231}
232
234(const T& solid)
235{
236 // Get and check applicable vis attributes.
237 fpVisAttribs = fpViewer->GetApplicableVisAttributes(fpVisAttribs);
238 // Draw with auxiliary edges unless otherwise specified.
239 if (!fpVisAttribs->IsForceAuxEdgeVisible()) {
240 // Create a vis atts object for the modified vis atts.
241 // It is static so that we may return a reliable pointer to it.
242 static G4VisAttributes visAttsWithAuxEdges;
243 // Initialise it with the current vis atts and reset the pointer.
244 visAttsWithAuxEdges = *fpVisAttribs;
245 // Force auxiliary edges visible.
246 visAttsWithAuxEdges.SetForceAuxEdgeVisible();
247 fpVisAttribs = &visAttsWithAuxEdges;
248 }
249 RequestPrimitives (solid);
250}
251
253 AddSolidT (box);
254 // If your graphics system is sophisticated enough to handle a
255 // particular solid shape as a primitive, in your derived class write a
256 // function to override this.
257 // Your function might look like this...
258 // void G4MySceneHandler::AddSolid (const G4Box& box) {
259 // Get and check applicable vis attributes.
260 // fpVisAttribs = fpViewer->GetApplicableVisAttributes(fpVisAttribs);
261 // Do not draw if not visible.
262 // if (fpVisAttribs->IsVisible()) {
263 // Get parameters of appropriate object, e.g.:
264 // G4double dx = box.GetXHalfLength ();
265 // G4double dy = box.GetYHalfLength ();
266 // G4double dz = box.GetZHalfLength ();
267 // ...
268 // and Draw or Store in your display List.
269}
270
272 AddSolidT (cons);
273}
274
278
280 AddSolidT (para);
281}
282
285}
286
289}
290
292 AddSolidT (trap);
293}
294
296 AddSolidT (trd);
297}
298
300 AddSolidT (tubs);
301}
302
303void G4VSceneHandler::AddSolid (const G4Ellipsoid& ellipsoid) {
304 AddSolidWithAuxiliaryEdges (ellipsoid);
305}
306
307void G4VSceneHandler::AddSolid (const G4Polycone& polycone) {
308 AddSolidT (polycone);
309}
310
311void G4VSceneHandler::AddSolid (const G4Polyhedra& polyhedra) {
312 AddSolidT (polyhedra);
313}
314
316 AddSolidT (tess);
317}
318
320 AddSolidT (solid);
321}
322
324 G4TrajectoriesModel* trajectoriesModel =
325 dynamic_cast<G4TrajectoriesModel*>(fpModel);
326 if (trajectoriesModel)
327 traj.DrawTrajectory();
328 else {
330 ("G4VSceneHandler::AddCompound(const G4VTrajectory&)",
331 "visman0105", FatalException, "Not a G4TrajectoriesModel.");
332 }
333}
334
336 // Cast away const because Draw is non-const!!!!
337 const_cast<G4VHit&>(hit).Draw();
338}
339
341 // Cast away const because Draw is non-const!!!!
342 const_cast<G4VDigi&>(digi).Draw();
343}
344
346 using MeshScoreMap = G4VScoringMesh::MeshScoreMap;
347 //G4cout << "AddCompound: hits: " << &hits << G4endl;
348 G4bool scoreMapHits = false;
350 if (scoringManager) {
351 std::size_t nMeshes = scoringManager->GetNumberOfMesh();
352 for (std::size_t iMesh = 0; iMesh < nMeshes; ++iMesh) {
353 G4VScoringMesh* mesh = scoringManager->GetMesh((G4int)iMesh);
354 if (mesh && mesh->IsActive()) {
355 MeshScoreMap scoreMap = mesh->GetScoreMap();
356 const G4String& mapNam = const_cast<G4THitsMap<G4double>&>(hits).GetName();
357 for(const auto& i : scoreMap) {
358 const G4String& scoreMapName = i.first;
359 if (scoreMapName == mapNam) {
360 G4DefaultLinearColorMap colorMap("G4VSceneHandlerColorMap");
361 scoreMapHits = true;
362 mesh->DrawMesh(scoreMapName, &colorMap);
363 }
364 }
365 }
366 }
367 }
368 if (scoreMapHits) {
369 static G4bool first = true;
370 if (first) {
371 first = false;
372 G4cout <<
373 "Scoring map drawn with default parameters."
374 "\n To get gMocren file for gMocren browser:"
375 "\n /vis/open gMocrenFile"
376 "\n /vis/viewer/flush"
377 "\n Many other options available with /score/draw... commands."
378 "\n You might want to \"/vis/viewer/set/autoRefresh false\"."
379 << G4endl;
380 }
381 } else { // Not score map hits. Just call DrawAllHits.
382 // Cast away const because DrawAllHits is non-const!!!!
383 const_cast<G4THitsMap<G4double>&>(hits).DrawAllHits();
384 }
385}
386
388 using MeshScoreMap = G4VScoringMesh::MeshScoreMap;
389 //G4cout << "AddCompound: hits: " << &hits << G4endl;
390 G4bool scoreMapHits = false;
392 if (scoringManager) {
393 std::size_t nMeshes = scoringManager->GetNumberOfMesh();
394 for (std::size_t iMesh = 0; iMesh < nMeshes; ++iMesh) {
395 G4VScoringMesh* mesh = scoringManager->GetMesh((G4int)iMesh);
396 if (mesh && mesh->IsActive()) {
397 MeshScoreMap scoreMap = mesh->GetScoreMap();
398 for(const auto& i : scoreMap) {
399 const G4String& scoreMapName = i.first;
400 const G4THitsMap<G4StatDouble>* foundHits = i.second;
401 if (foundHits == &hits) {
402 G4DefaultLinearColorMap colorMap("G4VSceneHandlerColorMap");
403 scoreMapHits = true;
404 mesh->DrawMesh(scoreMapName, &colorMap);
405 }
406 }
407 }
408 }
409 }
410 if (scoreMapHits) {
411 static G4bool first = true;
412 if (first) {
413 first = false;
414 G4cout <<
415 "Scoring map drawn with default parameters."
416 "\n To get gMocren file for gMocren browser:"
417 "\n /vis/open gMocrenFile"
418 "\n /vis/viewer/flush"
419 "\n Many other options available with /score/draw... commands."
420 "\n You might want to \"/vis/viewer/set/autoRefresh false\"."
421 << G4endl;
422 }
423 } else { // Not score map hits. Just call DrawAllHits.
424 // Cast away const because DrawAllHits is non-const!!!!
425 const_cast<G4THitsMap<G4StatDouble>&>(hits).DrawAllHits();
426 }
427}
428
430{
431 G4warn <<
432 "There has been an attempt to draw a mesh with option \""
433 << fpViewer->GetViewParameters().GetSpecialMeshRenderingOption()
434 << "\":\n" << mesh
435 << "but it is not of a recognised type or is not implemented"
436 "\nby the current graphics driver. Instead we draw its"
437 "\ncontainer \"" << mesh.GetContainerVolume()->GetName() << "\"."
438 << G4endl;
439 const auto& pv = mesh.GetContainerVolume();
440 const auto& lv = pv->GetLogicalVolume();
441 const auto& solid = lv->GetSolid();
442 const auto& transform = mesh.GetTransform();
443 // Make sure container is visible
444 G4VisAttributes tmpVisAtts; // Visible, white, not forced.
445 const auto& saveVisAtts = lv->GetVisAttributes();
446 if (saveVisAtts) {
447 tmpVisAtts = *saveVisAtts;
448 tmpVisAtts.SetVisibility(true);
449 auto colour = saveVisAtts->GetColour();
450 colour.SetAlpha(1.);
451 tmpVisAtts.SetColour(colour);
452 }
453 // Draw container
454 PreAddSolid(transform,tmpVisAtts);
455 solid->DescribeYourselfTo(*this);
456 PostAddSolid();
457 // Restore vis attributes
458 lv->SetVisAttributes(saveVisAtts);
459}
460
462 fViewerList.push_back (pViewer);
463}
464
466 switch (polymarker.GetMarkerType()) {
467 default:
469 {
470 G4Circle dot (polymarker);
471 dot.SetWorldSize (0.);
472 dot.SetScreenSize (0.1); // Very small circle.
473 for (const auto& iPoint : polymarker) {
474 dot.SetPosition (iPoint);
475 AddPrimitive (dot);
476 }
477 }
478 break;
480 {
481 G4Circle circle (polymarker); // Default circle
482 for (const auto& iPoint : polymarker) {
483 circle.SetPosition (iPoint);
484 AddPrimitive (circle);
485 }
486 }
487 break;
489 {
490 G4Square square (polymarker); // Default square
491 for (const auto& iPoint : polymarker) {
492 square.SetPosition (iPoint);
493 AddPrimitive (square);
494 }
495 }
496 break;
497 }
498}
499
501 fViewerList.remove(pViewer); // Does nothing if already removed
502 // And reset current viewer
503 auto visManager = G4VisManager::GetInstance();
504 visManager->SetCurrentViewer(nullptr);
505}
506
507
509 G4warn << "WARNING: Plotter not implemented for " << fSystem.GetName() << G4endl;
510 G4warn << " Open a plotter-aware graphics system or remove plotter with" << G4endl;
511 G4warn << " /vis/scene/removeModel Plotter" << G4endl;
512}
513
515 fpScene = pScene;
516 // Notify all viewers that a kernel visit is required.
518 for (i = fViewerList.begin(); i != fViewerList.end(); i++) {
519 (*i) -> SetNeedKernelVisit (true);
520 }
521}
522
524{
525 // Sometimes solids that have no substance get requested. They may
526 // be part of the geometry tree but have been "spirited away", for
527 // example by a Boolean subtraction in which the original volume
528 // is entirely inside the subtractor or an intersection in which
529 // the original volume is entirely outside the intersector.
530 // The problem is that the Boolean Processor still returns a
531 // polyhedron in these cases (IMHO it should not), so the
532 // workaround is to return before the damage is done.
533 // Algorithm by Evgueni Tcherniaev
534 auto pSolid = &solid;
535 auto pBooleanSolid = dynamic_cast<const G4BooleanSolid*>(pSolid);
536 if (pBooleanSolid) {
537 G4ThreeVector bmin, bmax;
538 pBooleanSolid->BoundingLimits(bmin, bmax);
539 G4bool isGood = false;
540 if (dynamic_cast<const G4SubtractionSolid*>(pBooleanSolid)) {
541 auto ptrB = pBooleanSolid->GetConstituentSolid(1);
542 for (G4int i=0; i<10; ++i) {
543 G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
544 G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
545 G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
546 if (ptrB->Inside(G4ThreeVector(x,y,bmin.z())) != kInside) { isGood = true; break; }
547 if (ptrB->Inside(G4ThreeVector(x,y,bmax.z())) != kInside) { isGood = true; break; }
548 if (ptrB->Inside(G4ThreeVector(x,bmin.y(),z)) != kInside) { isGood = true; break; }
549 if (ptrB->Inside(G4ThreeVector(x,bmax.y(),z)) != kInside) { isGood = true; break; }
550 if (ptrB->Inside(G4ThreeVector(bmin.x(),y,z)) != kInside) { isGood = true; break; }
551 if (ptrB->Inside(G4ThreeVector(bmax.x(),y,z)) != kInside) { isGood = true; break; }
552 }
553 } else if (dynamic_cast<const G4IntersectionSolid*>(pBooleanSolid)) {
554 auto ptrB = pBooleanSolid->GetConstituentSolid(1);
555 for (G4int i=0; i<10; ++i) {
556 G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
557 G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
558 G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
559 if (ptrB->Inside(G4ThreeVector(x,y,bmin.z())) == kInside) { isGood = true; break; }
560 if (ptrB->Inside(G4ThreeVector(x,y,bmax.z())) == kInside) { isGood = true; break; }
561 if (ptrB->Inside(G4ThreeVector(x,bmin.y(),z)) == kInside) { isGood = true; break; }
562 if (ptrB->Inside(G4ThreeVector(x,bmax.y(),z)) == kInside) { isGood = true; break; }
563 if (ptrB->Inside(G4ThreeVector(bmin.x(),y,z)) == kInside) { isGood = true; break; }
564 if (ptrB->Inside(G4ThreeVector(bmax.x(),y,z)) == kInside) { isGood = true; break; }
565 }
566 }
567 if (!isGood)
568 {
569 for (G4int i=0; i<10000; ++i) {
570 G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
571 G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
572 G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
573 if (pBooleanSolid->Inside(G4ThreeVector(x,y,z)) == kInside) { isGood = true; break; }
574 }
575 }
576 if (!isGood) return;
577 }
578
580 const G4ViewParameters& vp = fpViewer->GetViewParameters();
581
582 switch (style) {
583 default:
588 {
589 // Use polyhedral representation
591 G4Polyhedron* pPolyhedron = solid.GetPolyhedron ();
593 if (pPolyhedron) {
594 pPolyhedron -> SetVisAttributes (fpVisAttribs);
596 AddPrimitive (*pPolyhedron);
597 EndPrimitives ();
598 break;
599 } else { // Print warnings and drop through to cloud
601 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
602 if (pPVModel) {
603 auto problematicVolume = pPVModel->GetCurrentPV();
604 if (fProblematicVolumes.find(problematicVolume) == fProblematicVolumes.end()) {
605 fProblematicVolumes[problematicVolume] = "Null polyhedron";
606 if (verbosity >= G4VisManager::errors) {
607 G4warn <<
608 "ERROR: G4VSceneHandler::RequestPrimitives"
609 "\n Polyhedron not available for " << solid.GetName ();
610 G4warn << "\n Touchable path: " << pPVModel->GetFullPVPath();
611 static G4bool explanation = false;
612 if (!explanation) {
613 explanation = true;
614 G4warn <<
615 "\n This means it cannot be visualized in the usual way on most systems."
616 "\n 1) The solid may not have implemented the CreatePolyhedron method."
617 "\n 2) For Boolean solids, the BooleanProcessor, which attempts to create"
618 "\n the resultant polyhedron, may have failed."
619 "\n Try RayTracer. It uses Geant4's tracking algorithms instead.";
620 }
621 }
622 G4warn << "\n Drawing solid with cloud of points.";
623 G4warn << G4endl;
624 }
625 }
626 }
627 }
628 [[fallthrough]];
629
631 {
632 // Form solid out of cloud of dots on surface of solid
633 G4Polymarker dots;
634 // Note: OpenGL has a fast implementation of polymarker so it's better
635 // to build a polymarker rather than add a succession of circles.
636 // And anyway, in Qt, in the latter case each circle would be a scene-tree
637 // entry, something we would want to avoid.
640 G4int numberOfCloudPoints = GetNumberOfCloudPoints(fpVisAttribs);
641 if (numberOfCloudPoints <= 0) numberOfCloudPoints = vp.GetNumberOfCloudPoints();
642 for (G4int i = 0; i < numberOfCloudPoints; ++i) {
644 dots.push_back(p);
645 }
647 AddPrimitive(dots);
648 EndPrimitives ();
649 break;
650 }
651 }
652}
653
654//namespace {
655// void DrawExtent(const G4VModel* pModel)
656// {
657// // Show extent boxes - debug only, OGLSX only (OGLSQt problem?)
658// if (pModel->GetExtent() != G4VisExtent::GetNullExtent()) {
659// const auto& extent = pModel->GetExtent();
660// const auto& centre = extent.GetExtentCenter();
661// const auto& position = G4Translate3D(centre);
662// const auto& dx = (extent.GetXmax()-extent.GetXmin())/2.;
663// const auto& dy = (extent.GetYmax()-extent.GetYmin())/2.;
664// const auto& dz = (extent.GetZmax()-extent.GetZmin())/2.;
665// auto visAtts = G4VisAttributes();
666// visAtts.SetForceWireframe();
667// G4Box extentBox("Extent",dx,dy,dz);
668// G4VisManager::GetInstance()->Draw(extentBox,visAtts,position);
669// }
670// }
671//}
672
674{
675 // Assumes graphics database store has already been cleared if
676 // relevant for the particular scene handler.
677
678 if(!fpScene)
679 return;
680
681 if(fpScene->GetExtent() == G4VisExtent::GetNullExtent())
682 {
683 G4Exception("G4VSceneHandler::ProcessScene", "visman0106", JustWarning,
684 "The scene has no extent.");
685 }
686
688
689 if(!visManager->GetConcreteInstance())
690 return;
691
692 G4VisManager::Verbosity verbosity = visManager->GetVerbosity();
693
694 fReadyForTransients = false;
695
696 // Traverse geometry tree and send drawing primitives to window(s).
697
698 const std::vector<G4Scene::Model>& runDurationModelList =
699 fpScene->GetRunDurationModelList();
700
701 if(runDurationModelList.size()) {
702 if(verbosity >= G4VisManager::confirmations) {
703 G4cout << "Traversing scene data..." << G4endl;
704 static G4int first = true;
705 if (first) {
706 first = false;
707 G4cout <<
708 "(This could happen more than once - in fact, up to three times"
709 "\nper rebuild, for opaque, transparent and non-hidden markers.)"
710 << G4endl;
711 }
712 }
713
714 // Reset visibility of all objects to false - visible objects will then set to true
715 fpViewer->AccessSceneTree().ResetVisibility();
716
718
719 // Create modeling parameters from view parameters...
721
722 for(const auto& i : runDurationModelList) {
723 if(i.fActive) {
724 fpModel = i.fpModel;
725 fpModel->SetModelingParameters(pMP);
726
727 // Describe to the current scene handler
728 fpModel->DescribeYourselfTo(*this);
729
730 // To see the extents of each model represented as wireframe boxes,
731 // uncomment the next line and DrawExtent in namespace above.
732 // DrawExtent(fpModel);
733
734 // Enter models in the scene tree. Then for PV models, describe
735 // the model to the scene tree, i.e., enter all the touchables.
736 fpViewer->InsertModelInSceneTree(fpModel);
737 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
738 if (pPVModel) {
739 G4VViewer::SceneTreeScene sceneTreeScene(fpViewer, pPVModel);
740 fpModel->DescribeYourselfTo(sceneTreeScene);
741 const auto& maxDepth = pPVModel->GetMaxFullDepth();
742 if (fMaxGeometryDepth < maxDepth) {fMaxGeometryDepth = maxDepth;}
743 // This will be the maximum geometry depth for this scene handler
744 }
745
746 // Reset modeling parameters pointer
747 fpModel->SetModelingParameters(0);
748 }
749 }
750
751 fpModel = 0;
752 delete pMP;
753
754 EndModeling();
755 }
756
757 // Some printing
758 if(verbosity >= G4VisManager::parameters) {
759 for (const auto& model: runDurationModelList) {
760 if (model.fActive) {
761 auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(model.fpModel);
762 if (pvModel) {
763
764 G4cout << "Numbers of all touchables by depth \""
765 << pvModel->GetGlobalDescription() << "\":";
766 for (const auto& dn : pvModel->GetMapOfAllTouchables()) {
767 G4cout << "\n Depth " << dn.first << ": " << dn.second;
768 }
769 G4cout << "\n Total number of all touchables: "
770 << pvModel->GetTotalAllTouchables() << G4endl;
771
772 G4cout << "Numbers of touchables drawn by depth \""
773 << pvModel->GetGlobalDescription() << "\":";
774 for (const auto& dn : pvModel->GetMapOfDrawnTouchables()) {
775 G4cout << "\n Depth " << dn.first << ": " << dn.second;
776 }
777 G4cout << "\n Total number of drawn touchables: "
778 << pvModel->GetTotalDrawnTouchables() << G4endl;
779 }
780 }
781 }
782 }
783 if(verbosity >= G4VisManager::warnings) {
784 if (fProblematicVolumes.size() > 0) {
785 G4cout << "Problematic volumes:";
786 for (const auto& prob: fProblematicVolumes) {
787 G4cout << "\n " << prob.first->GetName() << " (" << prob.second << ')';
788 }
789 G4cout << G4endl;
790 }
791 }
792
794}
795
797{
798 // Assumes transient store has already been cleared
799
800 // Reset fMarkForClearingTransientStore. (Leaving
801 // fMarkForClearingTransientStore true causes problems with
802 // recomputing transients below.) Restore it again at end...
803 G4bool tmpMarkForClearingTransientStore = fMarkForClearingTransientStore;
805
807 G4VisManager::Verbosity verbosity = visManager->GetVerbosity();
808
809 fReadyForTransients = true;
810
811 // Refresh event from end-of-event model list.
812 // Allow only in Idle or GeomClosed state...
814 G4ApplicationState state = stateManager->GetCurrentState();
815 if(state == G4State_Idle || state == G4State_GeomClosed)
816 {
817 visManager->SetEventRefreshing(true);
818
819 if(visManager->GetRequestedEvent())
820 {
821 DrawEvent(visManager->GetRequestedEvent());
822 }
823 else
824 {
826 if(runManager)
827 {
828 const G4Run* run = runManager->GetCurrentRun();
829 // Draw a null event in order to pick up models for the scene tree even before a run
830 if (run == nullptr) DrawEvent(0);
831 const std::vector<const G4Event*>* events =
832 run ? run->GetEventVector() : 0;
833 std::size_t nKeptEvents = 0;
834 if(events)
835 nKeptEvents = events->size();
836 if(nKeptEvents)
837 {
838 if(fpScene->GetRefreshAtEndOfEvent())
839 {
840 if(verbosity >= G4VisManager::confirmations)
841 {
842 G4cout << "Refreshing event..." << G4endl;
843 }
844 const G4Event* event = 0;
845 if(events && events->size())
846 event = events->back();
847 if(event)
848 DrawEvent(event);
849 }
850 else
851 { // Accumulating events.
852
853 if(verbosity >= G4VisManager::confirmations)
854 {
855 G4cout << "Refreshing events in run..." << G4endl;
856 }
857 for(const auto& event : *events)
858 {
859 if(event)
860 DrawEvent(event);
861 }
862
863 if(!fpScene->GetRefreshAtEndOfRun())
864 {
865 if(verbosity >= G4VisManager::warnings)
866 {
867 G4warn << "WARNING: Cannot refresh events accumulated over more"
868 "\n than one runs. Refreshed just the last run."
869 << G4endl;
870 }
871 }
872 }
873 }
874 }
875 }
876 visManager->SetEventRefreshing(false);
877 }
878
879 // Refresh end-of-run model list.
880 // Allow only in Idle or GeomClosed state...
881 if(state == G4State_Idle || state == G4State_GeomClosed)
882 {
884 }
885
886 fMarkForClearingTransientStore = tmpMarkForClearingTransientStore;
887}
888
890{
891 if(!fpViewer->ReadyToDraw()) return;
892 const std::vector<G4Scene::Model>& EOEModelList =
893 fpScene -> GetEndOfEventModelList ();
894 std::size_t nModels = EOEModelList.size();
895 if (nModels) {
897 pMP->SetEvent(event);
898 for (std::size_t i = 0; i < nModels; ++i) {
899 if (EOEModelList[i].fActive) {
900 fpModel = EOEModelList[i].fpModel;
901 fpModel -> SetModelingParameters(pMP);
902
903 // Describe to the current scene handler
904 fpModel -> DescribeYourselfTo (*this);
905
906 // Enter models in the scene tree
907 fpViewer->InsertModelInSceneTree(fpModel);
908
909 // Reset modeling parameters pointer
910 fpModel -> SetModelingParameters(0);
911 }
912 }
913 fpModel = 0;
914 delete pMP;
915 }
916}
917
919{
920 if(!fpViewer->ReadyToDraw()) return;
921 const std::vector<G4Scene::Model>& EORModelList =
922 fpScene -> GetEndOfRunModelList ();
923 std::size_t nModels = EORModelList.size();
924 if (nModels) {
926 pMP->SetEvent(0);
927 for (std::size_t i = 0; i < nModels; ++i) {
928 if (EORModelList[i].fActive) {
929 fpModel = EORModelList[i].fpModel;
930 fpModel -> SetModelingParameters(pMP);
931
932 // Describe to the current scene handler
933 fpModel -> DescribeYourselfTo (*this);
934
935 // Enter models in the scene tree
936 fpViewer->InsertModelInSceneTree(fpModel);
937
938 // Reset modeling parameters pointer
939 fpModel -> SetModelingParameters(0);
940 }
941 }
942 fpModel = 0;
943 delete pMP;
944 }
945}
946
948{
949 // Create modeling parameters from View Parameters...
950 if (!fpViewer) return NULL;
951
952 const G4ViewParameters& vp = fpViewer -> GetViewParameters ();
953
954 // Convert drawing styles...
955 G4ModelingParameters::DrawingStyle modelDrawingStyle =
957 switch (vp.GetDrawingStyle ()) {
958 default:
960 modelDrawingStyle = G4ModelingParameters::wf;
961 break;
963 modelDrawingStyle = G4ModelingParameters::hlr;
964 break;
966 modelDrawingStyle = G4ModelingParameters::hsr;
967 break;
969 modelDrawingStyle = G4ModelingParameters::hlhsr;
970 break;
972 modelDrawingStyle = G4ModelingParameters::cloud;
973 break;
974 }
975
976 // Decide if covered daughters are really to be culled...
977 G4bool reallyCullCovered =
978 vp.IsCullingCovered() // Culling daughters depends also on...
979 && !vp.IsSection () // Sections (DCUT) not requested.
980 && !vp.IsCutaway () // Cutaways not requested.
981 ;
982
983 G4ModelingParameters* pModelingParams = new G4ModelingParameters
985 modelDrawingStyle,
986 vp.IsCulling (),
987 vp.IsCullingInvisible (),
988 vp.IsDensityCulling (),
989 vp.GetVisibleDensity (),
990 reallyCullCovered,
991 vp.GetNoOfSides ()
992 );
993
994 pModelingParams->SetNumberOfCloudPoints(vp.GetNumberOfCloudPoints());
995 pModelingParams->SetWarning
997
998 pModelingParams->SetCBDAlgorithmNumber(vp.GetCBDAlgorithmNumber());
999 pModelingParams->SetCBDParameters(vp.GetCBDParameters());
1000
1001 pModelingParams->SetExplodeFactor(vp.GetExplodeFactor());
1002 pModelingParams->SetExplodeCentre(vp.GetExplodeCentre());
1003
1004 pModelingParams->SetSectionSolid(CreateSectionSolid());
1005
1010 }
1011
1012 pModelingParams->SetCutawaySolid(CreateCutawaySolid());
1013 // The polyhedron objects are deleted in the modeling parameters destructor.
1014
1016
1017 pModelingParams->SetTimeParameters(vp.GetTimeParameters());
1018
1019 pModelingParams->SetSpecialMeshRendering(vp.IsSpecialMeshRendering());
1020 pModelingParams->SetSpecialMeshVolumes(vp.GetSpecialMeshVolumes());
1021
1022 pModelingParams->SetTransparencyByDepth(vp.GetTransparencyByDepth());
1024
1025 return pModelingParams;
1026}
1027
1029{
1030 G4DisplacedSolid* sectioner = 0;
1031
1032 const G4ViewParameters& vp = fpViewer->GetViewParameters();
1033 if (vp.IsSection () ) {
1034
1035 G4double radius = fpScene->GetExtent().GetExtentRadius();
1036 G4double safe = radius + fpScene->GetExtent().GetExtentCentre().mag();
1037 G4VSolid* sectionBox =
1038 new G4Box("_sectioner", safe, safe, 1.e-5 * radius); // Thin in z-plane...
1039
1040 const G4Plane3D& sp = vp.GetSectionPlane ();
1041 G4ThreeVector normal = sp.normal();
1042 G4Transform3D requiredTransform = G4Translate3D(normal*(-sp.d())) *
1043 G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
1044
1045 sectioner = new G4DisplacedSolid
1046 ("_displaced_sectioning_box", sectionBox, requiredTransform);
1047 }
1048
1049 return sectioner;
1050}
1051
1053{
1054 const auto& vp = fpViewer->GetViewParameters();
1055 const auto& nPlanes = vp.GetCutawayPlanes().size();
1056
1057 if (nPlanes == 0) return nullptr;
1058
1059 std::vector<G4DisplacedSolid*> cutaway_solids;
1060
1061 G4double radius = fpScene->GetExtent().GetExtentRadius();
1062 G4double safe = radius + fpScene->GetExtent().GetExtentCentre().mag();
1063 auto cutawayBox = new G4Box("_cutaway_box", safe, safe, safe);
1064
1065 // if (vp.GetCutawayMode() == G4ViewParameters::cutawayUnion) we need a subtractor that is
1066 // the intersection of displaced cutaway boxes, displaced so that a subtraction keeps the
1067 // positive values a*x+b*y+c*z+d>0, so we have to invert the normal. This may appear
1068 // "back to front". The parameter "cutawayUnion" means "the union of volumes
1069 // that remain *after* cutaway", because we base the concept on OpenGL cutaway planes and make
1070 // a "union" of what remains by superimposing up to 3 passes - see G4OpenGLViewer::SetView
1071 // and G4OpenGLImmediate/StoredViewer::ProcessView. So we have to create a subtractor
1072 // that is the intersection of inverted cutaway planes.
1073
1074 // Conversely, if (vp.GetCutawayMode() == G4ViewParameters::cutawayIntersection) we have to
1075 // create an intersector that is the intersector of intersected non-inverted cutaway planes.
1076
1077 for (size_t plane_no = 0; plane_no < nPlanes; plane_no++)
1078 {
1079 const G4Plane3D& sp = vp.GetCutawayPlanes()[plane_no];
1080 G4Transform3D requiredTransform;
1081 G4ThreeVector normal;
1082 switch (vp.GetCutawayMode()) {
1084 normal = -sp.normal(); // Invert normal - we want a subtractor
1085 requiredTransform = G4Translate3D(normal*(safe + sp.d())) *
1086 G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
1087 break;
1089 normal = sp.normal();
1090 requiredTransform = G4Translate3D(normal*(safe - sp.d())) *
1091 G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
1092 break;
1093 }
1094 cutaway_solids.push_back
1095 (new G4DisplacedSolid("_displaced_cutaway_box", cutawayBox, requiredTransform));
1096 }
1097
1098 if (nPlanes == 1) return (G4DisplacedSolid*) cutaway_solids[0];
1099
1100 G4IntersectionSolid *union2 = nullptr, *union3 = nullptr;
1101 G4IntersectionSolid *intersection2 = nullptr, *intersection3 = nullptr;
1102 switch (vp.GetCutawayMode()) {
1103
1105 // Here we make a subtractor of intersections of inverted cutaway planes.
1106 union2 = new G4IntersectionSolid("_union_2", cutaway_solids[0], cutaway_solids[1]);
1107 if (nPlanes == 2) return (G4DisplacedSolid*)union2;
1108 else if (nPlanes == 3) {
1109 union3 = new G4IntersectionSolid("_union_3", union2, cutaway_solids[2]);
1110 return (G4DisplacedSolid*)union3;
1111 }
1112 break;
1113
1115 // And here we make an intersector of intersections of non-inverted cutaway planes.
1116 intersection2
1117 = new G4IntersectionSolid("_intersection_2", cutaway_solids[0], cutaway_solids[1]);
1118 if (nPlanes == 2) return (G4DisplacedSolid*)intersection2;
1119 else if (nPlanes == 3) {
1120 intersection3
1121 = new G4IntersectionSolid("_intersection_3", intersection2, cutaway_solids[2]);
1122 return (G4DisplacedSolid*)intersection3;
1123 }
1124 break;
1125 }
1126
1127 G4Exception("G4VSceneHandler::CreateCutawaySolid", "visman0107", JustWarning,
1128 "Not programmed for more than 3 cutaway planes");
1129 return nullptr;
1130}
1131
1133{
1134 // Load G4Atts from G4VisAttributes, if any...
1135 const G4VisAttributes* va = visible.GetVisAttributes();
1136 if (va) {
1137 const std::map<G4String,G4AttDef>* vaDefs =
1138 va->GetAttDefs();
1139 if (vaDefs) {
1140 holder->AddAtts(visible.GetVisAttributes()->CreateAttValues(), vaDefs);
1141 }
1142 }
1143
1144 G4PhysicalVolumeModel* pPVModel =
1145 dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
1146 if (pPVModel) {
1147 // Load G4Atts from G4PhysicalVolumeModel...
1148 const std::map<G4String,G4AttDef>* pvDefs = pPVModel->GetAttDefs();
1149 if (pvDefs) {
1150 holder->AddAtts(pPVModel->CreateCurrentAttValues(), pvDefs);
1151 }
1152 }
1153
1154 G4TrajectoriesModel* trajModel = dynamic_cast<G4TrajectoriesModel*>(fpModel);
1155 if (trajModel) {
1156 // Load G4Atts from trajectory model...
1157 const std::map<G4String,G4AttDef>* trajModelDefs = trajModel->GetAttDefs();
1158 if (trajModelDefs) {
1159 holder->AddAtts(trajModel->CreateCurrentAttValues(), trajModelDefs);
1160 }
1161 // Load G4Atts from trajectory...
1162 const G4VTrajectory* traj = trajModel->GetCurrentTrajectory();
1163 if (traj) {
1164 const std::map<G4String,G4AttDef>* trajDefs = traj->GetAttDefs();
1165 if (trajDefs) {
1166 holder->AddAtts(traj->CreateAttValues(), trajDefs);
1167 }
1168 G4int nPoints = traj->GetPointEntries();
1169 for (G4int i = 0; i < nPoints; ++i) {
1170 G4VTrajectoryPoint* trajPoint = traj->GetPoint(i);
1171 if (trajPoint) {
1172 const std::map<G4String,G4AttDef>* pointDefs = trajPoint->GetAttDefs();
1173 if (pointDefs) {
1174 holder->AddAtts(trajPoint->CreateAttValues(), pointDefs);
1175 }
1176 }
1177 }
1178 }
1179 }
1180
1181 G4HitsModel* hitsModel = dynamic_cast<G4HitsModel*>(fpModel);
1182 if (hitsModel) {
1183 // Load G4Atts from hit...
1184 const G4VHit* hit = hitsModel->GetCurrentHit();
1185 const std::map<G4String,G4AttDef>* hitsDefs = hit->GetAttDefs();
1186 if (hitsDefs) {
1187 holder->AddAtts(hit->CreateAttValues(), hitsDefs);
1188 }
1189 }
1190}
1191
1193 fpVisAttribs = fpViewer->GetApplicableVisAttributes(fpVisAttribs);
1194 const G4Colour& colour = fpVisAttribs -> GetColour ();
1195 return colour;
1196}
1197
1199 auto pVA = visible.GetVisAttributes();
1200 if (!pVA) pVA = fpViewer->GetViewParameters().GetDefaultVisAttributes();
1201 return pVA->GetColour();
1202}
1203
1205 auto pVA = text.GetVisAttributes();
1206 if (!pVA) pVA = fpViewer->GetViewParameters().GetDefaultTextVisAttributes();
1207 return pVA->GetColour();
1208}
1209
1211{
1212 G4double lineWidth = pVisAttribs->GetLineWidth();
1213 if (lineWidth < 1.) lineWidth = 1.;
1214 lineWidth *= fpViewer -> GetViewParameters().GetGlobalLineWidthScale();
1215 if (lineWidth < 1.) lineWidth = 1.;
1216 return lineWidth;
1217}
1218
1220(const G4VisAttributes* pVisAttribs) {
1221 // Drawing style is normally determined by the view parameters, but
1222 // it can be overriddden by the ForceDrawingStyle flag in the vis
1223 // attributes.
1224 const G4ViewParameters& vp = fpViewer->GetViewParameters();
1225 const G4ViewParameters::DrawingStyle viewerStyle = vp.GetDrawingStyle();
1226 G4ViewParameters::DrawingStyle resultantStyle = viewerStyle;
1227 if (pVisAttribs -> IsForceDrawingStyle ()) {
1229 pVisAttribs -> GetForcedDrawingStyle ();
1230 // This is complicated because if hidden line and surface removal
1231 // has been requested we wish to preserve this sometimes.
1232 switch (forcedStyle) {
1234 switch (viewerStyle) {
1235 case (G4ViewParameters::hlr):
1236 resultantStyle = G4ViewParameters::hlhsr;
1237 break;
1239 resultantStyle = G4ViewParameters::hsr;
1240 break;
1242 resultantStyle = G4ViewParameters::hsr;
1243 break;
1245 case (G4ViewParameters::hsr):
1246 break;
1247 }
1248 break;
1250 resultantStyle = G4ViewParameters::cloud;
1251 break;
1253 default:
1254 // But if forced style is wireframe, do it, because one of its
1255 // main uses is in displaying the consituent solids of a Boolean
1256 // solid and their surfaces overlap with the resulting Booean
1257 // solid, making a mess if hlr is specified.
1258 resultantStyle = G4ViewParameters::wireframe;
1259 break;
1260 }
1261 }
1262 return resultantStyle;
1263}
1264
1266(const G4VisAttributes* pVisAttribs) const {
1267 // Returns no of cloud points from current view parameters, unless the user
1268 // has forced through the vis attributes, thereby over-riding the
1269 // current view parameter.
1270 G4int numberOfCloudPoints = fpViewer->GetViewParameters().GetNumberOfCloudPoints();
1271 if (pVisAttribs -> IsForceDrawingStyle() &&
1272 pVisAttribs -> GetForcedDrawingStyle() == G4VisAttributes::cloud &&
1273 pVisAttribs -> GetForcedNumberOfCloudPoints() > 0) {
1274 numberOfCloudPoints = pVisAttribs -> GetForcedNumberOfCloudPoints();
1275 }
1276 return numberOfCloudPoints;
1277}
1278
1280 G4bool isAuxEdgeVisible = fpViewer->GetViewParameters().IsAuxEdgeVisible ();
1281 if (pVisAttribs -> IsForceAuxEdgeVisible()) {
1282 isAuxEdgeVisible = pVisAttribs->IsForcedAuxEdgeVisible();
1283 }
1284 return isAuxEdgeVisible;
1285}
1286
1288(const G4VMarker& marker,
1289 G4VSceneHandler::MarkerSizeType& markerSizeType)
1290{
1291 // Deal with G4Polymarker::dots
1292 const auto& vp = fpViewer->GetViewParameters();
1293 try {
1294 const auto& polymarker = dynamic_cast<const G4Polymarker&>(marker);
1295 if (polymarker.GetMarkerType() == G4Polymarker::dots) {
1296 return vp.GetDotsSize();
1297 }
1298 }
1299 catch (const std::bad_cast&) {} // Continue
1300
1301 // Other markers
1302 G4bool userSpecified = marker.GetWorldSize() || marker.GetScreenSize();
1303 const G4VMarker& defaultMarker =
1304 fpViewer -> GetViewParameters().GetDefaultMarker();
1305 G4double size = userSpecified ?
1306 marker.GetWorldSize() : defaultMarker.GetWorldSize();
1307 if (size) {
1308 // Draw in world coordinates.
1309 markerSizeType = world;
1310 }
1311 else {
1312 size = userSpecified ?
1313 marker.GetScreenSize() : defaultMarker.GetScreenSize();
1314 // Draw in screen coordinates.
1315 markerSizeType = screen;
1316 }
1317 size *= fpViewer -> GetViewParameters().GetGlobalMarkerScale();
1318 if (markerSizeType == screen && size < 1.) size = 1.;
1319 return size;
1320}
1321
1323{
1324 // No. of sides (lines segments per circle) is normally determined
1325 // by the view parameters, but it can be overriddden by the
1326 // ForceLineSegmentsPerCircle in the vis attributes.
1327 G4int lineSegmentsPerCircle = fpViewer->GetViewParameters().GetNoOfSides();
1328 if (pVisAttribs) {
1329 if (pVisAttribs->IsForceLineSegmentsPerCircle())
1330 lineSegmentsPerCircle = pVisAttribs->GetForcedLineSegmentsPerCircle();
1331 if (lineSegmentsPerCircle < pVisAttribs->GetMinLineSegmentsPerCircle()) {
1332 lineSegmentsPerCircle = pVisAttribs->GetMinLineSegmentsPerCircle();
1333 G4warn <<
1334 "G4VSceneHandler::GetNoOfSides: attempt to set the"
1335 "\nnumber of line segments per circle < " << lineSegmentsPerCircle
1336 << "; forced to " << pVisAttribs->GetMinLineSegmentsPerCircle() << G4endl;
1337 }
1338 }
1339 return lineSegmentsPerCircle;
1340}
1341
1342std::ostream& operator << (std::ostream& os, const G4VSceneHandler& sh) {
1343
1344 os << "Scene handler " << sh.fName << " has "
1345 << sh.fViewerList.size () << " viewer(s):";
1346 for (const auto* i : sh.fViewerList) {
1347 os << "\n " << *i;
1348 }
1349
1350 if (sh.fpScene) {
1351 os << "\n " << *sh.fpScene;
1352 }
1353 else {
1354 os << "\n This scene handler currently has no scene.";
1355 }
1356
1357 return os;
1358}
1359
1360void G4VSceneHandler::PseudoSceneFor3DRectMeshPositions::AddSolid(const G4Box&) {
1361 if (fpPVModel->GetCurrentDepth() == fpMesh->GetMeshDepth()) { // Leaf-level cells only
1362 const auto& material = fpPVModel->GetCurrentLV()->GetMaterial();
1363 const auto& name = material? material->GetName(): fpMesh->GetContainerVolume()->GetName();
1364 const auto& pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
1365 // Get position in world coordinates
1366 // As a parameterisation the box is transformed by the current transformation
1367 // and its centre, originally by definition at (0,0,0), is now translated.
1369 fPositionByMaterial.insert(std::make_pair(material,position));
1370 if (fNameAndVisAttsByMaterial.find(material) == fNameAndVisAttsByMaterial.end())
1371 // Store name and vis attributes of first encounter with this material
1372 fNameAndVisAttsByMaterial[material] = NameAndVisAtts(name,*pVisAtts);
1373 }
1374}
1375
1376void G4VSceneHandler::PseudoSceneForTetVertices::AddSolid(const G4VSolid& solid) {
1377 if (fpPVModel->GetCurrentDepth() == fpMesh->GetMeshDepth()) { // Leaf-level cells only
1378 // Need to know it's a tet !!!! or implement G4VSceneHandler::AddSolid (const G4Tet&) !!!!
1379 try {
1380 const auto& tet = dynamic_cast<const G4Tet&>(solid);
1381 const auto& material = fpPVModel->GetCurrentLV()->GetMaterial();
1382 const auto& name = material? material->GetName(): fpMesh->GetContainerVolume()->GetName();
1383 const auto& pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
1384 // Transform into world coordinates if necessary
1385 if (fpCurrentObjectTransformation->xx() == 1. &&
1386 fpCurrentObjectTransformation->yy() == 1. &&
1387 fpCurrentObjectTransformation->zz() == 1.) { // No transformation necessary
1388 const auto& vertices = tet.GetVertices();
1389 fVerticesByMaterial.insert(std::make_pair(material,vertices));
1390 } else {
1391 auto vertices = tet.GetVertices();
1392 for (auto&& vertex: vertices) {
1393 vertex = G4Point3D(vertex).transform(*fpCurrentObjectTransformation);
1394 }
1395 fVerticesByMaterial.insert(std::make_pair(material,vertices));
1396 }
1397 if (fNameAndVisAttsByMaterial.find(material) == fNameAndVisAttsByMaterial.end())
1398 // Store name and vis attributes of first encounter with this material
1399 fNameAndVisAttsByMaterial[material] = NameAndVisAtts(name,*pVisAtts);
1400 }
1401 catch (const std::bad_cast&) {
1403 ed << "Called for a mesh that is not a tetrahedron mesh: " << solid.GetName();
1404 G4Exception("PseudoSceneForTetVertices","visman0108",JustWarning,ed);
1405 }
1406 }
1407}
1408
1410// Standard way of special mesh rendering.
1411// MySceneHandler::AddCompound(const G4Mesh& mesh) may use this if
1412// appropriate or implement its own special mesh rendereing.
1413{
1414 G4bool implemented = false;
1415 switch (mesh.GetMeshType()) {
1416 case G4Mesh::rectangle: [[fallthrough]];
1418 switch (fpViewer->GetViewParameters().GetSpecialMeshRenderingOption()) {
1420 [[fallthrough]];
1422 Draw3DRectMeshAsDots(mesh); // Rectangular 3-deep mesh as dots
1423 implemented = true;
1424 break;
1426 Draw3DRectMeshAsSurfaces(mesh); // Rectangular 3-deep mesh as surfaces
1427 implemented = true;
1428 break;
1429 }
1430 break;
1432 switch (fpViewer->GetViewParameters().GetSpecialMeshRenderingOption()) {
1434 [[fallthrough]];
1436 DrawTetMeshAsDots(mesh); // Tetrahedron mesh as dots
1437 implemented = true;
1438 break;
1440 DrawTetMeshAsSurfaces(mesh); // Tetrahedron mesh as surfaces
1441 implemented = true;
1442 break;
1443 }
1444 break;
1445 case G4Mesh::cylinder: [[fallthrough]];
1446 case G4Mesh::sphere: [[fallthrough]];
1447 case G4Mesh::invalid: break;
1448 }
1449 if (implemented) {
1450 // Draw container if not marked invisible...
1451 auto container = mesh.GetContainerVolume();
1452 auto containerLogical = container->GetLogicalVolume();
1453 auto containerVisAtts = containerLogical->GetVisAttributes();
1454 if (containerVisAtts == nullptr || containerVisAtts->IsVisible()) {
1455 auto solid = containerLogical->GetSolid();
1456 auto polyhedron = solid->GetPolyhedron();
1457 // Always draw as wireframe
1458 G4VisAttributes tmpVisAtts;
1459 if (containerVisAtts != nullptr) tmpVisAtts = *containerVisAtts;
1460 tmpVisAtts.SetForceWireframe();
1461 polyhedron->SetVisAttributes(tmpVisAtts);
1463 AddPrimitive(*polyhedron);
1464 EndPrimitives();
1465 }
1466 } else {
1467 // Invoke base class function
1469 }
1470 return;
1471}
1472
1474// For a rectangular 3-D mesh, draw as coloured dots by colour and material,
1475// one dot randomly placed in each visible mesh cell.
1476{
1477 // Check
1478 if (mesh.GetMeshType() != G4Mesh::rectangle &&
1481 ed << "Called with a mesh that is not rectangular:" << mesh;
1482 G4Exception("G4VSceneHandler::Draw3DRectMeshAsDots","visman0108",JustWarning,ed);
1483 return;
1484 }
1485
1486 static G4bool firstPrint = true;
1487 const auto& verbosity = G4VisManager::GetVerbosity();
1488 G4bool print = firstPrint && verbosity >= G4VisManager::errors;
1489 if (print) {
1490 G4cout
1491 << "Special case drawing of 3D rectangular G4VNestedParameterisation as dots:"
1492 << '\n' << mesh
1493 << G4endl;
1494 }
1495
1496 const auto& container = mesh.GetContainerVolume();
1497
1498 // This map is static so that once filled it stays filled.
1499 static std::map<G4String,std::map<const G4Material*,G4Polymarker>> dotsByMaterialAndMesh;
1500 auto& dotsByMaterial = dotsByMaterialAndMesh[mesh.GetContainerVolume()->GetName()];
1501
1502 // Fill map if not already filled
1503 if (dotsByMaterial.empty()) {
1504
1505 // Get positions and material one cell at a time (using PseudoSceneFor3DRectMeshPositions).
1506 // The pseudo scene allows a "private" descent into the parameterisation.
1507 // Instantiate a temporary G4PhysicalVolumeModel
1509 tmpMP.SetCulling(true); // This avoids drawing transparent...
1510 tmpMP.SetCullingInvisible(true); // ... or invisble volumes.
1511 const G4bool useFullExtent = true; // To avoid calculating the extent
1512 G4PhysicalVolumeModel tmpPVModel
1513 (container,
1515 G4Transform3D(), // so that positions are in local coordinates
1516 &tmpMP,
1517 useFullExtent);
1518 // Accumulate information in temporary maps by material
1519 std::multimap<const G4Material*,const G4ThreeVector> positionByMaterial;
1520 std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
1521 // Instantiate the pseudo scene
1523 (&tmpPVModel,&mesh,positionByMaterial,nameAndVisAttsByMaterial);
1524 // Make private descent into the parameterisation
1525 tmpPVModel.DescribeYourselfTo(pseudoScene);
1526 // Now we have a map of positions by material.
1527 // Also a map of name and colour by material.
1528
1529 const auto& prms = mesh.GetThreeDRectParameters();
1530 const auto& halfX = prms.fHalfX;
1531 const auto& halfY = prms.fHalfY;
1532 const auto& halfZ = prms.fHalfZ;
1533
1534 // Fill the permanent (static) map of dots by material
1535 G4int nDotsTotal = 0;
1536 for (const auto& entry: nameAndVisAttsByMaterial) {
1537 G4int nDots = 0;
1538 const auto& material = entry.first;
1539 const auto& nameAndVisAtts = nameAndVisAttsByMaterial[material];
1540 const auto& name = nameAndVisAtts.fName;
1541 const auto& visAtts = nameAndVisAtts.fVisAtts;
1542 G4Polymarker dots;
1543 dots.SetInfo(name);
1544 dots.SetVisAttributes(visAtts);
1546 // Enter empty polymarker into the map
1547 dotsByMaterial[material] = dots;
1548 // Now fill it in situ
1549 auto& dotsInMap = dotsByMaterial[material];
1550 const auto& range = positionByMaterial.equal_range(material);
1551 for (auto posByMat = range.first; posByMat != range.second; ++posByMat) {
1552 dotsInMap.push_back(GetPointInBox(posByMat->second, halfX, halfY, halfZ));
1553 ++nDots;
1554 }
1555
1556 if (print) {
1557 G4cout
1558 << std::setw(30) << std::left << name.substr(0,30) << std::right
1559 << ": " << std::setw(7) << nDots << " dots"
1560 << ": colour " << std::fixed << std::setprecision(2)
1561 << visAtts.GetColour() << std::defaultfloat
1562 << G4endl;
1563 }
1564
1565 nDotsTotal += nDots;
1566 }
1567
1568 if (print) {
1569 G4cout << "Total number of dots: " << nDotsTotal << G4endl;
1570 }
1571 }
1572
1573 // Some subsequent expressions apply only to G4PhysicalVolumeModel
1574 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
1575
1576 G4String parameterisationName;
1577 if (pPVModel) {
1578 parameterisationName = pPVModel->GetFullPVPath().back().GetPhysicalVolume()->GetName();
1579 }
1580
1581 // Draw the dots by material
1582 // Ensure they are "hidden", i.e., use the z-buffer as non-marker primitives do
1583 auto keepVP = fpViewer->GetViewParameters();
1584 auto vp = fpViewer->GetViewParameters();
1585 vp.SetMarkerHidden();
1586 fpViewer->SetViewParameters(vp);
1587 // Now we transform to world coordinates
1589 for (const auto& entry: dotsByMaterial) {
1590 const auto& dots = entry.second;
1591 // The current "leaf" node in the PVPath is the parameterisation. Here it has
1592 // been converted into polymarkers by material. So...temporarily...change
1593 // its name to that of the material (whose name has been stored in Info)
1594 // so that its appearance in the scene tree of, e.g., G4OpenGLQtViewer, has
1595 // an appropriate name and its visibility and colour may be changed.
1596 if (pPVModel) {
1597 const auto& fullPVPath = pPVModel->GetFullPVPath();
1598 auto leafPV = fullPVPath.back().GetPhysicalVolume();
1599 leafPV->SetName(dots.GetInfo());
1600 }
1601 // Add dots to the scene
1602 AddPrimitive(dots);
1603 }
1604 EndPrimitives ();
1605 // Restore view parameters
1606 fpViewer->SetViewParameters(keepVP);
1607 // Restore parameterisation name
1608 if (pPVModel) {
1609 pPVModel->GetFullPVPath().back().GetPhysicalVolume()->SetName(parameterisationName);
1610 }
1611
1612 firstPrint = false;
1613 return;
1614}
1615
1617// For a rectangular 3-D mesh, draw as surfaces by colour and material
1618// with inner shared faces removed.
1619{
1620 // Check
1621 if (mesh.GetMeshType() != G4Mesh::rectangle &&
1624 ed << "Called with a mesh that is not rectangular:" << mesh;
1625 G4Exception("G4VSceneHandler::Draw3DRectMeshAsSurfaces","visman0108",JustWarning,ed);
1626 return;
1627 }
1628
1629 static G4bool firstPrint = true;
1630 const auto& verbosity = G4VisManager::GetVerbosity();
1631 G4bool print = firstPrint && verbosity >= G4VisManager::errors;
1632 if (print) {
1633 G4cout
1634 << "Special case drawing of 3D rectangular G4VNestedParameterisation as surfaces:"
1635 << '\n' << mesh
1636 << G4endl;
1637 }
1638
1639 const auto& container = mesh.GetContainerVolume();
1640
1641 // This map is static so that once filled it stays filled.
1642 static std::map<G4String,std::map<const G4Material*,G4Polyhedron>> boxesByMaterialAndMesh;
1643 auto& boxesByMaterial = boxesByMaterialAndMesh[mesh.GetContainerVolume()->GetName()];
1644
1645 // Fill map if not already filled
1646 if (boxesByMaterial.empty()) {
1647
1648 // Get positions and material one cell at a time (using PseudoSceneFor3DRectMeshPositions).
1649 // The pseudo scene allows a "private" descent into the parameterisation.
1650 // Instantiate a temporary G4PhysicalVolumeModel
1652 tmpMP.SetCulling(true); // This avoids drawing transparent...
1653 tmpMP.SetCullingInvisible(true); // ... or invisble volumes.
1654 const G4bool useFullExtent = true; // To avoid calculating the extent
1655 G4PhysicalVolumeModel tmpPVModel
1656 (container,
1658 G4Transform3D(), // so that positions are in local coordinates
1659 &tmpMP,
1660 useFullExtent);
1661 // Accumulate information in temporary maps by material
1662 std::multimap<const G4Material*,const G4ThreeVector> positionByMaterial;
1663 std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
1664 // Instantiate the pseudo scene
1666 (&tmpPVModel,&mesh,positionByMaterial,nameAndVisAttsByMaterial);
1667 // Make private descent into the parameterisation
1668 tmpPVModel.DescribeYourselfTo(pseudoScene);
1669 // Now we have a map of positions by material.
1670 // Also a map of name and colour by material.
1671
1672 const auto& prms = mesh.GetThreeDRectParameters();
1673 const auto& sizeX = 2.*prms.fHalfX;
1674 const auto& sizeY = 2.*prms.fHalfY;
1675 const auto& sizeZ = 2.*prms.fHalfZ;
1676
1677 // Fill the permanent (static) map of boxes by material
1678 G4int nBoxesTotal = 0, nFacetsTotal = 0;
1679 for (const auto& entry: nameAndVisAttsByMaterial) {
1680 G4int nBoxes = 0;
1681 const auto& material = entry.first;
1682 const auto& nameAndVisAtts = nameAndVisAttsByMaterial[material];
1683 const auto& name = nameAndVisAtts.fName;
1684 const auto& visAtts = nameAndVisAtts.fVisAtts;
1685 // Transfer positions into a vector ready for creating polyhedral surface
1686 std::vector<G4ThreeVector> positionsForPolyhedron;
1687 const auto& range = positionByMaterial.equal_range(material);
1688 for (auto posByMat = range.first; posByMat != range.second; ++posByMat) {
1689 const auto& position = posByMat->second;
1690 positionsForPolyhedron.push_back(position);
1691 ++nBoxes;
1692 }
1693 // The polyhedron will be in local coordinates
1694 // Add an empty place-holder to the map and get a reference to it
1695 auto& polyhedron = boxesByMaterial[material];
1696 // Replace with the desired polyhedron (uses efficient "move assignment")
1697 polyhedron = G4PolyhedronBoxMesh(sizeX,sizeY,sizeZ,positionsForPolyhedron);
1698 polyhedron.SetVisAttributes(visAtts);
1699 polyhedron.SetInfo(name);
1700
1701 if (print) {
1702 G4cout
1703 << std::setw(30) << std::left << name.substr(0,30) << std::right
1704 << ": " << std::setw(7) << nBoxes << " boxes"
1705 << " (" << std::setw(7) << 6*nBoxes << " faces)"
1706 << ": reduced to " << std::setw(7) << polyhedron.GetNoFacets() << " facets ("
1707 << std::setw(2) << std::fixed << std::setprecision(2) << 100*polyhedron.GetNoFacets()/(6*nBoxes)
1708 << "%): colour " << std::fixed << std::setprecision(2)
1709 << visAtts.GetColour() << std::defaultfloat
1710 << G4endl;
1711 }
1712
1713 nBoxesTotal += nBoxes;
1714 nFacetsTotal += polyhedron.GetNoFacets();
1715 }
1716
1717 if (print) {
1718 G4cout << "Total number of boxes: " << nBoxesTotal << " (" << 6*nBoxesTotal << " faces)"
1719 << ": reduced to " << nFacetsTotal << " facets ("
1720 << std::setw(2) << std::fixed << std::setprecision(2) << 100*nFacetsTotal/(6*nBoxesTotal) << "%)"
1721 << G4endl;
1722 }
1723 }
1724
1725 // Some subsequent expressions apply only to G4PhysicalVolumeModel
1726 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
1727
1728 G4String parameterisationName;
1729 if (pPVModel) {
1730 parameterisationName = pPVModel->GetFullPVPath().back().GetPhysicalVolume()->GetName();
1731 }
1732
1733 // Draw the boxes by material
1734 // Now we transform to world coordinates
1736 for (const auto& entry: boxesByMaterial) {
1737 const auto& poly = entry.second;
1738 // The current "leaf" node in the PVPath is the parameterisation. Here it has
1739 // been converted into polyhedra by material. So...temporarily...change
1740 // its name to that of the material (whose name has been stored in Info)
1741 // so that its appearance in the scene tree of, e.g., G4OpenGLQtViewer, has
1742 // an appropriate name and its visibility and colour may be changed.
1743 if (pPVModel) {
1744 const auto& fullPVPath = pPVModel->GetFullPVPath();
1745 auto leafPV = fullPVPath.back().GetPhysicalVolume();
1746 leafPV->SetName(poly.GetInfo());
1747 }
1748 AddPrimitive(poly);
1749 }
1750 EndPrimitives ();
1751 // Restore parameterisation name
1752 if (pPVModel) {
1753 pPVModel->GetFullPVPath().back().GetPhysicalVolume()->SetName(parameterisationName);
1754 }
1755
1756 firstPrint = false;
1757 return;
1758}
1759
1761// For a tetrahedron mesh, draw as coloured dots by colour and material,
1762// one dot randomly placed in each visible mesh cell.
1763{
1764 // Check
1765 if (mesh.GetMeshType() != G4Mesh::tetrahedron) {
1767 ed << "Called with mesh that is not a tetrahedron mesh:" << mesh;
1768 G4Exception("G4VSceneHandler::DrawTetMeshAsDots","visman0108",JustWarning,ed);
1769 return;
1770 }
1771
1772 static G4bool firstPrint = true;
1773 const auto& verbosity = G4VisManager::GetVerbosity();
1774 G4bool print = firstPrint && verbosity >= G4VisManager::errors;
1775
1776 if (print) {
1777 G4cout
1778 << "Special case drawing of tetrahedron mesh as dots"
1779 << '\n' << mesh
1780 << G4endl;
1781 }
1782
1783 const auto& container = mesh.GetContainerVolume();
1784
1785 // This map is static so that once filled it stays filled.
1786 static std::map<G4String,std::map<const G4Material*,G4Polymarker>> dotsByMaterialAndMesh;
1787 auto& dotsByMaterial = dotsByMaterialAndMesh[mesh.GetContainerVolume()->GetName()];
1788
1789 // Fill map if not already filled
1790 if (dotsByMaterial.empty()) {
1791
1792 // Get vertices and colour one cell at a time (using PseudoSceneForTetVertices).
1793 // The pseudo scene allows a "private" descent into the parameterisation.
1794 // Instantiate a temporary G4PhysicalVolumeModel
1796 tmpMP.SetCulling(true); // This avoids drawing transparent...
1797 tmpMP.SetCullingInvisible(true); // ... or invisble volumes.
1798 const G4bool useFullExtent = true; // To avoid calculating the extent
1799 G4PhysicalVolumeModel tmpPVModel
1800 (container,
1802 G4Transform3D(), // so that positions are in local coordinates
1803 &tmpMP,
1804 useFullExtent);
1805 // Accumulate information in temporary maps by material
1806 std::multimap<const G4Material*,std::vector<G4ThreeVector>> verticesByMaterial;
1807 std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
1808 // Instantiate a pseudo scene
1809 PseudoSceneForTetVertices pseudoScene
1810 (&tmpPVModel,&mesh,verticesByMaterial,nameAndVisAttsByMaterial);
1811 // Make private descent into the parameterisation
1812 tmpPVModel.DescribeYourselfTo(pseudoScene);
1813 // Now we have a map of vertices by material.
1814 // Also a map of name and colour by material.
1815
1816 // Fill the permanent (static) map of dots by material
1817 G4int nDotsTotal = 0;
1818 for (const auto& entry: nameAndVisAttsByMaterial) {
1819 G4int nDots = 0;
1820 const auto& material = entry.first;
1821 const auto& nameAndVisAtts = nameAndVisAttsByMaterial[material];
1822 const auto& name = nameAndVisAtts.fName;
1823 const auto& visAtts = nameAndVisAtts.fVisAtts;
1824 G4Polymarker dots;
1825 dots.SetVisAttributes(visAtts);
1827 dots.SetInfo(name);
1828 // Enter empty polymarker into the map
1829 dotsByMaterial[material] = dots;
1830 // Now fill it in situ
1831 auto& dotsInMap = dotsByMaterial[material];
1832 const auto& range = verticesByMaterial.equal_range(material);
1833 for (auto vByMat = range.first; vByMat != range.second; ++vByMat) {
1834 dotsInMap.push_back(GetPointInTet(vByMat->second));
1835 ++nDots;
1836 }
1837
1838 if (print) {
1839 G4cout
1840 << std::setw(30) << std::left << name.substr(0,30) << std::right
1841 << ": " << std::setw(7) << nDots << " dots"
1842 << ": colour " << std::fixed << std::setprecision(2)
1843 << visAtts.GetColour() << std::defaultfloat
1844 << G4endl;
1845 }
1846
1847 nDotsTotal += nDots;
1848 }
1849
1850 if (print) {
1851 G4cout << "Total number of dots: " << nDotsTotal << G4endl;
1852 }
1853 }
1854
1855 // Some subsequent expressions apply only to G4PhysicalVolumeModel
1856 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
1857
1858 G4String parameterisationName;
1859 if (pPVModel) {
1860 parameterisationName = pPVModel->GetFullPVPath().back().GetPhysicalVolume()->GetName();
1861 }
1862
1863 // Draw the dots by material
1864 // Ensure they are "hidden", i.e., use the z-buffer as non-marker primitives do
1865 auto keepVP = fpViewer->GetViewParameters();
1866 auto vp = fpViewer->GetViewParameters();
1867 vp.SetMarkerHidden();
1868 fpViewer->SetViewParameters(vp);
1869
1870 // Now we transform to world coordinates
1872 for (const auto& entry: dotsByMaterial) {
1873 const auto& dots = entry.second;
1874 // The current "leaf" node in the PVPath is the parameterisation. Here it has
1875 // been converted into polymarkers by material. So...temporarily...change
1876 // its name to that of the material (whose name has been stored in Info)
1877 // so that its appearance in the scene tree of, e.g., G4OpenGLQtViewer, has
1878 // an appropriate name and its visibility and colour may be changed.
1879 if (pPVModel) {
1880 const auto& fullPVPath = pPVModel->GetFullPVPath();
1881 auto leafPV = fullPVPath.back().GetPhysicalVolume();
1882 leafPV->SetName(dots.GetInfo());
1883 }
1884 AddPrimitive(dots);
1885 }
1886 EndPrimitives ();
1887
1888 // Restore view parameters
1889 fpViewer->SetViewParameters(keepVP);
1890 // Restore parameterisation name
1891 if (pPVModel) {
1892 pPVModel->GetFullPVPath().back().GetPhysicalVolume()->SetName(parameterisationName);
1893 }
1894
1895 firstPrint = false;
1896 return;
1897}
1898
1900// For a tetrahedron mesh, draw as surfaces by colour and material
1901// with inner shared faces removed.
1902{
1903 // Check
1904 if (mesh.GetMeshType() != G4Mesh::tetrahedron) {
1906 ed << "Called with mesh that is not a tetrahedron mesh:" << mesh;
1907 G4Exception("G4VSceneHandler::DrawTetMeshAsSurfaces","visman0108",JustWarning,ed);
1908 return;
1909 }
1910
1911 static G4bool firstPrint = true;
1912 const auto& verbosity = G4VisManager::GetVerbosity();
1913 G4bool print = firstPrint && verbosity >= G4VisManager::errors;
1914
1915 if (print) {
1916 G4cout
1917 << "Special case drawing of tetrahedron mesh as surfaces"
1918 << '\n' << mesh
1919 << G4endl;
1920 }
1921
1922 // This map is static so that once filled it stays filled.
1923 static std::map<G4String,std::map<const G4Material*,G4Polyhedron>> surfacesByMaterialAndMesh;
1924 auto& surfacesByMaterial = surfacesByMaterialAndMesh[mesh.GetContainerVolume()->GetName()];
1925
1926 // Fill map if not already filled
1927 if (surfacesByMaterial.empty()) {
1928
1929 // Get vertices and colour one cell at a time (using PseudoSceneForTetVertices).
1930 // The pseudo scene allows a "private" descent into the parameterisation.
1931 // Instantiate a temporary G4PhysicalVolumeModel
1933 tmpMP.SetCulling(true); // This avoids drawing transparent...
1934 tmpMP.SetCullingInvisible(true); // ... or invisble volumes.
1935 const G4bool useFullExtent = true; // To avoid calculating the extent
1936 G4PhysicalVolumeModel tmpPVModel
1937 (mesh.GetContainerVolume(),
1939 G4Transform3D(), // so that positions are in local coordinates
1940 &tmpMP,
1941 useFullExtent);
1942 // Accumulate information in temporary maps by material
1943 std::multimap<const G4Material*,std::vector<G4ThreeVector>> verticesByMaterial;
1944 std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
1945 // Instantiate a pseudo scene
1946 PseudoSceneForTetVertices pseudoScene
1947 (&tmpPVModel,&mesh,verticesByMaterial,nameAndVisAttsByMaterial);
1948 // Make private descent into the parameterisation
1949 tmpPVModel.DescribeYourselfTo(pseudoScene);
1950 // Now we have a map of vertices by material.
1951 // Also a map of name and colour by material.
1952
1953 // Fill the permanent (static) map of surfaces by material
1954 G4int nTetsTotal = 0, nFacetsTotal = 0;
1955 for (const auto& entry: nameAndVisAttsByMaterial) {
1956 G4int nTets = 0;
1957 const auto& material = entry.first;
1958 const auto& nameAndVisAtts = nameAndVisAttsByMaterial[material];
1959 const auto& name = nameAndVisAtts.fName;
1960 const auto& visAtts = nameAndVisAtts.fVisAtts;
1961 // Transfer vertices into a vector ready for creating polyhedral surface
1962 std::vector<G4ThreeVector> verticesForPolyhedron;
1963 const auto& range = verticesByMaterial.equal_range(material);
1964 for (auto vByMat = range.first; vByMat != range.second; ++vByMat) {
1965 const std::vector<G4ThreeVector>& vertices = vByMat->second;
1966 for (const auto& vertex: vertices)
1967 verticesForPolyhedron.push_back(vertex);
1968 ++nTets;
1969 }
1970 // The polyhedron will be in local coordinates
1971 // Add an empty place-holder to the map and get a reference to it
1972 auto& polyhedron = surfacesByMaterial[material];
1973 // Replace with the desired polyhedron (uses efficient "move assignment")
1974 polyhedron = G4PolyhedronTetMesh(verticesForPolyhedron);
1975 polyhedron.SetVisAttributes(visAtts);
1976 polyhedron.SetInfo(name);
1977
1978 if (print) {
1979 G4cout
1980 << std::setw(30) << std::left << name.substr(0,30) << std::right
1981 << ": " << std::setw(7) << nTets << " tetrahedra"
1982 << " (" << std::setw(7) << 4*nTets << " faces)"
1983 << ": reduced to " << std::setw(7) << polyhedron.GetNoFacets() << " facets ("
1984 << std::setw(2) << std::fixed << std::setprecision(2) << 100*polyhedron.GetNoFacets()/(4*nTets)
1985 << "%): colour " << std::fixed << std::setprecision(2)
1986 << visAtts.GetColour() << std::defaultfloat
1987 << G4endl;
1988 }
1989
1990 nTetsTotal += nTets;
1991 nFacetsTotal += polyhedron.GetNoFacets();
1992 }
1993
1994 if (print) {
1995 G4cout << "Total number of tetrahedra: " << nTetsTotal << " (" << 4*nTetsTotal << " faces)"
1996 << ": reduced to " << nFacetsTotal << " facets ("
1997 << std::setw(2) << std::fixed << std::setprecision(2) << 100*nFacetsTotal/(4*nTetsTotal) << "%)"
1998 << G4endl;
1999 }
2000 }
2001
2002 // Some subsequent expressions apply only to G4PhysicalVolumeModel
2003 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
2004
2005 G4String parameterisationName;
2006 if (pPVModel) {
2007 parameterisationName = pPVModel->GetFullPVPath().back().GetPhysicalVolume()->GetName();
2008 }
2009
2010 // Draw the surfaces by material
2011 // Now we transform to world coordinates
2013 for (const auto& entry: surfacesByMaterial) {
2014 const auto& poly = entry.second;
2015 // The current "leaf" node in the PVPath is the parameterisation. Here it has
2016 // been converted into polyhedra by material. So...temporarily...change
2017 // its name to that of the material (whose name has been stored in Info)
2018 // so that its appearance in the scene tree of, e.g., G4OpenGLQtViewer, has
2019 // an appropriate name and its visibility and colour may be changed.
2020 if (pPVModel) {
2021 const auto& fullPVPath = pPVModel->GetFullPVPath();
2022 auto leafPV = fullPVPath.back().GetPhysicalVolume();
2023 leafPV->SetName(poly.GetInfo());
2024 }
2025 AddPrimitive(poly);
2026 }
2027 EndPrimitives ();
2028
2029 // Restore parameterisation name
2030 if (pPVModel) {
2031 pPVModel->GetFullPVPath().back().GetPhysicalVolume()->SetName(parameterisationName);
2032 }
2033
2034 firstPrint = false;
2035 return;
2036}
2037
2040 G4double halfX,
2041 G4double halfY,
2042 G4double halfZ) const
2043{
2044 G4double x = pos.getX() + (2.*G4QuickRand() - 1.)*halfX;
2045 G4double y = pos.getY() + (2.*G4QuickRand() - 1.)*halfY;
2046 G4double z = pos.getZ() + (2.*G4QuickRand() - 1.)*halfZ;
2047 return G4ThreeVector(x, y, z);
2048}
2049
2051G4VSceneHandler::GetPointInTet(const std::vector<G4ThreeVector>& vertices) const
2052{
2053 G4double p = G4QuickRand();
2054 G4double q = G4QuickRand();
2055 G4double r = G4QuickRand();
2056 if (p + q > 1.)
2057 {
2058 p = 1. - p;
2059 q = 1. - q;
2060 }
2061 if (q + r > 1.)
2062 {
2063 G4double tmp = r;
2064 r = 1. - p - q;
2065 q = 1. - tmp;
2066 }
2067 else if (p + q + r > 1.)
2068 {
2069 G4double tmp = r;
2070 r = p + q + r - 1.;
2071 p = 1. - q - tmp;
2072 }
2073 G4double a = 1. - p - q - r;
2074 return vertices[0]*a + vertices[1]*p + vertices[2]*q + vertices[3]*r;
2075}
G4ApplicationState
@ G4State_Idle
@ G4State_GeomClosed
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
HepGeom::Plane3D< G4double > G4Plane3D
Definition G4Plane3D.hh:34
HepGeom::Point3D< G4double > G4Point3D
Definition G4Point3D.hh:34
G4double G4QuickRand(uint32_t seed=0)
#define G4warn
Definition G4Scene.cc:41
CLHEP::Hep3Vector G4ThreeVector
HepGeom::Transform3D G4Transform3D
HepGeom::Translate3D G4Translate3D
HepGeom::Rotate3D G4Rotate3D
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
std::ostream & operator<<(std::ostream &os, const G4VSceneHandler &sh)
std::vector< G4VViewer * >::iterator G4ViewerListIterator
void print(G4double elem)
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector orthogonal() const
double x() const
double y() const
void AddAtts(const std::vector< G4AttValue > *values, const std::map< G4String, G4AttDef > *defs)
G4BooleanSolid is the base class for solids created by Boolean operations between other solids.
G4Box is a cuboid of given half lengths dx,dy,dz. The Box is centred on the origin with sides paralle...
Definition G4Box.hh:58
G4Cons is, in the general case, a Phi segment of a cone, with half-length fDz, inner and outer radii ...
Definition G4Cons.hh:85
G4DisplacedSolid is a solid that has been shifted from its original frame of reference to a new one....
G4Ellipsoid is an ellipsoidal solid, optionally cut at a given Z.
const G4VHit * GetCurrentHit() const
G4IntersectionSolid is a solid describing the Boolean intersection of two solids.
G4VSolid * GetSolid() const
const G4VisAttributes * GetVisAttributes() const
G4Material * GetMaterial() const
MeshType GetMeshType() const
Definition G4Mesh.hh:75
G4VPhysicalVolume * GetContainerVolume() const
Definition G4Mesh.hh:73
const G4Transform3D & GetTransform() const
Definition G4Mesh.hh:77
@ invalid
Definition G4Mesh.hh:52
@ rectangle
Definition G4Mesh.hh:53
@ nested3DRectangular
Definition G4Mesh.hh:54
@ sphere
Definition G4Mesh.hh:56
@ cylinder
Definition G4Mesh.hh:55
@ tetrahedron
Definition G4Mesh.hh:57
const ThreeDRectangleParameters & GetThreeDRectParameters() const
Definition G4Mesh.hh:78
G4int GetMeshDepth() const
Definition G4Mesh.hh:76
void SetCBDParameters(const std::vector< G4double > &)
void SetWarning(G4bool)
void SetTransparencyByDepth(G4double)
void SetNumberOfCloudPoints(G4int)
void SetCBDAlgorithmNumber(G4int)
void SetExplodeFactor(G4double explodeFactor)
void SetVisAttributesModifiers(const std::vector< VisAttributesModifier > &)
void SetExplodeCentre(const G4Point3D &explodeCentre)
void SetCutawayMode(CutawayMode)
void SetCutawaySolid(G4DisplacedSolid *pCutawaySolid)
void SetTimeParameters(const TimeParameters &)
void SetCulling(G4bool)
void SetSectionSolid(G4DisplacedSolid *pSectionSolid)
void SetEvent(const G4Event *pEvent)
void SetCullingInvisible(G4bool)
void SetSpecialMeshVolumes(const std::vector< PVNameCopyNo > &)
void SetSpecialMeshRendering(G4bool)
void SetTransparencyByDepthOption(G4int)
G4Orb represents a full sphere.
Definition G4Orb.hh:59
G4Para represents a parallelepiped, essentially a box with half lengths dx,dy,dz 'skewed' so that the...
Definition G4Para.hh:86
std::vector< G4AttValue > * CreateCurrentAttValues() const
void DescribeYourselfTo(G4VGraphicsScene &)
G4LogicalVolume * GetCurrentLV() const
const std::map< G4String, G4AttDef > * GetAttDefs() const
G4Polycone represents a composed closed shape (PCON) made of cones and cylinders, along the Z axis wi...
Definition G4Polycone.hh:82
G4Polyhedra represents a composed closed polyhedra (PGON) made of planar sizes along the Z axis,...
void SetMarkerType(MarkerType)
MarkerType GetMarkerType() const
const G4Transform3D * fpCurrentObjectTransformation
static G4RunManager * GetMasterRunManager()
const G4Run * GetCurrentRun() const
Definition G4Run.hh:48
std::vector< const G4Event * > * GetEventVector() const
Definition G4Run.hh:100
G4VScoringMesh * GetMesh(G4int i) const
std::size_t GetNumberOfMesh() const
static G4ScoringManager * GetScoringManagerIfExist()
G4Sphere is, in the general case, a section of a spherical shell, between specified phi and theta ang...
Definition G4Sphere.hh:89
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()
G4SubtractionSolid is a solid describing the Boolean subtraction of two solids.
G4TessellatedSolid is a solid defined by a number of facets. It is important that the supplied facets...
G4Torus represents a torus or torus segment with curved sides parallel to the z-axis....
Definition G4Torus.hh:102
const G4VTrajectory * GetCurrentTrajectory() const
std::vector< G4AttValue > * CreateCurrentAttValues() const
const std::map< G4String, G4AttDef > * GetAttDefs() const
G4Trap is a general trapezoid: the faces perpendicular to the Z planes are trapezia,...
Definition G4Trap.hh:116
G4Trd is a trapezoid with the X and Y dimensions varying along Z.
Definition G4Trd.hh:65
G4Tubs is a tube or tube segment with curved sides parallel to the Z-axis. The tube has a specified h...
Definition G4Tubs.hh:85
virtual std::vector< G4AttValue > * CreateAttValues() const
Definition G4VHit.hh:71
virtual const std::map< G4String, G4AttDef > * GetAttDefs() const
Definition G4VHit.hh:64
G4double GetScreenSize() const
void SetScreenSize(G4double)
void SetWorldSize(G4double)
void SetPosition(const G4Point3D &)
G4double GetWorldSize() const
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
virtual void BeginModeling()
G4int GetNumberOfCloudPoints(const G4VisAttributes *) const
G4int GetNoOfSides(const G4VisAttributes *)
void DrawTetMeshAsSurfaces(const G4Mesh &)
virtual void ClearTransientStore()
void LoadAtts(const G4Visible &, G4AttHolder *)
void DrawEvent(const G4Event *)
G4ModelingParameters * CreateModelingParameters()
const G4Colour & GetTextColour(const G4Text &)
const G4Colour & GetColour()
void Draw3DRectMeshAsDots(const G4Mesh &)
void AddSolidT(const T &solid)
G4Transform3D fObjectTransformation
virtual void EndPrimitives()
G4bool fTransientsDrawnThisEvent
void AddSolidWithAuxiliaryEdges(const T &solid)
virtual G4DisplacedSolid * CreateSectionSolid()
friend class G4VViewer
virtual void EndModeling()
std::map< G4VPhysicalVolume *, G4String > fProblematicVolumes
const G4int fSceneHandlerId
virtual const G4VisExtent & GetExtent() const
G4ViewerList fViewerList
virtual void ProcessScene()
G4double GetMarkerSize(const G4VMarker &, MarkerSizeType &)
virtual void ProcessTransients()
virtual void PreAddSolid(const G4Transform3D &objectTransformation, const G4VisAttributes &)
G4VSceneHandler(G4VGraphicsSystem &system, G4int id, const G4String &name="")
virtual void PostAddSolid()
const G4String & GetName() const
void AddViewerToList(G4VViewer *pView)
virtual void EndPrimitives2D()
virtual void SetScene(G4Scene *)
G4bool fMarkForClearingTransientStore
const G4VisAttributes * fpVisAttribs
virtual void BeginPrimitives2D(const G4Transform3D &objectTransformation=G4Transform3D())
G4ThreeVector GetPointInBox(const G4ThreeVector &pos, G4double halfX, G4double halfY, G4double halfZ) const
virtual void RequestPrimitives(const G4VSolid &solid)
G4ViewParameters::DrawingStyle GetDrawingStyle(const G4VisAttributes *)
void RemoveViewerFromList(G4VViewer *pView)
virtual G4DisplacedSolid * CreateCutawaySolid()
void DrawTetMeshAsDots(const G4Mesh &)
virtual void BeginPrimitives(const G4Transform3D &objectTransformation=G4Transform3D())
G4double GetLineWidth(const G4VisAttributes *)
G4ThreeVector GetPointInTet(const std::vector< G4ThreeVector > &vertices) const
G4VGraphicsSystem & fSystem
virtual void AddSolid(const G4Box &)
virtual void ClearStore()
void Draw3DRectMeshAsSurfaces(const G4Mesh &)
virtual void AddCompound(const G4VTrajectory &)
virtual ~G4VSceneHandler()
virtual void AddPrimitive(const G4Polyline &)=0
G4bool GetAuxEdgeVisible(const G4VisAttributes *)
void StandardSpecialMeshRendering(const G4Mesh &)
G4bool IsActive() const
std::map< G4String, RunScore * > MeshScoreMap
void DrawMesh(const G4String &psName, G4VScoreColorMap *colorMap, G4int axflg=111)
MeshScoreMap GetScoreMap() const
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
Definition G4VSolid.hh:80
G4String GetName() const
virtual G4ThreeVector GetPointOnSurface() const
Definition G4VSolid.cc:151
virtual G4Polyhedron * GetPolyhedron() const
Definition G4VSolid.cc:731
virtual std::vector< G4AttValue > * CreateAttValues() const
virtual const std::map< G4String, G4AttDef > * GetAttDefs() const
virtual G4VTrajectoryPoint * GetPoint(G4int i) const =0
virtual G4int GetPointEntries() const =0
virtual std::vector< G4AttValue > * CreateAttValues() const
virtual void DrawTrajectory() const
virtual const std::map< G4String, G4AttDef > * GetAttDefs() const
static G4VVisManager * GetConcreteInstance()
const std::vector< G4ModelingParameters::VisAttributesModifier > & GetVisAttributesModifiers() const
G4int GetNoOfSides() const
G4bool IsSpecialMeshRendering() const
CutawayMode GetCutawayMode() const
G4double GetExplodeFactor() const
const G4ModelingParameters::TimeParameters & GetTimeParameters() const
G4int GetNumberOfCloudPoints() const
G4bool IsCutaway() const
G4bool IsSection() const
G4bool IsCulling() const
const std::vector< G4double > & GetCBDParameters() const
G4int GetCBDAlgorithmNumber() const
const std::vector< G4ModelingParameters::PVNameCopyNo > & GetSpecialMeshVolumes() const
G4int GetTransparencyByDepthOption() const
G4bool IsCullingInvisible() const
const G4VisAttributes * GetDefaultVisAttributes() const
G4bool IsDensityCulling() const
G4double GetVisibleDensity() const
const G4Point3D & GetExplodeCentre() const
G4bool IsCullingCovered() const
const G4Plane3D & GetSectionPlane() const
DrawingStyle GetDrawingStyle() const
G4double GetTransparencyByDepth() const
const std::map< G4String, G4AttDef > * GetAttDefs() const
G4bool IsForceLineSegmentsPerCircle() const
G4double GetLineWidth() const
void SetColour(const G4Colour &)
void SetVisibility(G4bool=true)
void SetForceAuxEdgeVisible(G4bool=true)
G4int GetForcedLineSegmentsPerCircle() const
void SetForceWireframe(G4bool=true)
const std::vector< G4AttValue > * CreateAttValues() const
G4bool IsForcedAuxEdgeVisible() const
static G4int GetMinLineSegmentsPerCircle()
static const G4VisExtent & GetNullExtent()
void SetEventRefreshing(G4bool)
G4bool GetTransientsDrawnThisEvent() const
G4bool GetTransientsDrawnThisRun() const
static Verbosity GetVerbosity()
const G4Event * GetRequestedEvent() const
static G4VisManager * GetInstance()
friend class G4VSceneHandler
void SetVisAttributes(const G4VisAttributes *)
Definition G4Visible.cc:108
const G4VisAttributes * GetVisAttributes() const
virtual void SetInfo(const G4String &info)
CLHEP::Hep3Vector getTranslation() const
static void SetNumberOfRotationSteps(G4int n)
static void ResetNumberOfRotationSteps()
@ kInside
Definition geomdefs.hh:70
const char * name(G4int ptype)