Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/management/src/G4VSceneHandler.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /visualization/management/src/G4VSceneHandler.cc (Version 11.3.0) and /visualization/management/src/G4VSceneHandler.cc (Version 11.1.2)


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