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