441 lines
18 KiB
C++
441 lines
18 KiB
C++
//
|
|
// ********************************************************************
|
|
// * License and Disclaimer *
|
|
// * *
|
|
// * The Geant4 software is copyright of the Copyright Holders of *
|
|
// * the Geant4 Collaboration. It is provided under the terms and *
|
|
// * conditions of the Geant4 Software License, included in the file *
|
|
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
|
// * include a list of copyright holders. *
|
|
// * *
|
|
// * Neither the authors of this software system, nor their employing *
|
|
// * institutes,nor the agencies providing financial support for this *
|
|
// * work make any representation or warranty, express or implied, *
|
|
// * regarding this software system or assume any liability for its *
|
|
// * use. Please see the license in the file LICENSE and URL above *
|
|
// * for the full disclaimer and the limitation of liability. *
|
|
// * *
|
|
// * This code implementation is the result of the scientific and *
|
|
// * technical work of the GEANT4 collaboration. *
|
|
// * By using, copying, modifying or distributing the software (or *
|
|
// * any work based on the software) you agree to acknowledge its *
|
|
// * use in resulting scientific publications, and indicate your *
|
|
// * acceptance of all terms of the Geant4 Software license. *
|
|
// ********************************************************************
|
|
//
|
|
//
|
|
|
|
// /vis/touchable commands - John Allison 14th May 2014
|
|
|
|
#include "G4VisCommandsTouchable.hh"
|
|
|
|
#include "G4UImanager.hh"
|
|
#include "G4UIcmdWithAString.hh"
|
|
#include "G4UIcmdWithoutParameter.hh"
|
|
#include "G4UIcmdWithABool.hh"
|
|
#include "G4TransportationManager.hh"
|
|
#include "G4TouchableUtils.hh"
|
|
#include "G4PhysicalVolumesSearchScene.hh"
|
|
#include "G4AttDef.hh"
|
|
#include "G4AttValue.hh"
|
|
#include "G4AttCheck.hh"
|
|
#include "G4AxesModel.hh"
|
|
|
|
G4VisCommandsTouchable::G4VisCommandsTouchable()
|
|
{
|
|
G4bool omitable;
|
|
|
|
fpCommandCentreAndZoomInOn = new G4UIcmdWithoutParameter("/vis/touchable/centreAndZoomInOn",this);
|
|
fpCommandCentreAndZoomInOn->SetGuidance ("Centre and zoom in on the current touchable.");
|
|
fpCommandCentreAndZoomInOn->SetGuidance
|
|
("Use \"/vis/set/touchable\" to set current touchable.");
|
|
fpCommandCentreAndZoomInOn->SetGuidance
|
|
("You may also need \"/vis/touchable/findPath\".");
|
|
fpCommandCentreAndZoomInOn->SetGuidance
|
|
("Use \"/vis/touchable/set\" to set attributes.");
|
|
|
|
fpCommandCentreOn = new G4UIcmdWithoutParameter("/vis/touchable/centreOn",this);
|
|
fpCommandCentreOn->SetGuidance ("Centre the view on the current touchable.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandCentreOn,1);
|
|
|
|
fpCommandDraw = new G4UIcmdWithoutParameter("/vis/touchable/draw",this);
|
|
fpCommandDraw->SetGuidance("Draw touchable.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandDraw,1);
|
|
|
|
fpCommandDump = new G4UIcmdWithoutParameter("/vis/touchable/dump",this);
|
|
fpCommandDump->SetGuidance("Dump touchable attributes.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandDump,1);
|
|
|
|
fpCommandExtentForField = new G4UIcmdWithABool("/vis/touchable/extentForField",this);
|
|
fpCommandExtentForField->SetGuidance("Set extent for field.");
|
|
fpCommandExtentForField->SetGuidance("If parameter == true, also draw.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandExtentForField,1);
|
|
fpCommandExtentForField->SetParameterName("draw", omitable = true);
|
|
fpCommandExtentForField->SetDefaultValue(false);
|
|
|
|
fpCommandFindPath = new G4UIcommand("/vis/touchable/findPath",this);
|
|
fpCommandFindPath->SetGuidance
|
|
("Prints the path to touchable and its logical volume mother"
|
|
"\ngiven a physical volume name and copy no.");
|
|
fpCommandFindPath -> SetGuidance
|
|
("A search of all worlds is made and all physical volume names are"
|
|
"\nmatched against the argument of this command. If this is of the"
|
|
"\nform \"/regexp/\", where regexp is a regular expression (see C++ regex),"
|
|
"\nthe physical volume name is matched against regexp by the usual rules"
|
|
"\nof regular expression matching. Otherwise an exact match is required."
|
|
"\nFor example, \"/Shap/\" matches \"Shape1\" and \"Shape2\".");
|
|
fpCommandFindPath -> SetGuidance
|
|
("It may help to see a textual representation of the geometry hierarchy of"
|
|
"\nthe worlds. Try \"/vis/drawTree [worlds]\" or one of the driver/browser"
|
|
"\ncombinations that have the required functionality, e.g., HepRep.");
|
|
G4UIparameter* parameter;
|
|
parameter = new G4UIparameter ("physical-volume-name", 's', omitable = true);
|
|
parameter -> SetDefaultValue ("world");
|
|
fpCommandFindPath -> SetParameter (parameter);
|
|
parameter = new G4UIparameter ("copy-no", 'i', omitable = true);
|
|
parameter -> SetGuidance ("If negative, matches any copy no.");
|
|
parameter -> SetDefaultValue (-1);
|
|
fpCommandFindPath -> SetParameter (parameter);
|
|
|
|
fpCommandLocalAxes = new G4UIcmdWithoutParameter("/vis/touchable/localAxes",this);
|
|
fpCommandLocalAxes->SetGuidance("Draw local axes.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandLocalAxes,1);
|
|
|
|
fpCommandShowExtent = new G4UIcmdWithABool("/vis/touchable/showExtent",this);
|
|
fpCommandShowExtent->SetGuidance("Print extent of touchable.");
|
|
fpCommandShowExtent->SetGuidance("If parameter == true, also draw.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandShowExtent,1);
|
|
fpCommandShowExtent->SetParameterName("draw", omitable = true);
|
|
fpCommandShowExtent->SetDefaultValue(false);
|
|
|
|
fpCommandVolumeForField = new G4UIcmdWithABool("/vis/touchable/volumeForField",this);
|
|
fpCommandVolumeForField->SetGuidance("Set volume for field.");
|
|
fpCommandVolumeForField->SetGuidance("If parameter == true, also draw.");
|
|
// Pick up additional guidance from /vis/viewer/centreAndZoomInOn
|
|
CopyGuidanceFrom(fpCommandCentreAndZoomInOn,fpCommandVolumeForField,1);
|
|
fpCommandVolumeForField->SetParameterName("draw", omitable = true);
|
|
fpCommandVolumeForField->SetDefaultValue(false);
|
|
}
|
|
|
|
G4VisCommandsTouchable::~G4VisCommandsTouchable() {
|
|
delete fpCommandVolumeForField;
|
|
delete fpCommandShowExtent;
|
|
delete fpCommandLocalAxes;
|
|
delete fpCommandFindPath;
|
|
delete fpCommandExtentForField;
|
|
delete fpCommandDump;
|
|
delete fpCommandDraw;
|
|
delete fpCommandCentreAndZoomInOn;
|
|
delete fpCommandCentreOn;
|
|
}
|
|
|
|
G4String G4VisCommandsTouchable::GetCurrentValue(G4UIcommand*) {
|
|
return "";
|
|
}
|
|
|
|
void G4VisCommandsTouchable::SetNewValue
|
|
(G4UIcommand* command, G4String newValue)
|
|
{
|
|
G4VisManager::Verbosity verbosity = fpVisManager->GetVerbosity();
|
|
G4bool warn = verbosity >= G4VisManager::warnings;
|
|
|
|
G4UImanager* UImanager = G4UImanager::GetUIpointer();
|
|
|
|
G4TransportationManager* transportationManager =
|
|
G4TransportationManager::GetTransportationManager ();
|
|
|
|
size_t nWorlds = transportationManager->GetNoWorlds();
|
|
|
|
G4VPhysicalVolume* world = *(transportationManager->GetWorldsIterator());
|
|
if (!world) {
|
|
if (verbosity >= G4VisManager::errors) {
|
|
G4cerr <<
|
|
"ERROR: G4VisCommandsTouchable::SetNewValue:"
|
|
"\n No world. Maybe the geometry has not yet been defined."
|
|
"\n Try \"/run/initialize\""
|
|
<< G4endl;
|
|
}
|
|
return;
|
|
}
|
|
|
|
G4VViewer* currentViewer = fpVisManager -> GetCurrentViewer ();
|
|
if (!currentViewer) {
|
|
if (verbosity >= G4VisManager::errors) {
|
|
G4cerr <<
|
|
"ERROR: No current viewer - \"/vis/viewer/list\" to see possibilities."
|
|
<< G4endl;
|
|
}
|
|
return;
|
|
}
|
|
|
|
G4Scene* currentScene = fpVisManager->GetCurrentScene();
|
|
if (!currentScene) {
|
|
if (verbosity >= G4VisManager::errors) {
|
|
G4cerr <<
|
|
"ERROR: No current scene - \"/vis/scene/list\" to see possibilities."
|
|
<< G4endl;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (command == fpCommandCentreOn || command == fpCommandCentreAndZoomInOn) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
// To handle parameterisations, set copy number
|
|
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
|
|
G4PhysicalVolumeModel tempPVModel
|
|
(properties.fpTouchablePV,
|
|
G4PhysicalVolumeModel::UNLIMITED,
|
|
properties.fTouchableGlobalTransform,
|
|
nullptr, // Modelling parameters (not used)
|
|
true, // use full extent (prevents calculating own extent, which crashes)
|
|
properties.fTouchableBaseFullPVPath);
|
|
// Use a temporary scene in order to find vis extent
|
|
G4Scene tempScene("Centre Scene");
|
|
G4bool successful = tempScene.AddRunDurationModel(&tempPVModel,warn);
|
|
if (successful) {
|
|
if (verbosity >= G4VisManager::confirmations) {
|
|
G4cout
|
|
<< "Touchable " << fCurrentTouchableProperties.fTouchablePath
|
|
<< ",\n has been added to temporary scene \"" << tempScene.GetName() << "\"."
|
|
<< G4endl;
|
|
}
|
|
}
|
|
const G4VisExtent& newExtent = tempScene.GetExtent();
|
|
const G4ThreeVector& newTargetPoint = newExtent.GetExtentCentre();
|
|
G4ViewParameters saveVP = currentViewer->GetViewParameters();
|
|
G4ViewParameters newVP = saveVP;
|
|
if (command == fpCommandCentreAndZoomInOn) {
|
|
// Calculate the new zoom factor
|
|
const G4double zoomFactor
|
|
= currentScene->GetExtent().GetExtentRadius()/newExtent.GetExtentRadius();
|
|
newVP.SetZoomFactor(zoomFactor);
|
|
}
|
|
// Change the target point
|
|
const G4Point3D& standardTargetPoint = currentScene->GetStandardTargetPoint();
|
|
newVP.SetCurrentTargetPoint(newTargetPoint - standardTargetPoint);
|
|
// Interpolate
|
|
InterpolateToNewView(currentViewer, saveVP, newVP);
|
|
if (verbosity >= G4VisManager::confirmations) {
|
|
G4cout
|
|
<< "Viewer \"" << currentViewer->GetName()
|
|
<< "\" centred ";
|
|
if (fpCommandCentreAndZoomInOn) {
|
|
G4cout << "and zoomed in";
|
|
}
|
|
G4cout << " on touchable\n" << fCurrentTouchableProperties.fTouchablePath
|
|
<< G4endl;
|
|
}
|
|
SetViewParameters(currentViewer, newVP);
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else if (command == fpCommandDraw) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
// To handle paramaterisations we have to set the copy number
|
|
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
|
|
G4PhysicalVolumeModel* pvModel = new G4PhysicalVolumeModel
|
|
(properties.fpTouchablePV,
|
|
G4PhysicalVolumeModel::UNLIMITED,
|
|
properties.fTouchableGlobalTransform,
|
|
nullptr, // Modelling parameters (not used)
|
|
true, // use full extent (prevents calculating own extent, which crashes)
|
|
properties.fTouchableBaseFullPVPath);
|
|
|
|
G4int keepVerbose = UImanager->GetVerboseLevel();
|
|
G4int newVerbose(0);
|
|
if (keepVerbose >= 2 || verbosity >= G4VisManager::confirmations)
|
|
newVerbose = 2;
|
|
UImanager->SetVerboseLevel(newVerbose);
|
|
UImanager->ApplyCommand("/vis/scene/create");
|
|
currentScene = fpVisManager->GetCurrentScene(); // New current scene
|
|
G4bool successful = currentScene->AddRunDurationModel(pvModel,warn);
|
|
UImanager->ApplyCommand("/vis/sceneHandler/attach");
|
|
UImanager->SetVerboseLevel(keepVerbose);
|
|
|
|
if (successful) {
|
|
if (verbosity >= G4VisManager::confirmations) {
|
|
G4cout << "\"" << properties.fpTouchablePV->GetName()
|
|
<< "\", copy no. " << properties.fCopyNo << " drawn"
|
|
<< G4endl;
|
|
}
|
|
} else {
|
|
G4VisCommandsSceneAddUnsuccessful(verbosity);
|
|
}
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else if (command == fpCommandDump) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
// To handle paramaterisations we have to set the copy number
|
|
properties.fpTouchablePV->SetCopyNo(properties.fCopyNo);
|
|
G4PhysicalVolumeModel tempPVModel
|
|
(properties.fpTouchablePV,
|
|
G4PhysicalVolumeModel::UNLIMITED,
|
|
properties.fTouchableGlobalTransform,
|
|
nullptr, // Modelling parameters (not used)
|
|
true, // use full extent (prevents calculating own extent, which crashes)
|
|
properties.fTouchableBaseFullPVPath);
|
|
const std::map<G4String,G4AttDef>* attDefs = tempPVModel.GetAttDefs();
|
|
std::vector<G4AttValue>* attValues = tempPVModel.CreateCurrentAttValues();
|
|
G4cout << G4AttCheck(attValues,attDefs);
|
|
delete attValues;
|
|
G4Polyhedron* polyhedron =
|
|
properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetPolyhedron();
|
|
G4cout << "\nLocal polyhedron coordinates:\n" << *polyhedron;
|
|
const G4Transform3D& transform = tempPVModel.GetCurrentTransform();
|
|
polyhedron->Transform(transform);
|
|
G4cout << "\nGlobal polyhedron coordinates:\n" << *polyhedron;
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else if (command == fpCommandExtentForField) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
G4VisExtent extent
|
|
= properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
|
|
extent.Transform(properties.fTouchableGlobalTransform);
|
|
fCurrentExtentForField = extent;
|
|
fCurrrentPVFindingsForField.clear();
|
|
if (verbosity >= G4VisManager::confirmations) {
|
|
G4cout << "Extent for field set to " << extent
|
|
<< "\nVolume for field has been cleared."
|
|
<< G4endl;
|
|
}
|
|
if (fpCommandExtentForField->GetNewBoolValue(newValue)) {
|
|
DrawExtent(extent);
|
|
}
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else if (command == fpCommandFindPath) {
|
|
|
|
G4String pvName;
|
|
G4int copyNo;
|
|
std::istringstream iss(newValue);
|
|
iss >> pvName >> copyNo;
|
|
std::vector<G4PhysicalVolumesSearchScene::Findings> findingsVector;
|
|
std::vector<G4VPhysicalVolume*>::iterator iterWorld =
|
|
transportationManager->GetWorldsIterator();
|
|
for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
|
|
G4PhysicalVolumeModel searchModel (*iterWorld); // Unlimited depth.
|
|
G4ModelingParameters mp; // Default - no culling.
|
|
searchModel.SetModelingParameters (&mp);
|
|
// Find all instances at any position in the tree
|
|
G4PhysicalVolumesSearchScene searchScene (&searchModel, pvName, copyNo);
|
|
searchModel.DescribeYourselfTo (searchScene); // Initiate search.
|
|
for (const auto& findings: searchScene.GetFindings()) {
|
|
findingsVector.push_back(findings);
|
|
}
|
|
}
|
|
for (const auto& findings: findingsVector) {
|
|
G4cout
|
|
<< findings.fFoundBasePVPath
|
|
<< ' ' << findings.fpFoundPV->GetName()
|
|
<< ' ' << findings.fFoundPVCopyNo
|
|
<< " (mother logical volume: "
|
|
<< findings.fpFoundPV->GetMotherLogical()->GetName()
|
|
<< ')'
|
|
<< G4endl;
|
|
}
|
|
if (findingsVector.size()) {
|
|
G4cout
|
|
<< "Use this to set a particular touchable with \"/vis/set/touchable <path>\""
|
|
<< "\nor to see overlaps: \"/vis/drawLogicalVolume <mother-logical-volume-name>\""
|
|
<< G4endl;
|
|
} else {
|
|
G4cout << pvName;
|
|
if (copyNo >= 0) G4cout << ':' << copyNo;
|
|
G4cout << " not found" << G4endl;
|
|
}
|
|
|
|
} else if (command == fpCommandLocalAxes) {
|
|
|
|
const auto& transform = fCurrentTouchableProperties.fTouchableGlobalTransform;
|
|
const auto& extent = fCurrentTouchableProperties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
|
|
const G4double lengthMax = extent.GetExtentRadius()/2.;
|
|
const G4double intLog10LengthMax = std::floor(std::log10(lengthMax));
|
|
G4double length = std::pow(10,intLog10LengthMax);
|
|
if (5.*length < lengthMax) length *= 5.;
|
|
else if (2.*length < lengthMax) length *= 2.;
|
|
G4AxesModel axesModel(0.,0.,0.,length,transform);
|
|
axesModel.SetGlobalTag("LocalAxesModel");
|
|
axesModel.DescribeYourselfTo(*fpVisManager->GetCurrentSceneHandler());
|
|
|
|
} else if (command == fpCommandShowExtent) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
G4VisExtent extent
|
|
= properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
|
|
extent.Transform(properties.fTouchableGlobalTransform);
|
|
G4cout << extent << G4endl;
|
|
if (fpCommandShowExtent->GetNewBoolValue(newValue)) DrawExtent(extent);
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else if (command == fpCommandVolumeForField) {
|
|
|
|
G4PhysicalVolumeModel::TouchableProperties properties =
|
|
G4TouchableUtils::FindTouchableProperties(fCurrentTouchableProperties.fTouchablePath);
|
|
if (properties.fpTouchablePV) {
|
|
G4VisExtent extent
|
|
= properties.fpTouchablePV->GetLogicalVolume()->GetSolid()->GetExtent();
|
|
extent.Transform(properties.fTouchableGlobalTransform);
|
|
fCurrentExtentForField = extent;
|
|
fCurrrentPVFindingsForField.clear();
|
|
fCurrrentPVFindingsForField.push_back
|
|
(G4PhysicalVolumesSearchScene::Findings(properties));
|
|
if (verbosity >= G4VisManager::confirmations) {
|
|
G4cout
|
|
<< "Volume for field set to " << properties.fpTouchablePV->GetName()
|
|
<< ':' << properties.fCopyNo
|
|
<< " at " << properties.fTouchableBaseFullPVPath
|
|
<< G4endl;
|
|
}
|
|
if (fpCommandVolumeForField->GetNewBoolValue(newValue)) {
|
|
DrawExtent(extent);
|
|
}
|
|
} else {
|
|
G4cout << "Touchable not found." << G4endl;
|
|
}
|
|
return;
|
|
|
|
} else {
|
|
|
|
if (verbosity >= G4VisManager::errors) {
|
|
G4cerr <<
|
|
"ERROR: G4VisCommandsTouchable::SetNewValue: unrecognised command."
|
|
<< G4endl;
|
|
}
|
|
return;
|
|
}
|
|
}
|