Import Geant4 11.2.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2023-06-30 09:09:57 +02:00
parent aef78ca386
commit dd1f179cda
3780 changed files with 212808 additions and 142780 deletions
@@ -68,6 +68,7 @@
#include "G4DisplacedSolid.hh"
#include "G4UnionSolid.hh"
#include "G4IntersectionSolid.hh"
#include "G4SubtractionSolid.hh"
#include "G4LogicalVolume.hh"
#include "G4PhysicalVolumeModel.hh"
#include "G4ModelingParameters.hh"
@@ -88,6 +89,7 @@
#include "G4Transform3D.hh"
#include "G4AttHolder.hh"
#include "G4AttDef.hh"
#include "G4SceneTreeItem.hh"
#include "G4VVisCommand.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
@@ -526,29 +528,58 @@ void G4VSceneHandler::RequestPrimitives (const G4VSolid& solid)
{
// Sometimes solids that have no substance get requested. They may
// be part of the geometry tree but have been "spirited away", for
// example by a Boolean subtraction in wich the original volume
// is entirely inside the subtractor.
// example by a Boolean subtraction in which the original volume
// is entirely inside the subtractor or an intersection in which
// the original volume is entirely outside the intersector.
// The problem is that the Boolean Processor still returns a
// polyhedron in these cases (IMHO it should not), so the
// workaround is to return before the damage is done.
// Algorithm by Evgueni Tcherniaev
auto pSolid = &solid;
auto pBooleanSolid = dynamic_cast<const G4BooleanSolid*>(pSolid);
if (pBooleanSolid) {
G4ThreeVector bmin, bmax;
pBooleanSolid->BoundingLimits(bmin, bmax);
G4bool isGood = false;
for (G4int i=0; i<100000; ++i) {
G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
if (pBooleanSolid->Inside(G4ThreeVector(x,y,z)) == kInside) {
isGood = true;
break;
if (dynamic_cast<const G4SubtractionSolid*>(pBooleanSolid)) {
auto ptrB = pBooleanSolid->GetConstituentSolid(1);
for (G4int i=0; i<10; ++i) {
G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
if (ptrB->Inside(G4ThreeVector(x,y,bmin.z())) != kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,y,bmax.z())) != kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,bmin.y(),z)) != kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,bmax.y(),z)) != kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(bmin.x(),y,z)) != kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(bmax.x(),y,z)) != kInside) { isGood = true; break; }
}
} else if (dynamic_cast<const G4IntersectionSolid*>(pBooleanSolid)) {
auto ptrB = pBooleanSolid->GetConstituentSolid(1);
for (G4int i=0; i<10; ++i) {
G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
if (ptrB->Inside(G4ThreeVector(x,y,bmin.z())) == kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,y,bmax.z())) == kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,bmin.y(),z)) == kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(x,bmax.y(),z)) == kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(bmin.x(),y,z)) == kInside) { isGood = true; break; }
if (ptrB->Inside(G4ThreeVector(bmax.x(),y,z)) == kInside) { isGood = true; break; }
}
}
if (!isGood)
{
for (G4int i=0; i<10000; ++i) {
G4double x = bmin.x() + (bmax.x() - bmin.x())*G4QuickRand();
G4double y = bmin.y() + (bmax.y() - bmin.y())*G4QuickRand();
G4double z = bmin.z() + (bmax.z() - bmin.z())*G4QuickRand();
if (pBooleanSolid->Inside(G4ThreeVector(x,y,z)) == kInside) { isGood = true; break; }
}
}
if (!isGood) return;
}
const G4ViewParameters::DrawingStyle style = GetDrawingStyle(fpVisAttribs);
const G4ViewParameters& vp = fpViewer->GetViewParameters();
@@ -684,6 +715,9 @@ void G4VSceneHandler::ProcessScene()
G4cout << "Traversing scene data..." << G4endl;
}
// Reset visibility of all objects to false - visible objects will then set to true
fpViewer->AccessSceneTree().ResetVisibility();
BeginModeling();
// Create modeling parameters from view parameters...
@@ -695,10 +729,24 @@ void G4VSceneHandler::ProcessScene()
{
fpModel = runDurationModelList[i].fpModel;
fpModel->SetModelingParameters(pMP);
fpModel->DescribeYourselfTo(*this);
// To see the extents of each model represented as wireframe boxes,
// uncomment the next line and DrawExtent in namespace above
// DrawExtent(fpModel);
// Describe to the current scene handler
fpModel->DescribeYourselfTo(*this);
// To see the extents of each model represented as wireframe boxes,
// uncomment the next line and DrawExtent in namespace above.
// DrawExtent(fpModel);
// Enter models in the scene tree, and for PV models, describe
// the model to the scene tree, i.e., enter all the touchables.
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
if (dynamic_cast<G4PhysicalVolumeModel*>(fpModel)) {
fpModel->DescribeYourselfTo(sceneTreeScene);
}
// Reset modeling parameters pointer
fpModel->SetModelingParameters(0);
}
}
@@ -729,6 +777,8 @@ void G4VSceneHandler::ProcessScene()
if(runManager)
{
const G4Run* run = runManager->GetCurrentRun();
// Draw a null event in order to pick up models for the scene tree even before a run
if (run == nullptr) DrawEvent(0);
const std::vector<const G4Event*>* events =
run ? run->GetEventVector() : 0;
std::size_t nKeptEvents = 0;
@@ -797,9 +847,18 @@ void G4VSceneHandler::DrawEvent(const G4Event* event)
pMP->SetEvent(event);
for (std::size_t i = 0; i < nModels; ++i) {
if (EOEModelList[i].fActive) {
fpModel = EOEModelList[i].fpModel;
fpModel -> SetModelingParameters(pMP);
fpModel -> DescribeYourselfTo (*this);
fpModel = EOEModelList[i].fpModel;
fpModel -> SetModelingParameters(pMP);
// Describe to the current scene handler
fpModel -> DescribeYourselfTo (*this);
// Enter models in the scene tree
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
// Reset modeling parameters pointer
fpModel -> SetModelingParameters(0);
}
}
@@ -819,9 +878,18 @@ void G4VSceneHandler::DrawEndOfRunModels()
for (std::size_t i = 0; i < nModels; ++i) {
if (EORModelList[i].fActive) {
fpModel = EORModelList[i].fpModel;
fpModel -> SetModelingParameters(pMP);
fpModel -> SetModelingParameters(pMP);
// Describe to the current scene handler
fpModel -> DescribeYourselfTo (*this);
fpModel -> SetModelingParameters(0);
// Enter models in the scene tree
auto& sceneTreeScene = fpViewer->AccessSceneTreeScene();
sceneTreeScene.SetViewer(fpViewer);
sceneTreeScene.SetModel(fpModel);
// Reset modeling parameters pointer
fpModel -> SetModelingParameters(0);
}
}
fpModel = 0;
@@ -887,6 +955,13 @@ G4ModelingParameters* G4VSceneHandler::CreateModelingParameters ()
pModelingParams->SetExplodeCentre(vp.GetExplodeCentre());
pModelingParams->SetSectionSolid(CreateSectionSolid());
if (vp.GetCutawayMode() == G4ViewParameters::cutawayUnion) {
pModelingParams->SetCutawayMode(G4ModelingParameters::cutawayUnion);
} else if (vp.GetCutawayMode() == G4ViewParameters::cutawayIntersection) {
pModelingParams->SetCutawayMode(G4ModelingParameters::cutawayIntersection);
}
pModelingParams->SetCutawaySolid(CreateCutawaySolid());
// The polyhedron objects are deleted in the modeling parameters destructor.
@@ -909,27 +984,14 @@ G4DisplacedSolid* G4VSceneHandler::CreateSectionSolid()
G4double safe = radius + fpScene->GetExtent().GetExtentCentre().mag();
G4VSolid* sectionBox =
new G4Box("_sectioner", safe, safe, 1.e-5 * radius); // Thin in z-plane...
const G4Normal3D originalNormal(0,0,1); // ...so this is original normal.
const G4Plane3D& sp = vp.GetSectionPlane ();
const G4double& a = sp.a();
const G4double& b = sp.b();
const G4double& c = sp.c();
const G4double& d = sp.d();
const G4Normal3D newNormal(a,b,c);
G4Transform3D requiredTransform;
// Rotate
if (newNormal != originalNormal) {
const G4double& angle = std::acos(newNormal.dot(originalNormal));
const G4Vector3D& axis = originalNormal.cross(newNormal);
requiredTransform = G4Rotate3D(angle, axis);
}
// Translate
requiredTransform = requiredTransform * G4TranslateZ3D(-d);
G4ThreeVector normal = sp.normal();
G4Transform3D requiredTransform = G4Translate3D(normal*(-sp.d())) *
G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
sectioner = new G4DisplacedSolid
("_displaced_sectioning_box", sectionBox, requiredTransform);
("_displaced_sectioning_box", sectionBox, requiredTransform);
}
return sectioner;
@@ -937,69 +999,82 @@ G4DisplacedSolid* G4VSceneHandler::CreateSectionSolid()
G4DisplacedSolid* G4VSceneHandler::CreateCutawaySolid()
{
const G4ViewParameters& vp = fpViewer->GetViewParameters();
if (vp.IsCutaway()) {
const auto& vp = fpViewer->GetViewParameters();
const auto& nPlanes = vp.GetCutawayPlanes().size();
std::vector<G4DisplacedSolid*> cutaway_solids;
if (nPlanes == 0) return nullptr;
G4double radius = fpScene->GetExtent().GetExtentRadius();
G4double safe = radius + fpScene->GetExtent().GetExtentCentre().mag();
G4VSolid* cutawayBox =
new G4Box("_cutaway_box", safe, safe, safe); // world box...
std::vector<G4DisplacedSolid*> cutaway_solids;
for (int plane_no = 0; plane_no < int(vp.GetCutawayPlanes().size()); plane_no++){
G4double radius = fpScene->GetExtent().GetExtentRadius();
G4double safe = radius + fpScene->GetExtent().GetExtentCentre().mag();
auto cutawayBox = new G4Box("_cutaway_box", safe, safe, safe);
const G4Normal3D originalNormal(0,0,1); // ...so this is original normal.
// if (vp.GetCutawayMode() == G4ViewParameters::cutawayUnion) we need a subtractor that is
// the intersection of displaced cutaway boxes, displaced so that a subtraction keeps the
// positive values a*x+b*y+c*z+d>0, so we have to invert the normal. This may appear
// "back to front". The parameter "cutawayUnion" means "the union of volumes
// that remain *after* cutaway", because we base the concept on OpenGL cutaway planes and make
// a "union" of what remains by superimposing up to 3 passes - see G4OpenGLViewer::SetView
// and G4OpenGLImmediate/StoredViewer::ProcessView. So we have to create a subtractor
// that is the intersection of inverted cutaway planes.
const G4Plane3D& sp = vp.GetCutawayPlanes()[plane_no]; //];
const G4double& a = sp.a();
const G4double& b = sp.b();
const G4double& c = sp.c();
const G4double& d = sp.d();
const G4Normal3D newNormal(-a,-b,-c); // Convention: keep a*x+b*y+c*z+d>=0
// Not easy to see why the above gives the right convention, but it has been
// arrived at by trial and error to agree with the OpenGL implementation
// of clipping planes.
// Conversely, if (vp.GetCutawayMode() == G4ViewParameters::cutawayIntersection) we have to
// create an intersector that is the intersector of intersected non-inverted cutaway planes.
G4Transform3D requiredTransform; // Null transform
// Calculate the rotation
// If newNormal is (0,0,1), no need to do anything
// Treat (0,0,-1) as a special case, since cannot define axis in this case
if (newNormal == G4Normal3D(0,0,-1)) {
requiredTransform = G4Rotate3D(pi,G4Vector3D(1,0,0));
} else if (newNormal != originalNormal) {
const G4double& angle = std::acos(newNormal.dot(originalNormal));
const G4Vector3D& axis = originalNormal.cross(newNormal);
requiredTransform = G4Rotate3D(angle, axis);
}
// Translation
requiredTransform = requiredTransform * G4TranslateZ3D(d + safe);
cutaway_solids.push_back
(new G4DisplacedSolid("_displaced_cutaway_box", cutawayBox, requiredTransform));
}
if (cutaway_solids.size() == 1){
return (G4DisplacedSolid*) cutaway_solids[0];
} else if (vp.GetCutawayMode() == G4ViewParameters::cutawayUnion) {
G4UnionSolid* union2 =
new G4UnionSolid("_union_2", cutaway_solids[0], cutaway_solids[1]);
if (cutaway_solids.size() == 2)
return (G4DisplacedSolid*)union2;
else
return (G4DisplacedSolid*)
new G4UnionSolid("_union_3", union2, cutaway_solids[2]);
} else if (vp.GetCutawayMode() == G4ViewParameters::cutawayIntersection){
G4IntersectionSolid* intersection2 =
new G4IntersectionSolid("_intersection_2", cutaway_solids[0], cutaway_solids[1]);
if (cutaway_solids.size() == 2)
return (G4DisplacedSolid*)intersection2;
else
return (G4DisplacedSolid*)
new G4IntersectionSolid("_intersection_3", intersection2, cutaway_solids[2]);
for (size_t plane_no = 0; plane_no < nPlanes; plane_no++)
{
const G4Plane3D& sp = vp.GetCutawayPlanes()[plane_no];
G4Transform3D requiredTransform;
G4ThreeVector normal;
switch (vp.GetCutawayMode()) {
case G4ViewParameters::cutawayUnion:
normal = -sp.normal(); // Invert normal - we want a subtractor
requiredTransform = G4Translate3D(normal*(safe + sp.d())) *
G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
break;
case G4ViewParameters::cutawayIntersection:
normal = sp.normal();
requiredTransform = G4Translate3D(normal*(safe - sp.d())) *
G4Rotate3D(G4ThreeVector(0,0,1), G4ThreeVector(0,1,0), normal, normal.orthogonal());
break;
}
cutaway_solids.push_back
(new G4DisplacedSolid("_displaced_cutaway_box", cutawayBox, requiredTransform));
}
return 0;
if (nPlanes == 1) return (G4DisplacedSolid*) cutaway_solids[0];
G4IntersectionSolid *union2 = nullptr, *union3 = nullptr;
G4IntersectionSolid *intersection2 = nullptr, *intersection3 = nullptr;
switch (vp.GetCutawayMode()) {
case G4ViewParameters::cutawayUnion:
// Here we make a subtractor of intersections of inverted cutaway planes.
union2 = new G4IntersectionSolid("_union_2", cutaway_solids[0], cutaway_solids[1]);
if (nPlanes == 2) return (G4DisplacedSolid*)union2;
else if (nPlanes == 3) {
union3 = new G4IntersectionSolid("_union_3", union2, cutaway_solids[2]);
return (G4DisplacedSolid*)union3;
}
break;
case G4ViewParameters::cutawayIntersection:
// And here we make an intersector of intersections of non-inverted cutaway planes.
intersection2
= new G4IntersectionSolid("_intersection_2", cutaway_solids[0], cutaway_solids[1]);
if (nPlanes == 2) return (G4DisplacedSolid*)intersection2;
else if (nPlanes == 3) {
intersection3
= new G4IntersectionSolid("_intersection_3", intersection2, cutaway_solids[2]);
return (G4DisplacedSolid*)intersection3;
}
break;
}
G4Exception("G4VSceneHandler::CreateCutawaySolid", "visman107", JustWarning,
"Not programmed for more than 3 cutaway planes");
return nullptr;
}
void G4VSceneHandler::LoadAtts(const G4Visible& visible, G4AttHolder* holder)
@@ -1220,10 +1295,10 @@ std::ostream& operator << (std::ostream& os, const G4VSceneHandler& sh) {
}
void G4VSceneHandler::PseudoSceneFor3DRectMeshPositions::AddSolid(const G4Box&) {
if (fpPVModel->GetCurrentDepth() == fDepth) { // Leaf-level cells only
if (fpPVModel->GetCurrentDepth() == fpMesh->GetMeshDepth()) { // Leaf-level cells only
const auto& material = fpPVModel->GetCurrentLV()->GetMaterial();
const auto& name = material->GetName();
const auto* pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
const auto& name = material? material->GetName(): fpMesh->GetContainerVolume()->GetName();
const auto& pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
// Get position in world coordinates
// As a parameterisation the box is transformed by the current transformation
// and its centre, originally by definition at (0,0,0), is now translated.
@@ -1236,13 +1311,13 @@ void G4VSceneHandler::PseudoSceneFor3DRectMeshPositions::AddSolid(const G4Box&)
}
void G4VSceneHandler::PseudoSceneForTetVertices::AddSolid(const G4VSolid& solid) {
if (fpPVModel->GetCurrentDepth() == fDepth) { // Leaf-level cells only
if (fpPVModel->GetCurrentDepth() == fpMesh->GetMeshDepth()) { // Leaf-level cells only
// Need to know it's a tet !!!! or implement G4VSceneHandler::AddSolid (const G4Tet&) !!!!
try {
const G4Tet& tet = dynamic_cast<const G4Tet&>(solid);
const auto& tet = dynamic_cast<const G4Tet&>(solid);
const auto& material = fpPVModel->GetCurrentLV()->GetMaterial();
const auto& name = material->GetName();
const auto* pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
const auto& name = material? material->GetName(): fpMesh->GetContainerVolume()->GetName();
const auto& pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes();
// Transform into world coordinates if necessary
if (fpCurrentObjectTransformation->xx() == 1. &&
fpCurrentObjectTransformation->yy() == 1. &&
@@ -1278,6 +1353,8 @@ void G4VSceneHandler::StandardSpecialMeshRendering(const G4Mesh& mesh)
case G4Mesh::rectangle: [[fallthrough]];
case G4Mesh::nested3DRectangular:
switch (fpViewer->GetViewParameters().GetSpecialMeshRenderingOption()) {
case G4ViewParameters::meshAsDefault:
[[fallthrough]];
case G4ViewParameters::meshAsDots:
Draw3DRectMeshAsDots(mesh); // Rectangular 3-deep mesh as dots
implemented = true;
@@ -1290,6 +1367,8 @@ void G4VSceneHandler::StandardSpecialMeshRendering(const G4Mesh& mesh)
break;
case G4Mesh::tetrahedron:
switch (fpViewer->GetViewParameters().GetSpecialMeshRenderingOption()) {
case G4ViewParameters::meshAsDefault:
[[fallthrough]];
case G4ViewParameters::meshAsDots:
DrawTetMeshAsDots(mesh); // Tetrahedron mesh as dots
implemented = true;
@@ -1378,7 +1457,7 @@ void G4VSceneHandler::Draw3DRectMeshAsDots(const G4Mesh& mesh)
std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
// Instantiate the pseudo scene
PseudoSceneFor3DRectMeshPositions pseudoScene
(&tmpPVModel,mesh.GetMeshDepth(),positionByMaterial,nameAndVisAttsByMaterial);
(&tmpPVModel,&mesh,positionByMaterial,nameAndVisAttsByMaterial);
// Make private descent into the parameterisation
tmpPVModel.DescribeYourselfTo(pseudoScene);
// Now we have a map of positions by material.
@@ -1522,7 +1601,7 @@ void G4VSceneHandler::Draw3DRectMeshAsSurfaces(const G4Mesh& mesh)
std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
// Instantiate the pseudo scene
PseudoSceneFor3DRectMeshPositions pseudoScene
(&tmpPVModel,mesh.GetMeshDepth(),positionByMaterial,nameAndVisAttsByMaterial);
(&tmpPVModel,&mesh,positionByMaterial,nameAndVisAttsByMaterial);
// Make private descent into the parameterisation
tmpPVModel.DescribeYourselfTo(pseudoScene);
// Now we have a map of positions by material.
@@ -1666,7 +1745,7 @@ void G4VSceneHandler::DrawTetMeshAsDots(const G4Mesh& mesh)
std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
// Instantiate a pseudo scene
PseudoSceneForTetVertices pseudoScene
(&tmpPVModel,mesh.GetMeshDepth(),verticesByMaterial,nameAndVisAttsByMaterial);
(&tmpPVModel,&mesh,verticesByMaterial,nameAndVisAttsByMaterial);
// Make private descent into the parameterisation
tmpPVModel.DescribeYourselfTo(pseudoScene);
// Now we have a map of vertices by material.
@@ -1804,7 +1883,7 @@ void G4VSceneHandler::DrawTetMeshAsSurfaces(const G4Mesh& mesh)
std::map<const G4Material*,G4VSceneHandler::NameAndVisAtts> nameAndVisAttsByMaterial;
// Instantiate a pseudo scene
PseudoSceneForTetVertices pseudoScene
(&tmpPVModel,mesh.GetMeshDepth(),verticesByMaterial,nameAndVisAttsByMaterial);
(&tmpPVModel,&mesh,verticesByMaterial,nameAndVisAttsByMaterial);
// Make private descent into the parameterisation
tmpPVModel.DescribeYourselfTo(pseudoScene);
// Now we have a map of vertices by material.
@@ -44,6 +44,8 @@
#include "G4VPhysicalVolume.hh"
#include "G4Transform3D.hh"
#include "G4UImanager.hh"
#include "G4UIsession.hh"
#include "G4VInteractiveSession.hh"
G4VViewer::G4VViewer (G4VSceneHandler& sceneHandler,
G4int id, const G4String& name):
@@ -65,6 +67,8 @@ fNeedKernelVisit (true)
fVP = G4VisManager::GetInstance()->GetDefaultViewParameters();
fDefaultVP = fVP;
fSceneTree.SetType(G4SceneTreeItem::root);
}
G4VViewer::~G4VViewer () {
@@ -118,6 +122,7 @@ void G4VViewer::ProcessView ()
fNeedKernelVisit = false;
fSceneHandler.ClearStore ();
fSceneHandler.ProcessScene ();
UpdateGUISceneTree();
timer.Stop();
fKernelVisitElapsedTimeSeconds = timer.GetRealElapsed();
}
@@ -139,7 +144,7 @@ void G4VViewer::SetTouchable
if (iterator == pvStore->cend()) {
G4ExceptionDescription ed;
ed << "Volume no longer in physical volume store.";
G4Exception("G4VViewer::SetTouchable", "visman0501", JustWarning, ed);
G4Exception("G4VViewer::SetTouchable", "visman0401", JustWarning, ed);
} else {
oss
<< ' ' << pvNodeId.GetPhysicalVolume()->GetName()
@@ -153,7 +158,7 @@ void G4VViewer::TouchableSetVisibility
(const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& fullPath,
G4bool visibiity)
{
// Changes the Vis Attribute Modifiers WITHOUT triggering a rebuild.
// Changes the Vis Attribute Modifiers and scene tree WITHOUT triggering a rebuild.
// The following is equivalent to
// G4UImanager::GetUIpointer()->ApplyCommand("/vis/touchable/set/visibility ...");
@@ -172,13 +177,26 @@ void G4VViewer::TouchableSetVisibility
// G4ModelingParameters::VASVisibility (VAS = Vis Attribute Signifier)
// signifies that it is the visibility that should be picked out
// and merged with the touchable's normal vis attributes.
// Find scene tree item and set visibility
// The scene tree works with strings
G4String fullPathString = G4PhysicalVolumeModel::GetPVNamePathString(fullPath);
std::list<G4SceneTreeItem>::iterator foundIter;
if (fSceneTree.FindTouchableFromRoot(fullPathString,foundIter)) {
foundIter->AccessVisAttributes().SetVisibility(visibiity);
UpdateGUISceneTree();
} else {
G4ExceptionDescription ed;
ed << "Touchable \"" << fullPath << "\" not found";
G4Exception("G4VViewer::TouchableSetVisibility", "visman0402", JustWarning, ed);
}
}
void G4VViewer::TouchableSetColour
(const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& fullPath,
const G4Colour& colour)
{
// Changes the Vis Attribute Modifiers WITHOUT triggering a rebuild.
// Changes the Vis Attribute Modifiers and scene tree WITHOUT triggering a rebuild.
// The following is equivalent to
// G4UImanager::GetUIpointer()->ApplyCommand("/vis/touchable/set/colour ...");
@@ -197,6 +215,201 @@ void G4VViewer::TouchableSetColour
// G4ModelingParameters::VASColour (VAS = Vis Attribute Signifier)
// signifies that it is the colour that should be picked out
// and merged with the touchable's normal vis attributes.
// Find scene tree item and set colour
// The scene tree works with strings
G4String fullPathString = G4PhysicalVolumeModel::GetPVNamePathString(fullPath);
std::list<G4SceneTreeItem>::iterator foundIter;
if (fSceneTree.FindTouchableFromRoot(fullPathString,foundIter)) {
foundIter->AccessVisAttributes().SetColour(colour);
UpdateGUISceneTree();
} else {
G4ExceptionDescription ed;
ed << "Touchable \"" << fullPath << "\" not found";
G4Exception("G4VViewer::TouchableSetColour", "visman0403", JustWarning, ed);
}
}
void G4VViewer::UpdateGUISceneTree()
{
G4UImanager* UI = G4UImanager::GetUIpointer();
auto uiWindow = dynamic_cast<G4VInteractiveSession*>(UI->GetG4UIWindow());
if (uiWindow) uiWindow->UpdateSceneTree(fSceneTree);
}
void G4VViewer::SceneTreeScene::SetModel(G4VModel* pModel)
{
fpModel = pModel;
auto& modelType = fpModel->GetType();
auto& modelID = fpModel->GetGlobalDescription();
FindOrInsertModel(modelType,modelID);
}
std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertModel
(const G4String& modelType,const G4String& modelID)
{
G4SceneTreeItem::Type type = G4SceneTreeItem::unidentified;
if (dynamic_cast<G4PhysicalVolumeModel*>(fpModel)) {
type = G4SceneTreeItem::pvmodel;
} else {
type = G4SceneTreeItem::model;
}
auto& rootItem = fpViewer->fSceneTree;
rootItem.SetDescription(fpViewer->GetName());
// Find appropriate model
auto& modelItems = rootItem.AccessChildren();
auto modelIter = modelItems.begin();
auto pvModelIter = modelItems.end();
for (; modelIter != modelItems.end(); ++modelIter) {
if (modelIter->GetType() == G4SceneTreeItem::pvmodel) {
pvModelIter = modelIter; // Last PV model
}
if (modelIter->GetModelDescription() == modelID) break;
}
if (modelIter == modelItems.end()) {
// Model not seen before
G4SceneTreeItem modelItem(type);
modelItem.SetDescription("model");
modelItem.SetModelType(modelType);
modelItem.SetModelDescription(modelID);
if (pvModelIter != modelItems.end() && // There was pre-existing PV Model...
type == G4SceneTreeItem::pvmodel) { // ...and the new model is also PV...
modelIter = rootItem.InsertChild(++pvModelIter,modelItem); // ...insert after, else...
} else {
modelIter = rootItem.InsertChild(modelIter,modelItem); // ...insert at end
}
} else {
// Existing model - mark visible == active
modelIter->AccessVisAttributes().SetVisibility(true);
}
return modelIter;
}
std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouchable
(const G4String& modelID, G4SceneTreeItem& mother,
G4int depth, const G4String& partialPathString, const G4String& fullPathString)
{
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel == nullptr) {
G4ExceptionDescription ed;
ed << fpModel->GetType() << ": not a Physical VolumeModel";
G4Exception("G4VViewer::SceneTreeScene::FindOrInsertTouchable", "visman0404", FatalException, ed);
}
auto& children = mother.AccessChildren();
auto childIter = children.begin();
for (; childIter != children.end(); ++childIter) {
if (childIter->GetPVPath() == partialPathString) break;
}
if (childIter != children.end()) {
// Item already exists
if (childIter->GetType() == G4SceneTreeItem::ghost) {
// Previously it was a ghost - but maybe this time it's real
if (partialPathString == fullPathString) {
// Partial path string refers to the actual volume so it's a touchable
childIter->SetType(G4SceneTreeItem::touchable);
// Populate with information
childIter->SetDescription(fpModel->GetCurrentTag());
childIter->SetModelType(fpModel->GetType());
childIter->SetModelDescription(modelID);
childIter->SetPVPath(partialPathString);
if (fpVisAttributes) childIter->SetVisAttributes(*fpVisAttributes);
if (pPVModel) childIter->SetAttDefs(pPVModel->GetAttDefs());
if (pPVModel) childIter->SetAttValues(pPVModel->CreateCurrentAttValues());
} // Partial path string refers to an ancester - do nothing
} else {
// Already a pre-existing full touchable
if (partialPathString == fullPathString) {
// Partial path string refers to the actual volume
// Replace vis attributes (if any) - they might have changed
if (fpVisAttributes) childIter->SetVisAttributes(*fpVisAttributes);
} // Partial path string refers to an ancester - do nothing
}
} else {
// Item does not yet exist
if (partialPathString == fullPathString) {
// Partial path string refers to the actual volume
// Insert new touchable item
G4SceneTreeItem touchable(G4SceneTreeItem::touchable);
touchable.SetExpanded(depth > 2? false: true);
touchable.SetDescription(fpModel->GetCurrentTag());
touchable.SetModelType(fpModel->GetType());
touchable.SetModelDescription(modelID);
touchable.SetPVPath(partialPathString);
if (fpVisAttributes) touchable.SetVisAttributes(*fpVisAttributes);
if (pPVModel) touchable.SetAttDefs(pPVModel->GetAttDefs());
if (pPVModel) touchable.SetAttValues(pPVModel->CreateCurrentAttValues());
childIter = mother.InsertChild(childIter,touchable);
} else {
// Partial path string refers to an ancester - it's what we call a "ghost"
G4SceneTreeItem ghost(G4SceneTreeItem::ghost);
ghost.SetExpanded(depth > 2? false: true);
// Create a tag from the partial path
std::istringstream iss(partialPathString);
G4String name, copyNo;
while (iss >> name >> copyNo);
std::ostringstream oss;
oss << name << ':' << copyNo;
ghost.SetDescription(oss.str());
ghost.SetModelType(fpModel->GetType());
ghost.SetModelDescription(modelID);
ghost.SetPVPath(partialPathString);
ghost.AccessVisAttributes().SetVisibility(false);
childIter = mother.InsertChild(childIter,ghost);
}
}
return childIter;
}
void G4VViewer::SceneTreeScene::ProcessVolume(const G4VSolid&)
{
auto& modelType = fpModel->GetType();
auto& modelID = fpModel->GetGlobalDescription();
auto modelIter = FindOrInsertModel(modelType,modelID);
auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
if (pPVModel) { // G4PhysicalVolumeModel
std::ostringstream oss; oss << pPVModel->GetFullPVPath();
G4String fullPathString(oss.str()); // Has a leading space - OK
// Navigate scene tree and find or insert touchables one by one
const auto& nodeIDs = pPVModel->GetFullPVPath(); // std::vector<G4PhysicalVolumeNodeID>
// Work down the path - "name id", then "name id name id", etc.
G4String partialPathString;
auto currentIter = modelIter;
G4int depth = 0;
for (const auto& nodeID: nodeIDs) {
std::ostringstream oss1; oss1 << nodeID;
partialPathString += ' ' + oss1.str(); // Has a leading space - OK
currentIter = FindOrInsertTouchable
(modelID, *currentIter, ++depth, partialPathString, fullPathString);
}
} else {
// Orphan solid - what to do? Push an empty scene tree item????????????????????????
}
}
std::vector <G4ThreeVector> G4VViewer::ComputeFlyThrough(G4Vector3D* /*aVect*/)
@@ -55,6 +55,7 @@ G4VisExtent G4VVisCommand::fCurrentExten
std::vector<G4PhysicalVolumesSearchScene::Findings> G4VVisCommand::fCurrrentPVFindingsForField;
G4bool G4VVisCommand::fThereWasAViewer = false;
G4ViewParameters G4VVisCommand::fExistingVP;
G4SceneTreeItem G4VVisCommand::fExistingSceneTree;
G4VVisCommand::G4VVisCommand () {}
@@ -339,7 +340,6 @@ void G4VVisCommand::InterpolateToNewView
void G4VVisCommand::Twinkle
// Twinkles the touchables in paths
// /vis/viewer/centreOn to see its effect
(G4VViewer* currentViewer,
const G4ViewParameters& baseVP,
const std::vector<std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>>& paths)
@@ -379,16 +379,11 @@ void G4VVisCommand::Twinkle
// Twinkle
std::vector<G4ViewParameters> viewVector;
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
// Just 5 twinkles is reasonable to get a human's attention
for (G4int i = 0; i < 5; i++) {
viewVector.push_back(loVP);
viewVector.push_back(hiVP);
}
// Just 5 interpolation points for a reasonable twinkle rate
InterpolateViews(currentViewer,viewVector,5);
}
@@ -104,7 +104,7 @@ G4ViewParameters::G4ViewParameters ():
fDisplayLightFrontGreen(1.),
fDisplayLightFrontBlue(0.),
fSpecialMeshRendering(false),
fSpecialMeshRenderingOption(meshAsDots)
fSpecialMeshRenderingOption(meshAsDefault)
{
// Pick up default no of sides from G4Polyhedron.
// Note that this parameter is variously called:
@@ -896,6 +896,8 @@ std::ostream& operator <<
(std::ostream& os, G4ViewParameters::SMROption option)
{
switch (option) {
case G4ViewParameters::meshAsDefault:
os << "default"; break;
case G4ViewParameters::meshAsDots:
os << "dots"; break;
case G4ViewParameters::meshAsSurfaces:
@@ -324,10 +324,12 @@ void G4VisCommandSceneHandlerCreate::SetNewValue (G4UIcommand* command,
}
}
// If there is an existing viewer, store its view parameters
// If there is an existing viewer, store its view parameters and scene tree
if (fpVisManager->GetCurrentViewer()) {
fThereWasAViewer = true;
fExistingVP = fpVisManager->GetCurrentViewer()->GetViewParameters();
auto viewer = fpVisManager->GetCurrentViewer();
fExistingVP = viewer->GetViewParameters();
fExistingSceneTree = viewer->AccessSceneTree();
}
// Set current graphics system in preparation for
@@ -120,6 +120,11 @@ G4VisCommandsTouchable::G4VisCommandsTouchable()
fpCommandShowExtent->SetParameterName("draw", omitable = true);
fpCommandShowExtent->SetDefaultValue(false);
fpCommandTwinkle = new G4UIcmdWithoutParameter("/vis/touchable/twinkle",this);
fpCommandTwinkle->SetGuidance("Cause touchable to twinkle.");
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandTwinkle,1);
fpCommandVolumeForField = new G4UIcmdWithABool("/vis/touchable/volumeForField",this);
fpCommandVolumeForField->SetGuidance("Set volume for field.");
fpCommandVolumeForField->SetGuidance("If parameter == true, also draw.");
@@ -131,6 +136,7 @@ G4VisCommandsTouchable::G4VisCommandsTouchable()
G4VisCommandsTouchable::~G4VisCommandsTouchable() {
delete fpCommandVolumeForField;
delete fpCommandTwinkle;
delete fpCommandShowExtent;
delete fpCommandLocalAxes;
delete fpCommandFindPath;
@@ -255,7 +261,6 @@ void G4VisCommandsTouchable::SetNewValue
} else {
G4warn << "Touchable not found." << G4endl;
}
return;
} else if (command == fpCommandDraw) {
@@ -263,7 +268,7 @@ void G4VisCommandsTouchable::SetNewValue
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
// To handle paramaterisations we have to set the copy number
// To handle parameterisations we have to set the copy number
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
G4PhysicalVolumeModel* pvModel = new G4PhysicalVolumeModel
(properties.fpTouchablePV,
@@ -310,7 +315,7 @@ void G4VisCommandsTouchable::SetNewValue
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
// To handle paramaterisations we have to set the copy number
// To handle parameterisations we have to set the copy number
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
G4PhysicalVolumeModel tempPVModel
(properties.fpTouchablePV,
@@ -398,19 +403,27 @@ void G4VisCommandsTouchable::SetNewValue
if (copyNo >= 0) G4warn << ':' << copyNo;
G4warn << " not found" << G4endl;
}
return;
} else if (command == fpCommandLocalAxes) {
const auto& transform = fCurrentTouchableProperties.fTouchableGlobalTransform;
const auto& extent = fCurrentTouchableProperties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
const G4double lengthMax = extent.GetExtentRadius()/2.;
const G4double intLog10LengthMax = std::floor(std::log10(lengthMax));
G4double length = std::pow(10,intLog10LengthMax);
if (5.*length < lengthMax) length *= 5.;
else if (2.*length < lengthMax) length *= 2.;
G4AxesModel axesModel(0.,0.,0.,length,transform);
axesModel.SetGlobalTag("LocalAxesModel");
axesModel.DescribeYourselfTo(*fpVisManager->GetCurrentSceneHandler());
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
const auto& transform = fCurrentTouchableProperties.fTouchableGlobalTransform;
const auto& extent = fCurrentTouchableProperties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
const G4double lengthMax = extent.GetExtentRadius()/2.;
const G4double intLog10LengthMax = std::floor(std::log10(lengthMax));
G4double length = std::pow(10,intLog10LengthMax);
if (5.*length < lengthMax) length *= 5.;
else if (2.*length < lengthMax) length *= 2.;
G4AxesModel axesModel(0.,0.,0.,length,transform);
axesModel.SetGlobalTag("LocalAxesModel");
axesModel.DescribeYourselfTo(*fpVisManager->GetCurrentSceneHandler());
} else {
G4warn << "Touchable not found." << G4endl;
}
return;
} else if (command == fpCommandShowExtent) {
@@ -427,6 +440,24 @@ void G4VisCommandsTouchable::SetNewValue
}
return;
} else if (command == fpCommandTwinkle) {
G4PhysicalVolumeModel::TouchableProperties properties =
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
if (properties.fpTouchablePV) {
std::vector<std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>> touchables;
touchables.push_back(properties.fTouchableFullPVPath);
auto keepVisVerbose = fpVisManager->GetVerbosity();
fpVisManager->SetVerboseLevel(G4VisManager::errors);
auto keepVP = currentViewer->GetViewParameters();
Twinkle(currentViewer,currentViewer->GetViewParameters(),touchables);
SetViewParameters(currentViewer, keepVP);
fpVisManager->SetVerboseLevel(keepVisVerbose);
} else {
G4warn << "Touchable not found." << G4endl;
}
return;
} else if (command == fpCommandVolumeForField) {
G4PhysicalVolumeModel::TouchableProperties properties =
@@ -309,6 +309,20 @@ void G4VisCommandsTouchableSet::SetNewValue
(workingVisAtts,
G4ModelingParameters::VASVisibility,
fCurrentTouchableProperties.fTouchablePath));
if (verbosity >= G4VisManager::warnings) {
static G4bool first = true;
if (first) {
first = false;
G4warn << "WARNING: If \"/vis/touchable/set/visibility\" does not appear to"
"\n work, check that opacity (4th component of colour) is non-zero." << G4endl;
G4warn << "ALSO: The volume must be in a requested physical volume tree,"
"\n not in the \"base path\". E.g., if"
"\n /vis/drawVolume volume-name"
"\n there is no way to make a parent of volume-name visible except by"
"\n explicitly adding the parent:"
"\n /vis/scene/add/volume parent-name" << G4endl;
}
}
}
else {
@@ -1067,6 +1067,7 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
if (existingViewer) {
// ...bring view parameters up to date...
fExistingVP = existingViewer->GetViewParameters();
fExistingSceneTree = existingViewer->AccessSceneTree();
}
}
@@ -1090,13 +1091,16 @@ void G4VisCommandViewerCreate::SetNewValue (G4UIcommand* command, G4String newVa
fExistingVP.SetXGeometryString(vp.GetXGeometryString());
vp = fExistingVP;
newViewer->SetViewParameters(vp);
newViewer->AccessSceneTree() = fExistingSceneTree;
}
if (verbosity >= G4VisManager::confirmations) {
G4cout << "New viewer \"" << newName << "\" created." << G4endl;
}
// Keep for next time...
fThereWasAViewer = true;
fExistingVP = fpVisManager->GetCurrentViewer()->GetViewParameters();
auto viewer = fpVisManager->GetCurrentViewer();
fExistingVP = viewer->GetViewParameters();
fExistingSceneTree = viewer->AccessSceneTree();
} else {
G4ExceptionDescription ed;
if (newViewer) {
@@ -2168,6 +2172,9 @@ void G4VisCommandViewerSelect::SetNewValue (G4UIcommand*, G4String newValue) {
fpVisManager -> SetCurrentViewer (viewer);
RefreshIfRequired(viewer);
// Update GUI scene tree (make sure it's in sync)
viewer->UpdateGUISceneTree();
}
////////////// /vis/viewer/update ///////////////////////////////////////
@@ -388,10 +388,10 @@ fViewpointVector (G4ThreeVector(0.,0.,1.))
fpCommandSpecialMeshRenderingOption = new G4UIcmdWithAString
("/vis/viewer/set/specialMeshRenderingOption",this);
fpCommandSpecialMeshRenderingOption->SetGuidance
("Set special mesh rendering option - \"dots\" or \"surfaces\".");
("Set special mesh rendering option - \"default\", \"dots\" or \"surfaces\".");
fpCommandSpecialMeshRenderingOption->SetParameterName ("option",omitable = true);
fpCommandSpecialMeshRenderingOption->SetCandidates("dots surfaces");
fpCommandSpecialMeshRenderingOption->SetDefaultValue("dots");
fpCommandSpecialMeshRenderingOption->SetCandidates("default dots surfaces");
fpCommandSpecialMeshRenderingOption->SetDefaultValue("default");
fpCommandSpecialMeshVolumes = new G4UIcommand
("/vis/viewer/set/specialMeshVolumes",this);
@@ -1274,8 +1274,11 @@ void G4VisCommandsViewerSet::SetNewValue
}
else if (command == fpCommandSpecialMeshRenderingOption) {
G4ViewParameters::SMROption option = G4ViewParameters::meshAsDots;
if (newValue == "surfaces") {
G4ViewParameters::SMROption option = G4ViewParameters::meshAsDefault;
if (newValue == "dots") {
option = G4ViewParameters::meshAsDots;
}
else if(newValue == "surfaces") {
option = G4ViewParameters::meshAsSurfaces;
}
vp.SetSpecialMeshRenderingOption(option);