Import Geant4 11.2.0.beta source tree
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
# -------------------------------------------------------------
|
||||
# GNUmakefile for visualization library. John Allison, 5/7/95.
|
||||
|
||||
name := G4vis_management
|
||||
|
||||
ifndef G4INSTALL
|
||||
G4INSTALL = ../../..
|
||||
endif
|
||||
|
||||
# For debug mode
|
||||
# CPPFLAGS += -DG4DEBUG_VIS_MANAGEMENT
|
||||
|
||||
GLOBLIBS = libG4modeling.lib libG4tools.lib
|
||||
GLOBLIBS += libG4run.lib libG4event.lib
|
||||
GLOBLIBS += libG4tracking.lib libG4processes.lib libG4digits_hits.lib
|
||||
GLOBLIBS += libG4track.lib libG4particles.lib libG4geometry.lib
|
||||
GLOBLIBS += libG4materials.lib libG4graphics_reps.lib
|
||||
GLOBLIBS += libG4intercoms.lib libG4global.lib
|
||||
|
||||
include $(G4INSTALL)/config/architecture.gmk
|
||||
include $(G4INSTALL)/config/G4VIS_BUILD.gmk
|
||||
|
||||
CPPFLAGS += -I$(G4BASE)/visualization/management/include
|
||||
CPPFLAGS += -I$(G4BASE)/visualization/modeling/include
|
||||
CPPFLAGS += -I$(G4BASE)/externals/g4tools/include
|
||||
CPPFLAGS += -I$(G4BASE)/graphics_reps/include
|
||||
CPPFLAGS += -I$(G4BASE)/global/management/include
|
||||
CPPFLAGS += -I$(G4BASE)/global/HEPGeometry/include
|
||||
CPPFLAGS += -I$(G4BASE)/global/HEPRandom/include
|
||||
CPPFLAGS += -I$(G4BASE)/global/HEPNumerics/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/solids/CSG/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/solids/specific/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/solids/Boolean/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/management/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/volumes/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/navigation/include
|
||||
CPPFLAGS += -I$(G4BASE)/geometry/magneticfield/include
|
||||
CPPFLAGS += -I$(G4BASE)/intercoms/include
|
||||
CPPFLAGS += -I$(G4BASE)/tracking/include
|
||||
CPPFLAGS += -I$(G4BASE)/digits_hits/hits/include
|
||||
CPPFLAGS += -I$(G4BASE)/particles/management/include
|
||||
CPPFLAGS += -I$(G4BASE)/materials/include
|
||||
CPPFLAGS += -I$(G4BASE)/run/include
|
||||
CPPFLAGS += -I$(G4BASE)/tasking/include
|
||||
CPPFLAGS += -I$(G4BASE)/event/include
|
||||
CPPFLAGS += -I$(G4BASE)/track/include
|
||||
CPPFLAGS += -I$(G4BASE)/processes/management/include
|
||||
CPPFLAGS += -I$(G4BASE)/digits_hits/utils/include
|
||||
CPPFLAGS += -I$(G4BASE)/digits_hits/digits/include
|
||||
|
||||
include $(G4INSTALL)/config/common.gmk
|
||||
@@ -6,6 +6,194 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2023-06-16 John Allison (visman-V11-01-15)
|
||||
- G4VisExecutive.icc:
|
||||
- Temporary fix to divert OGL to TSG for Qt6.
|
||||
|
||||
## 2023-06-06 John Allison (visman-V11-01-14)
|
||||
- G4VisCommandsTouchable; Introduce /vis/touchable/twinkle.
|
||||
|
||||
## 2023-06-01 John Allison (visman-V11-01-13)
|
||||
- Rework issue of implicit type conversion.
|
||||
- Improve layout in G4VViewer::SceneTreeScene::FindOrInsertModel.
|
||||
- (No code changes.)
|
||||
|
||||
## 2023-05-29 Guy Barrand (visman-v11-01-12)
|
||||
- G4VisExecutive.icc: declare TOOLSSG_[X11,XT,WINDOWS,QT]_ZB drivers.
|
||||
|
||||
## 2023-05-23 Gabriele Cosmo (visman-V11-01-11)
|
||||
- Fixed compilation warning for implicit type conversion on macOS/XCode>=14.1.
|
||||
|
||||
## 2023-05-09 John Allison (visman-V11-01-10)
|
||||
- Coworks: greps-V11-01-04 and interfaces-V11-01-15.
|
||||
- New scene tree: Implement expand and collapse of touchables.
|
||||
- Expand only to depth 2 - thereafter sub-trees are collapsed.
|
||||
- When the scene tree is expanded or collapsed it is remembered in
|
||||
the viewer-side scene tree and may be propagated to other viewers.
|
||||
- G4VViewer.hh/cc:
|
||||
- Augment SceneTreeScene::FindOrInsertTouchable to handle depth of descent.
|
||||
|
||||
## 2023-05-02 John Allison (visman-V11-01-09)
|
||||
- Coworks: modeling-V11-01-04.
|
||||
- These two tags implement "generic cutaways"...finally...after 20 years!!!
|
||||
- It relies on the Boolean Processor (graphics_reps/src/BooleanProcessor.src),
|
||||
which handles the Boolean operations on polyhedral (G4Polyhedron)
|
||||
representations of solids. It is well known that this has its
|
||||
limitations, and the mistake, in the past, has been to ask too much of it.
|
||||
The most demanding task is cutaways, which attempts to mimic the effect
|
||||
of OpenGL clipping planes by using Boolean intersections and/or
|
||||
subtraction of a "cutaway solid". This cutaway solid can itself be the
|
||||
Boolean combination of up to 3 simple solids (boxes) to deal with up to
|
||||
3 "cutaway planes". It then goes forward in the G4PhysicalVolumeModel to a
|
||||
further Boolean operation on the volumes (touchables) of the detector
|
||||
geometry, which themselves might also be Boolean solids.
|
||||
- The most demanding case is the union of the result of 3 cutaway planes.
|
||||
The key breakthrough in this tag is to make a subtractor of the
|
||||
intersection of the *inverted* cutaways instead of an intersector of the
|
||||
union of normal cutaways. ("Inverted cutaway" means
|
||||
cutting away a*x+b*y+c*z+d>0, "normal" means a*x+b*y+c*z+d<0.) Although
|
||||
logically equivalent, the former is much less demanding because the
|
||||
shape of an intersection is invariably much simpler that the shape of
|
||||
a union - at least that's how it seems to be for the case of 3 boxes.
|
||||
- This work was triggered by an initial attempt by a Geant4 user,
|
||||
Pooria Heidary. Demanding tests showed that there needed to be careful
|
||||
checking of the validity of the results of the Boolean operations -
|
||||
Evgueni Tcherniaev has made a big contribution there. Pooria will
|
||||
hardly recognise the code compared to that submitted in the GitHub pull
|
||||
request after these tests and other checks have been added. Hopefully
|
||||
this update is now well tested and robust.
|
||||
- It means that clips, sections and cutaways will now be available to *all*
|
||||
viewers.
|
||||
- G4VSceneHandler.cc:
|
||||
- RequestPrimitives: Improve test for invalid Boolean solid.
|
||||
- Algorithm by Evgueni Tcherniaev.
|
||||
- CreateSectionSolid and CreateCutawaySolid: Improve algorithms.
|
||||
- Algorithms suggested by Evgueni Tcherniaev.
|
||||
|
||||
## 2023-04-30 John Allison (visman-V11-01-08)
|
||||
- G4VSceneHandler:
|
||||
- Bug fix: Protect material pointer used to name G4Mesh item.
|
||||
- If null, use name of container.
|
||||
- In particular, avoids crash for a G4Mesh is a parallel world.
|
||||
|
||||
## 2023-04-28 John Allison (visman-V11-01-07)
|
||||
- G4VViewer::SceneTreeScene::FindOrInsertTouchable:
|
||||
- Coverity fix - protect pPVModel pointer.
|
||||
|
||||
## 2023-04-25 John Allison (visman-V11-01-06)
|
||||
- G4VisCommandsTouchableSet.cc:
|
||||
- /vis/touchable/set/visibility:
|
||||
- Add one-time warning about circumstances in which the command may
|
||||
appear not to work.
|
||||
|
||||
## 2023-04-23 John Allison (visman-V11-01-05)
|
||||
- Correct Special Mesh Rendering Option default.
|
||||
- G4ViewParameters.cc:
|
||||
- Initialise fSpecialMeshRenderingOption(meshAsDefault).
|
||||
- G4VisCommandsViewerSet.cc:
|
||||
- /vis/viewer/set/specialMeshRenderingOption:
|
||||
- SetDefaultValue("default");
|
||||
|
||||
## 2023-04-14 John Allison (visman-V11-01-04)
|
||||
- Co-working: greps-V11-01-03, interfaces-V11-01-11, opengl-V11-01-06,
|
||||
openinventor-V11-01-04, vis_toolssg-V11-01-05.
|
||||
- New Scene Tree Phase 2 - first implementation of a no-frills GUI-side
|
||||
interactive scene tree.
|
||||
- Works with touchables - a touchable is a physical volume as rolled out
|
||||
by the geometry hierarchy.
|
||||
- You can change the visibility of a touchable.
|
||||
- Colour, transparency, etc., will be implemented in a future MR.
|
||||
- Providing you are using a scene-tree-enabled interactive session (only
|
||||
the Qt GUI at present), it works with any graphics driver...except OpenGL.
|
||||
- OpenGL for the time being uses its existing interactive scene tree.
|
||||
- You can prepare a view with a graphical driver, such as
|
||||
TSG, OI or Vtk, and transfer it to Ray Tracer, TOOLSSG_OFFSCREEN, etc.,
|
||||
simply with `/vis/open RayTracer`, etc.
|
||||
- G4VVisCommand:
|
||||
- Add static G4SceneTreeItem fExistingSceneTree.
|
||||
- Used for "remembering" scene tree of previous viewer.
|
||||
- G4VisCommandsSceneHandler:
|
||||
- If there is an existing viewer, store scene tree.
|
||||
- G4VisCommandsViewer:
|
||||
- If there is an existing viewer, store scene tree.
|
||||
- Copy existing scene tree to the new viewer.
|
||||
- /vis/viewer/select: Call UpdateGUISceneTree to ensure the scene tree
|
||||
of the newly selected viewer is in sync.
|
||||
- G4VViewer:
|
||||
- Improve G4VViewer::SceneTreeScene::FindOrInsertTouchable.
|
||||
- Simplify ghost-touchable transition.
|
||||
- Protect vis attributes pointer.
|
||||
- Add "utility" function UpdateGUISceneTree.
|
||||
- Calls GUI->UpdateSceneTree if session is interactive:
|
||||
```
|
||||
void G4VViewer::UpdateGUISceneTree()
|
||||
{
|
||||
G4UImanager* UI = G4UImanager::GetUIpointer();
|
||||
auto uiWindow = dynamic_cast<G4VInteractiveSession*>(UI->GetG4UIWindow());
|
||||
if (uiWindow) uiWindow->UpdateSceneTree(fSceneTree);
|
||||
}
|
||||
```
|
||||
- sources.cmake:
|
||||
- Add G4interfaces to geant4_module_link_libraries.
|
||||
|
||||
## 2023-04-07 Stewart Boogert (visman-v11-01-03)
|
||||
- Default special mesh rendering for viewers which can render all objects
|
||||
|
||||
## 2023-04-07 John Allison (visman-V11-01-02)
|
||||
- Co-works with: greps-V11-01-02.
|
||||
- Improve vis-side scene tree creation and maintenance.
|
||||
- G4VViewer::SceneTreeScene:
|
||||
- Simplify - remove unnecessary overrides.
|
||||
- Fix bugs in scene tree building and add some features.
|
||||
- Add "tags" that will become the identifier in the GUI tree.
|
||||
- G4VSceneHandler::ProcessScene:
|
||||
- Simplify scene tree processing.
|
||||
- G4VVisCommand::RefreshIfRequired:
|
||||
- Call viewer->UpdateGUISceneTree() after refreshing.
|
||||
- This ensures the GUI-side scene tree and vis-side scene tree
|
||||
are in sync.
|
||||
|
||||
## 2023-03-28 John Allison (visman-V11-01-01)
|
||||
- Co-works with: greps-V11-01-01, interfaces-V11-01-10, modeling-V11-01-02.
|
||||
- Introduce scene tree in G4VViewer.
|
||||
- The scene tree is a tree of G4SceneTreeItem objects (see graphics-reps).
|
||||
- Its root is a data member fSceneTree of all viewers by virtue of
|
||||
G4VViewer inheritance,
|
||||
- G4SceneTreeItem is an aggregate of data members that represent
|
||||
properties of objects in the scene (G4Scene). Its data members are
|
||||
low-level types - G4String, G4VisAttributes and G4AttDef/Value - so
|
||||
that it can be used across categories, avoiding coupling.
|
||||
- The root item has children that represent the models (G4VModel
|
||||
sub-classes) in the scene.
|
||||
- For a G4PhysicalVolumeModel (detector components), its children and
|
||||
children's children, etc., imitate the geometry hierarchy of that
|
||||
model. These descendants are called "touchables".
|
||||
- There may be more than one G4PhysicalVolumeModel, depending how
|
||||
the user creates his/her scene.
|
||||
- The scene tree is reviewed, and updated if necessary, at every pass
|
||||
of G4VSceneHandler::ProcessScene. This is called a "kernel visit".
|
||||
- A kernel visit is triggered by some vis commands (e.g.,
|
||||
/vis/viewer/rebuild) and by a viewer if it deems necessary. For
|
||||
example, a kernel visit may not be required for a rotation, zoom, etc.,
|
||||
but required for a change from surface to wireframe.
|
||||
- The idea is that the scene tree can be passed to a GUI, the GUI can
|
||||
create a tree widget, and interactions with it raise UI commands such as
|
||||
/vis/scene/activateModel, /vis/set/touchable and /vis/touchable/set/...
|
||||
The viewer decides if this requires a kernel visit, otherwise it
|
||||
must update fSceneTree itself (utilities are provided -
|
||||
G4VViewer::TouchableSetVisibility/Colour).
|
||||
- G4VViewer:
|
||||
- Add scene tree and related functionality.
|
||||
- G4VSceneHandler::ProcessScene:
|
||||
- Add code to build scene tree.
|
||||
|
||||
## 2022-12-31 John Allison (visman-V11-01-00)
|
||||
- Clean up G4VUserVisAction:
|
||||
- The central pure virtual Draw() method is not intended to be called
|
||||
directly - see longer explanation in G4VUserVisAction.hh - so make
|
||||
it protected (more hygienic).
|
||||
- Improve comments in G4VUserVisAction.hh.
|
||||
|
||||
## 2022-11-25 Gabriele Cosmo (visman-V11-00-31)
|
||||
- Fixed compilation warning for implicit type conversions on macOS/XCode 14.1.
|
||||
|
||||
|
||||
@@ -354,11 +354,11 @@ protected:
|
||||
public:
|
||||
PseudoSceneFor3DRectMeshPositions
|
||||
(G4PhysicalVolumeModel* pvModel // input
|
||||
, G4int depth // input...the following are outputs by reference
|
||||
, const G4Mesh* pMesh // input...the following are outputs by reference
|
||||
, std::multimap<const G4Material*,const G4ThreeVector>& positionByMaterial
|
||||
, std::map<const G4Material*,NameAndVisAtts>& nameAndVisAttsByMaterial)
|
||||
: fpPVModel(pvModel)
|
||||
, fDepth(depth)
|
||||
, fpMesh(pMesh)
|
||||
, fPositionByMaterial(positionByMaterial)
|
||||
, fNameAndVisAttsByMaterial(nameAndVisAttsByMaterial)
|
||||
{}
|
||||
@@ -369,7 +369,7 @@ protected:
|
||||
// Do nothing if uninteresting solids found, e.g., the container if not marked invisible.
|
||||
}
|
||||
G4PhysicalVolumeModel* fpPVModel;
|
||||
G4int fDepth;
|
||||
const G4Mesh* fpMesh;
|
||||
std::multimap<const G4Material*,const G4ThreeVector>& fPositionByMaterial;
|
||||
std::map<const G4Material*,NameAndVisAtts>& fNameAndVisAttsByMaterial;
|
||||
};
|
||||
@@ -378,11 +378,11 @@ protected:
|
||||
public:
|
||||
PseudoSceneForTetVertices
|
||||
(G4PhysicalVolumeModel* pvModel // input
|
||||
, G4int depth // input...the following are outputs by reference
|
||||
, const G4Mesh* pMesh // input...the following are outputs by reference
|
||||
, std::multimap<const G4Material*,std::vector<G4ThreeVector>>& verticesByMaterial
|
||||
, std::map<const G4Material*,NameAndVisAtts>& nameAndVisAttsByMaterial)
|
||||
: fpPVModel(pvModel)
|
||||
, fDepth(depth)
|
||||
, fpMesh(pMesh)
|
||||
, fVerticesByMaterial(verticesByMaterial)
|
||||
, fNameAndVisAttsByMaterial(nameAndVisAttsByMaterial)
|
||||
{}
|
||||
@@ -393,7 +393,7 @@ protected:
|
||||
// Do nothing if uninteresting solids found, e.g., the container if not marked invisible.
|
||||
}
|
||||
G4PhysicalVolumeModel* fpPVModel;
|
||||
G4int fDepth;
|
||||
const G4Mesh* fpMesh;
|
||||
std::multimap<const G4Material*,std::vector<G4ThreeVector>>& fVerticesByMaterial;
|
||||
std::map<const G4Material*,NameAndVisAtts>& fNameAndVisAttsByMaterial;
|
||||
};
|
||||
|
||||
@@ -24,45 +24,50 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// Class Description:
|
||||
//
|
||||
// G4VUserVisAction is added to the scene by the command
|
||||
// /vis/scene/add/userAction, which instantiates a G4CallbackModel to
|
||||
// add to the RunDurationModels. Thus the pure virtual Draw() method
|
||||
// G4VUserVisAction is brought into effect by the command
|
||||
// /vis/scene/add/userAction. The vis manager instantiates a
|
||||
// G4CallbackModel when the vis action is registered, and adds
|
||||
// it to the scene. The pure virtual Draw() method
|
||||
// is invoked whenever the viewer needs to "visit the kernel", e.g.,
|
||||
// to remake its graphical database, if any, or simply to refresh the
|
||||
// screen. operator() is defined to satisfy the template
|
||||
// screen. It is not intended to be called directly. It is called
|
||||
// via the operator() which is defined to satisfy the template
|
||||
// G4CallbackModel<G4VUserVisAction>.
|
||||
//
|
||||
// See the User Guide for Application Developers, Section 8.8.7 and 8.8.8.
|
||||
|
||||
// A concrete Draw() method would normally make use of the Draw() methods
|
||||
// of the vis manager, e.g:
|
||||
// G4VVisManager* pVisManager = G4VVisManager::GetConcreteInstance();
|
||||
// if (pVisManager) {
|
||||
// pVisManager->Draw(G4Box("box",2*cm,2*cm,2*cm),
|
||||
// G4VisAttributes(G4Colour(1,1,0)));
|
||||
// ...
|
||||
// but it can also use pointers fpSceneHandler and pMP that give it
|
||||
// direct access to the current scene handler and modeling parameters
|
||||
// for more advanced use.
|
||||
//
|
||||
// See the User Guide for Application Developers.
|
||||
|
||||
#ifndef G4VUSERVISACTION_HH
|
||||
#define G4VUSERVISACTION_HH
|
||||
|
||||
#include "G4Transform3D.hh"
|
||||
|
||||
class G4VGraphicsScene;
|
||||
class G4ModelingParameters;
|
||||
|
||||
class G4VUserVisAction
|
||||
{
|
||||
public: // With description
|
||||
G4VUserVisAction()
|
||||
: fpSceneHandler(nullptr)
|
||||
, fpMP(nullptr)
|
||||
{}
|
||||
G4VUserVisAction(): fpSceneHandler(nullptr), fpMP(nullptr) {}
|
||||
virtual ~G4VUserVisAction() {}
|
||||
virtual void Draw() = 0;
|
||||
void operator()(G4VGraphicsScene& scene, const G4ModelingParameters* pMP) {
|
||||
fpSceneHandler = &scene;
|
||||
fpMP = pMP;
|
||||
Draw();
|
||||
}
|
||||
protected:
|
||||
virtual void Draw() = 0;
|
||||
G4VGraphicsScene* fpSceneHandler;
|
||||
const G4ModelingParameters* fpMP;
|
||||
};
|
||||
|
||||
@@ -37,8 +37,14 @@
|
||||
|
||||
#include "globals.hh"
|
||||
|
||||
#include "G4SceneTreeItem.hh"
|
||||
|
||||
#include "G4ViewParameters.hh"
|
||||
#include "G4PhysicalVolumeModel.hh"
|
||||
#include "G4PseudoScene.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
class G4VSceneHandler;
|
||||
|
||||
@@ -131,6 +137,57 @@ public: // With description
|
||||
virtual void SwitchToMasterThread ();
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Stuff for scene tree.
|
||||
/**
|
||||
- The scene tree is a tree of G4SceneTreeItem objects (see graphics-reps).
|
||||
- Its root is a data member fSceneTree of all viewers by virtue of
|
||||
G4VViewer inheritance,
|
||||
- G4SceneTreeItem is an aggregate of data members that represent
|
||||
properties of objects in the scene (G4Scene). Its data members are
|
||||
low-level types - G4String, G4VisAttributes and G4AttDef/Value - so
|
||||
that it can be used across categories, avoiding coupling.
|
||||
- The root item has children that represent the models (G4VModel
|
||||
sub-classes) in the scene.
|
||||
- For a G4PhysicalVolumeModel (detector components), its children and
|
||||
children's children, etc., imitate the geometry hierarchy of that
|
||||
model. These descendants are called "touchables".
|
||||
- There may be more than one G4PhysicalVolumeModel, depending how
|
||||
the user creates his/her scene.
|
||||
- The scene tree is reviewed, and updated if necessary, at every pass
|
||||
of G4VSceneHandler::ProcessScene. This is called a "kernel visit".
|
||||
- A kernel visit is triggered by some vis commands (e.g.,
|
||||
/vis/viewer/rebuild) and by a viewer if it deems necessary. For
|
||||
example, a kernel visit may not be required for a rotation, zoom, etc.,
|
||||
but required for a change from surface to wireframe.
|
||||
- The idea is that the scene tree can be passed to a GUI, the GUI can
|
||||
create a tree widget, and interactions with it raise UI commands such as
|
||||
/vis/scene/activateModel, /vis/set/touchable and /vis/touchable/set/...
|
||||
The viewer decides if this requires a kernel visit, otherwise it
|
||||
must update fSceneTree itself (utilities are provided -
|
||||
G4VViewer::TouchableSetVisibility/Colour).
|
||||
*/
|
||||
class SceneTreeScene: public G4PseudoScene {
|
||||
// G4PhysicalVolumeModel sends touchables to this scene
|
||||
public:
|
||||
SceneTreeScene() = default;
|
||||
~SceneTreeScene() = default;
|
||||
void SetViewer(G4VViewer* pViewer) {fpViewer = pViewer;}
|
||||
void SetModel(G4VModel* pModel);
|
||||
private:
|
||||
void ProcessVolume(const G4VSolid& solid) override;
|
||||
std::list<G4SceneTreeItem>::iterator FindOrInsertModel
|
||||
(const G4String& modelType,const G4String& modelID);
|
||||
std::list<G4SceneTreeItem>::iterator FindOrInsertTouchable
|
||||
(const G4String& modelID, G4SceneTreeItem& mother,
|
||||
G4int depth, const G4String& partialPathString, const G4String& fullPathString);
|
||||
G4VViewer* fpViewer = nullptr;
|
||||
G4VModel* fpModel = nullptr;
|
||||
};
|
||||
SceneTreeScene& AccessSceneTreeScene() {return fSceneTreeScene;}
|
||||
G4SceneTreeItem& AccessSceneTree() {return fSceneTree;}
|
||||
void UpdateGUISceneTree(); // A utility
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Access functions.
|
||||
const G4String& GetName () const;
|
||||
@@ -221,6 +278,8 @@ protected:
|
||||
G4ViewParameters fDefaultVP; // Default view parameters.
|
||||
G4double fKernelVisitElapsedTimeSeconds = 999.; // Default to a large number
|
||||
// Note: fKernelVisitElapsedTimeSeconds is measured in ProcessView().
|
||||
SceneTreeScene fSceneTreeScene; // G4PhysicalVolumeModel sends touchables to this scene
|
||||
G4SceneTreeItem fSceneTree;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Other parameters.
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "G4VMarker.hh"
|
||||
#include "G4ModelingParameters.hh"
|
||||
#include "G4PhysicalVolumesSearchScene.hh"
|
||||
#include "G4SceneTreeItem.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class G4UIcommand;
|
||||
@@ -165,6 +167,7 @@ protected:
|
||||
// handler.
|
||||
static G4bool fThereWasAViewer; // True if there was a viewer
|
||||
static G4ViewParameters fExistingVP; // Its view parameters
|
||||
static G4SceneTreeItem fExistingSceneTree; // Its scene tree
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ public: // With description
|
||||
|
||||
enum CutawayMode {
|
||||
cutawayUnion, // Union (addition) of result of each cutaway plane.
|
||||
cutawayIntersection // Intersection (multiplication) " .
|
||||
cutawayIntersection // Intersection (multiplication).
|
||||
};
|
||||
|
||||
enum RotationStyle {
|
||||
@@ -110,6 +110,7 @@ public: // With description
|
||||
};
|
||||
|
||||
enum SMROption { // Special Mesh Rendering Option
|
||||
meshAsDefault,
|
||||
meshAsDots,
|
||||
meshAsSurfaces
|
||||
};
|
||||
|
||||
@@ -53,6 +53,7 @@ private:
|
||||
G4UIcommand* fpCommandFindPath;
|
||||
G4UIcmdWithoutParameter* fpCommandLocalAxes;
|
||||
G4UIcmdWithABool* fpCommandShowExtent;
|
||||
G4UIcmdWithoutParameter* fpCommandTwinkle;
|
||||
G4UIcmdWithABool* fpCommandVolumeForField;
|
||||
};
|
||||
|
||||
|
||||
@@ -93,18 +93,34 @@
|
||||
#include "G4ToolsSGX11GLES.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_X11_ZB
|
||||
#include "G4ToolsSGX11ZB.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_WINDOWS_GLES
|
||||
#include "G4ToolsSGWindowsGLES.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_WINDOWS_ZB
|
||||
#include "G4ToolsSGWindowsZB.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_XT_GLES
|
||||
#include "G4ToolsSGXtGLES.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_XT_ZB
|
||||
#include "G4ToolsSGXtZB.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_QT_GLES
|
||||
#include "G4ToolsSGQtGLES.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_QT_ZB
|
||||
#include "G4ToolsSGQtZB.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_VTK
|
||||
#include "G4Vtk.hh" // no_geant4_module_check
|
||||
#endif
|
||||
@@ -113,6 +129,10 @@
|
||||
#include "G4VtkQt.hh" // no_geant4_module_check
|
||||
#endif
|
||||
|
||||
#if defined (G4VIS_USE_OPENGLQT) || (G4VIS_USE_TOOLSSG_QT_GLES)
|
||||
#include <QtGlobal>
|
||||
#endif
|
||||
|
||||
// The inline keyword prevents the compiler making an external
|
||||
// reference even though they cannot actually be inlined since they
|
||||
// are virtual functions. This prevents a "multiple definition" error
|
||||
@@ -148,6 +168,7 @@ G4VisExecutive::RegisterGraphicsSystems () {
|
||||
// super-abbreviated names and fallback names where approproiate.
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLQT
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
G4VGraphicsSystem* ogliqt = new G4OpenGLImmediateQt;
|
||||
G4VGraphicsSystem* oglsqt = new G4OpenGLStoredQt;
|
||||
RegisterGraphicsSystem(ogliqt);
|
||||
@@ -156,6 +177,7 @@ G4VisExecutive::RegisterGraphicsSystems () {
|
||||
oglsqt->AddNickname("OGL");
|
||||
oglsqt->AddNickname("OGLS");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLXM
|
||||
G4VGraphicsSystem* oglixm = new G4OpenGLImmediateXm;
|
||||
@@ -252,6 +274,12 @@ G4VisExecutive::RegisterGraphicsSystems () {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_X11_ZB
|
||||
G4VGraphicsSystem* tsg_x11_zb = new G4ToolsSGX11ZB;
|
||||
RegisterGraphicsSystem(tsg_x11_zb);
|
||||
tsg_x11_zb->AddNickname("TSGX11ZB");
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_XT_GLES
|
||||
G4VGraphicsSystem* tsg_xt_gles = new G4ToolsSGXtGLES;
|
||||
RegisterGraphicsSystem(tsg_xt_gles);
|
||||
@@ -261,19 +289,40 @@ G4VisExecutive::RegisterGraphicsSystems () {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_XT_ZB
|
||||
G4VGraphicsSystem* tsg_xt_zb = new G4ToolsSGXtZB;
|
||||
RegisterGraphicsSystem(tsg_xt_zb);
|
||||
tsg_xt_zb->AddNickname("TSGXtZB");
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_QT_GLES
|
||||
G4VGraphicsSystem* tsg_qt_gles = new G4ToolsSGQtGLES;
|
||||
RegisterGraphicsSystem(tsg_qt_gles);
|
||||
tsg_qt_gles->AddNickname("TSGQt");
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_QT_ZB
|
||||
G4VGraphicsSystem* tsg_qt_zb = new G4ToolsSGQtZB;
|
||||
RegisterGraphicsSystem(tsg_qt_zb);
|
||||
tsg_qt_zb->AddNickname("TSGQtZB");
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_WINDOWS_GLES
|
||||
G4VGraphicsSystem* tsg_windows_gles = new G4ToolsSGWindowsGLES;
|
||||
RegisterGraphicsSystem(tsg_windows_gles);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_WINDOWS_ZB
|
||||
G4VGraphicsSystem* tsg_windows_zb = new G4ToolsSGWindowsZB;
|
||||
RegisterGraphicsSystem(tsg_windows_zb);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_TOOLSSG_QT_GLES
|
||||
tsg_qt_gles->AddNickname("TSG");
|
||||
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
G4cout << " Qt6: Asking ToolsSG to stand in for OpenGL" << G4endl;
|
||||
tsg_qt_gles->AddNickname("OGL");
|
||||
# endif
|
||||
#elif defined(G4VIS_USE_TOOLSSG_XT_GLES)
|
||||
tsg_xt_gles->AddNickname("TSG");
|
||||
#elif defined(G4VIS_USE_TOOLSSG_X11_GLES)
|
||||
|
||||
@@ -96,7 +96,8 @@ geant4_module_link_libraries(G4vis_management
|
||||
G4run
|
||||
G4navigation
|
||||
G4digits
|
||||
G4heprandom)
|
||||
G4heprandom
|
||||
G4UIcore)
|
||||
|
||||
if(GEANT4_BUILD_MULTITHREADED)
|
||||
geant4_module_link_libraries(G4vis_management PRIVATE G4volumes)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user