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