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