Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 28 // /vis/touchable commands - John Allison 14th May 2014 29 30 #include "G4VisCommandsTouchable.hh" 31 32 #include "G4UImanager.hh" 33 #include "G4UIcmdWithAString.hh" 34 #include "G4UIcmdWithoutParameter.hh" 35 #include "G4UIcmdWithABool.hh" 36 #include "G4TransportationManager.hh" 37 #include "G4TouchableUtils.hh" 38 #include "G4PhysicalVolumesSearchScene.hh" 39 #include "G4AttDef.hh" 40 #include "G4AttValue.hh" 41 #include "G4AttCheck.hh" 42 #include "G4AxesModel.hh" 43 44 #define G4warn G4cout 45 46 G4VisCommandsTouchable::G4VisCommandsTouchable() 47 { 48 G4bool omitable; 49 50 fpCommandCentreAndZoomInOn = new G4UIcmdWithoutParameter("/vis/touchable/centreAndZoomInOn",this); 51 fpCommandCentreAndZoomInOn->SetGuidance ("Centre and zoom in on the current touchable."); 52 fpCommandCentreAndZoomInOn->SetGuidance 53 ("Use \"/vis/set/touchable\" to set current touchable."); 54 fpCommandCentreAndZoomInOn->SetGuidance 55 ("You may also need \"/vis/touchable/findPath\"."); 56 fpCommandCentreAndZoomInOn->SetGuidance 57 ("Use \"/vis/touchable/set\" to set attributes."); 58 59 fpCommandCentreOn = new G4UIcmdWithoutParameter("/vis/touchable/centreOn",this); 60 fpCommandCentreOn->SetGuidance ("Centre the view on the current touchable."); 61 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 62 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandCentreOn,1); 63 64 fpCommandDraw = new G4UIcmdWithABool("/vis/touchable/draw",this); 65 fpCommandDraw->SetGuidance("Draw touchable."); 66 fpCommandDraw->SetGuidance 67 ("If parameter == true, also draw extent as a white wireframe box."); 68 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 69 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandDraw,1); 70 fpCommandDraw->SetParameterName("extent", omitable = true); 71 fpCommandDraw->SetDefaultValue(false); 72 73 fpCommandDump = new G4UIcmdWithoutParameter("/vis/touchable/dump",this); 74 fpCommandDump->SetGuidance("Dump touchable attributes."); 75 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 76 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandDump,1); 77 78 fpCommandExtentForField = new G4UIcmdWithABool("/vis/touchable/extentForField",this); 79 fpCommandExtentForField->SetGuidance("Set extent for field."); 80 fpCommandExtentForField->SetGuidance("If parameter == true, also draw."); 81 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 82 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandExtentForField,1); 83 fpCommandExtentForField->SetParameterName("draw", omitable = true); 84 fpCommandExtentForField->SetDefaultValue(false); 85 86 fpCommandFindPath = new G4UIcommand("/vis/touchable/findPath",this); 87 fpCommandFindPath->SetGuidance 88 ("Prints the path to touchable and its logical volume mother" 89 "\ngiven a physical volume name and copy no."); 90 fpCommandFindPath -> SetGuidance 91 ("A search of all worlds is made and all physical volume names are" 92 "\nmatched against the argument of this command. If this is of the" 93 "\nform \"/regexp/\", where regexp is a regular expression (see C++ regex)," 94 "\nthe physical volume name is matched against regexp by the usual rules" 95 "\nof regular expression matching. Otherwise an exact match is required." 96 "\nFor example, \"/Shap/\" matches \"Shape1\" and \"Shape2\"."); 97 fpCommandFindPath -> SetGuidance 98 ("It may help to see a textual representation of the geometry hierarchy of" 99 "\nthe worlds. Try \"/vis/drawTree [worlds]\" or one of the driver/browser" 100 "\ncombinations that have the required functionality, e.g., HepRep."); 101 G4UIparameter* parameter; 102 parameter = new G4UIparameter ("physical-volume-name", 's', omitable = true); 103 parameter -> SetDefaultValue ("world"); 104 fpCommandFindPath -> SetParameter (parameter); 105 parameter = new G4UIparameter ("copy-no", 'i', omitable = true); 106 parameter -> SetGuidance ("If negative, matches any copy no."); 107 parameter -> SetDefaultValue (-1); 108 fpCommandFindPath -> SetParameter (parameter); 109 110 fpCommandLocalAxes = new G4UIcmdWithoutParameter("/vis/touchable/localAxes",this); 111 fpCommandLocalAxes->SetGuidance("Draw local axes."); 112 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 113 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandLocalAxes,1); 114 115 fpCommandShowExtent = new G4UIcmdWithABool("/vis/touchable/showExtent",this); 116 fpCommandShowExtent->SetGuidance("Print extent of touchable."); 117 fpCommandShowExtent->SetGuidance("If parameter == true, also draw."); 118 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 119 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandShowExtent,1); 120 fpCommandShowExtent->SetParameterName("draw", omitable = true); 121 fpCommandShowExtent->SetDefaultValue(false); 122 123 fpCommandTwinkle = new G4UIcmdWithoutParameter("/vis/touchable/twinkle",this); 124 fpCommandTwinkle->SetGuidance("Cause touchable to twinkle."); 125 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 126 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandTwinkle,1); 127 128 fpCommandVolumeForField = new G4UIcmdWithABool("/vis/touchable/volumeForField",this); 129 fpCommandVolumeForField->SetGuidance("Set volume for field."); 130 fpCommandVolumeForField->SetGuidance("If parameter == true, also draw."); 131 // Pick up additional guidance from /vis/viewer/centreAndZoomInOn 132 CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandVolumeForField,1); 133 fpCommandVolumeForField->SetParameterName("draw", omitable = true); 134 fpCommandVolumeForField->SetDefaultValue(false); 135 } 136 137 G4VisCommandsTouchable::~G4VisCommandsTouchable() { 138 delete fpCommandVolumeForField; 139 delete fpCommandTwinkle; 140 delete fpCommandShowExtent; 141 delete fpCommandLocalAxes; 142 delete fpCommandFindPath; 143 delete fpCommandExtentForField; 144 delete fpCommandDump; 145 delete fpCommandDraw; 146 delete fpCommandCentreAndZoomInOn; 147 delete fpCommandCentreOn; 148 } 149 150 G4String G4VisCommandsTouchable::GetCurrentValue(G4UIcommand*) { 151 return ""; 152 } 153 154 void G4VisCommandsTouchable::SetNewValue 155 (G4UIcommand* command, G4String newValue) 156 { 157 G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity(); 158 G4bool warn = verbosity >= G4VisManager::warnings; 159 160 G4UImanager* UImanager = G4UImanager::GetUIpointer(); 161 162 G4TransportationManager* transportationManager = 163 G4TransportationManager::GetTransportationManager (); 164 165 size_t nWorlds = transportationManager->GetNoWorlds(); 166 167 G4VPhysicalVolume* world = *(transportationManager->GetWorldsIterator()); 168 if (!world) { 169 if (verbosity >= G4VisManager::errors) { 170 G4warn << 171 "ERROR: G4VisCommandsTouchable::SetNewValue:" 172 "\n No world. Maybe the geometry has not yet been defined." 173 "\n Try \"/run/initialize\"" 174 << G4endl; 175 } 176 return; 177 } 178 179 if (command == fpCommandDump) { 180 181 G4PhysicalVolumeModel::TouchableProperties properties = 182 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 183 if (properties.fpTouchablePV) { 184 // To handle parameterisations we have to set the copy number 185 properties.fpTouchablePV->SetCopyNo(properties.fCopyNo); 186 G4PhysicalVolumeModel tempPVModel 187 (properties.fpTouchablePV, 188 G4PhysicalVolumeModel::UNLIMITED, 189 properties.fTouchableGlobalTransform, 190 nullptr, // Modelling parameters (not used) 191 true, // use full extent (prevents calculating own extent, which crashes) 192 properties.fTouchableBaseFullPVPath); 193 const std::map<G4String,G4AttDef>* attDefs = tempPVModel.GetAttDefs(); 194 std::vector<G4AttValue>* attValues = tempPVModel.CreateCurrentAttValues(); 195 G4cout << G4AttCheck(attValues,attDefs); 196 delete attValues; 197 const auto lv = properties.fpTouchablePV->GetLogicalVolume(); 198 const auto polyhedron = lv->GetSolid()->GetPolyhedron(); 199 if (polyhedron) { 200 polyhedron->SetVisAttributes(lv->GetVisAttributes()); 201 G4cout << "\nLocal polyhedron coordinates:\n" << *polyhedron; 202 const G4Transform3D& transform = tempPVModel.GetCurrentTransform(); 203 polyhedron->Transform(transform); 204 G4cout << "\nGlobal polyhedron coordinates:\n" << *polyhedron; 205 } 206 } else { 207 G4warn << "Touchable not found." << G4endl; 208 } 209 return; 210 211 } else if (command == fpCommandFindPath) { 212 213 G4String pvName; 214 G4int copyNo; 215 std::istringstream iss(newValue); 216 iss >> pvName >> copyNo; 217 std::vector<G4PhysicalVolumesSearchScene::Findings> findingsVector; 218 std::vector<G4VPhysicalVolume*>::iterator iterWorld = 219 transportationManager->GetWorldsIterator(); 220 for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) { 221 G4PhysicalVolumeModel searchModel (*iterWorld); // Unlimited depth. 222 G4ModelingParameters mp; // Default - no culling. 223 searchModel.SetModelingParameters (&mp); 224 // Find all instances at any position in the tree 225 G4PhysicalVolumesSearchScene searchScene (&searchModel, pvName, copyNo); 226 searchModel.DescribeYourselfTo (searchScene); // Initiate search. 227 for (const auto& findings: searchScene.GetFindings()) { 228 findingsVector.push_back(findings); 229 } 230 } 231 for (const auto& findings: findingsVector) { 232 G4cout 233 << findings.fFoundBasePVPath 234 << ' ' << findings.fpFoundPV->GetName() 235 << ' ' << findings.fFoundPVCopyNo 236 << " (mother logical volume: " 237 << findings.fpFoundPV->GetMotherLogical()->GetName() 238 << ')' 239 << G4endl; 240 } 241 if (findingsVector.size()) { 242 G4cout 243 << "Use this to set a particular touchable with \"/vis/set/touchable <path>\"" 244 << "\nor to see overlaps: \"/vis/drawLogicalVolume <mother-logical-volume-name>\"" 245 << G4endl; 246 } else { 247 G4warn << pvName; 248 if (copyNo >= 0) G4warn << ':' << copyNo; 249 G4warn << " not found" << G4endl; 250 } 251 return; 252 } 253 254 G4VViewer* currentViewer = fpVisManager -> GetCurrentViewer (); 255 if (!currentViewer) { 256 if (verbosity >= G4VisManager::errors) { 257 G4warn << 258 "ERROR: No current viewer - \"/vis/viewer/list\" to see possibilities." 259 << G4endl; 260 } 261 return; 262 } 263 264 G4Scene* currentScene = fpVisManager->GetCurrentScene(); 265 if (!currentScene) { 266 if (verbosity >= G4VisManager::errors) { 267 G4warn << 268 "ERROR: No current scene - \"/vis/scene/list\" to see possibilities." 269 << G4endl; 270 } 271 return; 272 } 273 274 if (command == fpCommandCentreOn || command == fpCommandCentreAndZoomInOn) { 275 276 // For twinkling... 277 std::vector<std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>> touchables; 278 279 G4PhysicalVolumeModel::TouchableProperties properties = 280 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 281 if (properties.fpTouchablePV) { 282 // To handle parameterisations, set copy number 283 properties.fpTouchablePV->SetCopyNo(properties.fCopyNo); 284 G4PhysicalVolumeModel tempPVModel 285 (properties.fpTouchablePV, 286 G4PhysicalVolumeModel::UNLIMITED, 287 properties.fTouchableGlobalTransform, 288 nullptr, // Modelling parameters (not used) 289 true, // use full extent (prevents calculating own extent, which crashes) 290 properties.fTouchableBaseFullPVPath); 291 touchables.push_back(properties.fTouchableFullPVPath); // Only one in this case 292 // Use a temporary scene in order to find vis extent 293 G4Scene tempScene("Centre Scene"); 294 G4bool successful = tempScene.AddRunDurationModel(&tempPVModel,warn); 295 if (!successful) return; 296 if (verbosity >= G4VisManager::parameters) { 297 G4cout 298 << "Touchable " << fCurrentTouchableProperties.fTouchablePath 299 << ",\n has been added to temporary scene \"" << tempScene.GetName() << "\"." 300 << G4endl; 301 } 302 303 const G4VisExtent& newExtent = tempScene.GetExtent(); 304 const G4ThreeVector& newTargetPoint = newExtent.GetExtentCentre(); 305 G4ViewParameters saveVP = currentViewer->GetViewParameters(); 306 G4ViewParameters newVP = saveVP; 307 if (command == fpCommandCentreAndZoomInOn) { 308 // Calculate the new zoom factor 309 const G4double zoomFactor 310 = currentScene->GetExtent().GetExtentRadius()/newExtent.GetExtentRadius(); 311 newVP.SetZoomFactor(zoomFactor); 312 } 313 // Change the target point 314 const G4Point3D& standardTargetPoint = currentScene->GetStandardTargetPoint(); 315 newVP.SetCurrentTargetPoint(newTargetPoint - standardTargetPoint); 316 317 // Interpolate 318 auto keepVisVerbose = fpVisManager->GetVerbosity(); 319 fpVisManager->SetVerboseLevel(G4VisManager::errors); 320 if (newVP != saveVP) InterpolateToNewView(currentViewer, saveVP, newVP); 321 // ...and twinkle 322 Twinkle(currentViewer,newVP,touchables); 323 fpVisManager->SetVerboseLevel(keepVisVerbose); 324 325 if (verbosity >= G4VisManager::confirmations) { 326 G4cout 327 << "Viewer \"" << currentViewer->GetName() 328 << "\" centred "; 329 if (fpCommandCentreAndZoomInOn) { 330 G4cout << "and zoomed in"; 331 } 332 G4cout << " on touchable\n" << fCurrentTouchableProperties.fTouchablePath 333 << G4endl; 334 } 335 SetViewParameters(currentViewer, newVP); 336 } else { 337 G4warn << "Touchable not found." << G4endl; 338 } 339 return; 340 341 } else if (command == fpCommandDraw) { 342 343 G4PhysicalVolumeModel::TouchableProperties properties = 344 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 345 if (properties.fpTouchablePV) { 346 // To handle parameterisations we have to set the copy number 347 properties.fpTouchablePV->SetCopyNo(properties.fCopyNo); 348 G4PhysicalVolumeModel* pvModel = new G4PhysicalVolumeModel 349 (properties.fpTouchablePV, 350 G4PhysicalVolumeModel::UNLIMITED, 351 properties.fTouchableGlobalTransform, 352 nullptr, // Modelling parameters (not used) 353 true, // use full extent (prevents calculating own extent, which crashes) 354 properties.fTouchableBaseFullPVPath); 355 356 UImanager->ApplyCommand("/vis/scene/create"); 357 currentScene = fpVisManager->GetCurrentScene(); // New current scene 358 G4bool successful = currentScene->AddRunDurationModel(pvModel,warn); 359 UImanager->ApplyCommand("/vis/sceneHandler/attach"); 360 361 if (successful) { 362 if (fpCommandDraw->GetNewBoolValue(newValue)) { 363 const auto& extent = pvModel->GetExtent(); 364 const G4double halfX = (extent.GetXmax()-extent.GetXmin())/2.; 365 const G4double halfY = (extent.GetYmax()-extent.GetYmin())/2.; 366 const G4double halfZ = (extent.GetZmax()-extent.GetZmin())/2.; 367 G4Box extentBox("extent",halfX,halfY,halfZ); 368 G4VisAttributes extentVA; 369 extentVA.SetForceWireframe(); 370 fpVisManager->Draw(extentBox,extentVA,G4Translate3D(extent.GetExtentCentre())); 371 } 372 if (verbosity >= G4VisManager::confirmations) { 373 G4cout << "\"" << properties.fpTouchablePV->GetName() 374 << "\", copy no. " << properties.fCopyNo << " drawn"; 375 if (fpCommandDraw->GetNewBoolValue(newValue)) { 376 G4cout << " with extent box"; 377 } 378 G4cout << '.' << G4endl; 379 } 380 } else { 381 G4VisCommandsSceneAddUnsuccessful(verbosity); 382 } 383 } else { 384 G4warn << "Touchable not found." << G4endl; 385 } 386 return; 387 388 } else if (command == fpCommandExtentForField) { 389 390 G4PhysicalVolumeModel::TouchableProperties properties = 391 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 392 if (properties.fpTouchablePV) { 393 G4VisExtent extent 394 = properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent(); 395 extent.Transform(properties.fTouchableGlobalTransform); 396 fCurrentExtentForField = extent; 397 fCurrrentPVFindingsForField.clear(); 398 if (verbosity >= G4VisManager::confirmations) { 399 G4cout << "Extent for field set to " << extent 400 << "\nVolume for field has been cleared." 401 << G4endl; 402 } 403 if (fpCommandExtentForField->GetNewBoolValue(newValue)) { 404 DrawExtent(extent); 405 } 406 } else { 407 G4warn << "Touchable not found." << G4endl; 408 } 409 return; 410 411 } else if (command == fpCommandLocalAxes) { 412 413 G4PhysicalVolumeModel::TouchableProperties properties = 414 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 415 if (properties.fpTouchablePV) { 416 const auto& transform = fCurrentTouchableProperties.fTouchableGlobalTransform; 417 const auto& extent = fCurrentTouchableProperties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent(); 418 const G4double lengthMax = extent.GetExtentRadius()/2.; 419 const G4double intLog10LengthMax = std::floor(std::log10(lengthMax)); 420 G4double length = std::pow(10,intLog10LengthMax); 421 if (5.*length < lengthMax) length *= 5.; 422 else if (2.*length < lengthMax) length *= 2.; 423 G4AxesModel axesModel(0.,0.,0.,length,transform); 424 axesModel.SetGlobalTag("LocalAxesModel"); 425 axesModel.DescribeYourselfTo(*fpVisManager->GetCurrentSceneHandler()); 426 G4UImanager::GetUIpointer()->ApplyCommand("/vis/viewer/refresh"); 427 } else { 428 G4warn << "Touchable not found." << G4endl; 429 } 430 return; 431 432 } else if (command == fpCommandShowExtent) { 433 434 G4PhysicalVolumeModel::TouchableProperties properties = 435 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 436 if (properties.fpTouchablePV) { 437 G4VisExtent extent 438 = properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent(); 439 extent.Transform(properties.fTouchableGlobalTransform); 440 G4cout << extent << G4endl; 441 if (fpCommandShowExtent->GetNewBoolValue(newValue)) DrawExtent(extent); 442 } else { 443 G4warn << "Touchable not found." << G4endl; 444 } 445 return; 446 447 } else if (command == fpCommandTwinkle) { 448 449 G4PhysicalVolumeModel::TouchableProperties properties = 450 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 451 if (properties.fpTouchablePV) { 452 std::vector<std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>> touchables; 453 touchables.push_back(properties.fTouchableFullPVPath); 454 auto keepVisVerbose = fpVisManager->GetVerbosity(); 455 fpVisManager->SetVerboseLevel(G4VisManager::errors); 456 auto keepVP = currentViewer->GetViewParameters(); 457 Twinkle(currentViewer,currentViewer->GetViewParameters(),touchables); 458 SetViewParameters(currentViewer, keepVP); 459 fpVisManager->SetVerboseLevel(keepVisVerbose); 460 } else { 461 G4warn << "Touchable not found." << G4endl; 462 } 463 return; 464 465 } else if (command == fpCommandVolumeForField) { 466 467 G4PhysicalVolumeModel::TouchableProperties properties = 468 G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath); 469 if (properties.fpTouchablePV) { 470 G4VisExtent extent 471 = properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent(); 472 extent.Transform(properties.fTouchableGlobalTransform); 473 fCurrentExtentForField = extent; 474 fCurrrentPVFindingsForField.clear(); 475 fCurrrentPVFindingsForField.push_back 476 (G4PhysicalVolumesSearchScene::Findings(properties)); 477 if (verbosity >= G4VisManager::confirmations) { 478 G4cout 479 << "Volume for field set to " << properties.fpTouchablePV->GetName() 480 << ':' << properties.fCopyNo 481 << " at " << properties.fTouchableBaseFullPVPath 482 << G4endl; 483 } 484 if (fpCommandVolumeForField->GetNewBoolValue(newValue)) { 485 DrawExtent(extent); 486 } 487 } else { 488 G4warn << "Touchable not found." << G4endl; 489 } 490 return; 491 492 } else { 493 494 if (verbosity >= G4VisManager::errors) { 495 G4warn << 496 "ERROR: G4VisCommandsTouchable::SetNewValue: unrecognised command." 497 << G4endl; 498 } 499 return; 500 } 501 } 502