Geant4 Cross Reference |
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