Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4VViewer.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27//
28//
29// John Allison 27th March 1996
30// Abstract interface class for graphics views.
31
32#include "G4VViewer.hh"
33
35#include "G4Scene.hh"
36#include "G4Timer.hh"
37#include "G4Transform3D.hh"
38#include "G4UImanager.hh"
39#include "G4UIsession.hh"
40#include "G4VGraphicsSystem.hh"
42#include "G4VPhysicalVolume.hh"
43#include "G4VSceneHandler.hh"
44#include "G4VisManager.hh"
45#include "G4ios.hh"
46
47#include <sstream>
48
49G4VViewer::G4VViewer(G4VSceneHandler& sceneHandler, G4int id, const G4String& name)
50 : fSceneHandler(sceneHandler), fViewId(id), fNeedKernelVisit(true)
51{
52 if (name == "") {
53 std::ostringstream ost;
54 ost << fSceneHandler.GetName() << '-' << fViewId;
55 fName = ost.str();
56 }
57 else {
58 fName = name;
59 }
60 fShortName = fName.substr(0, fName.find(' '));
61 G4StrUtil::strip(fShortName);
62
65
67}
68
73
75{
76 fName = name;
77 fShortName = fName.substr(0, fName.find(' '));
78 G4StrUtil::strip(fShortName);
79}
80
82{
83 fNeedKernelVisit = true;
84
85 // At one time I thought we'd better notify all viewers. But I guess
86 // each viewer can take care of itself, so the following code is
87 // redundant (but keep it commented out for now). (John Allison)
88 // Notify all viewers that a kernel visit is required.
89 // const G4ViewerList& viewerList = fSceneHandler.GetViewerList ();
90 // G4ViewerListConstIterator i;
91 // for (i = viewerList.begin(); i != viewerList.end(); i++) {
92 // (*i) -> SetNeedKernelVisit ();
93 // }
94 // ??...but, there's a problem in OpenGL Stored which seems to
95 // require *all* viewers to revisit the kernel, so...
96 // const G4ViewerList& viewerList = fSceneHandler.GetViewerList ();
97 // G4ViewerListConstIterator i;
98 // for (i = viewerList.begin(); i != viewerList.end(); i++) {
99 // (*i) -> SetNeedKernelVisit (true);
100 // }
101 // Feb 2005 - commented out. Let's fix OpenGL if necessary.
102}
103
105
107
109{
110 // If the scene has changed, or if the concrete viewer has decided
111 // that it necessary to visit the kernel, perhaps because the view
112 // parameters have changed significantly (this should be done in the
113 // concrete viewer's DrawView)...
114 if (fNeedKernelVisit) {
115 // Reset flag. This must be done before ProcessScene to prevent
116 // recursive calls when recomputing transients...
117 G4Timer timer;
118 timer.Start();
119 fNeedKernelVisit = false;
123 timer.Stop();
125 }
126}
127
129{
130 fVP = vp;
131}
132
134 const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& fullPath)
135{
136 // Set the touchable for /vis/touchable/set/... commands.
137 std::ostringstream oss;
138 const auto& pvStore = G4PhysicalVolumeStore::GetInstance();
139 for (const auto& pvNodeId : fullPath) {
140 const auto& pv = pvNodeId.GetPhysicalVolume();
141 auto iterator = find(pvStore->cbegin(), pvStore->cend(), pv);
142 if (iterator == pvStore->cend()) {
144 ed << "Volume no longer in physical volume store.";
145 G4Exception("G4VViewer::SetTouchable", "visman0401", JustWarning, ed);
146 }
147 else {
148 oss << ' ' << pvNodeId.GetPhysicalVolume()->GetName() << ' ' << pvNodeId.GetCopyNo();
149 }
150 }
151 G4UImanager::GetUIpointer()->ApplyCommand("/vis/set/touchable" + oss.str());
152}
153
155 const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& fullPath, G4bool visibiity)
156{
157 // Changes the Vis Attribute Modifiers and scene tree WITHOUT triggering a rebuild.
158
159 // The following is equivalent to
160 // G4UImanager::GetUIpointer()->ApplyCommand("/vis/touchable/set/visibility ...");
161 // (assuming the touchable has already been set), but avoids view rebuild.
162
163 // Instantiate a working copy of a G4VisAttributes object...
164 G4VisAttributes workingVisAtts;
165 // and set the visibility.
166 workingVisAtts.SetVisibility(visibiity);
167
171 // G4ModelingParameters::VASVisibility (VAS = Vis Attribute Signifier)
172 // signifies that it is the visibility that should be picked out
173 // and merged with the touchable's normal vis attributes.
174
175 // Find scene tree item and set visibility
176 // The scene tree works with strings
177 G4String fullPathString = G4PhysicalVolumeModel::GetPVNamePathString(fullPath);
178 std::list<G4SceneTreeItem>::iterator foundIter;
179 if (fSceneTree.FindTouchableFromRoot(fullPathString, foundIter)) {
180 foundIter->AccessVisAttributes().SetVisibility(visibiity);
182 }
183 else {
185 ed << "Touchable \"" << fullPath << "\" not found";
186 G4Exception("G4VViewer::TouchableSetVisibility", "visman0402", JustWarning, ed);
187 }
188}
189
191 const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& fullPath,
192 const G4Colour& colour)
193{
194 // Changes the Vis Attribute Modifiers and scene tree WITHOUT triggering a rebuild.
195
196 // The following is equivalent to
197 // G4UImanager::GetUIpointer()->ApplyCommand("/vis/touchable/set/colour ...");
198 // (assuming the touchable has already been set), but avoids view rebuild.
199
200 // Instantiate a working copy of a G4VisAttributes object...
201 G4VisAttributes workingVisAtts;
202 // and set the colour.
203 workingVisAtts.SetColour(colour);
204
206 workingVisAtts, G4ModelingParameters::VASColour,
208 // G4ModelingParameters::VASColour (VAS = Vis Attribute Signifier)
209 // signifies that it is the colour that should be picked out
210 // and merged with the touchable's normal vis attributes.
211
212 // Find scene tree item and set colour
213 // The scene tree works with strings
214 G4String fullPathString = G4PhysicalVolumeModel::GetPVNamePathString(fullPath);
215 std::list<G4SceneTreeItem>::iterator foundIter;
216 if (fSceneTree.FindTouchableFromRoot(fullPathString, foundIter)) {
217 foundIter->AccessVisAttributes().SetColour(colour);
219 }
220 else {
222 ed << "Touchable \"" << fullPath << "\" not found";
223 G4Exception("G4VViewer::TouchableSetColour", "visman0403", JustWarning, ed);
224 }
225}
226
228{
230 auto uiWindow = dynamic_cast<G4VInteractiveSession*>(UI->GetG4UIWindow());
231 if (uiWindow) uiWindow->UpdateSceneTree(fSceneTree);
232}
233
235{
236 fpModel = pModel;
237
238 // Insert in tree (if not already inserted)
239 auto& modelType = fpModel->GetType();
240 auto& modelID = fpModel->GetGlobalDescription();
241 FindOrInsertModel(modelType, modelID);
242
243 auto pvModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
244 if (pvModel) {
245 // Limit the expanded depth to limit the number expanded so as not to swamp the GUI
246 G4int expanded = 0;
247 for (const auto& dn : pvModel->GetNumberOfTouchables()) {
248 expanded += dn.second;
249 if (fMaximumExpandedDepth < dn.first) fMaximumExpandedDepth = dn.first;
250 if (expanded > fMaximumExpanded) break;
251 }
252 }
253}
254
255std::list<G4SceneTreeItem>::iterator
256G4VViewer::SceneTreeScene::FindOrInsertModel(const G4String& modelType, const G4String& modelID)
257{
259 if (dynamic_cast<G4PhysicalVolumeModel*>(fpModel)) {
261 }
262 else {
264 }
265
266 auto& rootItem = fpViewer->fSceneTree;
267 rootItem.SetDescription(fpViewer->GetName());
268
269 // Find appropriate model
270 auto& modelItems = rootItem.AccessChildren();
271 auto modelIter = modelItems.begin();
272 auto pvModelIter = modelItems.end();
273 for (; modelIter != modelItems.end(); ++modelIter) {
274 if (modelIter->GetType() == G4SceneTreeItem::pvmodel) {
275 pvModelIter = modelIter; // Last PV model
276 }
277 if (modelIter->GetModelDescription() == modelID) break;
278 }
279
280 if (modelIter == modelItems.end()) {
281 // Model not seen before
282 G4SceneTreeItem modelItem(type);
283 modelItem.SetDescription("model");
284 modelItem.SetModelType(modelType);
285 modelItem.SetModelDescription(modelID);
286 if (pvModelIter != modelItems.end() && // There was pre-existing PV Model...
288 { // ...and the new model is also PV...
289 modelIter = rootItem.InsertChild(++pvModelIter, modelItem); // ...insert after, else...
290 }
291 else {
292 modelIter = rootItem.InsertChild(modelIter, modelItem); // ...insert at end
293 }
294 }
295 else {
296 // Existing model - mark visible == active
297 modelIter->AccessVisAttributes().SetVisibility(true);
298 }
299
300 return modelIter;
301}
302
303// clang-format off
304std::list<G4SceneTreeItem>::iterator G4VViewer::SceneTreeScene::FindOrInsertTouchable
305 (const G4String& modelID, G4SceneTreeItem& mother,
306 G4int depth, const G4String& partialPathString, const G4String& fullPathString)
307{
308 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
309 if (pPVModel == nullptr) {
311 ed << fpModel->GetType() << ": not a Physical VolumeModel";
312 G4Exception("G4VViewer::SceneTreeScene::FindOrInsertTouchable", "visman0404", FatalException, ed);
313 }
314 auto& children = mother.AccessChildren();
315 auto childIter = children.begin();
316 for (; childIter != children.end(); ++childIter) {
317 if (childIter->GetPVPath() == partialPathString) break;
318 }
319 if (childIter != children.end()) {
320
321 // Item already exists
322
323 if (childIter->GetType() == G4SceneTreeItem::ghost) {
324
325 // Previously it was a ghost - but maybe this time it's real
326
327 if (partialPathString == fullPathString) {
328 // Partial path string refers to the actual volume so it's a touchable
329 childIter->SetType(G4SceneTreeItem::touchable);
330 // Populate with information
331 childIter->SetDescription(fpModel->GetCurrentTag());
332 childIter->SetModelType(fpModel->GetType());
333 childIter->SetModelDescription(modelID);
334 childIter->SetPVPath(partialPathString);
335 if (fpVisAttributes) childIter->SetVisAttributes(*fpVisAttributes);
336 if (pPVModel) childIter->SetAttDefs(pPVModel->GetAttDefs());
337 if (pPVModel) childIter->SetAttValues(pPVModel->CreateCurrentAttValues());
338 } // Partial path string refers to an ancester - do nothing
339
340 } else {
341
342 // Already a pre-existing full touchable
343
344 if (partialPathString == fullPathString) {
345 // Partial path string refers to the actual volume
346 // Replace vis attributes (if any) - they might have changed
347 if (fpVisAttributes) childIter->SetVisAttributes(*fpVisAttributes);
348 } // Partial path string refers to an ancester - do nothing
349
350 }
351
352 } else {
353
354 // Item does not yet exist
355
356 if (partialPathString == fullPathString) {
357
358 // Partial path string refers to the actual volume
359 // Insert new touchable item
361 touchable.SetExpanded(depth > fMaximumExpandedDepth? false: true);
362 touchable.SetDescription(fpModel->GetCurrentTag());
363 touchable.SetModelType(fpModel->GetType());
364 touchable.SetModelDescription(modelID);
365 touchable.SetPVPath(partialPathString);
366 if (fpVisAttributes) touchable.SetVisAttributes(*fpVisAttributes);
367 if (pPVModel) touchable.SetAttDefs(pPVModel->GetAttDefs());
368 if (pPVModel) touchable.SetAttValues(pPVModel->CreateCurrentAttValues());
369 childIter = mother.InsertChild(childIter,touchable);
370
371 } else {
372
373 // Partial path string refers to an ancester - it's what we call a "ghost"
375 ghost.SetExpanded(depth > fMaximumExpandedDepth? false: true);
376 // Create a tag from the partial path
377 std::istringstream iss(partialPathString);
378 G4String name, copyNo;
379 while (iss >> name >> copyNo);
380 std::ostringstream oss;
381 oss << name << ':' << copyNo;
382 ghost.SetDescription(oss.str());
383 ghost.SetModelType(fpModel->GetType());
384 ghost.SetModelDescription(modelID);
385 ghost.SetPVPath(partialPathString);
386 ghost.AccessVisAttributes().SetVisibility(false);
387 childIter = mother.InsertChild(childIter,ghost);
388 }
389 }
390
391 return childIter;
392}
393// clang-format on
394
395void G4VViewer::SceneTreeScene::ProcessVolume(const G4VSolid&)
396{
397 auto& modelType = fpModel->GetType();
398 auto& modelID = fpModel->GetGlobalDescription();
399 auto modelIter = FindOrInsertModel(modelType, modelID);
400
401 auto pPVModel = dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
402 if (pPVModel) { // G4PhysicalVolumeModel
403
404 std::ostringstream oss;
405 oss << pPVModel->GetFullPVPath();
406 G4String fullPathString(oss.str()); // Has a leading space - OK
407
408 // Navigate scene tree and find or insert touchables one by one
409 const auto& nodeIDs = pPVModel->GetFullPVPath(); // std::vector<G4PhysicalVolumeNodeID>
410
411 // Work down the path - "name id", then "name id name id", etc.
412 G4String partialPathString;
413 auto currentIter = modelIter;
414 G4int depth = 0;
415 for (const auto& nodeID : nodeIDs) {
416 std::ostringstream oss1;
417 oss1 << nodeID;
418 partialPathString += ' ' + oss1.str(); // Has a leading space - OK
419 currentIter =
420 FindOrInsertTouchable(modelID, *currentIter, ++depth, partialPathString, fullPathString);
421 }
422 }
423 else {
424 // Orphan solid - what to do? Push an empty scene tree item????????????????????????
425 }
426}
427
428#ifdef G4MULTITHREADED
429
430void G4VViewer::DoneWithMasterThread()
431{
432 // G4cout << "G4VViewer::DoneWithMasterThread" << G4endl;
433}
434
435void G4VViewer::MovingToMasterThread()
436{
437 // G4cout << "G4VViewer::MovingToMasterThread" << G4endl;
438}
439
440void G4VViewer::SwitchToVisSubThread()
441{
442 // G4cout << "G4VViewer::SwitchToVisSubThread" << G4endl;
443}
444
445void G4VViewer::DoneWithVisSubThread()
446{
447 // G4cout << "G4VViewer::DoneWithVisSubThread" << G4endl;
448}
449
450void G4VViewer::MovingToVisSubThread()
451{
452 // G4cout << "G4VViewer::MovingToVisSubThread" << G4endl;
453}
454
455void G4VViewer::SwitchToMasterThread()
456{
457 // G4cout << "G4VViewer::SwitchToMasterThread" << G4endl;
458}
459
460#endif
461
462std::ostream& operator<<(std::ostream& os, const G4VViewer& v)
463{
464 os << "View " << v.fName << ":\n";
465 os << v.fVP;
466 return os;
467}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
static G4String GetPVNamePathString(const std::vector< G4PhysicalVolumeNodeID > &)
static G4ModelingParameters::PVNameCopyNoPath GetPVNameCopyNoPath(const std::vector< G4PhysicalVolumeNodeID > &)
static G4PhysicalVolumeStore * GetInstance()
std::list< G4SceneTreeItem > & AccessChildren()
G4bool FindTouchableFromRoot(const G4String &fullPathString, std::list< G4SceneTreeItem >::iterator &foundIter)
std::list< G4SceneTreeItem >::iterator InsertChild(std::list< G4SceneTreeItem >::iterator pos, const G4SceneTreeItem &item)
void SetType(Type type)
void Stop()
void Start()
G4double GetRealElapsed() const
Definition G4Timer.cc:113
G4int ApplyCommand(const char *aCommand)
G4UIsession * GetG4UIWindow() const
static G4UImanager * GetUIpointer()
virtual void UpdateSceneTree(const G4SceneTreeItem &)
const G4String & GetGlobalDescription() const
const G4String & GetType() const
virtual void ProcessScene()
const G4String & GetName() const
void RemoveViewerFromList(G4VViewer *pView)
virtual void ClearStore()
void SetModel(G4VModel *pModel)
Definition G4VViewer.cc:234
void SetTouchable(const std::vector< G4PhysicalVolumeModel::G4PhysicalVolumeNodeID > &fullPath)
Definition G4VViewer.cc:133
G4bool fNeedKernelVisit
Definition G4VViewer.hh:266
void SetName(const G4String &)
Definition G4VViewer.cc:74
friend std::ostream & operator<<(std::ostream &os, const G4VViewer &v)
Definition G4VViewer.cc:462
void ProcessView()
Definition G4VViewer.cc:108
G4VSceneHandler & fSceneHandler
Definition G4VViewer.hh:253
G4String fShortName
Definition G4VViewer.hh:256
G4double fKernelVisitElapsedTimeSeconds
Definition G4VViewer.hh:259
virtual ~G4VViewer()
Definition G4VViewer.cc:69
void UpdateGUISceneTree()
Definition G4VViewer.cc:227
G4String fName
Definition G4VViewer.hh:255
void NeedKernelVisit()
Definition G4VViewer.cc:81
G4ViewParameters fDefaultVP
Definition G4VViewer.hh:258
G4int fViewId
Definition G4VViewer.hh:254
void TouchableSetVisibility(const std::vector< G4PhysicalVolumeModel::G4PhysicalVolumeNodeID > &fullPath, G4bool visibility)
Definition G4VViewer.cc:154
G4ViewParameters fVP
Definition G4VViewer.hh:257
virtual void FinishView()
Definition G4VViewer.cc:104
G4VViewer(G4VSceneHandler &, G4int id, const G4String &name="")
Definition G4VViewer.cc:49
void SetViewParameters(const G4ViewParameters &vp)
Definition G4VViewer.cc:128
void TouchableSetColour(const std::vector< G4PhysicalVolumeModel::G4PhysicalVolumeNodeID > &fullPath, const G4Colour &)
Definition G4VViewer.cc:190
virtual void ShowView()
Definition G4VViewer.cc:106
G4SceneTreeItem fSceneTree
Definition G4VViewer.hh:262
void AddVisAttributesModifier(const G4ModelingParameters::VisAttributesModifier &)
void SetColour(const G4Colour &)
void SetVisibility(G4bool=true)
const G4ViewParameters & GetDefaultViewParameters() const
static G4VisManager * GetInstance()
const char * name(G4int ptype)