Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/modeling/src/G4PhysicalVolumeModel.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/modeling/src/G4PhysicalVolumeModel.cc (Version 11.3.0) and /visualization/modeling/src/G4PhysicalVolumeModel.cc (Version 11.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  31st December 1997.               29 // John Allison  31st December 1997.
 30 // Model for physical volumes.                     30 // Model for physical volumes.
 31                                                    31 
 32 #include "G4PhysicalVolumeModel.hh"                32 #include "G4PhysicalVolumeModel.hh"
 33                                                    33 
 34 #include "G4VGraphicsScene.hh"                     34 #include "G4VGraphicsScene.hh"
 35 #include "G4VPhysicalVolume.hh"                    35 #include "G4VPhysicalVolume.hh"
 36 #include "G4PhysicalVolumeStore.hh"                36 #include "G4PhysicalVolumeStore.hh"
 37 #include "G4VPVParameterisation.hh"                37 #include "G4VPVParameterisation.hh"
 38 #include "G4LogicalVolume.hh"                      38 #include "G4LogicalVolume.hh"
 39 #include "G4VSolid.hh"                             39 #include "G4VSolid.hh"
 40 #include "G4SubtractionSolid.hh"                   40 #include "G4SubtractionSolid.hh"
 41 #include "G4IntersectionSolid.hh"                  41 #include "G4IntersectionSolid.hh"
 42 #include "G4Material.hh"                           42 #include "G4Material.hh"
 43 #include "G4VisAttributes.hh"                      43 #include "G4VisAttributes.hh"
 44 #include "G4BoundingExtentScene.hh"                44 #include "G4BoundingExtentScene.hh"
 45 #include "G4TransportationManager.hh"              45 #include "G4TransportationManager.hh"
 46 #include "G4Polyhedron.hh"                         46 #include "G4Polyhedron.hh"
 47 #include "HepPolyhedronProcessor.h"                47 #include "HepPolyhedronProcessor.h"
 48 #include "G4AttDefStore.hh"                        48 #include "G4AttDefStore.hh"
 49 #include "G4AttDef.hh"                             49 #include "G4AttDef.hh"
 50 #include "G4AttValue.hh"                           50 #include "G4AttValue.hh"
 51 #include "G4UnitsTable.hh"                         51 #include "G4UnitsTable.hh"
 52 #include "G4Vector3D.hh"                           52 #include "G4Vector3D.hh"
 53 #include "G4Mesh.hh"                               53 #include "G4Mesh.hh"
 54                                                    54 
 55 #include <sstream>                                 55 #include <sstream>
 56 #include <iomanip>                                 56 #include <iomanip>
 57                                                    57 
 58 #define G4warn G4cout                              58 #define G4warn G4cout
 59                                                    59 
 60 G4PhysicalVolumeModel::G4PhysicalVolumeModel       60 G4PhysicalVolumeModel::G4PhysicalVolumeModel
 61 (G4VPhysicalVolume*            pVPV                61 (G4VPhysicalVolume*            pVPV
 62  , G4int                       requestedDepth      62  , G4int                       requestedDepth
 63  , const G4Transform3D&        modelTransform      63  , const G4Transform3D&        modelTransform
 64  , const G4ModelingParameters* pMP                 64  , const G4ModelingParameters* pMP
 65  , G4bool                      useFullExtent       65  , G4bool                      useFullExtent
 66  , const std::vector<G4PhysicalVolumeNodeID>&      66  , const std::vector<G4PhysicalVolumeNodeID>& baseFullPVPath)
 67 : G4VModel           (pMP)                         67 : G4VModel           (pMP)
 68 , fpTopPV            (pVPV)                        68 , fpTopPV            (pVPV)
 69 , fTopPVCopyNo       (pVPV? pVPV->GetCopyNo():     69 , fTopPVCopyNo       (pVPV? pVPV->GetCopyNo(): 0)
 70 , fRequestedDepth    (requestedDepth)              70 , fRequestedDepth    (requestedDepth)
 71 , fUseFullExtent     (useFullExtent)               71 , fUseFullExtent     (useFullExtent)
 72 , fTransform         (modelTransform)              72 , fTransform         (modelTransform)
 73 , fCurrentDepth      (0)                           73 , fCurrentDepth      (0)
 74 , fpCurrentPV        (fpTopPV)                     74 , fpCurrentPV        (fpTopPV)
 75 , fCurrentPVCopyNo   (fpTopPV? fpTopPV->GetCop     75 , fCurrentPVCopyNo   (fpTopPV? fpTopPV->GetCopyNo(): 0)
 76 , fpCurrentLV        (fpTopPV? fpTopPV->GetLog     76 , fpCurrentLV        (fpTopPV? fpTopPV->GetLogicalVolume(): 0)
 77 , fpCurrentMaterial  (fpCurrentLV? fpCurrentLV     77 , fpCurrentMaterial  (fpCurrentLV? fpCurrentLV->GetMaterial(): 0)
 78 , fCurrentTransform  (modelTransform)              78 , fCurrentTransform  (modelTransform)
 79 , fBaseFullPVPath    (baseFullPVPath)              79 , fBaseFullPVPath    (baseFullPVPath)
 80 , fFullPVPath        (fBaseFullPVPath)             80 , fFullPVPath        (fBaseFullPVPath)
 81 , fAbort             (false)                       81 , fAbort             (false)
 82 , fCurtailDescent    (false)                       82 , fCurtailDescent    (false)
 83 , fpClippingSolid    (0)                           83 , fpClippingSolid    (0)
 84 , fClippingMode      (subtraction)                 84 , fClippingMode      (subtraction)
 85 , fNClippers         (0)                           85 , fNClippers         (0)
 86 , fTotalTouchables   (0)                       << 
 87 {                                                  86 {
 88   fType = "G4PhysicalVolumeModel";                 87   fType = "G4PhysicalVolumeModel";
 89                                                    88 
 90   if (!fpTopPV) {                                  89   if (!fpTopPV) {
 91                                                    90 
 92     // In some circumstances creating an "empt     91     // In some circumstances creating an "empty" G4PhysicalVolumeModel is
 93     // allowed, so I have supressed the G4Exce     92     // allowed, so I have supressed the G4Exception below.  If it proves to
 94     // be a problem we might have to re-instat     93     // be a problem we might have to re-instate it, but it is unlikley to
 95     // be used except by visualisation experts     94     // be used except by visualisation experts.  See, for example, /vis/list,
 96     // where it is used simply to get a list o     95     // where it is used simply to get a list of G4AttDefs.
 97     //    G4Exception                              96     //    G4Exception
 98     //    ("G4PhysicalVolumeModel::G4PhysicalV     97     //    ("G4PhysicalVolumeModel::G4PhysicalVolumeModel",
 99     //     "modeling0010", FatalException, "Nu     98     //     "modeling0010", FatalException, "Null G4PhysicalVolumeModel pointer.");
100                                                    99 
101     fTopPVName = "NULL";                          100     fTopPVName = "NULL";
102     fGlobalTag = "Empty";                         101     fGlobalTag = "Empty";
103     fGlobalDescription = "G4PhysicalVolumeMode    102     fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
104                                                   103 
105   } else {                                        104   } else {
106                                                   105 
107     fTopPVName = fpTopPV -> GetName ();           106     fTopPVName = fpTopPV -> GetName ();
108     std::ostringstream oss;                       107     std::ostringstream oss;
109     oss << fpTopPV->GetName() << ':' << fpTopP    108     oss << fpTopPV->GetName() << ':' << fpTopPV->GetCopyNo()
110     << " BasePath:" << fBaseFullPVPath;           109     << " BasePath:" << fBaseFullPVPath;
111     fGlobalTag = oss.str();                       110     fGlobalTag = oss.str();
112     fGlobalDescription = "G4PhysicalVolumeMode    111     fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
113     CalculateExtent ();                           112     CalculateExtent ();
114   }                                               113   }
115 }                                                 114 }
116                                                   115 
117 G4PhysicalVolumeModel::~G4PhysicalVolumeModel     116 G4PhysicalVolumeModel::~G4PhysicalVolumeModel ()
118 {                                                 117 {
119   delete fpClippingSolid;                         118   delete fpClippingSolid;
120 }                                                 119 }
121                                                   120 
122 G4ModelingParameters::PVNameCopyNoPath G4Physi    121 G4ModelingParameters::PVNameCopyNoPath G4PhysicalVolumeModel::GetPVNameCopyNoPath
123 (const std::vector<G4PhysicalVolumeNodeID>& pa    122 (const std::vector<G4PhysicalVolumeNodeID>& path)
124 {                                                 123 {
125   G4ModelingParameters::PVNameCopyNoPath PVNam    124   G4ModelingParameters::PVNameCopyNoPath PVNameCopyNoPath;
126   for (const auto& node: path) {                  125   for (const auto& node: path) {
127     PVNameCopyNoPath.push_back                    126     PVNameCopyNoPath.push_back
128     (G4ModelingParameters::PVNameCopyNo           127     (G4ModelingParameters::PVNameCopyNo
129      (node.GetPhysicalVolume()->GetName(),node    128      (node.GetPhysicalVolume()->GetName(),node.GetCopyNo()));
130   }                                               129   }
131   return PVNameCopyNoPath;                        130   return PVNameCopyNoPath;
132 }                                                 131 }
133                                                   132 
134 G4String G4PhysicalVolumeModel::GetPVNamePathS    133 G4String G4PhysicalVolumeModel::GetPVNamePathString
135 (const std::vector<G4PhysicalVolumeNodeID>& pa    134 (const std::vector<G4PhysicalVolumeNodeID>& path)
136 // Converts to path string, e.g., " World 0 En    135 // Converts to path string, e.g., " World 0 Envelope 0 Shape1 0".
137 // Note leading space character.                  136 // Note leading space character.
138 {                                                 137 {
139   std::ostringstream oss;                         138   std::ostringstream oss;
140   oss << path;                                    139   oss << path;
141   return oss.str();                               140   return oss.str();
142 }                                                 141 }
143                                                   142 
144 void G4PhysicalVolumeModel::CalculateExtent ()    143 void G4PhysicalVolumeModel::CalculateExtent ()
145 {                                                 144 {
146   // To handle paramaterisations, set copy num    145   // To handle paramaterisations, set copy number and compute dimensions
147   // to get extent right                          146   // to get extent right
148   G4VPVParameterisation* pP = fpTopPV -> GetPa    147   G4VPVParameterisation* pP = fpTopPV -> GetParameterisation ();
149   if (pP) {                                       148   if (pP) {
150     fpTopPV -> SetCopyNo (fTopPVCopyNo);          149     fpTopPV -> SetCopyNo (fTopPVCopyNo);
151     G4VSolid* solid = pP -> ComputeSolid (fTop    150     G4VSolid* solid = pP -> ComputeSolid (fTopPVCopyNo, fpTopPV);
152     solid -> ComputeDimensions (pP, fTopPVCopy    151     solid -> ComputeDimensions (pP, fTopPVCopyNo, fpTopPV);
153   }                                               152   }
154   if (fUseFullExtent) {                           153   if (fUseFullExtent) {
155     fExtent = fpTopPV -> GetLogicalVolume () -    154     fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
156   } else {                                        155   } else {
157     // Calculate extent of *drawn* volumes, i.    156     // Calculate extent of *drawn* volumes, i.e., ignoring culled, e.g.,
158     // invisible volumes, by traversing the wh    157     // invisible volumes, by traversing the whole geometry hierarchy below
159     // this physical volume.                      158     // this physical volume.
160     G4BoundingExtentScene beScene(this);          159     G4BoundingExtentScene beScene(this);
161     const G4int tempRequestedDepth = fRequeste    160     const G4int tempRequestedDepth = fRequestedDepth;
162     const G4Transform3D tempTransform = fTrans    161     const G4Transform3D tempTransform = fTransform;
163     const G4ModelingParameters* tempMP = fpMP;    162     const G4ModelingParameters* tempMP = fpMP;
164     fRequestedDepth = -1;  // Always search to    163     fRequestedDepth = -1;  // Always search to all depths to define extent.
165     fTransform = G4Transform3D();  // Extent i    164     fTransform = G4Transform3D();  // Extent is in local cooridinates
166     G4ModelingParameters mParams                  165     G4ModelingParameters mParams
167       (0,      // No default vis attributes ne    166       (0,      // No default vis attributes needed.
168        G4ModelingParameters::wf,  // wireframe    167        G4ModelingParameters::wf,  // wireframe (not relevant for this).
169        true,   // Global culling.                 168        true,   // Global culling.
170        true,   // Cull invisible volumes.         169        true,   // Cull invisible volumes.
171        false,  // Density culling.                170        false,  // Density culling.
172        0.,     // Density (not relevant if den    171        0.,     // Density (not relevant if density culling false).
173        true,   // Cull daughters of opaque mot    172        true,   // Cull daughters of opaque mothers.
174        24);    // No of sides (not relevant fo    173        24);    // No of sides (not relevant for this operation).
175     mParams.SetSpecialMeshRendering(true);  //    174     mParams.SetSpecialMeshRendering(true);  // Avoids traversing parameterisations
176     fpMP = &mParams;                              175     fpMP = &mParams;
177     DescribeYourselfTo (beScene);                 176     DescribeYourselfTo (beScene);
178     fExtent = beScene.GetBoundingExtent();        177     fExtent = beScene.GetBoundingExtent();
179     fpMP = tempMP;                                178     fpMP = tempMP;
180     fTransform = tempTransform;                   179     fTransform = tempTransform;
181     fRequestedDepth = tempRequestedDepth;         180     fRequestedDepth = tempRequestedDepth;
182   }                                               181   }
183   G4double radius = fExtent.GetExtentRadius();    182   G4double radius = fExtent.GetExtentRadius();
184   if (radius < 0.) {  // Nothing in the scene     183   if (radius < 0.) {  // Nothing in the scene - revert to top extent
185     fExtent = fpTopPV -> GetLogicalVolume () -    184     fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
186   }                                               185   }
187   fExtent.Transform(fTransform);                  186   fExtent.Transform(fTransform);
188 }                                                 187 }
189                                                   188 
190 void G4PhysicalVolumeModel::DescribeYourselfTo    189 void G4PhysicalVolumeModel::DescribeYourselfTo
191 (G4VGraphicsScene& sceneHandler)                  190 (G4VGraphicsScene& sceneHandler)
192 {                                                 191 {
193   if (!fpTopPV) {                                 192   if (!fpTopPV) {
194     G4Exception                                   193     G4Exception
195     ("G4PhysicalVolumeModel::DescribeYourselfT    194     ("G4PhysicalVolumeModel::DescribeYourselfTo",
196      "modeling0012", FatalException, "No model    195      "modeling0012", FatalException, "No model.");
197     return;  // Should never reach here, but k    196     return;  // Should never reach here, but keeps Coverity happy.
198   }                                               197   }
199                                                   198 
200   if (!fpMP) {                                    199   if (!fpMP) {
201     G4Exception                                   200     G4Exception
202     ("G4PhysicalVolumeModel::DescribeYourselfT    201     ("G4PhysicalVolumeModel::DescribeYourselfTo",
203      "modeling0013", FatalException, "No model    202      "modeling0013", FatalException, "No modeling parameters.");
204     return;  // Should never reach here, but k    203     return;  // Should never reach here, but keeps Coverity happy.
205   }                                               204   }
206                                                   205 
207   fNClippers = 0;                                 206   fNClippers = 0;
208   G4DisplacedSolid* pSectionSolid = fpMP->GetS    207   G4DisplacedSolid* pSectionSolid = fpMP->GetSectionSolid();
209   G4DisplacedSolid* pCutawaySolid = fpMP->GetC    208   G4DisplacedSolid* pCutawaySolid = fpMP->GetCutawaySolid();
210   if (fpClippingSolid) fNClippers++;              209   if (fpClippingSolid) fNClippers++;
211   if (pSectionSolid)   fNClippers++;              210   if (pSectionSolid)   fNClippers++;
212   if (pCutawaySolid)   fNClippers++;              211   if (pCutawaySolid)   fNClippers++;
213   if (fNClippers > 1) {                           212   if (fNClippers > 1) {
214     G4ExceptionDescription ed;                    213     G4ExceptionDescription ed;
215     ed << "More than one solid cutter/clipper:    214     ed << "More than one solid cutter/clipper:";
216     if (fpClippingSolid) ed << "\nclipper in f    215     if (fpClippingSolid) ed << "\nclipper in force";
217     if (pSectionSolid)   ed << "\nsectioner in    216     if (pSectionSolid)   ed << "\nsectioner in force";
218     if (pCutawaySolid)   ed << "\ncutaway in f    217     if (pCutawaySolid)   ed << "\ncutaway in force";
219     G4Exception("G4PhysicalVolumeModel::Descri    218     G4Exception("G4PhysicalVolumeModel::DescribeSolid", "modeling0016", JustWarning, ed);
220   }                                               219   }
221                                                   220 
222   G4Transform3D startingTransformation = fTran    221   G4Transform3D startingTransformation = fTransform;
223                                                   222 
224   fNTouchables.clear();  // Keeps count of tou    223   fNTouchables.clear();  // Keeps count of touchable drawn at each depth
225                                                   224 
226   VisitGeometryAndGetVisReps                      225   VisitGeometryAndGetVisReps
227     (fpTopPV,                                     226     (fpTopPV,
228      fRequestedDepth,                             227      fRequestedDepth,
229      startingTransformation,                      228      startingTransformation,
230      sceneHandler);                               229      sceneHandler);
231                                                   230 
232   fTotalTouchables = 0;                        << 
233   for (const auto& entry : fNTouchables) {     << 
234     fTotalTouchables += entry.second;          << 
235   }                                            << 
236                                                << 
237   // Reset or clear data...                       231   // Reset or clear data...
238   fCurrentDepth     = 0;                          232   fCurrentDepth     = 0;
239   fpCurrentPV       = fpTopPV;                    233   fpCurrentPV       = fpTopPV;
240   fCurrentPVCopyNo  = fpTopPV->GetCopyNo();       234   fCurrentPVCopyNo  = fpTopPV->GetCopyNo();
241   fpCurrentLV       = fpTopPV->GetLogicalVolum    235   fpCurrentLV       = fpTopPV->GetLogicalVolume();
242   fpCurrentMaterial = fpCurrentLV? fpCurrentLV    236   fpCurrentMaterial = fpCurrentLV? fpCurrentLV->GetMaterial(): 0;
243   fFullPVPath       = fBaseFullPVPath;            237   fFullPVPath       = fBaseFullPVPath;
244   fDrawnPVPath.clear();                           238   fDrawnPVPath.clear();
245   fAbort            = false;                      239   fAbort            = false;
246   fCurtailDescent   = false;                      240   fCurtailDescent   = false;
247 }                                                 241 }
248                                                   242 
249 G4String G4PhysicalVolumeModel::GetCurrentTag     243 G4String G4PhysicalVolumeModel::GetCurrentTag () const
250 {                                                 244 {
251   if (fpCurrentPV) {                              245   if (fpCurrentPV) {
252     std::ostringstream o;                         246     std::ostringstream o;
253     o << fpCurrentPV -> GetCopyNo ();             247     o << fpCurrentPV -> GetCopyNo ();
254     return fpCurrentPV -> GetName () + ":" + o    248     return fpCurrentPV -> GetName () + ":" + o.str();
255   }                                               249   }
256   else {                                          250   else {
257     return "WARNING: NO CURRENT VOLUME - globa    251     return "WARNING: NO CURRENT VOLUME - global tag is " + fGlobalTag;
258   }                                               252   }
259 }                                                 253 }
260                                                   254 
261 G4String G4PhysicalVolumeModel::GetCurrentDesc    255 G4String G4PhysicalVolumeModel::GetCurrentDescription () const
262 {                                                 256 {
263   return "G4PhysicalVolumeModel " + GetCurrent    257   return "G4PhysicalVolumeModel " + GetCurrentTag ();
264 }                                                 258 }
265                                                   259 
266 void G4PhysicalVolumeModel::VisitGeometryAndGe    260 void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
267 (G4VPhysicalVolume* pVPV,                         261 (G4VPhysicalVolume* pVPV,
268  G4int requestedDepth,                            262  G4int requestedDepth,
269  const G4Transform3D& theAT,                      263  const G4Transform3D& theAT,
270  G4VGraphicsScene& sceneHandler)                  264  G4VGraphicsScene& sceneHandler)
271 {                                                 265 {
272   // Visits geometry structure to a given dept    266   // Visits geometry structure to a given depth (requestedDepth), starting
273   //   at given physical volume with given sta    267   //   at given physical volume with given starting transformation and
274   //   describes volumes to the scene handler.    268   //   describes volumes to the scene handler.
275   // requestedDepth < 0 (default) implies full    269   // requestedDepth < 0 (default) implies full visit.
276   // theAT is the Accumulated Transformation.     270   // theAT is the Accumulated Transformation.
277                                                   271 
278   // Find corresponding logical volume and (la    272   // Find corresponding logical volume and (later) solid, storing in
279   // local variables to preserve re-entrancy.     273   // local variables to preserve re-entrancy.
280   G4LogicalVolume* pLV  = pVPV -> GetLogicalVo    274   G4LogicalVolume* pLV  = pVPV -> GetLogicalVolume ();
281   G4VSolid* pSol = nullptr;                       275   G4VSolid* pSol = nullptr;
282   G4Material* pMaterial = nullptr;                276   G4Material* pMaterial = nullptr;
283                                                   277 
284   if (!(pVPV -> IsReplicated ())) {               278   if (!(pVPV -> IsReplicated ())) {
285     // Non-replicated physical volume.            279     // Non-replicated physical volume.
286     pSol = pLV -> GetSolid ();                    280     pSol = pLV -> GetSolid ();
287     pMaterial = pLV -> GetMaterial ();            281     pMaterial = pLV -> GetMaterial ();
288     DescribeAndDescend (pVPV, requestedDepth,     282     DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
289       theAT, sceneHandler);                       283       theAT, sceneHandler);
290   }                                               284   }
291   else {                                          285   else {
292     // Replicated or parametrised physical vol    286     // Replicated or parametrised physical volume.
293     EAxis axis;                                   287     EAxis axis;
294     G4int nReplicas;                              288     G4int nReplicas;
295     G4double width;                               289     G4double width;
296     G4double offset;                              290     G4double offset;
297     G4bool consuming;                             291     G4bool consuming;
298     pVPV -> GetReplicationData (axis, nReplica    292     pVPV -> GetReplicationData (axis, nReplicas, width,  offset, consuming);
299     G4int nBegin = 0;                             293     G4int nBegin = 0;
300     G4int nEnd = nReplicas;                       294     G4int nEnd = nReplicas;
301     if (fCurrentDepth == 0) { // i.e., top vol    295     if (fCurrentDepth == 0) { // i.e., top volume
302       nBegin = fTopPVCopyNo;  // Describe only    296       nBegin = fTopPVCopyNo;  // Describe only one volume, namely the one
303       nEnd = nBegin + 1;      // specified by     297       nEnd = nBegin + 1;      // specified by the given copy number.
304     }                                             298     }
305     G4VPVParameterisation* pP = pVPV -> GetPar    299     G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
306     if (pP) {  // Parametrised volume.            300     if (pP) {  // Parametrised volume.
307       for (int n = nBegin; n < nEnd; n++) {       301       for (int n = nBegin; n < nEnd; n++) {
308         pSol = pP -> ComputeSolid (n, pVPV);   << 302   pSol = pP -> ComputeSolid (n, pVPV);
309         pP -> ComputeTransformation (n, pVPV); << 303   pP -> ComputeTransformation (n, pVPV);
310         pSol -> ComputeDimensions (pP, n, pVPV << 304   pSol -> ComputeDimensions (pP, n, pVPV);
311         pVPV -> SetCopyNo (n);                 << 305   pVPV -> SetCopyNo (n);
312         fCurrentPVCopyNo = n;                     306         fCurrentPVCopyNo = n;
313         // Create a touchable of current paren << 307   // Create a touchable of current parent for ComputeMaterial.
314         // fFullPVPath has not been updated ye << 308   // fFullPVPath has not been updated yet so at this point it
315         // corresponds to the parent.          << 309   // corresponds to the parent.
316         G4PhysicalVolumeModelTouchable parentT << 310   G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
317         pMaterial = pP -> ComputeMaterial (n,  << 311   pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
318         DescribeAndDescend (pVPV, requestedDep << 312   DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
319                             theAT, sceneHandle << 313           theAT, sceneHandler);
320       }                                           314       }
321     }                                             315     }
322     else {  // Plain replicated volume.  From     316     else {  // Plain replicated volume.  From geometry_guide.txt...
323       // The replica's positions are claculate    317       // The replica's positions are claculated by means of a linear formula.
324       // Replication may occur along:             318       // Replication may occur along:
325       //                                          319       // 
326       // o Cartesian axes (kXAxis,kYAxis,kZAxi    320       // o Cartesian axes (kXAxis,kYAxis,kZAxis)
327       //                                          321       // 
328       //   The replications, of specified widt    322       //   The replications, of specified width have coordinates of
329       //   form (-width*(nReplicas-1)*0.5+n*wi    323       //   form (-width*(nReplicas-1)*0.5+n*width,0,0) where n=0.. nReplicas-1
330       //   for the case of kXAxis, and are unr    324       //   for the case of kXAxis, and are unrotated.
331       //                                          325       // 
332       // o Radial axis (cylindrical polar) (kR    326       // o Radial axis (cylindrical polar) (kRho)
333       //                                          327       // 
334       //   The replications are cons/tubs sect    328       //   The replications are cons/tubs sections, centred on the origin
335       //   and are unrotated.                     329       //   and are unrotated.
336       //   They have radii of width*n+offset t    330       //   They have radii of width*n+offset to width*(n+1)+offset
337       //                      where n=0..nRepl    331       //                      where n=0..nReplicas-1
338       //                                          332       // 
339       // o Phi axis (cylindrical polar) (kPhi)    333       // o Phi axis (cylindrical polar) (kPhi)
340       //   The replications are `phi sections'    334       //   The replications are `phi sections' or wedges, and of cons/tubs form
341       //   They have phi of offset+n*width to     335       //   They have phi of offset+n*width to offset+(n+1)*width where
342       //   n=0..nReplicas-1                       336       //   n=0..nReplicas-1
343       //                                          337       // 
344       pSol = pLV -> GetSolid ();                  338       pSol = pLV -> GetSolid ();
345       pMaterial = pLV -> GetMaterial ();          339       pMaterial = pLV -> GetMaterial ();
346       G4ThreeVector originalTranslation = pVPV    340       G4ThreeVector originalTranslation = pVPV -> GetTranslation ();
347       G4RotationMatrix* pOriginalRotation = pV    341       G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
348       G4double originalRMin = 0., originalRMax    342       G4double originalRMin = 0., originalRMax = 0.;
349       if (axis == kRho && pSol->GetEntityType(    343       if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
350         originalRMin = ((G4Tubs*)pSol)->GetInn << 344   originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
351         originalRMax = ((G4Tubs*)pSol)->GetOut << 345   originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
352       }                                           346       }
353       G4bool visualisable = true;                 347       G4bool visualisable = true;
354       for (int n = nBegin; n < nEnd; n++) {       348       for (int n = nBegin; n < nEnd; n++) {
355         G4ThreeVector translation;  // Identit << 349   G4ThreeVector translation;  // Identity.
356         G4RotationMatrix rotation;  // Identit << 350   G4RotationMatrix rotation;  // Identity - life enough for visualizing.
357         G4RotationMatrix* pRotation = 0;       << 351   G4RotationMatrix* pRotation = 0;
358         switch (axis) {                        << 352   switch (axis) {
359           default:                             << 353   default:
360           case kXAxis:                         << 354   case kXAxis:
361             translation = G4ThreeVector (-widt << 355     translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
362             break;                             << 356     break;
363           case kYAxis:                         << 357   case kYAxis:
364             translation = G4ThreeVector (0,-wi << 358     translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
365             break;                             << 359     break;
366           case kZAxis:                         << 360   case kZAxis:
367             translation = G4ThreeVector (0,0,- << 361     translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
368             break;                             << 362     break;
369           case kRho:                           << 363   case kRho:
370             if (pSol->GetEntityType() == "G4Tu << 364     if (pSol->GetEntityType() == "G4Tubs") {
371               ((G4Tubs*)pSol)->SetInnerRadius( << 365       ((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
372               ((G4Tubs*)pSol)->SetOuterRadius( << 366       ((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
373             } else {                           << 367     } else {
374               if (fpMP->IsWarning())           << 368       if (fpMP->IsWarning())
375                 G4warn <<                      << 369         G4warn <<
376                 "G4PhysicalVolumeModel::VisitG << 370     "G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
377                 "\n  built-in replicated volum << 371     "\n  built-in replicated volumes replicated in radius for "
378                 << pSol->GetEntityType() <<    << 372          << pSol->GetEntityType() <<
379                 "-type\n  solids (your solid \ << 373     "-type\n  solids (your solid \""
380                 << pSol->GetName() <<          << 374          << pSol->GetName() <<
381                 "\") are not visualisable."    << 375     "\") are not visualisable."
382                 << G4endl;                     << 376          << G4endl;
383               visualisable = false;            << 377       visualisable = false;
384             }                                  << 378     }
385             break;                             << 379     break;
386           case kPhi:                           << 380   case kPhi:
387             rotation.rotateZ (-(offset+(n+0.5) << 381     rotation.rotateZ (-(offset+(n+0.5)*width));
388             // Minus Sign because for the phys << 382     // Minus Sign because for the physical volume we need the
389             // coordinate system rotation.     << 383     // coordinate system rotation.
390             pRotation = &rotation;             << 384     pRotation = &rotation;
391             break;                             << 385     break;
392         }                                      << 386   } 
393         pVPV -> SetTranslation (translation);  << 387   pVPV -> SetTranslation (translation);
394         pVPV -> SetRotation    (pRotation);    << 388   pVPV -> SetRotation    (pRotation);
395         pVPV -> SetCopyNo (n);                 << 389   pVPV -> SetCopyNo (n);
396         fCurrentPVCopyNo = n;                     390         fCurrentPVCopyNo = n;
397         if (visualisable) {                    << 391   if (visualisable) {
398           DescribeAndDescend (pVPV, requestedD << 392     DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
399                               theAT, sceneHand << 393           theAT, sceneHandler);
400         }                                      << 394   }
401       }                                           395       }
402       // Restore originals...                     396       // Restore originals...
403       pVPV -> SetTranslation (originalTranslat    397       pVPV -> SetTranslation (originalTranslation);
404       pVPV -> SetRotation    (pOriginalRotatio    398       pVPV -> SetRotation    (pOriginalRotation);
405       if (axis == kRho && pSol->GetEntityType(    399       if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
406         ((G4Tubs*)pSol)->SetInnerRadius(origin << 400   ((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
407         ((G4Tubs*)pSol)->SetOuterRadius(origin << 401   ((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
408       }                                           402       }
409     }                                             403     }
410   }                                               404   }
411 }                                                 405 }
412                                                   406 
413 void G4PhysicalVolumeModel::DescribeAndDescend    407 void G4PhysicalVolumeModel::DescribeAndDescend
414 (G4VPhysicalVolume* pVPV,                         408 (G4VPhysicalVolume* pVPV,
415  G4int requestedDepth,                            409  G4int requestedDepth,
416  G4LogicalVolume* pLV,                            410  G4LogicalVolume* pLV,
417  G4VSolid* pSol,                                  411  G4VSolid* pSol,
418  G4Material* pMaterial,                           412  G4Material* pMaterial,
419  const G4Transform3D& theAT,                      413  const G4Transform3D& theAT,
420  G4VGraphicsScene& sceneHandler)                  414  G4VGraphicsScene& sceneHandler)
421 {                                                 415 {
422   // Maintain useful data members...              416   // Maintain useful data members...
423   fpCurrentPV = pVPV;                             417   fpCurrentPV = pVPV;
424   fCurrentPVCopyNo = pVPV->GetCopyNo();           418   fCurrentPVCopyNo = pVPV->GetCopyNo();
425   fpCurrentLV = pLV;                              419   fpCurrentLV = pLV;
426   fpCurrentMaterial = pMaterial;                  420   fpCurrentMaterial = pMaterial;
427                                                   421 
428   // Create a nodeID for use below - note the     422   // Create a nodeID for use below - note the "drawn" flag is true
429   G4int copyNo = fpCurrentPV->GetCopyNo();        423   G4int copyNo = fpCurrentPV->GetCopyNo();
430   auto nodeID = G4PhysicalVolumeNodeID            424   auto nodeID = G4PhysicalVolumeNodeID
431   (fpCurrentPV,copyNo,fCurrentDepth,fCurrentTr    425   (fpCurrentPV,copyNo,fCurrentDepth,fCurrentTransform);
432                                                   426 
433   // Update full path of physical volumes...      427   // Update full path of physical volumes...
434   fFullPVPath.push_back(nodeID);                  428   fFullPVPath.push_back(nodeID);
435                                                   429 
436   const G4RotationMatrix objectRotation = pVPV    430   const G4RotationMatrix objectRotation = pVPV -> GetObjectRotationValue ();
437   const G4ThreeVector&  translation     = pVPV    431   const G4ThreeVector&  translation     = pVPV -> GetTranslation ();
438   G4Transform3D theLT (G4Transform3D (objectRo    432   G4Transform3D theLT (G4Transform3D (objectRotation, translation));
439                                                   433 
440   // Compute the accumulated transformation...    434   // Compute the accumulated transformation...
441   // Note that top volume's transformation rel    435   // Note that top volume's transformation relative to the world
442   // coordinate system is specified in theAT =    436   // coordinate system is specified in theAT == startingTransformation
443   // = fTransform (see DescribeYourselfTo), so    437   // = fTransform (see DescribeYourselfTo), so first time through the
444   // volume's own transformation, which is onl    438   // volume's own transformation, which is only relative to its
445   // mother, i.e., not relative to the world c    439   // mother, i.e., not relative to the world coordinate system, should
446   // not be accumulated.                          440   // not be accumulated.
447   G4Transform3D theNewAT (theAT);                 441   G4Transform3D theNewAT (theAT);
448   if (fCurrentDepth != 0) theNewAT = theAT * t    442   if (fCurrentDepth != 0) theNewAT = theAT * theLT;
449   fCurrentTransform = theNewAT;                   443   fCurrentTransform = theNewAT;
450                                                   444 
451   const G4VisAttributes* pVisAttribs = pLV->Ge    445   const G4VisAttributes* pVisAttribs = pLV->GetVisAttributes();
452   //  If the volume does not have any vis attr    446   //  If the volume does not have any vis attributes, create it.
453   G4VisAttributes* tempVisAtts = nullptr;         447   G4VisAttributes* tempVisAtts = nullptr;
454   if (!pVisAttribs) {                             448   if (!pVisAttribs) {
455     if (fpMP->GetDefaultVisAttributes()) {        449     if (fpMP->GetDefaultVisAttributes()) {
456       tempVisAtts = new G4VisAttributes(*fpMP-    450       tempVisAtts = new G4VisAttributes(*fpMP->GetDefaultVisAttributes());
457     } else {                                      451     } else {
458       tempVisAtts = new G4VisAttributes;          452       tempVisAtts = new G4VisAttributes;
459     }                                             453     }
460     // The user may request /vis/viewer/set/co    454     // The user may request /vis/viewer/set/colourByDensity.
461     if (fpMP->GetCBDAlgorithmNumber() == 1) {     455     if (fpMP->GetCBDAlgorithmNumber() == 1) {
462       // Algorithm 1: 3 parameters: Simple rai    456       // Algorithm 1: 3 parameters: Simple rainbow mapping.
463       if (fpMP->GetCBDParameters().size() != 3    457       if (fpMP->GetCBDParameters().size() != 3) {
464         G4Exception("G4PhysicalVolumeModelTouc    458         G4Exception("G4PhysicalVolumeModelTouchable::DescribeAndDescend",
465                     "modeling0014",               459                     "modeling0014",
466                     FatalErrorInArgument,         460                     FatalErrorInArgument,
467                     "Algorithm-parameter misma    461                     "Algorithm-parameter mismatch for Colour By Density");
468       } else {                                    462       } else {
469         const G4double d = pMaterial? pMateria    463         const G4double d = pMaterial? pMaterial->GetDensity(): 0.;
470         const G4double d0 = fpMP->GetCBDParame    464         const G4double d0 = fpMP->GetCBDParameters()[0]; // Invisible d < d0.
471         const G4double d1 = fpMP->GetCBDParame    465         const G4double d1 = fpMP->GetCBDParameters()[1]; // Rainbow d0->d1->d2.
472         const G4double d2 = fpMP->GetCBDParame    466         const G4double d2 = fpMP->GetCBDParameters()[2]; // Blue d > d2.
473         if (d < d0) { // Density < d0 is invis    467         if (d < d0) { // Density < d0 is invisible.
474           tempVisAtts->SetVisibility(false);      468           tempVisAtts->SetVisibility(false);
475         } else { // Intermediate densities are    469         } else { // Intermediate densities are on a spectrum.
476           G4double red, green, blue;              470           G4double red, green, blue;
477           if (d < d1) {                           471           if (d < d1) {
478             red = (d1-d)/(d1-d0); green = (d-d    472             red = (d1-d)/(d1-d0); green = (d-d0)/(d1-d0); blue = 0.;
479           } else if (d < d2) {                    473           } else if (d < d2) {
480             red = 0.; green = (d2-d)/(d2-d1);     474             red = 0.; green = (d2-d)/(d2-d1); blue = (d-d1)/(d2-d1);
481           } else {  // Density >= d2 is blue.     475           } else {  // Density >= d2 is blue.
482             red = 0.; green = 0.; blue = 1.;      476             red = 0.; green = 0.; blue = 1.;
483           }                                       477           }
484           tempVisAtts->SetColour(G4Colour(red,    478           tempVisAtts->SetColour(G4Colour(red,green,blue));
485         }                                         479         }
486       }                                           480       }
487     } else if (fpMP->GetCBDAlgorithmNumber() =    481     } else if (fpMP->GetCBDAlgorithmNumber() == 2) {
488       // Algorithm 2                              482       // Algorithm 2
489       // ...etc.                                  483       // ...etc.
490     }                                             484     }
491     pVisAttribs = tempVisAtts;                    485     pVisAttribs = tempVisAtts;
492   }                                               486   }
493   // From here, can assume pVisAttribs is a va    487   // From here, can assume pVisAttribs is a valid pointer.  This is necessary
494   // because PreAddSolid needs a vis attribute    488   // because PreAddSolid needs a vis attributes object.
495                                                   489 
496   // Check if vis attributes are to be modifie    490   // Check if vis attributes are to be modified by a /vis/touchable/set/ command.
497   const auto& vams = fpMP->GetVisAttributesMod    491   const auto& vams = fpMP->GetVisAttributesModifiers();
498   if (vams.size()) {                              492   if (vams.size()) {
499     // OK, we have some VAMs (Vis Attributes M    493     // OK, we have some VAMs (Vis Attributes Modifiers).
500     for (const auto& vam: vams) {                 494     for (const auto& vam: vams) {
501       const auto& vamPath = vam.GetPVNameCopyN    495       const auto& vamPath = vam.GetPVNameCopyNoPath();
502       if (vamPath.size() == fFullPVPath.size()    496       if (vamPath.size() == fFullPVPath.size()) {
503         // OK, we have a size match.              497         // OK, we have a size match.
504         // Check the volume name/copy number p    498         // Check the volume name/copy number path.
505         auto iVAMNameCopyNo = vamPath.begin();    499         auto iVAMNameCopyNo = vamPath.begin();
506         auto iPVNodeId = fFullPVPath.begin();     500         auto iPVNodeId = fFullPVPath.begin();
507         for (; iVAMNameCopyNo != vamPath.end()    501         for (; iVAMNameCopyNo != vamPath.end(); ++iVAMNameCopyNo, ++iPVNodeId) {
508           if (!(                                  502           if (!(
509                 iVAMNameCopyNo->GetName() ==      503                 iVAMNameCopyNo->GetName() ==
510                 iPVNodeId->GetPhysicalVolume()    504                 iPVNodeId->GetPhysicalVolume()->GetName() &&
511                 iVAMNameCopyNo->GetCopyNo() ==    505                 iVAMNameCopyNo->GetCopyNo() ==
512                 iPVNodeId->GetPhysicalVolume()    506                 iPVNodeId->GetPhysicalVolume()->GetCopyNo()
513                 )) {                              507                 )) {
514             // This path element does NOT matc    508             // This path element does NOT match.
515             break;                                509             break;
516           }                                       510           }
517         }                                         511         }
518         if (iVAMNameCopyNo == vamPath.end()) {    512         if (iVAMNameCopyNo == vamPath.end()) {
519           // OK, the paths match (the above lo    513           // OK, the paths match (the above loop terminated normally).
520           // Create a vis atts object for the     514           // Create a vis atts object for the modified vis atts.
521           // It is static so that we may retur    515           // It is static so that we may return a reliable pointer to it.
522           static G4VisAttributes modifiedVisAt    516           static G4VisAttributes modifiedVisAtts;
523           // Initialise it with the current vi    517           // Initialise it with the current vis atts and reset the pointer.
524           modifiedVisAtts = *pVisAttribs;         518           modifiedVisAtts = *pVisAttribs;
525           pVisAttribs = &modifiedVisAtts;         519           pVisAttribs = &modifiedVisAtts;
526           const G4VisAttributes& transVisAtts     520           const G4VisAttributes& transVisAtts = vam.GetVisAttributes();
527           switch (vam.GetVisAttributesSignifie    521           switch (vam.GetVisAttributesSignifier()) {
528             case G4ModelingParameters::VASVisi    522             case G4ModelingParameters::VASVisibility:
529               modifiedVisAtts.SetVisibility(tr    523               modifiedVisAtts.SetVisibility(transVisAtts.IsVisible());
530               break;                              524               break;
531             case G4ModelingParameters::VASDaug    525             case G4ModelingParameters::VASDaughtersInvisible:
532               modifiedVisAtts.SetDaughtersInvi    526               modifiedVisAtts.SetDaughtersInvisible
533               (transVisAtts.IsDaughtersInvisib    527               (transVisAtts.IsDaughtersInvisible());
534               break;                              528               break;
535             case G4ModelingParameters::VASColo    529             case G4ModelingParameters::VASColour:
536               modifiedVisAtts.SetColour(transV    530               modifiedVisAtts.SetColour(transVisAtts.GetColour());
537               break;                              531               break;
538             case G4ModelingParameters::VASLine    532             case G4ModelingParameters::VASLineStyle:
539               modifiedVisAtts.SetLineStyle(tra    533               modifiedVisAtts.SetLineStyle(transVisAtts.GetLineStyle());
540               break;                              534               break;
541             case G4ModelingParameters::VASLine    535             case G4ModelingParameters::VASLineWidth:
542               modifiedVisAtts.SetLineWidth(tra    536               modifiedVisAtts.SetLineWidth(transVisAtts.GetLineWidth());
543               break;                              537               break;
544             case G4ModelingParameters::VASForc    538             case G4ModelingParameters::VASForceWireframe:
545               if (transVisAtts.IsForceDrawingS    539               if (transVisAtts.IsForceDrawingStyle()) {
546                 if (transVisAtts.GetForcedDraw    540                 if (transVisAtts.GetForcedDrawingStyle() ==
547                     G4VisAttributes::wireframe    541                     G4VisAttributes::wireframe) {
548                   modifiedVisAtts.SetForceWire    542                   modifiedVisAtts.SetForceWireframe(true);
549                 }                                 543                 }
550               }                                   544               }
551               break;                              545               break;
552             case G4ModelingParameters::VASForc    546             case G4ModelingParameters::VASForceSolid:
553               if (transVisAtts.IsForceDrawingS    547               if (transVisAtts.IsForceDrawingStyle()) {
554                 if (transVisAtts.GetForcedDraw    548                 if (transVisAtts.GetForcedDrawingStyle() ==
555                     G4VisAttributes::solid) {     549                     G4VisAttributes::solid) {
556                   modifiedVisAtts.SetForceSoli    550                   modifiedVisAtts.SetForceSolid(true);
557                 }                                 551                 }
558               }                                   552               }
559               break;                              553               break;
560             case G4ModelingParameters::VASForc    554             case G4ModelingParameters::VASForceCloud:
561               if (transVisAtts.IsForceDrawingS    555               if (transVisAtts.IsForceDrawingStyle()) {
562                 if (transVisAtts.GetForcedDraw    556                 if (transVisAtts.GetForcedDrawingStyle() ==
563                     G4VisAttributes::cloud) {     557                     G4VisAttributes::cloud) {
564                   modifiedVisAtts.SetForceClou    558                   modifiedVisAtts.SetForceCloud(true);
565                 }                                 559                 }
566               }                                   560               }
567               break;                              561               break;
568             case G4ModelingParameters::VASForc    562             case G4ModelingParameters::VASForceNumberOfCloudPoints:
569               modifiedVisAtts.SetForceNumberOf    563               modifiedVisAtts.SetForceNumberOfCloudPoints
570               (transVisAtts.GetForcedNumberOfC    564               (transVisAtts.GetForcedNumberOfCloudPoints());
571               break;                              565               break;
572             case G4ModelingParameters::VASForc    566             case G4ModelingParameters::VASForceAuxEdgeVisible:
573               if (transVisAtts.IsForceAuxEdgeV    567               if (transVisAtts.IsForceAuxEdgeVisible()) {
574                 modifiedVisAtts.SetForceAuxEdg    568                 modifiedVisAtts.SetForceAuxEdgeVisible
575                 (transVisAtts.IsForcedAuxEdgeV    569                 (transVisAtts.IsForcedAuxEdgeVisible());
576               }                                   570               }
577               break;                              571               break;
578             case G4ModelingParameters::VASForc    572             case G4ModelingParameters::VASForceLineSegmentsPerCircle:
579               modifiedVisAtts.SetForceLineSegm    573               modifiedVisAtts.SetForceLineSegmentsPerCircle
580               (transVisAtts.GetForcedLineSegme    574               (transVisAtts.GetForcedLineSegmentsPerCircle());
581               break;                              575               break;
582           }                                       576           }
583         }                                         577         }
584       }                                           578       }
585     }                                             579     }
586   }                                               580   }
587                                                   581 
588   // Check for special mesh rendering             582   // Check for special mesh rendering
589   if (fpMP->IsSpecialMeshRendering()) {           583   if (fpMP->IsSpecialMeshRendering()) {
590     G4bool potentialG4Mesh = false;               584     G4bool potentialG4Mesh = false;
591     if (fpMP->GetSpecialMeshVolumes().empty())    585     if (fpMP->GetSpecialMeshVolumes().empty()) {
592       // No volumes specified - all are potent    586       // No volumes specified - all are potentially possible
593       potentialG4Mesh = true;                     587       potentialG4Mesh = true;
594     } else {                                      588     } else {
595       // Name and (optionally) copy number of     589       // Name and (optionally) copy number of container volume is specified
596       for (const auto& pvNameCopyNo: fpMP->Get    590       for (const auto& pvNameCopyNo: fpMP->GetSpecialMeshVolumes()) {
597         if (pVPV->GetName() == pvNameCopyNo.Ge    591         if (pVPV->GetName() == pvNameCopyNo.GetName()) {
598           // We have a name match                 592           // We have a name match
599           if (pvNameCopyNo.GetCopyNo() < 0) {     593           if (pvNameCopyNo.GetCopyNo() < 0) {
600             // Any copy number is OK              594             // Any copy number is OK
601             potentialG4Mesh = true;               595             potentialG4Mesh = true;
602           } else {                                596           } else {
603             if (pVPV->GetCopyNo() == pvNameCop    597             if (pVPV->GetCopyNo() == pvNameCopyNo.GetCopyNo()) {
604               // We have a name and copy numbe    598               // We have a name and copy number match
605               potentialG4Mesh = true;             599               potentialG4Mesh = true;
606             }                                     600             }
607           }                                       601           }
608         }                                         602         }
609       }                                           603       }
610     }                                             604     }
611     if (potentialG4Mesh) {                        605     if (potentialG4Mesh) {
612       // Create - or at least attempt to creat    606       // Create - or at least attempt to create - a mesh. If it cannot be created
613       // out of this pVPV the type will be "in    607       // out of this pVPV the type will be "invalid".
614       G4Mesh mesh(pVPV,theNewAT);                 608       G4Mesh mesh(pVPV,theNewAT);
615       if (mesh.GetMeshType() != G4Mesh::invali    609       if (mesh.GetMeshType() != G4Mesh::invalid) {
616         // Create "artificial" nodeID to repre    610         // Create "artificial" nodeID to represent the replaced volumes
617         G4int artCopyNo = 0;                      611         G4int artCopyNo = 0;
618         auto artPV = mesh.GetParameterisedVolu    612         auto artPV = mesh.GetParameterisedVolume();
619         auto artDepth = fCurrentDepth + 1;        613         auto artDepth = fCurrentDepth + 1;
620         auto artNodeID = G4PhysicalVolumeNodeI    614         auto artNodeID = G4PhysicalVolumeNodeID(artPV,artCopyNo,artDepth);
621         fFullPVPath.push_back(artNodeID);         615         fFullPVPath.push_back(artNodeID);
622         fDrawnPVPath.push_back(artNodeID);        616         fDrawnPVPath.push_back(artNodeID);
623         sceneHandler.AddCompound(mesh);           617         sceneHandler.AddCompound(mesh);
624         fFullPVPath.pop_back();                   618         fFullPVPath.pop_back();
625         fDrawnPVPath.pop_back();                  619         fDrawnPVPath.pop_back();
626         delete tempVisAtts;  // Needs cleaning    620         delete tempVisAtts;  // Needs cleaning up (Coverity warning!!)
627         return;  // Mesh found and processed -    621         return;  // Mesh found and processed - nothing more to do.
628       }  // else continue processing              622       }  // else continue processing
629     }                                             623     }
630   }                                               624   }
631                                                   625 
632   // Make decision to draw...                     626   // Make decision to draw...
633   G4bool thisToBeDrawn = true;                    627   G4bool thisToBeDrawn = true;
634                                                   628 
635   // There are various reasons why this volume    629   // There are various reasons why this volume
636   // might not be drawn...                        630   // might not be drawn...
637   G4bool culling = fpMP->IsCulling();             631   G4bool culling = fpMP->IsCulling();
638   G4bool cullingInvisible = fpMP->IsCullingInv    632   G4bool cullingInvisible = fpMP->IsCullingInvisible();
639   G4bool markedVisible                            633   G4bool markedVisible
640   = pVisAttribs->IsVisible() && pVisAttribs->G    634   = pVisAttribs->IsVisible() && pVisAttribs->GetColour().GetAlpha() > 0;
641   G4bool cullingLowDensity = fpMP->IsDensityCu    635   G4bool cullingLowDensity = fpMP->IsDensityCulling();
642   G4double density = pMaterial? pMaterial->Get    636   G4double density = pMaterial? pMaterial->GetDensity(): 0;
643   G4double densityCut = fpMP -> GetVisibleDens    637   G4double densityCut = fpMP -> GetVisibleDensity ();
644                                                   638 
645   // 1) Global culling is on....                  639   // 1) Global culling is on....
646   if (culling) {                                  640   if (culling) {
647     // 2) Culling of invisible volumes is on..    641     // 2) Culling of invisible volumes is on...
648     if (cullingInvisible) {                       642     if (cullingInvisible) {
649       // 3) ...and the volume is marked not vi    643       // 3) ...and the volume is marked not visible...
650       if (!markedVisible) thisToBeDrawn = fals    644       if (!markedVisible) thisToBeDrawn = false;
651     }                                             645     }
652     // 4) Or culling of low density volumes is    646     // 4) Or culling of low density volumes is on...
653     if (cullingLowDensity) {                      647     if (cullingLowDensity) {
654       // 5) ...and density is less than cut va    648       // 5) ...and density is less than cut value...
655       if (density < densityCut) thisToBeDrawn     649       if (density < densityCut) thisToBeDrawn = false;
656     }                                             650     }
657   }                                               651   }
658   // 6) The user has asked for all further tra    652   // 6) The user has asked for all further traversing to be aborted...
659   if (fAbort) thisToBeDrawn = false;              653   if (fAbort) thisToBeDrawn = false;
660                                                   654 
661   // Set "drawn" flag (it was true by default)    655   // Set "drawn" flag (it was true by default) - thisToBeDrawn may be false
662   nodeID.SetDrawn(thisToBeDrawn);                 656   nodeID.SetDrawn(thisToBeDrawn);
663                                                   657 
664   if (thisToBeDrawn) {                            658   if (thisToBeDrawn) {
665                                                   659 
666     // Update path of drawn physical volumes..    660     // Update path of drawn physical volumes...
667     fDrawnPVPath.push_back(nodeID);               661     fDrawnPVPath.push_back(nodeID);
668                                                   662 
669     if (fpMP->IsExplode() && fDrawnPVPath.size    663     if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
670       // For top-level drawn volumes, explode     664       // For top-level drawn volumes, explode along radius...
671       G4Transform3D centering = G4Translate3D(    665       G4Transform3D centering = G4Translate3D(fpMP->GetExplodeCentre());
672       G4Transform3D centred = centering.invers    666       G4Transform3D centred = centering.inverse() * theNewAT;
673       G4Scale3D oldScale;                         667       G4Scale3D oldScale;
674       G4Rotate3D oldRotation;                     668       G4Rotate3D oldRotation;
675       G4Translate3D oldTranslation;               669       G4Translate3D oldTranslation;
676       centred.getDecomposition(oldScale, oldRo    670       centred.getDecomposition(oldScale, oldRotation, oldTranslation);
677       G4double explodeFactor = fpMP->GetExplod    671       G4double explodeFactor = fpMP->GetExplodeFactor();
678       G4Translate3D newTranslation =              672       G4Translate3D newTranslation =
679   G4Translate3D(explodeFactor * oldTranslation    673   G4Translate3D(explodeFactor * oldTranslation.dx(),
680           explodeFactor * oldTranslation.dy(),    674           explodeFactor * oldTranslation.dy(),
681           explodeFactor * oldTranslation.dz())    675           explodeFactor * oldTranslation.dz());
682       theNewAT = centering * newTranslation *     676       theNewAT = centering * newTranslation * oldRotation * oldScale;
683     }                                             677     }
684                                                   678 
685     auto fullDepth = fCurrentDepth + (G4int)fB    679     auto fullDepth = fCurrentDepth + (G4int)fBaseFullPVPath.size();
686     fNTouchables[fullDepth]++;  // Increment f    680     fNTouchables[fullDepth]++;  // Increment for every touchable drawn at each depth
687                                                   681 
688     DescribeSolid (theNewAT, pSol, pVisAttribs    682     DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
689                                                   683 
690   }                                               684   }
691                                                   685 
692   // Make decision to draw daughters, if any.     686   // Make decision to draw daughters, if any.  There are various
693   // reasons why daughters might not be drawn.    687   // reasons why daughters might not be drawn...
694                                                   688 
695   // First, reasons that do not depend on cull    689   // First, reasons that do not depend on culling policy...
696   G4int nDaughters = (G4int)pLV->GetNoDaughter    690   G4int nDaughters = (G4int)pLV->GetNoDaughters();
697   G4bool daughtersToBeDrawn = true;               691   G4bool daughtersToBeDrawn = true;
698   // 1) There are no daughters...                 692   // 1) There are no daughters...
699   if (!nDaughters) daughtersToBeDrawn = false;    693   if (!nDaughters) daughtersToBeDrawn = false;
700   // 2) We are at the limit if requested depth    694   // 2) We are at the limit if requested depth...
701   else if (requestedDepth == 0) daughtersToBeD    695   else if (requestedDepth == 0) daughtersToBeDrawn = false;
702   // 3) The user has asked for all further tra    696   // 3) The user has asked for all further traversing to be aborted...
703   else if (fAbort) daughtersToBeDrawn = false;    697   else if (fAbort) daughtersToBeDrawn = false;
704   // 4) The user has asked that the descent be    698   // 4) The user has asked that the descent be curtailed...
705   else if (fCurtailDescent) daughtersToBeDrawn    699   else if (fCurtailDescent) daughtersToBeDrawn = false;
706                                                   700 
707   // Now, reasons that depend on culling polic    701   // Now, reasons that depend on culling policy...
708   else {                                          702   else {
709     G4bool daughtersInvisible = pVisAttribs->I    703     G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
710     // Culling of covered daughters request.      704     // Culling of covered daughters request.  This is computed in
711     // G4VSceneHandler::CreateModelingParamete    705     // G4VSceneHandler::CreateModelingParameters() depending on view
712     // parameters...                              706     // parameters...
713     G4bool cullingCovered = fpMP->IsCullingCov    707     G4bool cullingCovered = fpMP->IsCullingCovered();
714     G4bool surfaceDrawing =                       708     G4bool surfaceDrawing =
715       fpMP->GetDrawingStyle() == G4ModelingPar    709       fpMP->GetDrawingStyle() == G4ModelingParameters::hsr ||
716       fpMP->GetDrawingStyle() == G4ModelingPar    710       fpMP->GetDrawingStyle() == G4ModelingParameters::hlhsr;    
717     if (pVisAttribs->IsForceDrawingStyle()) {     711     if (pVisAttribs->IsForceDrawingStyle()) {
718       switch (pVisAttribs->GetForcedDrawingSty    712       switch (pVisAttribs->GetForcedDrawingStyle()) {
719       default:                                    713       default:
720       case G4VisAttributes::wireframe: surface    714       case G4VisAttributes::wireframe: surfaceDrawing = false; break;
721       case G4VisAttributes::solid: surfaceDraw    715       case G4VisAttributes::solid: surfaceDrawing = true; break;
722       }                                           716       }
723     }                                             717     }
724     G4bool opaque = pVisAttribs->GetColour().G    718     G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
725     // 5) Global culling is on....                719     // 5) Global culling is on....
726     if (culling) {                                720     if (culling) {
727       // 6) ..and culling of invisible volumes    721       // 6) ..and culling of invisible volumes is on...
728       if (cullingInvisible) {                     722       if (cullingInvisible) {
729   // 7) ...and the mother requests daughters i    723   // 7) ...and the mother requests daughters invisible
730   if (daughtersInvisible) daughtersToBeDrawn =    724   if (daughtersInvisible) daughtersToBeDrawn = false;
731       }                                           725       }
732       // 8) Or culling of covered daughters is    726       // 8) Or culling of covered daughters is requested...
733       if (cullingCovered) {                       727       if (cullingCovered) {
734   // 9) ...and surface drawing is operating...    728   // 9) ...and surface drawing is operating...
735   if (surfaceDrawing) {                           729   if (surfaceDrawing) {
736     // 10) ...but only if mother is visible...    730     // 10) ...but only if mother is visible...
737     if (thisToBeDrawn) {                          731     if (thisToBeDrawn) {
738       // 11) ...and opaque...                     732       // 11) ...and opaque...
739         if (opaque) daughtersToBeDrawn = false    733         if (opaque) daughtersToBeDrawn = false;
740     }                                             734     }
741   }                                               735   }
742       }                                           736       }
743     }                                             737     }
744   }                                               738   }
745                                                   739 
746   if (daughtersToBeDrawn) {                       740   if (daughtersToBeDrawn) {
747     for (G4int iDaughter = 0; iDaughter < nDau    741     for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
748       // Store daughter pVPV in local variable    742       // Store daughter pVPV in local variable ready for recursion...
749       G4VPhysicalVolume* pDaughterVPV = pLV ->    743       G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
750       // Descend the geometry structure recurs    744       // Descend the geometry structure recursively...
751       fCurrentDepth++;                            745       fCurrentDepth++;
752       VisitGeometryAndGetVisReps                  746       VisitGeometryAndGetVisReps
753   (pDaughterVPV, requestedDepth - 1, theNewAT,    747   (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
754       fCurrentDepth--;                            748       fCurrentDepth--;
755     }                                             749     }
756   }                                               750   }
757                                                   751 
758   // Clean up                                     752   // Clean up
759   delete tempVisAtts;                             753   delete tempVisAtts;
760                                                   754 
761   // Reset for normal descending of next volum    755   // Reset for normal descending of next volume at this level...
762   fCurtailDescent = false;                        756   fCurtailDescent = false;
763                                                   757 
764   // Pop item from paths physical volumes...      758   // Pop item from paths physical volumes...
765   fFullPVPath.pop_back();                         759   fFullPVPath.pop_back();
766   if (thisToBeDrawn) {                            760   if (thisToBeDrawn) {
767     fDrawnPVPath.pop_back();                      761     fDrawnPVPath.pop_back();
768   }                                               762   }
769 }                                                 763 }
770                                                   764 
771 namespace                                         765 namespace
772 {                                                 766 {
773   G4bool SubtractionBoundingLimits(const G4VSo    767   G4bool SubtractionBoundingLimits(const G4VSolid* target)
774   {                                               768   {
775     // Algorithm from G4SubtractionSolid::Boun    769     // Algorithm from G4SubtractionSolid::BoundingLimits
776     // Since it is unclear how the shape of th    770     // Since it is unclear how the shape of the first solid will be changed
777     // after subtraction, just return its orig    771     // after subtraction, just return its original bounding box.
778     G4ThreeVector pMin, pMax;                     772     G4ThreeVector pMin, pMax;
779     const auto& pSolA = target;                   773     const auto& pSolA = target;
780     pSolA->BoundingLimits(pMin,pMax);             774     pSolA->BoundingLimits(pMin,pMax);
781     // Check correctness of the bounding box      775     // Check correctness of the bounding box
782     if (pMin.x() >= pMax.x() || pMin.y() >= pM    776     if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) {
783       // Bad bounding box (min >= max)            777       // Bad bounding box (min >= max)
784       // This signifies a subtraction of non-i    778       // This signifies a subtraction of non-intersecting volumes
785       return false;                               779       return false;
786     }                                             780     }
787     return true;                                  781     return true;
788   }                                               782   }
789                                                   783 
790   G4bool IntersectionBoundingLimits(const G4VS    784   G4bool IntersectionBoundingLimits(const G4VSolid* target, const G4DisplacedSolid* intersector)
791   {                                               785   {
792     // Algorithm from G4IntersectionSolid::Bou    786     // Algorithm from G4IntersectionSolid::BoundingLimits
793     G4ThreeVector pMin, pMax;                     787     G4ThreeVector pMin, pMax;
794     G4ThreeVector minA,maxA, minB,maxB;           788     G4ThreeVector minA,maxA, minB,maxB;
795     const auto& pSolA = target;                   789     const auto& pSolA = target;
796     const auto& pSolB = intersector;              790     const auto& pSolB = intersector;
797     pSolA->BoundingLimits(minA,maxA);             791     pSolA->BoundingLimits(minA,maxA);
798     pSolB->BoundingLimits(minB,maxB);             792     pSolB->BoundingLimits(minB,maxB);
799     pMin.set(std::max(minA.x(),minB.x()),         793     pMin.set(std::max(minA.x(),minB.x()),
800              std::max(minA.y(),minB.y()),         794              std::max(minA.y(),minB.y()),
801              std::max(minA.z(),minB.z()));        795              std::max(minA.z(),minB.z()));
802     pMax.set(std::min(maxA.x(),maxB.x()),         796     pMax.set(std::min(maxA.x(),maxB.x()),
803              std::min(maxA.y(),maxB.y()),         797              std::min(maxA.y(),maxB.y()),
804              std::min(maxA.z(),maxB.z()));        798              std::min(maxA.z(),maxB.z()));
805     if (pMin.x() >= pMax.x() || pMin.y() >= pM    799     if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) {
806       // Bad bounding box (min >= max)            800       // Bad bounding box (min >= max)
807       // This signifies a subtraction of non-i    801       // This signifies a subtraction of non-intersecting volumes
808       return false;                               802       return false;
809     }                                             803     }
810     return true;                                  804     return true;
811   }                                               805   }
812 }                                                 806 }
813                                                   807 
814 void G4PhysicalVolumeModel::DescribeSolid         808 void G4PhysicalVolumeModel::DescribeSolid
815 (const G4Transform3D& theAT,                      809 (const G4Transform3D& theAT,
816  G4VSolid* pSol,                                  810  G4VSolid* pSol,
817  const G4VisAttributes* pVisAttribs,              811  const G4VisAttributes* pVisAttribs,
818  G4VGraphicsScene& sceneHandler)                  812  G4VGraphicsScene& sceneHandler)
819 {                                                 813 {
820   G4DisplacedSolid* pSectionSolid = fpMP->GetS    814   G4DisplacedSolid* pSectionSolid = fpMP->GetSectionSolid();
821   G4DisplacedSolid* pCutawaySolid = fpMP->GetC    815   G4DisplacedSolid* pCutawaySolid = fpMP->GetCutawaySolid();
822                                                   816 
823   if (fNClippers <= 0 || fNClippers > 1) {        817   if (fNClippers <= 0 || fNClippers > 1) {
824                                                   818 
825     // Normal case - no clipping, etc. - or, i    819     // Normal case - no clipping, etc. - or, illegally, more than one of those
826     sceneHandler.PreAddSolid (theAT, *pVisAttr    820     sceneHandler.PreAddSolid (theAT, *pVisAttribs);
827     pSol -> DescribeYourselfTo (sceneHandler);    821     pSol -> DescribeYourselfTo (sceneHandler);  // Standard treatment.
828     sceneHandler.PostAddSolid ();                 822     sceneHandler.PostAddSolid ();
829                                                   823 
830   } else {  // fNClippers == 1                    824   } else {  // fNClippers == 1
831                                                   825 
832     G4VSolid*         pResultantSolid = nullpt    826     G4VSolid*         pResultantSolid = nullptr;
833     G4DisplacedSolid* pDisplacedSolid = nullpt    827     G4DisplacedSolid* pDisplacedSolid = nullptr;
834                                                   828 
835     if (fpClippingSolid) {                        829     if (fpClippingSolid) {
836       pDisplacedSolid = new G4DisplacedSolid("    830       pDisplacedSolid = new G4DisplacedSolid("clipper", fpClippingSolid, theAT.inverse());
837       switch (fClippingMode) {                    831       switch (fClippingMode) {
838         case subtraction:                         832         case subtraction:
839           if (SubtractionBoundingLimits(pSol))    833           if (SubtractionBoundingLimits(pSol)) {
840             pResultantSolid = new G4Subtractio    834             pResultantSolid = new G4SubtractionSolid
841             ("subtracted_clipped_solid", pSol,    835             ("subtracted_clipped_solid", pSol, pDisplacedSolid);
842           }                                       836           }
843           break;                                  837           break;
844         case intersection:                        838         case intersection:
845           if (IntersectionBoundingLimits(pSol,    839           if (IntersectionBoundingLimits(pSol, pDisplacedSolid)) {
846             pResultantSolid = new G4Intersecti    840             pResultantSolid = new G4IntersectionSolid
847             ("intersected_clipped_solid", pSol    841             ("intersected_clipped_solid", pSol, pDisplacedSolid);
848           }                                       842           }
849           break;                                  843           break;
850       }                                           844       }
851                                                   845 
852     } else if (pSectionSolid) {                   846     } else if (pSectionSolid) {
853       pDisplacedSolid = new G4DisplacedSolid("    847       pDisplacedSolid = new G4DisplacedSolid("intersector", pSectionSolid, theAT.inverse());
854       if (IntersectionBoundingLimits(pSol, pDi    848       if (IntersectionBoundingLimits(pSol, pDisplacedSolid)) {
855         pResultantSolid = new G4IntersectionSo    849         pResultantSolid = new G4IntersectionSolid("sectioned_solid", pSol, pDisplacedSolid);
856       }                                           850       }
857                                                   851 
858     } else if (pCutawaySolid) {                   852     } else if (pCutawaySolid) {
859       pDisplacedSolid = new G4DisplacedSolid("    853       pDisplacedSolid = new G4DisplacedSolid("cutaway", pCutawaySolid, theAT.inverse());
860       switch (fpMP->GetCutawayMode()) {           854       switch (fpMP->GetCutawayMode()) {
861         case G4ModelingParameters::cutawayUnio    855         case G4ModelingParameters::cutawayUnion:
862           if (SubtractionBoundingLimits(pSol))    856           if (SubtractionBoundingLimits(pSol)) {
863             pResultantSolid = new G4Subtractio    857             pResultantSolid = new G4SubtractionSolid("cutaway_solid", pSol, pDisplacedSolid);
864           }                                       858           }
865           break;                                  859           break;
866         case G4ModelingParameters::cutawayInte    860         case G4ModelingParameters::cutawayIntersection:
867           if (IntersectionBoundingLimits(pSol,    861           if (IntersectionBoundingLimits(pSol, pDisplacedSolid)) {
868             pResultantSolid = new G4Intersecti    862             pResultantSolid = new G4IntersectionSolid("cutaway_solid", pSol, pDisplacedSolid);
869           }                                       863           }
870           break;                                  864           break;
871       }                                           865       }
872     }                                             866     }
873                                                   867 
874     if (pResultantSolid) {                        868     if (pResultantSolid) {
875       sceneHandler.PreAddSolid (theAT, *pVisAt    869       sceneHandler.PreAddSolid (theAT, *pVisAttribs);
876       pResultantSolid -> DescribeYourselfTo (s    870       pResultantSolid -> DescribeYourselfTo (sceneHandler);
877       sceneHandler.PostAddSolid ();               871       sceneHandler.PostAddSolid ();
878     }                                             872     }
879                                                   873 
880     delete pResultantSolid;                       874     delete pResultantSolid;
881     delete pDisplacedSolid;                       875     delete pDisplacedSolid;
882   }                                               876   }
883 }                                                 877 }
884                                                   878 
885 G4bool G4PhysicalVolumeModel::Validate (G4bool    879 G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
886 {                                                 880 {
887 // Not easy to see how to validate this sort o    881 // Not easy to see how to validate this sort of model. Previously there was
888 // a check that a volume of the same name (fTo    882 // a check that a volume of the same name (fTopPVName) existed somewhere in
889 // the geometry tree but under some circumstan    883 // the geometry tree but under some circumstances this consumed lots of CPU
890 // time. Instead, let us simply check that the    884 // time. Instead, let us simply check that the volume (fpTopPV) exists in the
891 // physical volume store.                         885 // physical volume store.
892   const auto& pvStore = G4PhysicalVolumeStore:    886   const auto& pvStore = G4PhysicalVolumeStore::GetInstance();
893   auto iterator = find(pvStore->begin(),pvStor    887   auto iterator = find(pvStore->begin(),pvStore->end(),fpTopPV);
894   if (iterator == pvStore->end()) {               888   if (iterator == pvStore->end()) {
895     if (warn) {                                   889     if (warn) {
896       G4ExceptionDescription ed;                  890       G4ExceptionDescription ed;
897       ed << "Attempt to validate a volume that    891       ed << "Attempt to validate a volume that is no longer in the physical volume store.";
898       G4Exception("G4PhysicalVolumeModel::Vali    892       G4Exception("G4PhysicalVolumeModel::Validate", "modeling0015", JustWarning, ed);
899     }                                             893     }
900     return false;                                 894     return false;
901   } else {                                        895   } else {
902     return true;                                  896     return true;
903   }                                               897   }
904 }                                                 898 }
905                                                   899 
906 const std::map<G4String,G4AttDef>* G4PhysicalV    900 const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
907 {                                                 901 {
908     G4bool isNew;                                 902     G4bool isNew;
909     std::map<G4String,G4AttDef>* store            903     std::map<G4String,G4AttDef>* store
910       = G4AttDefStore::GetInstance("G4Physical    904       = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
911     if (isNew) {                                  905     if (isNew) {
912       (*store)["PVPath"] =                        906       (*store)["PVPath"] =
913       G4AttDef("PVPath","Physical Volume Path"    907       G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
914       (*store)["BasePVPath"] =                    908       (*store)["BasePVPath"] =
915       G4AttDef("BasePVPath","Base Physical Vol    909       G4AttDef("BasePVPath","Base Physical Volume Path","Physics","","G4String");
916       (*store)["LVol"] =                          910       (*store)["LVol"] =
917       G4AttDef("LVol","Logical Volume","Physic    911       G4AttDef("LVol","Logical Volume","Physics","","G4String");
918       (*store)["Solid"] =                         912       (*store)["Solid"] =
919       G4AttDef("Solid","Solid Name","Physics",    913       G4AttDef("Solid","Solid Name","Physics","","G4String");
920       (*store)["EType"] =                         914       (*store)["EType"] =
921       G4AttDef("EType","Entity Type","Physics"    915       G4AttDef("EType","Entity Type","Physics","","G4String");
922       (*store)["DmpSol"] =                        916       (*store)["DmpSol"] =
923       G4AttDef("DmpSol","Dump of Solid propert    917       G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
924       (*store)["LocalTrans"] =                    918       (*store)["LocalTrans"] =
925       G4AttDef("LocalTrans","Local transformat    919       G4AttDef("LocalTrans","Local transformation of volume","Physics","","G4String");
926       (*store)["LocalExtent"] =                   920       (*store)["LocalExtent"] =
927       G4AttDef("LocalExtent","Local extent of     921       G4AttDef("LocalExtent","Local extent of volume","Physics","","G4String");
928       (*store)["GlobalTrans"] =                   922       (*store)["GlobalTrans"] =
929       G4AttDef("GlobalTrans","Global transform    923       G4AttDef("GlobalTrans","Global transformation of volume","Physics","","G4String");
930       (*store)["GlobalExtent"] =                  924       (*store)["GlobalExtent"] =
931       G4AttDef("GlobalExtent","Global extent o    925       G4AttDef("GlobalExtent","Global extent of volume","Physics","","G4String");
932       (*store)["Material"] =                      926       (*store)["Material"] =
933       G4AttDef("Material","Material Name","Phy    927       G4AttDef("Material","Material Name","Physics","","G4String");
934       (*store)["Density"] =                       928       (*store)["Density"] =
935       G4AttDef("Density","Material Density","P    929       G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
936       (*store)["State"] =                         930       (*store)["State"] =
937       G4AttDef("State","Material State (enum u    931       G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
938       (*store)["Radlen"] =                        932       (*store)["Radlen"] =
939       G4AttDef("Radlen","Material Radiation Le    933       G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
940       (*store)["Region"] =                        934       (*store)["Region"] =
941       G4AttDef("Region","Cuts Region","Physics    935       G4AttDef("Region","Cuts Region","Physics","","G4String");
942       (*store)["RootRegion"] =                    936       (*store)["RootRegion"] =
943       G4AttDef("RootRegion","Root Region (0/1     937       G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
944     }                                             938     }
945   return store;                                   939   return store;
946 }                                                 940 }
947                                                   941 
948 static std::ostream& operator<< (std::ostream&    942 static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
949 {                                                 943 {
950   using namespace std;                            944   using namespace std;
951                                                   945 
952   G4Scale3D sc;                                   946   G4Scale3D sc;
953   G4Rotate3D r;                                   947   G4Rotate3D r;
954   G4Translate3D tl;                               948   G4Translate3D tl;
955   t.getDecomposition(sc, r, tl);                  949   t.getDecomposition(sc, r, tl);
956                                                   950 
957   const int w = 10;                               951   const int w = 10;
958                                                   952 
959   // Transformation itself                        953   // Transformation itself
960   o << setw(w) << t.xx() << setw(w) << t.xy()     954   o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
961   o << setw(w) << t.yx() << setw(w) << t.yy()     955   o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
962   o << setw(w) << t.zx() << setw(w) << t.zy()     956   o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
963                                                   957 
964   // Translation                                  958   // Translation
965   o << "= translation:" << endl;                  959   o << "= translation:" << endl;
966   o << setw(w) << tl.dx() << setw(w) << tl.dy(    960   o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
967                                                   961 
968   // Rotation                                     962   // Rotation
969   o << "* rotation:" << endl;                     963   o << "* rotation:" << endl;
970   o << setw(w) << r.xx() << setw(w) << r.xy()     964   o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
971   o << setw(w) << r.yx() << setw(w) << r.yy()     965   o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
972   o << setw(w) << r.zx() << setw(w) << r.zy()     966   o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
973                                                   967 
974   // Scale                                        968   // Scale
975   o << "* scale:" << endl;                        969   o << "* scale:" << endl;
976   o << setw(w) << sc.xx() << setw(w) << sc.yy(    970   o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl;
977                                                   971 
978   // Transformed axes                             972   // Transformed axes
979   o << "Transformed axes:" << endl;               973   o << "Transformed axes:" << endl;
980   o << "x': " << r * G4Vector3D(1., 0., 0.) <<    974   o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
981   o << "y': " << r * G4Vector3D(0., 1., 0.) <<    975   o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
982   o << "z': " << r * G4Vector3D(0., 0., 1.) <<    976   o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
983                                                   977 
984   return o;                                       978   return o;
985 }                                                 979 }
986                                                   980 
987 std::vector<G4AttValue>* G4PhysicalVolumeModel    981 std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
988 {                                                 982 {
989   std::vector<G4AttValue>* values = new std::v    983   std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
990                                                   984 
991   if (!fpCurrentLV) {                             985   if (!fpCurrentLV) {
992      G4Exception                                  986      G4Exception
993         ("G4PhysicalVolumeModel::CreateCurrent    987         ("G4PhysicalVolumeModel::CreateCurrentAttValues",
994          "modeling0004",                          988          "modeling0004",
995          JustWarning,                             989          JustWarning,
996          "Current logical volume not defined."    990          "Current logical volume not defined.");
997      return values;                               991      return values;
998   }                                               992   }
999                                                   993 
1000   std::ostringstream oss; oss << fFullPVPath;    994   std::ostringstream oss; oss << fFullPVPath;
1001   values->push_back(G4AttValue("PVPath", oss.    995   values->push_back(G4AttValue("PVPath", oss.str(),""));
1002                                                  996 
1003   oss.str(""); oss << fBaseFullPVPath;           997   oss.str(""); oss << fBaseFullPVPath;
1004   values->push_back(G4AttValue("BasePVPath",     998   values->push_back(G4AttValue("BasePVPath", oss.str(),""));
1005                                                  999 
1006   values->push_back(G4AttValue("LVol", fpCurr    1000   values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
1007   G4VSolid* pSol = fpCurrentLV->GetSolid();      1001   G4VSolid* pSol = fpCurrentLV->GetSolid();
1008                                                  1002 
1009   values->push_back(G4AttValue("Solid", pSol-    1003   values->push_back(G4AttValue("Solid", pSol->GetName(),""));
1010                                                  1004 
1011   values->push_back(G4AttValue("EType", pSol-    1005   values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
1012                                                  1006 
1013   oss.str(""); oss << '\n' << *pSol;             1007   oss.str(""); oss << '\n' << *pSol;
1014   values->push_back(G4AttValue("DmpSol", oss.    1008   values->push_back(G4AttValue("DmpSol", oss.str(),""));
1015                                                  1009 
1016   const G4RotationMatrix localRotation = fpCu    1010   const G4RotationMatrix localRotation = fpCurrentPV->GetObjectRotationValue();
1017   const G4ThreeVector& localTranslation = fpC    1011   const G4ThreeVector& localTranslation = fpCurrentPV->GetTranslation();
1018   oss.str(""); oss << '\n' << G4Transform3D(l    1012   oss.str(""); oss << '\n' << G4Transform3D(localRotation,localTranslation);
1019   values->push_back(G4AttValue("LocalTrans",     1013   values->push_back(G4AttValue("LocalTrans", oss.str(),""));
1020                                                  1014 
1021   oss.str(""); oss << '\n' << pSol->GetExtent    1015   oss.str(""); oss << '\n' << pSol->GetExtent() << std::endl;
1022   values->push_back(G4AttValue("LocalExtent",    1016   values->push_back(G4AttValue("LocalExtent", oss.str(),""));
1023                                                  1017 
1024   oss.str(""); oss << '\n' << fCurrentTransfo    1018   oss.str(""); oss << '\n' << fCurrentTransform;
1025   values->push_back(G4AttValue("GlobalTrans",    1019   values->push_back(G4AttValue("GlobalTrans", oss.str(),""));
1026                                                  1020 
1027   oss.str(""); oss << '\n' << (pSol->GetExten    1021   oss.str(""); oss << '\n' << (pSol->GetExtent()).Transform(fCurrentTransform) << std::endl;
1028   values->push_back(G4AttValue("GlobalExtent"    1022   values->push_back(G4AttValue("GlobalExtent", oss.str(),""));
1029                                                  1023 
1030   G4String matName = fpCurrentMaterial? fpCur    1024   G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
1031   values->push_back(G4AttValue("Material", ma    1025   values->push_back(G4AttValue("Material", matName,""));
1032                                                  1026 
1033   G4double matDensity = fpCurrentMaterial? fp    1027   G4double matDensity = fpCurrentMaterial? fpCurrentMaterial->GetDensity(): 0.;
1034   values->push_back(G4AttValue("Density", G4B    1028   values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
1035                                                  1029 
1036   G4State matState = fpCurrentMaterial? fpCur    1030   G4State matState = fpCurrentMaterial? fpCurrentMaterial->GetState(): kStateUndefined;
1037   oss.str(""); oss << matState;                  1031   oss.str(""); oss << matState;
1038   values->push_back(G4AttValue("State", oss.s    1032   values->push_back(G4AttValue("State", oss.str(),""));
1039                                                  1033 
1040   G4double matRadlen = fpCurrentMaterial? fpC    1034   G4double matRadlen = fpCurrentMaterial? fpCurrentMaterial->GetRadlen(): 0.;
1041   values->push_back(G4AttValue("Radlen", G4Be    1035   values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
1042                                                  1036 
1043   G4Region* region = fpCurrentLV->GetRegion()    1037   G4Region* region = fpCurrentLV->GetRegion();
1044   G4String regionName = region? region->GetNa    1038   G4String regionName = region? region->GetName(): G4String("No region");
1045   values->push_back(G4AttValue("Region", regi    1039   values->push_back(G4AttValue("Region", regionName,""));
1046                                                  1040 
1047   oss.str(""); oss << fpCurrentLV->IsRootRegi    1041   oss.str(""); oss << fpCurrentLV->IsRootRegion();
1048   values->push_back(G4AttValue("RootRegion",     1042   values->push_back(G4AttValue("RootRegion", oss.str(),""));
1049                                                  1043 
1050   return values;                                 1044   return values;
1051 }                                                1045 }
1052                                                  1046 
1053 G4bool G4PhysicalVolumeModel::G4PhysicalVolum    1047 G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
1054   (const G4PhysicalVolumeModel::G4PhysicalVol    1048   (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
1055 {                                                1049 {
1056   if (fpPV < right.fpPV) return true;            1050   if (fpPV < right.fpPV) return true;
1057   if (fpPV == right.fpPV) {                      1051   if (fpPV == right.fpPV) {
1058     if (fCopyNo < right.fCopyNo) return true;    1052     if (fCopyNo < right.fCopyNo) return true;
1059     if (fCopyNo == right.fCopyNo)                1053     if (fCopyNo == right.fCopyNo)
1060       return fNonCulledDepth < right.fNonCull    1054       return fNonCulledDepth < right.fNonCulledDepth;
1061   }                                              1055   }
1062   return false;                                  1056   return false;
1063 }                                                1057 }
1064                                                  1058 
1065 G4bool G4PhysicalVolumeModel::G4PhysicalVolum    1059 G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator!=
1066   (const G4PhysicalVolumeModel::G4PhysicalVol    1060   (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
1067 {                                                1061 {
1068   if (fpPV            != right.fpPV ||           1062   if (fpPV            != right.fpPV ||
1069       fCopyNo         != right.fCopyNo ||        1063       fCopyNo         != right.fCopyNo ||
1070       fNonCulledDepth != right.fNonCulledDept    1064       fNonCulledDepth != right.fNonCulledDepth ||
1071       fTransform      != right.fTransform ||     1065       fTransform      != right.fTransform ||
1072       fDrawn          != right.fDrawn) return    1066       fDrawn          != right.fDrawn) return true;
1073   return false;                                  1067   return false;
1074 }                                                1068 }
1075                                                  1069 
1076 std::ostream& operator<<                         1070 std::ostream& operator<<
1077   (std::ostream& os, const G4PhysicalVolumeMo    1071   (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& node)
1078 {                                                1072 {
1079   G4VPhysicalVolume* pPV = node.GetPhysicalVo    1073   G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
1080   if (pPV) {                                     1074   if (pPV) {
1081     os << pPV->GetName()                         1075     os << pPV->GetName()
1082        << ' ' << node.GetCopyNo()                1076        << ' ' << node.GetCopyNo()
1083 //       << '[' << node.GetNonCulledDepth() <    1077 //       << '[' << node.GetNonCulledDepth() << ']'
1084 //       << ':' << node.GetTransform()           1078 //       << ':' << node.GetTransform()
1085     ;                                            1079     ;
1086 //    os << " (";                                1080 //    os << " (";
1087 //    if (!node.GetDrawn()) os << "not ";        1081 //    if (!node.GetDrawn()) os << "not ";
1088 //    os << "drawn)";                            1082 //    os << "drawn)";
1089   } else {                                       1083   } else {
1090     os << " (Null PV node)";                     1084     os << " (Null PV node)";
1091   }                                              1085   }
1092   return os;                                     1086   return os;
1093 }                                                1087 }
1094                                                  1088 
1095 std::ostream& operator<<                         1089 std::ostream& operator<<
1096 (std::ostream& os, const std::vector<G4Physic    1090 (std::ostream& os, const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& path)
1097 {                                                1091 {
1098   if (path.empty()) {                            1092   if (path.empty()) {
1099     os << " TOP";                                1093     os << " TOP";
1100   } else {                                       1094   } else {
1101     for (const auto& nodeID: path) {             1095     for (const auto& nodeID: path) {
1102       os << ' ' << nodeID;                       1096       os << ' ' << nodeID;
1103     }                                            1097     }
1104   }                                              1098   }
1105   return os;                                     1099   return os;
1106 }                                                1100 }
1107                                                  1101 
1108 G4PhysicalVolumeModel::G4PhysicalVolumeModelT    1102 G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable
1109 (const std::vector<G4PhysicalVolumeNodeID>& f    1103 (const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
1110   fFullPVPath(fullPVPath) {}                     1104   fFullPVPath(fullPVPath) {}
1111                                                  1105 
1112 const G4ThreeVector& G4PhysicalVolumeModel::G    1106 const G4ThreeVector& G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetTranslation(G4int depth) const
1113 {                                                1107 {
1114   size_t i = fFullPVPath.size() - depth - 1;     1108   size_t i = fFullPVPath.size() - depth - 1;
1115   if (i >= fFullPVPath.size()) {                 1109   if (i >= fFullPVPath.size()) {
1116     G4Exception("G4PhysicalVolumeModelTouchab    1110     G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
1117     "modeling0005",                              1111     "modeling0005",
1118     FatalErrorInArgument,                        1112     FatalErrorInArgument,
1119     "Index out of range. Asking for non-exist    1113     "Index out of range. Asking for non-existent depth");
1120   }                                              1114   }
1121   static G4ThreeVector tempTranslation;          1115   static G4ThreeVector tempTranslation;
1122   tempTranslation = fFullPVPath[i].GetTransfo    1116   tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
1123   return tempTranslation;                        1117   return tempTranslation;
1124 }                                                1118 }
1125                                                  1119 
1126 const G4RotationMatrix* G4PhysicalVolumeModel    1120 const G4RotationMatrix* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetRotation(G4int depth) const
1127 {                                                1121 {
1128   size_t i = fFullPVPath.size() - depth - 1;     1122   size_t i = fFullPVPath.size() - depth - 1;
1129   if (i >= fFullPVPath.size()) {                 1123   if (i >= fFullPVPath.size()) {
1130     G4Exception("G4PhysicalVolumeModelTouchab    1124     G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
1131     "modeling0006",                              1125     "modeling0006",
1132     FatalErrorInArgument,                        1126     FatalErrorInArgument,
1133     "Index out of range. Asking for non-exist    1127     "Index out of range. Asking for non-existent depth");
1134   }                                              1128   }
1135   static G4RotationMatrix tempRotation;          1129   static G4RotationMatrix tempRotation;
1136   tempRotation = fFullPVPath[i].GetTransform(    1130   tempRotation = fFullPVPath[i].GetTransform().getRotation();
1137   return &tempRotation;                          1131   return &tempRotation;
1138 }                                                1132 }
1139                                                  1133 
1140 G4VPhysicalVolume* G4PhysicalVolumeModel::G4P    1134 G4VPhysicalVolume* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetVolume(G4int depth) const
1141 {                                                1135 {
1142   size_t i = fFullPVPath.size() - depth - 1;     1136   size_t i = fFullPVPath.size() - depth - 1;
1143   if (i >= fFullPVPath.size()) {                 1137   if (i >= fFullPVPath.size()) {
1144     G4Exception("G4PhysicalVolumeModelTouchab    1138     G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
1145     "modeling0007",                              1139     "modeling0007",
1146     FatalErrorInArgument,                        1140     FatalErrorInArgument,
1147     "Index out of range. Asking for non-exist    1141     "Index out of range. Asking for non-existent depth");
1148   }                                              1142   }
1149   return fFullPVPath[i].GetPhysicalVolume();     1143   return fFullPVPath[i].GetPhysicalVolume();
1150 }                                                1144 }
1151                                                  1145 
1152 G4VSolid* G4PhysicalVolumeModel::G4PhysicalVo    1146 G4VSolid* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetSolid(G4int depth) const
1153 {                                                1147 {
1154   size_t i = fFullPVPath.size() - depth - 1;     1148   size_t i = fFullPVPath.size() - depth - 1;
1155   if (i >= fFullPVPath.size()) {                 1149   if (i >= fFullPVPath.size()) {
1156     G4Exception("G4PhysicalVolumeModelTouchab    1150     G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
1157     "modeling0008",                              1151     "modeling0008",
1158     FatalErrorInArgument,                        1152     FatalErrorInArgument,
1159     "Index out of range. Asking for non-exist    1153     "Index out of range. Asking for non-existent depth");
1160   }                                              1154   }
1161   return fFullPVPath[i].GetPhysicalVolume()->    1155   return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
1162 }                                                1156 }
1163                                                  1157 
1164 G4int G4PhysicalVolumeModel::G4PhysicalVolume    1158 G4int G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetReplicaNumber(G4int depth) const
1165 {                                                1159 {
1166   size_t i = fFullPVPath.size() - depth - 1;     1160   size_t i = fFullPVPath.size() - depth - 1;
1167   if (i >= fFullPVPath.size()) {                 1161   if (i >= fFullPVPath.size()) {
1168     G4Exception("G4PhysicalVolumeModelTouchab    1162     G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
1169     "modeling0009",                              1163     "modeling0009",
1170     FatalErrorInArgument,                        1164     FatalErrorInArgument,
1171     "Index out of range. Asking for non-exist    1165     "Index out of range. Asking for non-existent depth");
1172   }                                              1166   }
1173   return fFullPVPath[i].GetCopyNo();             1167   return fFullPVPath[i].GetCopyNo();
1174 }                                                1168 }
1175                                                  1169