Files
geant4/source/visualization/OpenInventor/src/G4OpenInventorXtExaminerViewer.cc
T
2016-06-10 12:08:39 +02:00

4854 lines
166 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// Open Inventor Xt Extended Viewer - 30 Oct 2012
// Rastislav Ondrasek, Pierre-Luc Gagnon, Frederick Jones TRIUMF
#include <stdio.h>
#include <string.h>
#include <string>
#include <sstream>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <algorithm> // For using sort on a vector
#include <X11/keysym.h>
#include <Xm/Xm.h>
#include <Xm/Text.h>
#include <Xm/List.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/CascadeB.h>
#include <Xm/ArrowBG.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/FileSB.h>
#include <Xm/SelectioB.h>
#include <Xm/Protocols.h>
#include <Xm/SeparatoG.h>
#include <Xm/DialogS.h>
#include <Xm/PanedW.h>
#include <Xm/LabelG.h>
#include <Xm/Scale.h>
#include <Xm/DrawingA.h>
#include <Inventor/Xt/SoXt.h>
//#include <Inventor/Xt/SoXtInternal.h>
#include <Inventor/Xt/SoXtCursor.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoOrthographicCamera.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
// FWJ moved to header file
//#include <Inventor/nodes/SoEventCallback.h>
#include <Inventor/nodes/SoLineSet.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/actions/SoWriteAction.h>
#include "G4OpenInventorXtExaminerViewer.hh"
#include "wheelmouse.h" // To use mouse scrolling in dialogs
#include "SoXtInternal.h"
#include <Inventor/sensors/SoTimerSensor.h> // Animation
#include <Inventor/sensors/SoNodeSensor.h> // Detect start of run
#include "saveViewPt.h"
#include "console.h"
#include "favorites.h"
#include "Geant4_SoPolyhedron.h"
//#include "G4RunManager.hh"
//#include "G4Run.hh"
#include "G4TrajectoryPoint.hh"
#include "G4AttHolder.hh"
#include "G4AttCheck.hh"
#include <Inventor/nodes/SoCallback.h>
#include <Inventor/nodes/SoSwitch.h>
#include <Inventor/nodes/SoScale.h>
#include <Inventor/nodes/SoTranslation.h>
#include <Inventor/actions/SoSearchAction.h>
#include <Inventor/actions/SoGetBoundingBoxAction.h>
#include <Inventor/nodes/SoCoordinate3.h>
// For rendering distance during animation:
#include <Inventor/nodes/SoText2.h>
#include <Inventor/nodes/SoFont.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoBaseColor.h>
// For searching for nodes within kits:
#include <Inventor/nodekits/SoBaseKit.h>
// FWJ
#include <Inventor/SbVec3f.h>
G4OpenInventorXtExaminerViewer* G4OpenInventorXtExaminerViewer::viewer = 0;
static const char* thisClassName = "G4OpenInventorXtExaminerViewer";
#define MIN_SPEED 2.1 // Lower number means faster
#define START_STEP 0.3
#define SPEED_INDICATOR_STEP 0.045
#define MAX_SPEED_INDICATOR 0.81
// Number of steps 90 degree rotation around an element is split into
#define ROT_CNT 6
// Public constructor
G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent,
const char *name, SbBool embed,
SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type) :
SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
{
// Tell GLWidget not to build just yet
this->constructor(TRUE);
}
// Protected constructor for classes deriving from this viewer.
G4OpenInventorXtExaminerViewer::G4OpenInventorXtExaminerViewer(Widget parent,
const char *name, SbBool embed,
SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type,
SbBool build) :
SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
{
this->constructor(build);
}
// Called by all constructors to set up widgets and initialize member fields.
void G4OpenInventorXtExaminerViewer::constructor(const SbBool build)
{
setClassName(thisClassName);
hookBeamOn = new HookEventProcState(this);
this->newEvents = false;
fileName = ".bookmarkFile"; // Default viewpoint file name
viewPtIdx = -1; // index of the most recent viewpoint in viewPtList vector
animateSensor = new SoTimerSensor(
G4OpenInventorXtExaminerViewer::animateSensorCB, this);
animateSensorRotation = new SoTimerSensor(
G4OpenInventorXtExaminerViewer::animateSensorRotationCB, this);
animateBtwPtsPeriod = MIN_SPEED;
currentState = GENERAL;
myCam = new SoPerspectiveCamera;
MAX_VP_IDX = 3;
MAX_VP_NAME = 35; // Max length of a viewpoint name, padded with spaces
rotCnt = ROT_CNT; // For 90 degree rotations
curViewPtName = new char[MAX_VP_NAME + 1];
left_right = up_down = 0; // For movements around the beam during animation
speedStep = START_STEP; // For smoother animation speed increase/decrease
rotUpVec = false; // Used during scene element rotations
step = 1; //By default
// Used for moving along the beam with the
// mouse instead of rotating the view
lshiftdown = rshiftdown = false;
// Used for rotating the view with the camera
// staying in place
lctrldown = rctrldown = false;
// Used to send abbreviated output to the console when
abbrOutputFlag = false;
pickRefPathFlag = false;
prevColorField = NULL;
warningFlag = false; // We come from the warning dialog
viewer = this;
openFileDialog = newFileDialog = listsDialog = (Widget) NULL;
loadRefCoordsDialog = saveRefCoordsDialog = NULL;
loadSceneGraphDialog = saveSceneGraphDialog = NULL;
myElementList = NULL;
// FWJ default path look-ahead
pathLookahead = 5;
newSceneGraph = NULL;
zcoordSetFlag = false;
//////////////////////////SUPERIMPOSED SCENE//////////////////////////
searcher = NULL;
// Used in animation; progressively scaled for gradual speed change
maxSpeed = 0.0f;
static const char * superimposed[] = {
"#Inventor V2.1 ascii", "",
"Separator ",
"{",
" MaterialBinding ",
" {",
" value OVERALL",
" }",
" OrthographicCamera ",
" {",
" height 1",
" nearDistance 0",
" farDistance 1",
" }",
" DEF soxt->callback Callback { }",
" Separator ",
" {",
" DEF soxt->translation Translation ",
" {",
" translation 0 0 0",
" }",
" DEF soxt->scale Scale ",
" {",
" scaleFactor 1 1 1",
" }",
" DEF soxt->geometry Coordinate3 ",
" {",
" point ",
" [",
" -0.81 -0.04 0, -0.81 0 0,",
" -0.81 0.04 0, 0 -0.04 0,",
" 0 0 0, 0 0.04 0,",
" 0.81 -0.04 0, 0.81 0 0,",
" 0.81 0.04 0,",
" 0 0.02 0,", // idx 9
" 0.81 0.02 0, 0.81 -0.02 0,",
" 0 -0.02 0,",
" 0 0.01 0,", // idx 13
" 0.4 0.01 0, 0.4 -0.01 0,",
" 0 -0.01 0",
" ]",
" }",
// current speed indicator (outline)
" DEF soxt->animSpeedOutlineSwitch Switch ",
" {",
" whichChild -3",
" Material ",
" {",
" emissiveColor 0 0 0",
" }",
" IndexedFaceSet ",
" {",
" coordIndex ",
" [",
" 12, 11, 10, 9, -1",
" ]",
" }",
" }",
// the coordinate system
" DEF soxt->axisSwitch Switch ",
" {",
" whichChild -3",
" BaseColor ",
" {",
" rgb 1 1 1",
" }",
" IndexedLineSet ",
" {",
" coordIndex ",
" [",
" 0, 2, -1,",
" 3, 5, -1,",
" 6, 8, -1,",
" 1, 7, -1",
" ]",
" }",
" }",
// current speed indicator
" DEF soxt->animSpeedSwitch Switch ",
" {",
" whichChild -3",
" Material ",
" {",
" emissiveColor 0 1 0",
" }",
" IndexedFaceSet ",
" {",
" coordIndex ",
" [",
" 16, 15, 14, 13, -1",
" ]",
" }",
" }",
" }",
// For displaying either z position (during animation) or current viewpoint name
" DEF soxt->curInfoSwitch Switch ",
" {",
" whichChild -3",
" DEF soxt->curInfoTrans Translation ",
" {",
" translation 10 20 30 ",
" }",
" DEF soxt->curInfoFont Font ",
" {",
" name defaultFont:Bold",
" size 16",
" }",
" DEF soxt->curInfoText Text2 ",
" {",
" string Hello",
" }",
" }",
// Need to use different fields for mouseover
// because newlines are ignored when the scene is rendered
" Separator ",
" {",
" DEF soxt->mouseOverTransLogName Translation ",
" {",
" translation 0 0 0 ",
" }",
" DEF soxt->mouseOverFontLogName Font ",
" {",
" name defaultFont:Bold",
" size 16",
" }",
" DEF soxt->mouseOverTextLogName Text2 { } ",
" }",
" Separator ",
" {",
" DEF soxt->mouseOverTransSolid Translation ",
" {",
" translation 0 0 0 ",
" }",
" DEF soxt->mouseOverFontSolid Font ",
" {",
" name defaultFont:Bold",
" size 16",
" }",
" DEF soxt->mouseOverTextSolid Text2 { } ",
" }",
" Separator ",
" {",
" DEF soxt->mouseOverTransMaterial Translation ",
" {",
" translation 0 0 0 ",
" }",
" DEF soxt->mouseOverFontMaterial Font ",
" {",
" name defaultFont:Bold",
" size 16",
" }",
" DEF soxt->mouseOverTextMaterial Text2 { } ",
" }",
" Separator ",
" {",
" DEF soxt->mouseOverTransZPos Translation ",
" {",
" translation 0 0 0 ",
" }",
" DEF soxt->mouseOverFontZPos Font ",
" {",
" name defaultFont:Bold",
" size 16",
" }",
" DEF soxt->mouseOverTextZPos Text2 { } ",
" }",
"}", NULL
};
int i, bufsize;
for (i = bufsize = 0; superimposed[i]; i++)
bufsize += strlen(superimposed[i]) + 1;
char * buf = new char[bufsize + 1];
for (i = bufsize = 0; superimposed[i]; i++) {
strcpy(buf + bufsize, superimposed[i]);
bufsize += strlen(superimposed[i]);
buf[bufsize] = '\n';
bufsize++;
}
SoInput * input = new SoInput;
input->setBuffer(buf, bufsize);
SbBool ok = SoDB::read(input, this->superimposition);
(void)ok; // FWJ added to avoid compiler warning
assert(ok);
delete input;
delete[] buf;
this->superimposition->ref();
this->sscale = (SoScale *) this->getSuperimpositionNode(
this->superimposition, "soxt->scale");
this->stranslation = (SoTranslation *) this->getSuperimpositionNode(
this->superimposition, "soxt->translation");
this->sgeometry = (SoCoordinate3 *) this->getSuperimpositionNode(
this->superimposition, "soxt->geometry");
this->axisSwitch = (SoSwitch *) this->getSuperimpositionNode(
this->superimposition, "soxt->axisSwitch");
this->animSpeedOutlineSwitch = (SoSwitch *) this->getSuperimpositionNode(
this->superimposition, "soxt->animSpeedOutlineSwitch");
this->animSpeedSwitch = (SoSwitch *) this->getSuperimpositionNode(
this->superimposition, "soxt->animSpeedSwitch");
this->curInfoSwitch = (SoSwitch *) this->getSuperimpositionNode(
this->superimposition, "soxt->curInfoSwitch");
this->curInfoTrans = (SoTranslation *) this->getSuperimpositionNode(
this->superimposition, "soxt->curInfoTrans");
this->curInfoFont = (SoFont *) this->getSuperimpositionNode(
this->superimposition, "soxt->curInfoFont");
this->curInfoText = (SoText2 *) this->getSuperimpositionNode(
this->superimposition, "soxt->curInfoText");
this->mouseOverTransLogName = (SoTranslation*)this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTransLogName");
this->mouseOverFontLogName = (SoFont *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverFontLogName");
this->mouseOverTextLogName = (SoText2 *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTextLogName");
this->mouseOverTransSolid = (SoTranslation *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTransSolid");
this->mouseOverFontSolid = (SoFont *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverFontSolid");
this->mouseOverTextSolid = (SoText2 *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTextSolid");
this->mouseOverTransMaterial = (SoTranslation*)this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTransMaterial");
this->mouseOverFontMaterial = (SoFont *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverFontMaterial");
this->mouseOverTextMaterial = (SoText2 *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTextMaterial");
this->mouseOverTransZPos = (SoTranslation *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTransZPos");
this->mouseOverFontZPos = (SoFont *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverFontZPos");
this->mouseOverTextZPos = (SoText2 *) this->getSuperimpositionNode(
this->superimposition, "soxt->mouseOverTextZPos");
SoCallback * cb = (SoCallback *) this->getSuperimpositionNode(
this->superimposition, "soxt->callback");
cb->setCallback(superimpositionCB, this);
this->addSuperimposition(this->superimposition);
this->setSuperimpositionEnabled(this->superimposition, FALSE);
axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
/////////////////////\SUPERIMPOSED SCENE///////////////////////////////////
// Build everything else like the parent viewer does
if (build) {
Widget w = buildWidget(getParentWidget());
setBaseWidget(w);
// Make this window a little bigger because of the extra buttons
// FWJ but it is already set to 600x600 by vis/open
// setSize(SbVec2s(500, 550));
}
}
// Static function that returns the pointer to G4OpenInventorXtExaminerViewer
// FWJ DISABLED
//G4OpenInventorXtExaminerViewer *G4OpenInventorXtExaminerViewer::getObject()
//{
// if (!viewer)
// new G4OpenInventorXtExaminerViewer();
// return viewer;
//}
// This method locates a named node in the superimposed or original scene.
SoNode *
G4OpenInventorXtExaminerViewer::getSuperimpositionNode(SoNode *root,
const char * name)
{
if (!this->searcher)
this->searcher = new SoSearchAction;
searcher->reset();
searcher->setName(SbName(name));
searcher->setInterest(SoSearchAction::FIRST);
searcher->setSearchingAll(TRUE);
searcher->apply(root);
assert(searcher->getPath());
return searcher->getPath()->getTail();
}
void G4OpenInventorXtExaminerViewer::superimpositionCB(void * closure,
SoAction * action)
{
if (closure)
((G4OpenInventorXtExaminerViewer*)closure)->superimpositionEvent(action);
}
// Renders and positions speed indicator and longitudinal
// distance/viewpoint name on the drawing canvas
void G4OpenInventorXtExaminerViewer::superimpositionEvent(SoAction * action)
{
if (!action->isOfType(SoGLRenderAction::getClassTypeId()))
return;
SbViewportRegion vpRegion =
((SoGLRenderAction *) action)->getViewportRegion();
SbVec2s viewportSize = vpRegion.getViewportSizePixels();
float aspect = float(viewportSize[0]) / float(viewportSize[1]);
float factorx = 1.0f / float(viewportSize[1]) * 220.0f;
float factory = factorx;
if (aspect > 1.0f) {
this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
} else {
this->stranslation->translation.setValue(
SbVec3f(0.0f, -0.4f / aspect, 0.0f));
factorx /= aspect;
factory /= aspect;
}
if (viewportSize[0] > 500)
factorx *= 500.0f / 400.0f;
else
factorx *= float(viewportSize[0]) / 400.0f;
this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
float xInfo, yInfo, xMouseLogName, yMouseLogName, xMouseSolid, yMouseSolid,
xMouseMaterial, yMouseMaterial, xMouseZPos, yMouseZPos;
xInfo = -.45;
yInfo = .45;
xMouseLogName = 0.0;
yMouseLogName = -.75;
xMouseSolid = 0.0;
yMouseSolid = -.78;
xMouseMaterial = 0.0;
yMouseMaterial = -.81;
xMouseZPos = 0.0;
yMouseZPos = -.84;
if (aspect > 1.0f) {
xInfo *= aspect;
xMouseSolid *= aspect;
xMouseMaterial *= aspect;
this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
this->mouseOverTransLogName->translation.setValue(
SbVec3f(xMouseLogName, yMouseLogName, 0.0));
this->mouseOverTransSolid->translation.setValue(
SbVec3f(xMouseSolid, yMouseSolid, 0.0));
this->mouseOverTransMaterial->translation.setValue(
SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
this->mouseOverTransZPos->translation.setValue(
SbVec3f(xMouseZPos, yMouseZPos, 0.0));
} else {
yInfo /= aspect;
yMouseSolid /= aspect;
yMouseMaterial /= aspect;
this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
this->mouseOverTransLogName->translation.setValue(
SbVec3f(xMouseLogName, yMouseLogName, 0.0));
this->mouseOverTransSolid->translation.setValue(
SbVec3f(xMouseSolid, yMouseSolid, 0.0));
this->mouseOverTransMaterial->translation.setValue(
SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
this->mouseOverTransZPos->translation.setValue(
SbVec3f(xMouseZPos, yMouseZPos, 0.0));
}
if (currentState == VIEWPOINT) { // Displaying viewpoint name
this->curInfoFont->size.setValue(15);
this->curInfoFont->name.setValue("defaultFont:Italic");
this->curInfoText->string.setValue(SbString(curViewPtName));
}
else if(currentState == GENERAL) { // Displaying longitudinal distance
this->curInfoFont->size.setValue(16);
this->curInfoFont->name.setValue("defaultFont:Bold");
this->curInfoText->string.setValue(SbString(""));
}
else {
if (refParticleIdx < (int) refParticleTrajectory.size() - 1) {
this->curInfoFont->size.setValue(16);
this->curInfoFont->name.setValue("defaultFont:Bold");
char zPos[20];
sprintf(zPos, "%7.2f [m]", refZPositions[refParticleIdx] / 1000);
this->curInfoText->string.setValue(SbString(zPos));
}
}
}
G4OpenInventorXtExaminerViewer::~G4OpenInventorXtExaminerViewer()
{
if (superimposition != NULL) {
removeSuperimposition(superimposition);
superimposition->unref();
superimposition = NULL;
}
if (animateSensor->isScheduled())
animateSensor->unschedule();
delete animateSensor;
delete sceneChangeSensor;
delete[] curViewPtName;
delete searcher;
viewer = 0;
}
// Adds a menu bar and a few menu items to the viewer.
Widget G4OpenInventorXtExaminerViewer::buildWidget(Widget parent)
{
Widget shell;
Atom WM_DELETE_WINDOW;
if (!parent)
SoDebugError::post("G4OpenInventorXtExaminerViewer::buildWidget", "Error: Parent is null.");
Arg args[10];
XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
XtSetArg(args[3], XmNbottomAttachment, XmATTACH_FORM);
Widget form = XmCreateForm(parent, (char *) "Form", args, 4);
XtManageChild(form);
shell = XtParent(form);
WM_DELETE_WINDOW = XInternAtom(XtDisplay(parent), "WM_DELETE_WINDOW",
False);
XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW,
(XtCallbackProc)closeMainWindowCB, this);
XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
menuBar = XmCreateMenuBar(form, (char *) "MenuBar", args, 3);
XtManageChild(menuBar);
fileMenu = addMenu("File");
this->addButton(fileMenu, "Open Viewpoint File...", openViewPtFileCB);
addButton(fileMenu, "New Viewpoint File", newViewPtFileCB);
addButton(fileMenu, "Load Ref. Coords", loadRefCoordsDialogCB);
addButton(fileMenu, "Save Ref. Coords", saveRefCoordsDialogCB);
addButton(fileMenu, "Load Scene Graph", loadSceneGraphDialogCB);
addButton(fileMenu, "Save Scene Graph", saveSceneGraphDialogCB);
XtManageChild(
XmCreateSeparatorGadget(fileMenu, (char *) "Separator", NULL, 0));
Widget menu = addMenu("Tools");
addButton(menu, "Animate Ref. Particle", animateRefParticleCB);
addButton(menu, "Go to start of Ref path", gotoRefPathStartCB);
addButton(menu, "Invert Ref path", invertRefPathCB);
Widget viewerBase = SoXtFullViewer::buildWidget(form);
XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
XtSetArg(args[1], XmNtopWidget, menuBar);
XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM);
XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
XtSetValues(viewerBase, args, 5);
return viewerBase;
}
// Adds a new menu to menuBar
Widget G4OpenInventorXtExaminerViewer::addMenu(std::string name)
{
Arg args[1];
Widget menu = XmCreatePulldownMenu(menuBar, (char *) name.c_str(), NULL, 0);
XtSetArg(args[0], XmNsubMenuId, menu);
Widget w = XmCreateCascadeButton(menuBar, (char *) name.c_str(), args, 1);
XtManageChild(w);
return menu;
}
// Adds a new button to menu
void G4OpenInventorXtExaminerViewer::addButton(Widget menu, std::string name,
XtCallbackProc cb)
{
Widget button = XmCreatePushButton(menu, (char *) name.c_str(), NULL, 0);
XtManageChild(button);
XtAddCallback(button, XmNactivateCallback, cb, this);
}
// Overloaded for saving of and browsing through viewpoints.
void G4OpenInventorXtExaminerViewer::createViewerButtons(Widget parent,
SbPList * buttonlist)
{
int n;
Arg args[6];
Widget saveViewPtButton, abbrOutputButton, pickRefPathButton;
// Create original buttons
SoXtExaminerViewer::createViewerButtons(parent, buttonlist);
// Handle disappearing button caused by SoXtExaminerViewer::setCamera
Widget emptyButton = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
parent, NULL);
buttonlist->append(emptyButton);
// Left arrow that goes back one view point on click
n = 0;
XtSetArg(args[n], XmNtopPosition, 1); n++;
XtSetArg(args[n], XmNbottomPosition, 2); n++;
XtSetArg(args[n], XmNleftPosition, 0); n++;
XtSetArg(args[n], XmNrightPosition, 1); n++;
XtSetArg(args[n], XmNarrowDirection, XmARROW_LEFT); n++;
XtSetArg(args[n], XmNsensitive, False); n++;
prevViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowL",
args, n);
XtManageChild(prevViewPtButton);
XtAddCallback(prevViewPtButton, XmNactivateCallback,
G4OpenInventorXtExaminerViewer::prevViewPtCB, this);
buttonlist->append(prevViewPtButton);
// Right arrow that goes forward one view point on click
n = 0;
XtSetArg(args[n], XmNtopPosition, 1); n++;
XtSetArg(args[n], XmNbottomPosition, 2); n++;
XtSetArg(args[n], XmNleftPosition, 0); n++;
XtSetArg(args[n], XmNrightPosition, 1); n++;
XtSetArg(args[n], XmNarrowDirection, XmARROW_RIGHT); n++;
XtSetArg(args[n], XmNsensitive, False); n++;
nextViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowR",
args, n);
XtManageChild(nextViewPtButton);
XtAddCallback(nextViewPtButton, XmNactivateCallback,
G4OpenInventorXtExaminerViewer::nextViewPtCB, this);
buttonlist->append(nextViewPtButton);
// Save button for storing current camera parameters
saveViewPtButton = XtVaCreateManagedWidget("Save", xmPushButtonWidgetClass,
parent, NULL);
XtAddCallback(saveViewPtButton, XmNactivateCallback,
G4OpenInventorXtExaminerViewer::saveViewPtCB, this);
Pixmap saveVP, saveVP_ins;
saveVP = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
saveViewPt_xpm);
saveVP_ins = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
saveViewPt_xpm, TRUE);
XtVaSetValues(saveViewPtButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
saveVP, XmNselectPixmap, saveVP, XmNlabelInsensitivePixmap,
saveVP_ins, XmNselectInsensitivePixmap, saveVP_ins, NULL);
buttonlist->append(saveViewPtButton);
// Toggle button to get abbreviated output
abbrOutputButton = XtVaCreateManagedWidget("Abbr",
xmToggleButtonWidgetClass, parent, XmNindicatorOn, False, NULL);
XtAddCallback(abbrOutputButton, XmNdisarmCallback, G4OpenInventorXtExaminerViewer::abbrOutputCB,
this);
Pixmap consolexpm, consolexpm_ins;
consolexpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
console_xpm);
consolexpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
console_xpm, TRUE);
XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
consolexpm, XmNselectPixmap, consolexpm, XmNlabelInsensitivePixmap,
consolexpm_ins, XmNselectInsensitivePixmap, consolexpm_ins, NULL);
buttonlist->append(abbrOutputButton);
// Button for selecting the beam that will act as reference path
pickRefPathButton = XtVaCreateManagedWidget("Refpath", xmPushButtonWidgetClass,
parent, NULL);
XtAddCallback(pickRefPathButton, XmNactivateCallback,
G4OpenInventorXtExaminerViewer::pickRefPathCB, this);
Pixmap favoritesxpm, favoritesxpm_ins;
favoritesxpm = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
favorites_xpm);
favoritesxpm_ins = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
favorites_xpm, TRUE);
XtVaSetValues(pickRefPathButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
favoritesxpm, XmNselectPixmap, favoritesxpm, XmNlabelInsensitivePixmap,
favoritesxpm_ins, XmNselectInsensitivePixmap, favoritesxpm_ins, NULL);
buttonlist->append(pickRefPathButton);
}
// Called right after buttons and widgets get realized.
// It sets the viewpoint last accessed.
void G4OpenInventorXtExaminerViewer::afterRealizeHook()
{
SoXtExaminerViewer::afterRealizeHook();
// Default height is used when selecting and viewing scene elements
// FWJ Added defaultHeight for Ortho camera
SoCamera *cam = getCamera();
if (cam) {
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
defaultHeightAngle =
((SoPerspectiveCamera *) cam)->heightAngle.getValue();
toggleCameraType();
defaultHeight =
((SoOrthographicCamera *) cam)->height.getValue();
toggleCameraType();
} else {
defaultHeight =
((SoOrthographicCamera *) cam)->height.getValue();
toggleCameraType();
cam = getCamera();
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
defaultHeightAngle =
((SoPerspectiveCamera *) cam)->heightAngle.getValue();
toggleCameraType();
}
}
// Open the default bookmark file
fileIn.open(fileName.c_str());
if (!fileIn.fail()) {
if (!loadViewPts()) {
String dialogName = (char *) "Error Loading File";
std::string msg = "Wrong or corrupted input file.";
warningMsgDialog(msg, dialogName, NULL);
} else {
// Opens a file without erasing it
fileOut.open(fileName.c_str(), std::ios::in);
fileOut.seekp(0, std::ios::end); // For appending new data to the end
constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
if (viewPtList.size()) {
// FWJ disabled auto-selection of first viewpoint.
// Initial view should be user-controllable & not forced
// setViewPt();
XtSetSensitive(nextViewPtButton, True);
XtSetSensitive(prevViewPtButton, True);
}
}
fileIn.close();
} else {
// Creates a new default bookmark file
fileOut.open(fileName.c_str());
constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
}
fileIn.clear();
SoSeparator *root = (SoSeparator *) (getSceneManager()->getSceneGraph());
if (root == NULL)
SoDebugError::post("G4OpenInventorXtExaminerViewer::afterRealizeHook", "Root is null.");
else {
root->addChild(myCam); // For position/orientation calculation during animation
}
sceneChangeSensor = new SoNodeSensor;
sceneChangeSensor->setFunction(sceneChangeCB);
sceneChangeSensor->attach(root);
sceneChangeSensor->setData(this);
// Monitor mouseover events for displaying the name of scene elements
// An SoEventCallback is needed instead of using the default processSoEvent
// because that last one does not provide us with an SoPath to the object
// that was picked
SoEventCallback *moCB = new SoEventCallback;
moCB->addEventCallback(
SoLocation2Event::getClassTypeId(),
mouseoverCB, static_cast<void *>(this));
root->addChild(moCB);
// Override the default picking mechanism present in G4OpenInventorViewer
// because we want abbreviated output when picking a trajectory
SoEventCallback *pickCB = new SoEventCallback;
pickCB->addEventCallback(
SoMouseButtonEvent::getClassTypeId(),
pickingCB, static_cast<void *>(this));
root->addChild(pickCB);
}
// Rotates camera 90 degrees around a scene element.
// Rotation is animated for smoothness.
void G4OpenInventorXtExaminerViewer::rotateCamera()
{
SoCamera *cam = getCamera();
SbRotation rot(rotAxis, M_PI / (2 * ROT_CNT));
rot.multVec(camDir, camDir);
rot.multVec(camUpVec, camUpVec);
SbVec3f camPosNew = prevPt - (camDir*distance);
cam->position = camPosNew;
cam->pointAt(prevPt, camUpVec);
cam->focalDistance = (prevPt - camPosNew).length();
rotCnt--;
if (animateSensorRotation->isScheduled()) {
animateSensorRotation->unschedule();
}
animateSensorRotation->setBaseTime(SbTime::getTimeOfDay());
animateSensorRotation->setInterval(SbTime(0.02));
animateSensorRotation->schedule();
}
// Slides camera along the beamline.
void G4OpenInventorXtExaminerViewer::moveCamera(float dist, bool lookdown)
{
SoCamera *cam = getCamera();
SbVec3f p1, p2; // The particle moves from p1 to p2
SbVec3f particleDir; // Direction vector from p1 to p2
SbVec3f camPosNew; // New position of the camera
if(refParticleTrajectory.size() == 0) {
//refParticleTrajectory hasn't been set yet
if(dist)
distance = dist;
else
distance = (cam->position.getValue() - center).length();
cam->position.setValue(center + offsetFromCenter*distance);
cam->focalDistance = (cam->position.getValue() - center).length();
cam->pointAt(center, upVector);
}
else{
// If we move forward past the last trajectory point,
// go back to the beginning
if (refParticleIdx >= (int) refParticleTrajectory.size() - 1) {
prevPt = refParticleTrajectory[refParticleIdx - step];
dist = (prevPt - cam->position.getValue()).length();
refParticleIdx = 0;
}
// If we move backward past the beginning,
// go to the last trajectory point
if (refParticleIdx < 0) {
prevPt = refParticleTrajectory[refParticleIdx + step];
dist = (prevPt - cam->position.getValue()).length();
refParticleIdx = refParticleTrajectory.size() - 2;
}
// Set start and end points
p1 = refParticleTrajectory[refParticleIdx];
p2 = refParticleTrajectory[refParticleIdx + step];
// Get the direction from p1 to p2
particleDir = p2 - p1;
particleDir.normalize();
if(prevParticleDir == SbVec3f(0,0,0)){
// First time entering BEAMLINE mode, look at
// the element from the front, with camera upright
if(lookdown)
camDir = SbVec3f(0,0,1);
else
camDir = SbVec3f(1,0,0);
camUpVec = SbVec3f(0,1,0);
// In case the start of the goes in a
// direction other than +z, rotate the camera accordingly
SbRotation rot(SbVec3f(0,0,1), particleDir);
rot.multVec(camDir, camDir);
rot.multVec(camUpVec, camUpVec);
}
else if(particleDir != prevParticleDir) {
// The beamline has changed direction
SbRotation rot(prevParticleDir, particleDir);
rot.multVec(camDir, camDir);
rot.multVec(camUpVec, camUpVec);
}
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
if (!dist)
distance = (prevPt - cam->position.getValue()).length();
else
distance = dist;
}
if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
if (!dist)
distance = (prevPt - cam->position.getValue()).length();
else
distance = dist;
}
float x,y,z;
prevPt.getValue(x,y,z);
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
camPosNew = p2 - (camDir*distance);
}
if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
camPosNew = p2 - (camDir);
}
cam->position = camPosNew;
cam->pointAt(p2, camUpVec);
// FWJ Disabled: zooms out the Persp camera much too far
// and can't recover by zooming in!
// cam->focalDistance = (p2 - camPosNew).length();
p2.getValue(x,y,z);
camPosNew.getValue(x,y,z);
prevParticleDir = particleDir;
prevPt = p1; // For accurate distance calculation
}
}
void G4OpenInventorXtExaminerViewer::pickingCB(void *aThis,
SoEventCallback *eventCB)
{
SoHandleEventAction* action = eventCB->getAction();
const SoPickedPoint *pp = action->getPickedPoint();
G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis;
if(pp != NULL) {
SoPath* path = pp->getPath();
SoNode* node = ((SoFullPath*)path)->getTail();
if(node->getTypeId() == SoLineSet::getClassTypeId()){
if(This->pickRefPathFlag){
This->pickRefPathFlag = false;
if(This->viewingBeforePickRef != This->isViewing())
This->setViewing(This->viewingBeforePickRef);
else
This->setComponentCursor(SoXtCursor(SoXtCursor::DEFAULT));
// The trajectory is a set of lines stored in a LineSet
SoLineSet * trajectory = (SoLineSet *)node;
// The set of all trajectories is stored in a Seperator group node
// one level above the LineSet that was picked. The nodes under that
// seperator are as follows (in this order): Material, LightModel,
// ResetTransform, MatrixTransform, Coordinate3, DrawStyle, LineSet
SoSeparator * grpNode =
(SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
// The node that contains the coordinates for the trajectory is a
// Coordinate3 node which occurs before the LineSet node. We iterate
// back through the nodes in the group until we find the Coordinate3 node
int nodeIndex = grpNode->findChild(trajectory);
SoNode * tmpNode;
// FWJ needs initialization
SoCoordinate3 * coords = 0;
// SoCoordinate3 * coords;
// We allow only 100 iterations, in case the node isn't found
// (should take only a few iterations)
for(int i = 0; i < 100; ++i) {
--nodeIndex;
tmpNode = grpNode->getChild(nodeIndex);
if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
//node found
coords = (SoCoordinate3 *)tmpNode;
break;
}
}
if(coords == NULL){
String dialogName = (char *) "No coordinates";
std::string msg = "Could not find the coordinates node"
" for the picked trajectory."
" Reference trajectory not set";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
if ((This->lshiftdown) || (This->rshiftdown))
This->setReferencePath(trajectory, coords, true);
else
This->setReferencePath(trajectory, coords, false);
return;
}
else if(This->abbrOutputFlag) {
G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
if(attHolder && attHolder->GetAttDefs().size()) {
std::string strTrajPoint = "G4TrajectoryPoint:";
std::ostringstream oss;
for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
G4cout << G4AttCheck(attHolder->GetAttValues()[i],
attHolder->GetAttDefs()[i]);
oss << G4AttCheck(attHolder->GetAttValues()[i],
attHolder->GetAttDefs()[i]);
if(oss.str().find(strTrajPoint) != std::string::npos) {
// Last attribute displayed was a trajectory point. Since we
// want abbreviated output, display the last one and exit
// (unless we're already at the last (and only) trajectory point)
if(i != attHolder->GetAttDefs().size()-1) {
G4cout << G4AttCheck(
attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1],
attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]);
}
break;
}
}
} else {
G4String name((char*)node->getName().getString());
G4String cls((char*)node->getTypeId().getName().getString());
G4cout << "SoNode : " << node
<< " SoType : " << cls
<< " name : " << name
<< G4endl;
G4cout << "No attributes attached." << G4endl;
}
return;
}
else{
//Go to default behavior
}
}
else {
//Go to default behavior
}
// Default behavior in G4OpenInventorViewer::SelectionCB
G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
if(attHolder && attHolder->GetAttDefs().size()) {
for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
G4cout << G4AttCheck(attHolder->GetAttValues()[i],
attHolder->GetAttDefs()[i]);
}
} else {
G4String name((char*)node->getName().getString());
G4String cls((char*)node->getTypeId().getName().getString());
G4cout << "SoNode : " << node
<< " SoType : " << cls
<< " name : " << name
<< G4endl;
G4cout << "No attributes attached." << G4endl;
}
//Suppress other event handlers
eventCB->setHandled();
}
}
void G4OpenInventorXtExaminerViewer::mouseoverCB(void *aThis, SoEventCallback *eventCB)
{
SoHandleEventAction* action = eventCB->getAction();
const SoPickedPoint* pp = action->getPickedPoint();
G4OpenInventorXtExaminerViewer* This = (G4OpenInventorXtExaminerViewer*)aThis;
if(!This->abbrOutputFlag)
return;
if(pp != NULL) {
const SbViewportRegion & viewportRegion = action->getViewportRegion();
std::string sLogName;
float x,y,z;
std::stringstream ssZPos;
std::stringstream ssSolids;
std::stringstream ssMaterials;
SoPath * path = pp->getPath();
SoNode* node = ((SoFullPath*)path)->getTail();
if(node->getTypeId() == Geant4_SoPolyhedron::getClassTypeId()) {
sLogName = "Logical Volume: ";
sLogName += ((Geant4_SoPolyhedron *)node)->getName().getString();
SoGetBoundingBoxAction bAction(viewportRegion);
bAction.apply((SoFullPath*)path);
SbBox3f bBox = bAction.getBoundingBox();
SbVec3f center = bBox.getCenter();
center.getValue(x,y,z);
ssZPos << "Pos: " << x << " " << y << " " << z;
G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
if(attHolder && attHolder->GetAttDefs().size()) {
std::vector<const std::map<G4String,G4AttDef>*> vecDefs =
attHolder->GetAttDefs();
std::vector<const std::vector<G4AttValue>*> vecVals =
attHolder->GetAttValues();
for (size_t i = 0; i < vecDefs.size(); ++i) {
const std::vector<G4AttValue> * vals = vecVals[i];
std::vector<G4AttValue>::const_iterator iValue;
for (iValue = vals->begin(); iValue != vals->end(); ++iValue) {
const G4String& valueName = iValue->GetName();
const G4String& value = iValue->GetValue();
if(valueName == "Solid") {
if(ssSolids.str() == "")
ssSolids << "Solid Name: " << value;
else
ssSolids << ", " << value;
}
if(valueName == "Material") {
if(ssMaterials.str() == "")
ssMaterials << "Material Name: " << value;
else
ssMaterials << ", " << value;
}
}
}
}
}
// FWJ Mouseover for trajectories
else if(node->getTypeId() == SoLineSet::getClassTypeId()) {
// G4cout << "Trajectory!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << G4endl;
G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
if(attHolder && attHolder->GetAttDefs().size()) {
std::string strTrajPoint = "G4TrajectoryPoint:";
std::ostringstream oss;
G4String t1, t2, t3, t4;
for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
// G4cout << "Getting index " << i << " from attHolder" << G4endl;
// No, returns a vector! G4AttValue* attValue = attHolder->GetAttValues()[i];
const std::vector<G4AttValue>* vals = attHolder->GetAttValues()[i];
std::vector<G4AttValue>::const_iterator iValue;
for (iValue = vals->begin(); iValue != vals->end(); ++iValue) {
const G4String& valueName = iValue->GetName();
const G4String& value = iValue->GetValue();
// G4cout << " valueName = " << valueName << G4endl;
// G4cout << " value = " << value << G4endl;
// LINE 1
if (valueName == "PN") t1 = value;
if (valueName == "Ch") {
if (atof(value.c_str()) > 0)
t1 += " +";
else
t1 += " ";
t1 += value;
}
if (valueName == "PDG") {
t1 += " ";
t1 += value;
This->mouseOverTextLogName->string.setValue(t1);
}
// G4cout << " t1 = " << t1 << G4endl;
// LINE 2
if (valueName == "EventID") t2 = "Evt " + value;
if (valueName == "ID") t2 += " Trk " + value;
if (valueName == "PID") {
t2 += " Prt " + value;
This->mouseOverTextSolid->string.setValue(t2);
}
// LINE 3
if (valueName == "IKE") t3 = "KE " + value;
if (valueName == "IMom") {
// Remove units
unsigned ipos = value.rfind(" ");
G4String value1 = value;
value1.erase(ipos);
t3 += " P (" + value1 + ")";
}
if (valueName == "IMag") {
t3 += " " + value;
This->mouseOverTextMaterial->string.setValue(t3);
}
// LINE 4
if (valueName == "NTP") {
std::ostringstream t4oss;
t4oss << "TrjPts " << value;
t4oss << " Pos " << pp->getPoint()[0] << " " << pp->getPoint()[1] <<
" " << pp->getPoint()[2];
This->mouseOverTextZPos->string.setValue(SbString(t4oss.str().c_str()));
}
}
// G4cout << " NOW CALLING G4AttCheck" << G4endl;
// G4cout << G4AttCheck(attHolder->GetAttValues()[i],
// attHolder->GetAttDefs()[i]);
// oss << G4AttCheck(attHolder->GetAttValues()[i],
// attHolder->GetAttDefs()[i]);
// if(oss.str().find(strTrajPoint) != std::string::npos) {
// // Last attribute displayed was a trajectory point. Since we
// // want abbreviated output, display the last one and exit
// // (unless we're already at the last (and only) trajectory point)
// if(i != attHolder->GetAttDefs().size()-1) {
// G4cout << G4AttCheck(
// attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1],
// attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]);
// }
// break;
// }
}
}
This->setSuperimpositionEnabled(This->superimposition, TRUE);
This->scheduleRedraw();
eventCB->setHandled();
return;
}
bool redraw = false;
if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != sLogName) {
This->mouseOverTextLogName->string.setValue(SbString(sLogName.c_str()));
redraw = true;
}
if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != ssSolids.str()) {
This->mouseOverTextSolid->string.setValue(SbString(ssSolids.str().c_str()));
redraw = true;
}
if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != ssMaterials.str()){
This->mouseOverTextMaterial->string.setValue(SbString(ssMaterials.str().c_str()));
redraw = true;
}
if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != ssZPos.str()) {
This->mouseOverTextZPos->string.setValue(SbString(ssZPos.str().c_str()));
redraw = true;
}
if(redraw) {
This->setSuperimpositionEnabled(This->superimposition, TRUE);
This->scheduleRedraw();
}
eventCB->setHandled();
}
else {
if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != "") {
This->mouseOverTextLogName->string.setValue(SbString(""));
This->scheduleRedraw();
}
if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != "") {
This->mouseOverTextSolid->string.setValue(SbString(""));
This->scheduleRedraw();
}
if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != "") {
This->mouseOverTextMaterial->string.setValue(SbString(""));
This->scheduleRedraw();
}
if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != "") {
This->mouseOverTextZPos->string.setValue(SbString(""));
This->scheduleRedraw();
}
}
}
SbBool G4OpenInventorXtExaminerViewer::processSoEvent(const SoEvent * const ev) {
SoCamera *cam = getCamera();
const SoType type(ev->getTypeId());
if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
SoMouseButtonEvent * me = (SoMouseButtonEvent *) ev;
if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
|| currentState == PAUSED_ANIMATION) {
switch (me->getButton()) {
case SoMouseButtonEvent::BUTTON4: // Scroll wheel up
if (me->getState() == SoButtonEvent::DOWN) {
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
float hAngle =
((SoPerspectiveCamera *) cam)->heightAngle.getValue();
((SoPerspectiveCamera *) cam)->heightAngle = hAngle
+ 0.01f;
return TRUE;
} else if (cam->isOfType(
SoOrthographicCamera::getClassTypeId())) {
float height =
((SoOrthographicCamera *) cam)->height.getValue();
((SoOrthographicCamera *) cam)->height = height + 5;
return TRUE;
}
}
break;
case SoMouseButtonEvent::BUTTON5: // Scroll wheel down
if (me->getState() == SoButtonEvent::DOWN) {
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
float hAngle =
((SoPerspectiveCamera *) cam)->heightAngle.getValue();
if (hAngle > 0.01)
((SoPerspectiveCamera *) cam)->heightAngle = hAngle
- 0.01f;
return TRUE;
} else if (cam->isOfType(
SoOrthographicCamera::getClassTypeId())) {
float height =
((SoOrthographicCamera *) cam)->height.getValue();
if (height > 5)
((SoOrthographicCamera *) cam)->height = height - 5;
return TRUE;
}
}
break;
default:
break;
}
}
if (currentState == GENERAL) {
}
}
if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
SoKeyboardEvent * ke = (SoKeyboardEvent *) ev;
if (SoKeyboardEvent::isKeyPressEvent(ev, ke->getKey())) {
switch (ke->getKey()) {
case SoKeyboardEvent::LEFT_SHIFT:
this->lshiftdown = true;
return TRUE;
case SoKeyboardEvent::RIGHT_SHIFT:
this->rshiftdown = true;
return TRUE;
case SoKeyboardEvent::LEFT_CONTROL:
this->lctrldown = true;
return TRUE;
case SoKeyboardEvent::RIGHT_CONTROL:
this->rctrldown = true;
return TRUE;
case SoKeyboardEvent::SPACE:
if (currentState == ANIMATION
|| currentState == REVERSED_ANIMATION) {
beforePausing = currentState;
currentState = PAUSED_ANIMATION;
if (animateSensor->isScheduled())
animateSensor->unschedule();
return TRUE;
} else if (currentState == PAUSED_ANIMATION) {
if (maxSpeed) {
if ((beforePausing == ANIMATION
&& refParticleIdx
< (int) refParticleTrajectory.size() - 1)
|| (beforePausing == REVERSED_ANIMATION
&& refParticleIdx > 0)) {
currentState = beforePausing;
animateRefParticle();
}
}
return TRUE;
}
break;
case SoKeyboardEvent::ESCAPE:
if (currentState == ANIMATION
|| currentState == REVERSED_ANIMATION
|| currentState == PAUSED_ANIMATION) {
if (animateSensor->isScheduled())
animateSensor->unschedule();
currentState = prevState;
refParticleIdx = prevRefIdx;
setSuperimpositionEnabled(superimposition, FALSE);
maxSpeed = 0.0f;
step = 1;
scheduleRedraw();
if (currentState == VIEWPOINT) {
setSuperimpositionEnabled(superimposition, TRUE);
axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
animSpeedOutlineSwitch->whichChild.setValue(
SO_SWITCH_NONE);
animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
scheduleRedraw();
}
restoreCamera();
return TRUE;
}
break;
case SoKeyboardEvent::DELETE:
if (viewPtList.size()
&& (currentState != ANIMATION
|| currentState != REVERSED_ANIMATION
|| currentState != PAUSED_ANIMATION)) {
String dialogName = (char *) "Delete Viewpoint";
std::string msg = "Are you sure you want to delete current viewpoint?";
warningMsgDialog(msg, dialogName, deleteViewPtCB);
return TRUE;
}
break;
case SoKeyboardEvent::LEFT_ARROW:
switch (currentState) {
case BEAMLINE:
if ((this->lshiftdown) || (this->rshiftdown)){
refParticleIdx -= step;
moveCamera();
}
else if ((this->lctrldown) || (this->rctrldown)){
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
SbVec3f tmp = camDir;
tmp.negate();
rotAxis = tmp;
rotCnt = ROT_CNT;
moveCamera(); // To make sure camera is perpendicular to the beamline
rotateCamera();
}
else{
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
SbVec3f tmp = camUpVec;
tmp.negate();
rotAxis = tmp;
rotCnt = ROT_CNT;
moveCamera(); // To make sure camera is perpendicular to the beamline
rotateCamera();
}
return TRUE;
case ANIMATION:
case REVERSED_ANIMATION:
left_right -= 1.5f;
return TRUE;
case PAUSED_ANIMATION:
left_right -= 1.5f;
setStartingPtForAnimation();
cam->position = myCam->position;
return TRUE;
case GENERAL:
case VIEWPOINT:
if ((!this->lshiftdown) && (!this->rshiftdown)) {
// Using this allows us to look around without
// changing the camera parameters (camDir, camUpVec)
this->bottomWheelMotion(
this->getBottomWheelValue() + 0.1f);
return TRUE;
}
break;
case ROTATING:
// For this state, let the keyboard event
// be handled by superclass
break;
default:
SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
"Unhandled viewer state");
break;
}
break;
case SoKeyboardEvent::RIGHT_ARROW:
switch(currentState){
case BEAMLINE:
if ((this->lshiftdown) || (this->rshiftdown)){
refParticleIdx += step;
moveCamera();
}
else if ((this->lctrldown) || (this->rctrldown)){
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
rotAxis = camDir;
rotCnt = ROT_CNT;
moveCamera(); // To make sure camera is perpendicular to the beamline
rotateCamera();
}
else{
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
rotAxis = camUpVec;
rotCnt = ROT_CNT;
moveCamera(); // To make sure camera is perpendicular to the beamline
rotateCamera();
}
return TRUE;
case ANIMATION:
case REVERSED_ANIMATION:
left_right += 1.5f;
return TRUE;
case PAUSED_ANIMATION:
left_right += 1.5f;
setStartingPtForAnimation();
cam->position = myCam->position;
return TRUE;
case GENERAL:
case VIEWPOINT:
if ((!this->lshiftdown) && (!this->rshiftdown)) {
// Using this allows us to look around without
// changing the camera parameters (camDir, camUpVec)
this->bottomWheelMotion(
this->getBottomWheelValue() - 0.1f);
return TRUE;
}
break;
case ROTATING:
// For this state, let the keyboard event
// be handled by superclass
break;
default:
SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
"Unhandled viewer state");
break;
}
break;
case SoKeyboardEvent::DOWN_ARROW:
switch(currentState){
case BEAMLINE:
if ((this->lshiftdown) || (this->rshiftdown)){
refParticleIdx -= step;
moveCamera();
}
else{
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
rotAxis = camDir.cross(camUpVec);
rotCnt = ROT_CNT;
moveCamera(); // To make sure camera is perpendicular to the beamline
rotateCamera();
}
return TRUE;
case ANIMATION:
case REVERSED_ANIMATION:
up_down -= 1.5f;
return TRUE;
case PAUSED_ANIMATION:
up_down -= 1.5f;
setStartingPtForAnimation();
cam->position = myCam->position;
return TRUE;
case GENERAL:
case VIEWPOINT:
// Using this allows us to look around without
// changing the camera parameters (camDir, camUpVec)
if ((!this->lshiftdown) && (!this->rshiftdown)) {
this->leftWheelMotion(this->getLeftWheelValue() - 0.1f);
return TRUE;
}
break;
case ROTATING:
// For this state, let the keyboard event
// be handled by superclass
break;
default:
SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
"Unhandled viewer state");
break;
}
break;
case SoKeyboardEvent::UP_ARROW:
switch(currentState){
case BEAMLINE:
if ((this->lshiftdown) || (this->rshiftdown)){
refParticleIdx -= step;
moveCamera();
}
else{
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
prevState = currentState;
currentState = ROTATING;
animateBtwPtsPeriod = 0.08f;
rotAxis = camUpVec.cross(camDir);
rotCnt = ROT_CNT;
moveCamera();
rotateCamera();
}
return TRUE;
case ANIMATION:
case REVERSED_ANIMATION:
up_down += 1.5f;
return TRUE;
case PAUSED_ANIMATION:
up_down += 1.5f;
setStartingPtForAnimation();
cam->position = myCam->position;
return TRUE;
case GENERAL:
case VIEWPOINT:
// Using this allows us to look around without
// changing the camera parameters (camDir, camUpVec)
if ((!this->lshiftdown) && (!this->rshiftdown)) {
this->leftWheelMotion(this->getLeftWheelValue() + 0.1f);
return TRUE;
}
break;
case ROTATING:
// For this state, let the keyboard event
// be handled by superclass
break;
default:
SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
"Unhandled viewer state");
break;
}
break;
case SoKeyboardEvent::PAGE_UP:
switch(currentState){
case BEAMLINE:
if (step < (int) refParticleTrajectory.size() / 5) // Magic number
step++;
return TRUE;
case ANIMATION:
incSpeed();
maxSpeed += SPEED_INDICATOR_STEP;
if (maxSpeed > 0.8)
maxSpeed = MAX_SPEED_INDICATOR;
scheduleRedraw();
return TRUE;
case REVERSED_ANIMATION:
if(!animateSensor->isScheduled()){
currentState = ANIMATION;
if (refParticleIdx
< (int) refParticleTrajectory.size() - 1) {
refParticleIdx++;
maxSpeed = SPEED_INDICATOR_STEP;
scheduleRedraw();
animateRefParticle();
}
}
else{
maxSpeed += SPEED_INDICATOR_STEP;
decSpeed();
scheduleRedraw();
}
return TRUE;
case PAUSED_ANIMATION:
maxSpeed += SPEED_INDICATOR_STEP;
if (maxSpeed > 0.8)
maxSpeed = MAX_SPEED_INDICATOR;
if (beforePausing == ANIMATION) {
incSpeed();
} else {
decSpeed();
if (animateBtwPtsPeriod >= MIN_SPEED)
beforePausing = ANIMATION;
}
scheduleRedraw();
return TRUE;
default: //fall through
break;
}
break;
case SoKeyboardEvent::PAGE_DOWN:
switch(currentState){
case BEAMLINE:
if (step > 1)
step--;
return TRUE;
case ANIMATION:
if(!animateSensor->isScheduled()){
currentState = REVERSED_ANIMATION;
if (refParticleIdx > 1) {
refParticleIdx--;
maxSpeed = -SPEED_INDICATOR_STEP;
scheduleRedraw();
animateRefParticle();
}
}
else{
maxSpeed -= SPEED_INDICATOR_STEP;
decSpeed();
scheduleRedraw();
}
return TRUE;
case REVERSED_ANIMATION:
incSpeed();
maxSpeed -= SPEED_INDICATOR_STEP;
if (maxSpeed < -0.8)
maxSpeed = -MAX_SPEED_INDICATOR;
scheduleRedraw();
return TRUE;
case PAUSED_ANIMATION:
maxSpeed -= SPEED_INDICATOR_STEP;
if (maxSpeed < -0.8)
maxSpeed = -MAX_SPEED_INDICATOR;
if (beforePausing == REVERSED_ANIMATION) {
incSpeed();
} else {
decSpeed();
if (animateBtwPtsPeriod >= MIN_SPEED)
beforePausing = REVERSED_ANIMATION;
}
scheduleRedraw();
return TRUE;
default:
//fall through
break;
}
break;
case SoKeyboardEvent::E:
this->escapeCallback(this->examinerObject);
break;
default:
break; // To get rid of compiler warnings
}
}
if (SoKeyboardEvent::isKeyReleaseEvent(ev, ke->getKey())) {
switch (ke->getKey()) {
case SoKeyboardEvent::LEFT_SHIFT:
this->lshiftdown = false;
return TRUE;
case SoKeyboardEvent::RIGHT_SHIFT:
this->rshiftdown = false;
return TRUE;
case SoKeyboardEvent::LEFT_CONTROL:
this->lctrldown = false;
return TRUE;
case SoKeyboardEvent::RIGHT_CONTROL:
this->rctrldown = false;
return TRUE;
default:
break;
}
}
}
if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
|| currentState == ROTATING)
return FALSE;
else
return SoXtExaminerViewer::processSoEvent(ev);
}
// Called by hitting PageUp during animation.
void G4OpenInventorXtExaminerViewer::incSpeed() {
if (std::ceil(animateBtwPtsPeriod * 100) >= 4) {
if (speedStep > 0.08)
speedStep -= 0.02;
else
speedStep = 0.02;
animateBtwPtsPeriod -= speedStep;
} else
animateBtwPtsPeriod = 0.0;
if (currentState != PAUSED_ANIMATION) {
int lastIdx = refParticleTrajectory.size() - 1;
if (refParticleIdx < lastIdx && !animateSensor->isScheduled())
animateRefParticle();
}
}
// Called by hitting PageDown during animation.
void G4OpenInventorXtExaminerViewer::decSpeed() {
animateBtwPtsPeriod += speedStep;
if (animateBtwPtsPeriod < MIN_SPEED) {
if (std::floor(animateBtwPtsPeriod * 100) == 12) { // Errors in double representation
speedStep = 0.08;
} else if (animateBtwPtsPeriod > 0.12)
speedStep += 0.02;
} else {
animateBtwPtsPeriod = MIN_SPEED;
speedStep = START_STEP;
maxSpeed = 0.0f;
if (animateSensor->isScheduled())
animateSensor->unschedule();
}
}
// Based on the user's interaction the speed indicator bar needs to be adjusted.
void G4OpenInventorXtExaminerViewer::updateSpeedIndicator(void) {
assert(this->sgeometry != NULL);
SbVec3f * points = this->sgeometry->point.startEditing();
if (points[10][0] == 0.0f)
this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
if (points[14][0] == 0.0f)
this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
points[10][0] = this->maxSpeed;
points[11][0] = this->maxSpeed;
points[14][0] = this->maxSpeed;
points[15][0] = this->maxSpeed;
this->sgeometry->point.finishEditing();
if (this->maxSpeed == 0.0f) {
this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
}
}
void G4OpenInventorXtExaminerViewer::actualRedraw(void) {
switch (currentState) {
case ANIMATION:
case REVERSED_ANIMATION:
case PAUSED_ANIMATION:
updateSpeedIndicator();
SoXtExaminerViewer::actualRedraw();
break;
default:
SoXtExaminerViewer::actualRedraw();
break;
}
}
void G4OpenInventorXtExaminerViewer::setReferencePath(SoLineSet *lineset, SoCoordinate3 *coords, bool append)
{
// TODO: Color the reference path
// Disable the color stuff for now: changes all trajectories
// // We change the color of the trajectory too, so we get its material
// nodeIndex = grpNode->findChild(trajectory);
// SoMaterial * mat;
// for(int i = 0; i < 100; ++i){
// --nodeIndex;
//
// tmpNode = grpNode->getChild(nodeIndex);
// if(tmpNode->getTypeId() == SoMaterial::getClassTypeId()){
// //node found
// mat = (SoMaterial *)tmpNode;
//
// break;
// }
// }
//
//
// // Restore default color for previously picked trajectory
// // and set different color for current pick
// if(This->prevColorField)
// ((SoMFColor *)This->prevColorField)->setValue(0.0, 1.0, 0.0);
// This->prevColorField = (void *)&mat->diffuseColor;
//
//
// if(mat->diffuseColor.isConnected())
// std::cout << "connected" << std::endl;
//
// mat->diffuseColor.setValue(41.0/255.0, 230.0/255.0, 230.0/255.0);
//
// std::cout << "R: " << mat->diffuseColor[0][0] << " ";
// std::cout << "G: " << mat->diffuseColor[0][1] << " ";
// std::cout << "B: " << mat->diffuseColor[0][2] << std::endl;
// The trajectory is composed of all the polyline segments in the
// multiple value field (SoMFInt32) numVertices.
// For each of the numVertices.getNum()* polyline segments,
// retrieve the points from the SoCoordinate3 node
SbVec3f refParticlePt;
if(!append)
this->refParticleTrajectory.clear();
for(int i = 0; i < lineset->numVertices.getNum(); ++i){
for(int j = 0; j < lineset->numVertices[i]; ++j){
refParticlePt = coords->point[j];
this->refParticleTrajectory.push_back(refParticlePt);
}
}
// Remove points that are too close to each other
this->evenOutRefParticlePts();
this->setReferencePathZPos();
this->sortElements();
}
void G4OpenInventorXtExaminerViewer::setReferencePathZPos()
{
refZPositions.clear();
refZPositions.push_back(0);
float dist;
for(unsigned int i=0; i < this->refParticleTrajectory.size() - 1; ++i){
dist = (refParticleTrajectory[i] -
refParticleTrajectory[i + 1]).length();
refZPositions.push_back(refZPositions[i] + dist);
}
}
void G4OpenInventorXtExaminerViewer::findAndSetRefPath()
{
SoSearchAction action;
action.setType(SoLineSet::getClassTypeId(),false);
action.setInterest(SoSearchAction::ALL);
action.apply(this->getSceneGraph());
SoPathList &pathList = action.getPaths();
if(pathList.getLength() != 0){
SoCoordinate3 * coords = NULL;
std::vector<SoCoordinate3 *> coordvec;
std::vector<SoLineSet *> linevec;
bool refPathFound = false;
for(int i = 0; i < pathList.getLength(); ++i) {
SoFullPath *path = (SoFullPath *)pathList[i];
G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(path->getTail());
for (size_t j = 0; j < attHolder->GetAttDefs().size(); ++j) {
std::ostringstream oss;
oss << G4AttCheck(attHolder->GetAttValues()[j], attHolder->GetAttDefs()[j]);
std::string findStr = "Type of trajectory (Type): ";
std::string compareValue = "REFERENCE";
size_t idx = oss.str().find(findStr);
if(idx != std::string::npos) {
if(oss.str().substr(idx + findStr.size(), compareValue.size()) == compareValue) {
coords = this->getCoordsNode(path);
if(coords != NULL){
refPathFound = true;
coordvec.push_back(coords);
linevec.push_back((SoLineSet *)path->getTail());
}
break;
}
}
findStr = "Track ID (ID): ";
idx = oss.str().find(findStr);
if(idx != std::string::npos) {
//index all primary tracks
std::string tmpstr = oss.str().substr(idx + findStr.size(),1);
std::istringstream buffer(tmpstr);
int num;
buffer >> num;
if(num == 1) {
// Check if next character is a number,
// in which case we don't have Track ID 1
const char * nextChar =
oss.str().substr(idx + findStr.size() + 1,1).c_str();
if(std::isdigit(nextChar[0]))
break; //Not a primary track, continue with next track
coords = this->getCoordsNode(path);
if(coords != NULL){
coordvec.push_back(coords);
linevec.push_back((SoLineSet *)path->getTail());
break; //Found coords node, continue with next track
}
}
else
break; //Not a primary track, continue with next track
}
else{
//Not a Track ID attribute, fall through
}
}
if(refPathFound)
break;
}
if(coordvec.empty())
return; //No track with a Coordinate3 node found
if(refPathFound){
//set ref path to last traj, coord in the vecs
this->setReferencePath(linevec.back(), coordvec.back());
return;
}
//else
int longestIdx = 0;
float longestLength = 0.0;
// For all paths
for(unsigned int i=0;i < linevec.size(); ++i){
//First generate a vector with all the points in this lineset
std::vector<SbVec3f> trajectory;
// For all lines in the i path
for(int j=0; j < linevec[i]->numVertices.getNum(); ++j){
// For all points in line j
for(int k=0; k < linevec[i]->numVertices[j]; ++k){
trajectory.push_back(coordvec[i]->point[k]);
}
}
// Then calculate the total length
float tmpLength=0.0;
for(unsigned int j=0; j < trajectory.size() - 1; ++j){
tmpLength += (trajectory[j] - trajectory[j + 1]).length();
}
if(tmpLength > longestLength){
longestIdx = i;
longestLength = tmpLength;
}
}
// Set the longest path as the reference path
this->setReferencePath(linevec[longestIdx], coordvec[longestIdx]);
}
}
SoCoordinate3 * G4OpenInventorXtExaminerViewer::getCoordsNode(SoFullPath *path)
{
SoLineSet *trajectory = (SoLineSet *)path->getTail();
SoSeparator * grpNode = (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
int nodeIndex = grpNode->findChild(trajectory);
SoNode * tmpNode;
// We allow only 100 iterations, in case the node isn't found
// (should take only a few iterations)
for(int i = 0; i < 100; ++i){
--nodeIndex;
tmpNode = grpNode->getChild(nodeIndex);
if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
//node found
return (SoCoordinate3 *)tmpNode;
}
}
return NULL; //coords node not found
}
// Displays scene elements on the right side of listsDialog.
// else: scene graph is searched for Geant4_SoPolyhedron type nodes
void G4OpenInventorXtExaminerViewer::getSceneElements()
{
std::string field, eltName;
std::map<std::string, int> duplicates;
std::map<std::string, int> sceneElts;
SoSearchAction search;
Geant4_SoPolyhedron *node;
SoGroup *root = (SoGroup *)getSceneManager()->getSceneGraph();
SoBaseKit::setSearchingChildren(TRUE);
search.reset();
search.setSearchingAll(TRUE);
search.setInterest(SoSearchAction::ALL);
search.setType(Geant4_SoPolyhedron::getClassTypeId(), 0);
search.apply(root);
SoPathList &pl = search.getPaths();
// First find which names occur more than once so we can append a counter to them
for(int i = 0; i < pl.getLength(); i++) {
SoFullPath *path = (SoFullPath *)pl[i];
node = (Geant4_SoPolyhedron *)path->getTail();
eltName = node->getName();
if(duplicates.count(eltName))
duplicates[eltName]++;
else
duplicates[eltName] = 1;
}
for(int i = 0; i < pl.getLength(); i++) {
float x,y,z;
std::stringstream ssCount;
SoFullPath *path = (SoFullPath *)pl[i];
node = (Geant4_SoPolyhedron *)path->getTail();
eltName = node->getName();
field = eltName;
if(duplicates[eltName] == 1)
ssCount << "";//duplicates[field]
else {
if(sceneElts.count(eltName))
sceneElts[eltName]++;
else
sceneElts[eltName] = 1;
ssCount << sceneElts[eltName];
field += "_";
}
field += ssCount.str();
SoGetBoundingBoxAction bAction(getViewportRegion());
bAction.apply(path);
SbBox3f bBox = bAction.getBoundingBox();
SbVec3f centr = bBox.getCenter();
centr.getValue(x,y,z);
path->ref();
sceneElement el = { field, path, centr, 0.0 };
this->sceneElements.push_back(el);
}
}
float G4OpenInventorXtExaminerViewer::sqrlen(const SbVec3f &a)
{
float x,y,z;
a.getValue(x,y,z);
return x*x + y*y + z*z;
}
void G4OpenInventorXtExaminerViewer::distanceToTrajectory(const SbVec3f &q,
float &dist,
SbVec3f &closestPoint,
int &index)
{
// a : Previous point on trajectory
// b : Next point on trajectory
// q : the point in space
// dab, daq, dbq: distance between a & b, a & q, b & q
//
// Theory: A point p on a line ab is defined as:
//
// p(t) = a+t⋅(ba)
//
// note: All are vectors except the parameter t
//
// When t is between 0 and 1 the point p is situated between a and b on ab.
// The point p is defined in terms of the parameter t, subsequently so does
// the distance from the query point q to the point p. To find the minimum
// of that distance we differentiate it and set equal to zero:
//
// diff(Norm(p(t)- q)) = 0
//
// note: diff means taking the derivative with regard to t
//
// The resulting t is given in the code below. The square of the distance
// between p and q is given by:
//
// d^2 = (Norm(p(t)-q))^2
//
// The expression found is given in the code below (current_dist)
//
// Ref: http://programmizm.sourceforge.net/blog/2012/
// distance-from-a-point-to-a-polyline
//
// --PLG
const size_t count = this->refParticleTrajectory.size();
assert(count>0);
SbVec3f b = this->refParticleTrajectory[0];
SbVec3f dbq = b - q;
float sqrDist = sqrlen(dbq);
closestPoint = b;
index = 0;
for (size_t i = 1; i < count; ++i) {
const SbVec3f a = b;
const SbVec3f daq = dbq;
b = this->refParticleTrajectory[i];
dbq = b - q;
const SbVec3f dab = a - b;
float dab_x, dab_y, dab_z;
dab.getValue(dab_x,dab_y,dab_z);
float daq_x, daq_y, daq_z;
daq.getValue(daq_x, daq_y, daq_z);
float dbq_x, dbq_y, dbq_z;
dbq.getValue(dbq_x, dbq_y, dbq_z);
const float inv_sqrlen = 1./sqrlen(dab);
const float t = (dab_x*daq_x + dab_y*daq_y + dab_z*daq_z)*inv_sqrlen;
if (t<0.){
// The trajectory point occurs before point a
// Go to the next point
continue;
}
float current_dist;
if (t<=1.){
// The trajectory point occurs between a and b.
// Compute the distance to that point
current_dist = daq_x*daq_x + daq_y*daq_y + daq_z*daq_z
- t*(daq_x*dab_x + daq_y*dab_y + daq_z*dab_z)
+ t*t*(dab_x*dab_x + dab_y*dab_y + dab_z*dab_z);
}
else { //t>1.
// The trajectory point occurs after b.
// Get the distance to point b
current_dist = sqrlen(dbq);
}
if (current_dist < sqrDist){
sqrDist = current_dist;
closestPoint = a + t*(b-a);
index = i;
}
}
dist = std::sqrt(sqrDist);
}
void G4OpenInventorXtExaminerViewer::sortElements()
{
if(this->refParticleTrajectory.empty())
return;
float * trajLength = new float[this->refParticleTrajectory.size()];
typedef std::map<elementForSorting, sceneElement> sortedMap;
sortedMap sorted;
// For every point on the reference trajectory, compute
// the total length from the start
SbVec3f prevPoint;
std::vector<SbVec3f>::iterator itRef = this->refParticleTrajectory.begin();
int trajIndex = 0;
prevPoint = *itRef;
trajLength[trajIndex] = 0.0;
++itRef;
++trajIndex;
for(; itRef != this->refParticleTrajectory.end(); ++itRef, ++trajIndex){
trajLength[trajIndex] = trajLength[trajIndex-1] + (*itRef - prevPoint).length();
prevPoint = *itRef;
}
// Compute the smallest distance between the element
// and the reference trajectory (find the closest point),
// then map the element to the trajectory length of that
// point (calculated above)
SoGetBoundingBoxAction bAction(this->getViewportRegion());
SbVec3f elementCoord;
std::vector<sceneElement>::iterator itEl;
int elementIndex;
elementForSorting el;
for(itEl = this->sceneElements.begin(), elementIndex = 0;
itEl != this->sceneElements.end(); ++itEl, ++elementIndex){
bAction.apply(itEl->path);
elementCoord = bAction.getBoundingBox().getCenter();
int index;
distanceToTrajectory(elementCoord, el.smallestDistance, el.closestPoint, index);
itEl->closestPointZCoord = el.closestPointZCoord = trajLength[index];
el.distanceToBeamlineStart = (itEl->center - this->refParticleTrajectory[0]).length();
// This map of the scene elements (or their coordinates rather)
// is automatically sorted by trajectory length (Z coord), then
// by the distance between the element and the point in case the Z coord
// is the same as another element. This is done by using as a key
// an element structure which implements the operator for weak ordering
sorted.insert(std::make_pair(el,*itEl));
}
// store the sorted elements into the vector field
this->sceneElements.clear();
sortedMap::iterator itSorted = sorted.begin();
for(; itSorted != sorted.end(); itSorted++)
this->sceneElements.push_back(itSorted->second);
this->zcoordSetFlag = true;
Widget formTop = XtNameToWidget(this->listsDialog, "FormTop");
Widget formTopRight = XtNameToWidget(formTop, "FormTopRight");
this->createElementsList(formTopRight);
delete[] trajLength;
}
void G4OpenInventorXtExaminerViewer::createElementsList(Widget formTopRight)
{
if(this->myElementList != NULL)
XtUnmanageChild(this->myElementList);
int size = this->sceneElements.size();
XmString *elements = (XmString *) XtMalloc(size * sizeof(XmString));
std::vector<sceneElement>::const_iterator it;
int count = 0;
std::stringstream ss;
for(it=this->sceneElements.begin(); it!=this->sceneElements.end(); ++it) {
ss << it->name;
if(zcoordSetFlag)
ss << " [" << it->closestPointZCoord << "]";
elements[count] = XmStringCreateLocalized((char *)ss.str().c_str());
++count;
ss.str("");
}
Arg args[10];
int n;
// Label Right
n = 0;
Widget labelRight;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
labelRight = XmCreateLabelGadget(formTopRight, (char*)"Element [S mm]",
args, n);
XtManageChild(labelRight);
// List Right
n = 0;
XtSetArg(args[n], XmNvisibleItemCount, 7); n++;
XtSetArg(args[n], XmNitemCount, size); n++;
XtSetArg(args[n], XmNitems, elements); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, labelRight); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
// FWJ
XtSetArg(args[n], XmNwidth, 240); n++;
// XtSetArg(args[n], XmNwidth, 280); n++;
// XtSetArg(args[n], XmNwidth, 300); n++;
this->myElementList = XmCreateScrolledList(formTopRight, (char *) "ListRight", args, n);
XtAddCallback(this->myElementList, XmNbrowseSelectionCallback,
(XtCallbackProc) lookAtSceneElementCB, this);
xmAddMouseEventHandler(this->myElementList); // Add scrolling functionality
XtManageChild(this->myElementList);
if (elements != NULL) {
for (int i = 0; i < size; i++)
XmStringFree(elements[i]);
XtFree((char *) elements);
}
}
// Pops up a custom dialog listsDialog containing
// scene elements and viewpoints.
void G4OpenInventorXtExaminerViewer::constructListsDialog(Widget w,
XtPointer client_data,
XtPointer)
{
G4cout << "DEBUG constructListsDialog w = " << w << G4endl;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (This->listsDialog) {
return;
}
if (This->currentState == ANIMATION || This->currentState == PAUSED_ANIMATION) {
if (This->animateSensor->isScheduled())
This->animateSensor->unschedule();
This->refParticleIdx = This->prevRefIdx;
This->restoreCamera();
This->currentState = This->prevState;
}
This->step = 1; // Default values
This->refParticleIdx = 0;
if (This->refParticleTrajectory.size()){
This->prevPt = This->refParticleTrajectory[0]; // For calculating distance
}
This->getSceneElements();
int n = 0;
Arg args[10];
Atom WM_DELETE_WINDOW;
///////////////////////CUSTOM listsDialog///////////////////////////////
Widget topShell;
// FWJ gets the topmost window containing This->getParentWidget()
// This is unnecessary because the parent is passed in
// topShell = SoXt::getShellWidget(This->getParentWidget());
topShell = w;
G4cout << "DEBUG PARENT (topShell) FOR AUX WINDOW = " << topShell << G4endl;
// Shell Dialog
std::string dialogNameStr = This->fileName.substr(This->fileName.rfind('/') + 1);
const int nDialog = dialogNameStr.size() + 1;
char *dialogName = new char[nDialog];
strncpy(dialogName, dialogNameStr.c_str(), nDialog);
n = 0;
XtSetArg(args[n], XmNx, 610); n++;
This->myShellDialog = XmCreateDialogShell(topShell, dialogName, args, n);
delete[] dialogName;
WM_DELETE_WINDOW = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False);
XmAddWMProtocolCallback(This->myShellDialog, WM_DELETE_WINDOW,
(XtCallbackProc)closeListsDialogCB, This);
// Main Pane(listsDialog)
n = 0;
XtSetArg(args[n], XmNsashWidth, 1); n++;
XtSetArg(args[n], XmNsashHeight, 1); n++;
XtSetArg(args[n], XmNseparatorOn, False); n++;
// FWJ
This->listsDialog = XmCreatePanedWindow(This->myShellDialog, (char *) "MainPane",
args, n);
////////////////////////TOP FORM//////////////////////////
n = 0;
// FWJ fails compile
// Widget formTop = XmCreateForm(This, (char *) "FormTop", args, n);
Widget formTop = XmCreateForm(This->listsDialog, (char *) "FormTop", args, n);
n = 0;
XtSetArg(args[n], XmNmarginWidth, 8); n++;
XtSetArg(args[n], XmNmarginHeight, 8); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
Widget formTopRight = XmCreateForm(formTop, (char *) "FormTopRight", args,
n);
n = 0;
XtSetArg(args[n], XmNmarginWidth, 8); n++;
XtSetArg(args[n], XmNmarginHeight, 8); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, formTopRight); n++;
XtSetArg(args[n], XmNrightOffset, 10); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
Widget formTopLeft = XmCreateForm(formTop, (char *) "FormTopLeft", args, n);
/////TOP RIGHT/////
This->createElementsList(formTopRight);
XtManageChild(formTopRight);
/////TOP LEFT/////
// Label Left
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
Widget labelLeft = XmCreateLabelGadget(formTopLeft, (char *) "ViewPoints",
args, n);
XtManageChild(labelLeft);
// List Left
n = 0;
XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
XtSetArg(args[n], XmNvisibleItemCount, 7); n++;
// XtSetArg(args[n], XmNwidth, 140); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, labelLeft); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, This->myElementList); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
// FWJ
XtSetArg(args[n], XmNwidth, 160); n++;
// XtSetArg(args[n], XmNwidth, 200); n++;
This->myViewPtList = XmCreateScrolledList(formTopLeft, (char *) "ListLeft",
args, n);
if (This->viewPtList.size())
This->addViewPoints();
XtAddCallback(This->myViewPtList, XmNbrowseSelectionCallback,
(XtCallbackProc) loadBookmarkCB, This);
xmAddMouseEventHandler(This->myViewPtList); // Add scrolling functionality
XtManageChild(This->myViewPtList);
XtManageChild(formTopLeft);
XtManageChild(formTop);
////////////////////MIDDLE FORM///////////////////////////
n = 0;
XtSetArg(args[n], XmNmarginWidth, 6); n++;
// FWJ fails compile
// Widget formMiddle = XmCreateForm(This->canvas, (char *) "MiddleForm", args, n);
Widget formMiddle = XmCreateForm(This->listsDialog, (char *) "MiddleForm", args, n);
// Label
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, This->myViewPtList); n++;
Widget label = XmCreateLabelGadget(formMiddle, (char *) "Selection", args,
n);
XtManageChild(label);
// Text
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, label); n++;
XtSetArg(args[n], XmNtopOffset, 3); n++;
XtSetArg(args[n], XmNmaxLength, This->MAX_VP_NAME); n++;
This->viewPtSelection = XmCreateText(formMiddle, (char *) "Txt", args, n);
XtManageChild(This->viewPtSelection);
Dimension h1, h2, h;
XtVaGetValues(label, XmNheight, &h1, NULL);
XtVaGetValues(This->viewPtSelection, XmNheight, &h2, NULL);
h = (Dimension) (1.1 * (h1 + h2));
XtVaSetValues(formMiddle, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
XtManageChild(formMiddle);
/////////////////////BOTTOM FORM///////////////////////////
// Action Area Form
n = 0;
XtSetArg(args[n], XmNfractionBase, 4); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, This->viewPtSelection); n++;
// FWJ fails compile
// Widget formAction = XmCreateForm(This, (char *) "ActionForm", args, n);
Widget formAction = XmCreateForm(This->listsDialog, (char *) "ActionForm", args, n);
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopOffset, 3); n++;
XtSetArg(args[n], XmNbottomOffset, 5); n++;
Widget separator = XmCreateSeparatorGadget(formAction, (char *) "Sep", args, n);
XtManageChild(separator);
Widget button = XmCreatePushButton(formAction, (char *) "Delete", NULL, 0);
XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
XmATTACH_POSITION, XmNleftPosition, 0, XmNrightAttachment,
XmATTACH_POSITION, XmNrightPosition, 1,
XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
NULL);
XtAddCallback(button, XmNactivateCallback,
(XtCallbackProc) deleteBookmarkCB, This);
XtManageChild(button);
button = XmCreatePushButton(formAction, (char *) "Rename", NULL, 0);
XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment,
XmATTACH_POSITION, XmNrightPosition, 2,
XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
NULL);
XtAddCallback(button, XmNactivateCallback,
(XtCallbackProc) renameBookmarkCB, This);
XtManageChild(button);
button = XmCreatePushButton(formAction, (char *) "Sort", NULL, 0);
XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
XmATTACH_POSITION, XmNleftPosition, 2, XmNrightAttachment,
XmATTACH_POSITION, XmNrightPosition, 3,
XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
NULL);
XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) sortBookmarksCB, This);
XtManageChild(button);
button = XmCreatePushButton(formAction, (char *) "Close", NULL, 0);
XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
XmATTACH_POSITION, XmNleftPosition, 3, XmNrightAttachment,
XmATTACH_POSITION, XmNrightPosition, 4,
XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
NULL);
XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) closeListsDialogCB, This);
XtManageChild(button);
XtManageChild(formAction);
XtVaGetValues(button, XmNheight, &h1, NULL);
XtVaSetValues(formAction, XmNpaneMaximum, h1, XmNpaneMinimum, h1, NULL);
XtManageChild(This->listsDialog);
////////////////////////CUSTOM listsDialog///////////////////////////////
}
// Called when user clicks a scene element in listsDialog.
// Zooms onto that element.
void G4OpenInventorXtExaminerViewer::lookAtSceneElementCB(Widget,
XtPointer client_data,
XtPointer call_data)
{
char *value;
std::string elementField;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
SoCamera * cam = This->getCamera();
if (This->SoXtExaminerViewer::isAnimating())
This->stopAnimating();
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
value = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
|| This->currentState == PAUSED_ANIMATION ) {
if (This->animateSensor->isScheduled())
This->animateSensor->unschedule();
This->setSuperimpositionEnabled(This->superimposition, FALSE);
This->maxSpeed = 0.0f;
This->scheduleRedraw();
This->restoreCamera();
This->currentState = This->prevState;
} else if (This->currentState == VIEWPOINT)
This->setSuperimpositionEnabled(This->superimposition, FALSE);
elementField = value;
int idx = elementField.find_last_of("[");
if(idx == -1)
idx = elementField.size(); //if "[" not found for whatever reason (list not sorted)
else
idx--; // To get rid of the space that is between the name and '['
bool error = false;
SoFullPath *path;
SoSearchAction search;
SoNode *root = This->getSceneManager()->getSceneGraph();
int counter, idxUnderscore = elementField.find_last_of("_");
This->parseString<int>(counter, elementField.substr(idxUnderscore + 1, idx), error);
SoBaseKit::setSearchingChildren(TRUE);
search.reset();
search.setSearchingAll(TRUE);
if(error) { // No counter is present => element name was not modified
This->curEltName = elementField.substr(0, idx);
search.setName(This->curEltName.c_str());
search.apply(root);
path = (SoFullPath *)search.getPath();
}
else {
This->curEltName = elementField.substr(0, idxUnderscore);
search.setInterest(SoSearchAction::ALL);
search.setName(This->curEltName.c_str());
search.apply(root);
SoPathList &pl = search.getPaths();
path = (SoFullPath *)pl[counter - 1]; // Since counter starts at 1, not 0
}
G4ThreeVector global;
if ((idx > 0) && (path)) {
if(!This->refParticleTrajectory.empty()){
SoGetBoundingBoxAction bAction(This->getViewportRegion());
bAction.apply(path);
SbBox3f bBox = bAction.getBoundingBox();
SbVec3f elementCoord = bBox.getCenter();
This->refParticleIdx = 0;
SbVec3f p;
float absLengthNow, absLengthMin;
int maxIdx = This->refParticleTrajectory.size() - 2;
int targetIdx = 0;
SbVec3f dir;
p = This->refParticleTrajectory[This->refParticleIdx];
absLengthMin = (p - elementCoord).length();
This->refParticleIdx++;
// Find a ref. particle's point closest to element's global coords
while (This->refParticleIdx < maxIdx) {
p = This->refParticleTrajectory[This->refParticleIdx];
absLengthNow = (p - elementCoord).length();
if (absLengthNow < absLengthMin) {
absLengthMin = absLengthNow;
targetIdx = This->refParticleIdx;
}
This->refParticleIdx++;
}
if (This->currentState != BEAMLINE) { // Set up default zoom
SbVec3f p1, pN;
This->currentState = BEAMLINE;
This->prevParticleDir = SbVec3f(0,0,0); //so that moveCamera() knows sets default parameters
p1 = This->prevPt = This->refParticleTrajectory[0];
pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
This->distance = (pN - p1).length() / 10;
// FWJ Restore the default height instead of hard-wired value
if (cam->isOfType(SoOrthographicCamera::getClassTypeId()))
((SoOrthographicCamera *) cam)->height.setValue(This->defaultHeight);
// ((SoOrthographicCamera *) cam)->height.setValue(10000.0f);
else if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
((SoPerspectiveCamera *) cam)->heightAngle.setValue(
This->defaultHeightAngle);
} else {
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
This->distance = (This->prevPt - cam->position.getValue()).length();
}
This->refParticleIdx = targetIdx;
//////////////////////////////////////////////////////////////
This->setSuperimpositionEnabled(This->superimposition, TRUE);
This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->scheduleRedraw();
//////////////////////////////////////////////////////////////
This->moveCamera(This->distance);
XtFree(value);
}
else{
This->offsetFromCenter.setValue(0, 0, 1);
This->distance = 50;// small number since using viewAll() for default zoom
This->upVector.setValue(0, 1, 0);
This->moveCamera(This->distance);
cam->viewAll(path, This->getViewportRegion());
}
}
XmTextSetString(This->viewPtSelection, NULL);
}
// Destroyes listsDialog and resets necessary member fields.
void G4OpenInventorXtExaminerViewer::closeListsDialogCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
This->sceneElements.clear();
This->refParticleTrajectory.clear();
This->currentState = GENERAL;
XtDestroyWidget(This->myShellDialog);
This->listsDialog = NULL;
}
// Called when user clicks left arrow button. Loads previous viewpoint.
void G4OpenInventorXtExaminerViewer::prevViewPtCB(Widget, XtPointer client_data,
XtPointer) {
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (This->viewPtIdx == 0)
This->viewPtIdx = This->viewPtList.size() - 1;
else
This->viewPtIdx--;
This->writeViewPtIdx();
This->setViewPt();
}
// Called when user clicks right arrow button. Loads next viewpoint.
void G4OpenInventorXtExaminerViewer::nextViewPtCB(Widget, XtPointer client_data,
XtPointer) {
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (This->viewPtIdx >= (int) This->viewPtList.size() - 1)
This->viewPtIdx = 0;
else
This->viewPtIdx++;
This->writeViewPtIdx();
This->setViewPt();
}
// Updates the viewPtIdx in a viewpoint file.
void G4OpenInventorXtExaminerViewer::writeViewPtIdx()
{
std::string idxStr;
std::stringstream out;
out << viewPtIdx;
idxStr = out.str();
fileOut.seekp(0, std::ios::beg);
while ((int) idxStr.length() < MAX_VP_IDX) {
idxStr += " ";
}
fileOut << idxStr << "\n";
fileOut.flush();
fileOut.seekp(0, std::ios::end);
}
// Sets the viewpoint based on camera data that viewPtIdx is pointing to.
void G4OpenInventorXtExaminerViewer::setViewPt()
{
if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
|| currentState == ROTATING) {
if (animateSensor->isScheduled())
animateSensor->unschedule();
setSuperimpositionEnabled(superimposition, FALSE);
maxSpeed = 0.0f;
scheduleRedraw();
}
SoCamera * camera = getCamera();
if (camera == NULL) {
String dialogName = (char *) "Missing Camera Node";
std::string msg = "Camera is null. Unable to set the viewpoint.";
warningMsgDialog(msg, dialogName, NULL);
return;
}
if (!viewPtList.size()) {
String dialogName = (char *) "Missing Viewpoints";
std::string msg = "There are no viewpoints to load.";
warningMsgDialog(msg, dialogName, NULL);
return;
}
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
if (currentState != VIEWPOINT) {
currentState = VIEWPOINT;
//////////////////////////////////////////////////////////////
setSuperimpositionEnabled(superimposition, TRUE);
axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
scheduleRedraw();
///////////////////////////////////////////////////////////////
}
curViewPtName = viewPtList[viewPtIdx].viewPtName;
camera->viewportMapping = viewPtList[viewPtIdx].viewportMapping;
camera->position = viewPtList[viewPtIdx].position;
camera->orientation = viewPtList[viewPtIdx].orientation;
camera->aspectRatio = viewPtList[viewPtIdx].aspectRatio;
camera->nearDistance = viewPtList[viewPtIdx].nearDistance;
camera->farDistance = viewPtList[viewPtIdx].farDistance;
camera->focalDistance = viewPtList[viewPtIdx].focalDistance;
// Restore camera height (changed by zooming)
if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
if (viewPtList[viewPtIdx].camType == ORTHOGRAPHIC) {
toggleCameraType();
camera = getCamera();
((SoOrthographicCamera *) camera)->height.setValue(
viewPtList[viewPtIdx].height);
} else
((SoPerspectiveCamera *) camera)->heightAngle.setValue(
viewPtList[viewPtIdx].height);
} else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
if (viewPtList[viewPtIdx].camType == PERSPECTIVE) {
toggleCameraType();
camera = getCamera();
((SoPerspectiveCamera *) camera)->heightAngle.setValue(
viewPtList[viewPtIdx].height);
} else
((SoOrthographicCamera *) camera)->height.setValue(
viewPtList[viewPtIdx].height);
} else {
SoDebugError::post("G4OpenInventorXtExaminerViewer::setViewPt",
"Only Perspective and Orthographic cameras are supported.");
return;
}
}
// Pops up a prompt asking for a new viewpoint name.
void G4OpenInventorXtExaminerViewer::saveViewPtCB(Widget w,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (This->fileName.empty()) {
newViewPtFileCB(w, This, NULL);
This->returnToSaveVP = true;
return; // Need to return and call this fn again from newViewPtFileCB since flow of control does not stall here but keeps going
}
int n = 0;
Arg args[4];
Widget nameViewPtDialog;
Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
XmString label = XmStringCreateLocalized((char *) "Name the viewpoint:");
XtSetArg(args[n], XmNselectionLabelString, label); n++;
XtSetArg(args[n], XmNautoUnmanage, False); n++; //prevent the dialog from closing
//automatically, in case the name
//is wrong
nameViewPtDialog = XmCreatePromptDialog(parent, (char *) "Save Viewpoint",
args, n);
XmStringFree(label);
XtAddCallback(nameViewPtDialog, XmNokCallback, getViewPtNameCB, This);
XtAddCallback(nameViewPtDialog, XmNcancelCallback,
(XtCallbackProc) XtDestroyWidget, NULL);
Widget text = XtNameToWidget(nameViewPtDialog, "Text");
XtVaSetValues(text, XmNmaxLength, This->MAX_VP_NAME, NULL);
std::string autoName = "";
if (!This->warningFlag) { //leave the TextField as it is if coming back from warning dialog
autoName = This->viewPtAutoName();
}
This->warningFlag = false;
XmTextSetString(text, (char *) autoName.c_str());
XmTextSetInsertionPosition(text, autoName.length());
XtUnmanageChild(XtNameToWidget(nameViewPtDialog, "Help"));
XtManageChild(nameViewPtDialog);
}
std::string G4OpenInventorXtExaminerViewer::viewPtAutoName()
{
std::string viewPt;
std::stringstream sstream;
std::vector<int> existingViewPts;
int tmp;
//Build the list of names of the form viewpoint_* already present
for (unsigned int i = 0; i < this->viewPtList.size(); ++i) {
viewPt = this->viewPtList[i].viewPtName;
if (viewPt.find("viewpoint_") != std::string::npos) {
tmp = atoi(viewPt.substr(10).c_str());
if (tmp == 0) {
//0 means couldn't convert to integer OR viewpoint_0
if (!viewPt.compare("viewpoint_0"))
existingViewPts.push_back(0);
} else
existingViewPts.push_back(tmp);
}
}
sstream.str("");
sstream.clear();
//Return the view viewpoint_* name available
if (existingViewPts.size() > 0) {
int vpNum = 0;
while (true) {
if (std::find(existingViewPts.begin(), existingViewPts.end(), vpNum)
== existingViewPts.end()) {
sstream << "viewpoint_" << vpNum;
return sstream.str();
}
++vpNum;
}
} else {
return "viewpoint_0";
}
return "";
}
void G4OpenInventorXtExaminerViewer::abbrOutputCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
This->abbrOutputFlag = !(This->abbrOutputFlag);
}
void G4OpenInventorXtExaminerViewer::pickRefPathCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
// Save viewing state and go to picking mode
This->viewingBeforePickRef = This->isViewing();
if(This->isViewing())
This->setViewing(false);
This->setComponentCursor(SoXtCursor(SoXtCursor::CROSSHAIR));
This->pickRefPathFlag = true;
}
// Examines new viewpoint name and if OK calls saveViewPt.
void G4OpenInventorXtExaminerViewer::getViewPtNameCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *name = NULL;
std::string strName;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmSelectionBoxCallbackStruct *cbs =
(XmSelectionBoxCallbackStruct *) call_data;
XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &name);
if (!name) {
return;
}
if (!*name) {
XtFree(name);
return;
}
strName = name;
XtFree(name);
int beg = strName.find_first_not_of(' '); // Remove leading/trailing spaces
int end = strName.find_last_not_of(' ');
strName = strName.substr(beg, end - beg + 1);
bool nameExists = false;
int size = This->viewPtList.size();
for (int i = 0; i < size; i++) {
if (!strcmp(This->viewPtList[i].viewPtName, strName.c_str())) {
nameExists = true;
break;
}
}
if (!nameExists) {
const int nVPName = This->MAX_VP_NAME + 1;
name = new char[nVPName];
strncpy(name, strName.c_str(), nVPName);
if (This->viewPtIdx == -1)
This->viewPtIdx = 0;
This->saveViewPt(name);
if (This->listsDialog) {
XmListAddItemUnselected(This->myViewPtList, cbs->value, 0); // vpName
}
//Dismiss the nameViewPtDialog dialog
XtUnmanageChild(w);
} else {
String dialogName = (char *) "Existing Viewpoint";
std::string msg = "The viewpoint already exists.";
This->warningMsgDialog(msg, dialogName, NULL);
}
}
// Saves current camera parameters to a viewpoint file.
void G4OpenInventorXtExaminerViewer::saveViewPt(char *name)
{
SbVec3f axis;
viewPtData tmp;
float x, y, z, angle;
SoCamera * camera = getCamera();
if (viewPtList.size() == 0) {
writeViewPtIdx();
XtSetSensitive(nextViewPtButton, True); // Makes arrow buttons clickable
XtSetSensitive(prevViewPtButton, True);
}
tmp.viewPtName = name;
tmp.viewportMapping = camera->viewportMapping.getValue();
tmp.position = camera->position.getValue();
tmp.orientation = camera->orientation.getValue();
tmp.aspectRatio = camera->aspectRatio.getValue();
tmp.nearDistance = camera->nearDistance.getValue();
tmp.farDistance = camera->farDistance.getValue();
tmp.focalDistance = camera->focalDistance.getValue();
// Save camera height (changed by zooming)
if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
tmp.height = ((SoPerspectiveCamera *) camera)->heightAngle.getValue();
tmp.camType = PERSPECTIVE;
} else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
tmp.height = ((SoOrthographicCamera *) camera)->height.getValue();
tmp.camType = ORTHOGRAPHIC;
} else {
SoDebugError::post("G4OpenInventorXtExaminerViewer::saveViewPtCB",
"Only Perspective and Orthographic cameras are supported.");
return;
}
viewPtList.push_back(tmp);
// Now save the view point to a .txt file
std::string vpName = name;
while ((int) vpName.size() <= MAX_VP_NAME)
vpName += " ";
fileOut << vpName << std::endl;
tmp.position.getValue(x, y, z);
fileOut << x << " " << y << " " << z << std::endl;
// Reusing x, y and z for storing the axis
tmp.orientation.getValue(axis, angle);
axis.getValue(x, y, z);
fileOut << x << " " << y << " " << z << " " << angle << std::endl;
fileOut << tmp.camType << " " << tmp.height << std::endl;
fileOut << tmp.focalDistance << " ";
fileOut << tmp.nearDistance << " ";
fileOut << tmp.farDistance << std::endl;
fileOut << tmp.viewportMapping << " ";
fileOut << tmp.aspectRatio << "\n" << std::endl;
fileOut.flush();
viewPtIdx++;
}
void G4OpenInventorXtExaminerViewer::deleteViewPtCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
This->deleteViewPt();
}
// Deletes current viewpoint the user is looking at.
// Updates the input file and bookmarks as well.
void G4OpenInventorXtExaminerViewer::deleteViewPt(char *vpName)
{
std::string line;
int end;
fileIn.open(fileName.c_str());
std::ofstream out("temporaryFile.txt");
if (!vpName)
vpName = viewPtList[viewPtIdx].viewPtName;
if (listsDialog) {
XmString vpNameStr = XmStringCreateLocalized(vpName);
XmListDeleteItem(myViewPtList, vpNameStr);
XmStringFree(vpNameStr);
}
getline(fileIn, line); // Printing the viewpoint idx
out << line << "\n";
while (getline(fileIn, line)) {
end = line.find_last_not_of(' ');
line = line.substr(0, end + 1);
if (!strcmp(line.c_str(), vpName)) { // Equal
while (line.size()) {
getline(fileIn, line);
}
while (getline(fileIn, line))
out << line << "\n";
} else {
while (line.size()) {
out << line << "\n";
getline(fileIn, line);
}
out << "\n";
}
}
int idx = 0; // Remove viewpoint from the vector
int size = viewPtList.size();
while (idx < size) {
if (!strcmp(viewPtList[idx].viewPtName, vpName)) {
viewPtList.erase(viewPtList.begin() + idx);
break;
}
idx++;
}
out.close();
fileOut.close();
fileIn.clear();
fileIn.close();
remove(fileName.c_str());
rename("temporaryFile.txt", fileName.c_str());
fileOut.open(fileName.c_str(), std::ios::in);
fileOut.seekp(0, std::ios::end);
if (!viewPtList.size()) { // viewPtList is empty
curViewPtName = (char *) "";
scheduleRedraw();
XtSetSensitive(nextViewPtButton, False);
XtSetSensitive(prevViewPtButton, False);
} else {
if (viewPtIdx >= (int) viewPtList.size())
viewPtIdx--;
writeViewPtIdx();
setViewPt();
}
}
// Renames currently selected viewpoint.
void G4OpenInventorXtExaminerViewer::renameViewPt(char *vpName)
{
int idx = 0, end, pos;
int size = viewPtList.size();
std::string line, newName;
fileIn.open(fileName.c_str());
newName = vpName;
while ((int) newName.size() < MAX_VP_NAME)
newName += " ";
getline(fileIn, line);
pos = fileIn.tellg();
while (getline(fileIn, line)) {
end = line.find_last_not_of(' ');
line = line.substr(0, end + 1);
if (!strcmp(line.c_str(), curViewPtName)) {
fileOut.seekp(pos);
fileOut << newName;
fileOut.seekp(0, std::ios::end); // Set the file pointer to the end of the file
break;
}
while (line.size())
getline(fileIn, line);
pos = fileIn.tellg();
}
fileIn.close();
fileIn.clear();
while (idx < size) {
if (!strcmp(viewPtList[idx].viewPtName, curViewPtName)) {
strcpy(viewPtList[idx].viewPtName, vpName);
break;
}
idx++;
}
}
// Rewrites entire viewpoint file with sorted viewpoints.
void G4OpenInventorXtExaminerViewer::sortViewPts(std::vector<std::string> sortedViewPts)
{
SbVec3f axis;
float x, y, z, angle;
int sortIdx = 0, unsortIdx = 0;
if (fileOut.is_open())
fileOut.close();
fileOut.open(fileName.c_str()); // Erase current viewpoint file
writeViewPtIdx();
int size = sortedViewPts.size();
while (sortIdx < size) {
while (strcmp(sortedViewPts[sortIdx].c_str(),
viewPtList[unsortIdx].viewPtName))
unsortIdx++;
std::string vpName = viewPtList[unsortIdx].viewPtName;
while ((int) vpName.size() < MAX_VP_NAME)
vpName += " ";
fileOut << vpName << std::endl;
viewPtList[unsortIdx].position.getValue(x, y, z);
fileOut << x << " " << y << " " << z << std::endl;
// Reusing x, y and z for storing the axis
viewPtList[unsortIdx].orientation.getValue(axis, angle);
axis.getValue(x, y, z);
fileOut << x << " " << y << " " << z << " " << angle << std::endl;
fileOut << viewPtList[unsortIdx].camType << " "
<< viewPtList[unsortIdx].height << std::endl;
fileOut << viewPtList[unsortIdx].focalDistance << " ";
fileOut << viewPtList[unsortIdx].nearDistance << " ";
fileOut << viewPtList[unsortIdx].farDistance << std::endl;
fileOut << viewPtList[unsortIdx].viewportMapping << " ";
fileOut << viewPtList[unsortIdx].aspectRatio << "\n" << std::endl;
fileOut.flush();
unsortIdx = 0;
sortIdx++;
}
}
// Loads view point data from a file into a vector.
bool G4OpenInventorXtExaminerViewer::loadViewPts()
{
bool error = false;
viewPtData tmp;
std::string token;
SbVec3f axis;
SbRotation orient;
float x, y, z, angle;
// Gets the last view point accessed, stored in the first line of the data file.
fileIn >> token;
parseString<int>(viewPtIdx, token, error);
getline(fileIn, token); // Remove "\n"
// Converts data from string type into necessary types
while (getline(fileIn, token)) {
int end = token.find_last_not_of(' '); // Remove padded spaces
token = token.substr(0, end + 1);
char *vpName = new char[token.size() + 1];
strcpy(vpName, token.c_str());
tmp.viewPtName = vpName;
fileIn >> token;
parseString<float>(x, token, error);
fileIn >> token;
parseString<float>(y, token, error);
fileIn >> token;
parseString<float>(z, token, error);
fileIn >> token;
tmp.position = axis.setValue(x, y, z);
parseString<float>(x, token, error);
fileIn >> token;
parseString<float>(y, token, error);
fileIn >> token;
parseString<float>(z, token, error);
fileIn >> token;
parseString<float>(angle, token, error);
fileIn >> token;
orient.setValue(axis.setValue(x, y, z), angle);
tmp.orientation = orient.getValue();
int camType;
parseString<int>(camType, token, error);
fileIn >> token;
tmp.camType = (CameraType) camType;
parseString<float>(tmp.height, token, error);
fileIn >> token;
parseString<float>(tmp.focalDistance, token, error);
fileIn >> token;
parseString<float>(tmp.nearDistance, token, error);
fileIn >> token;
parseString<float>(tmp.farDistance, token, error);
fileIn >> token;
parseString<int>(tmp.viewportMapping, token, error);
fileIn >> token;
parseString<float>(tmp.aspectRatio, token, error);
getline(fileIn, token); // To remove "\n" characters
getline(fileIn, token);
if (error) {
viewPtIdx = 0;
viewPtList.clear();
return false;
}
viewPtList.push_back(tmp);
}
return true;
}
// Converts a string type word into a float type.
template<class T>
void G4OpenInventorXtExaminerViewer::parseString(T &t, const std::string &s,
bool &error)
{
std::istringstream str(s);
if ((str >> t).fail())
error = true;
}
// Generic fileSelectionDialog creation.
void G4OpenInventorXtExaminerViewer::popUpFileSelDialog(Widget &dialog,
std::string dialogName,
std::string buttonLabel,
XtCallbackProc cbOK)
{
int n;
Arg args[3];
Widget parent, scrollWidget;
parent = SoXt::getShellWidget(getParentWidget());
if (dialog == NULL) {
// Change the 'OK' button to whatever buttonLabel contains
XmString str = XmStringCreateLocalized((char *) buttonLabel.c_str());
n = 0;
XtSetArg(args[n], XmNokLabelString, str); n++;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
dialog = XmCreateFileSelectionDialog(parent,
(char *) dialogName.c_str(), args, n);
XtAddCallback(dialog, XmNokCallback, cbOK, this);
XtAddCallback(dialog, XmNcancelCallback, cancelFileSelDialogCB, this);
// Adding scrolling functionality to the widget
scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_DIR_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
XmStringFree(str);
}
XtManageChild(dialog);
}
// Generic fileSelectionDialog cancelation.
void G4OpenInventorXtExaminerViewer::cancelFileSelDialogCB(Widget w,
XtPointer,
XtPointer)
{
XtUnmanageChild(w);
}
// Displays a file selection dialog that allows to open a new viewpoint file.
void G4OpenInventorXtExaminerViewer::openViewPtFileCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
This->popUpFileSelDialog(This->openFileDialog, "Open File", "Load",
viewPtFileSelectedCB);
}
void G4OpenInventorXtExaminerViewer::viewPtFileSelectedCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file = NULL;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmFileSelectionBoxCallbackStruct *cbs =
(XmFileSelectionBoxCallbackStruct *) call_data;
// Get the file
if (cbs) {
if (!(file = (char *) XmStringUnparse(cbs->value,
XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
XmOUTPUT_ALL))) {
SoDebugError::post("G4OpenInventorXtExaminerViewer::fileSelectedCB",
"Internal error during file opening");
return;
}
This->fileIn.open(file);
if (!This->fileIn.fail()) {
// Opens a file without erasing it
This->cleanUpAfterPrevFile();
if (!This->loadViewPts()) {
String dialogName = (char *) "Error Loading File";
std::string msg = "Wrong or corrupted input file.";
This->warningMsgDialog(msg, dialogName, NULL);
} else {
This->fileName = file;
This->fileOut.open(This->fileName.c_str(), std::ios::in);
This->fileOut.seekp(0, std::ios::end);
if (!This->listsDialog)
constructListsDialog(w, This, NULL); // Pop up listsDialog
else
This->addViewPoints();
std::string newDialogName = This->fileName.substr(
This->fileName.rfind('/') + 1);
XtVaSetValues(This->myShellDialog, XmNtitle,
(char *) newDialogName.c_str(), NULL);
if (This->viewPtList.size()) {
This->setViewPt();
XmTextSetString(This->viewPtSelection, NULL);
XtSetSensitive(This->nextViewPtButton, True);
XtSetSensitive(This->prevViewPtButton, True);
} else {
XtSetSensitive(This->nextViewPtButton, False);
XtSetSensitive(This->prevViewPtButton, False);
}
XtUnmanageChild(w);
}
This->fileIn.close();
} else {
String dialogName = (char *) "Nonexistent File";
std::string msg = "Unable to open file.";
This->warningMsgDialog(msg, dialogName, NULL);
}
}
This->fileIn.clear();
XtFree(file);
}
// Adds bookmarks to listsDialog.
void G4OpenInventorXtExaminerViewer::addViewPoints()
{
int size = viewPtList.size();
if (!size)
return;
XmString *viewPts;
viewPts = (XmString *) XtMalloc(size * sizeof(XmString));
for (int i = 0; i < size; i++)
viewPts[i] = XmStringCreateLocalized(viewPtList[i].viewPtName);
XmListAddItemsUnselected(myViewPtList, viewPts, size, 1);
if (viewPts != NULL) {
for (int i = 0; i < size; i++)
XmStringFree(viewPts[i]);
XtFree((char *) viewPts);
}
}
// Called before loading a new viewpoint file.
// Resets member fields to default values.
void G4OpenInventorXtExaminerViewer::cleanUpAfterPrevFile()
{
viewPtIdx = -1;
viewPtList.clear();
setSuperimpositionEnabled(superimposition, FALSE);
scheduleRedraw();
currentState = GENERAL;
if (fileOut.is_open())
fileOut.close();
if (listsDialog) // Clear viewpoints
XmListDeleteAllItems(myViewPtList);
}
// Generic function for displaying a warning dialog.
void G4OpenInventorXtExaminerViewer::warningMsgDialog(std::string msg,
String dialogName,
XtCallbackProc cb)
{
Arg args[5];
unsigned int n;
XmString warningMsg;
warningMsg = XmStringCreateLocalized((char *)msg.c_str());
n = 0;
XtSetArg(args[n], XmNmessageString, warningMsg); n++;
Widget warningDialog = XmCreateWarningDialog(getParentWidget(), dialogName, args, n);
if (cb)
XtAddCallback(warningDialog, XmNokCallback, cb, this);
XmStringFree(warningMsg);
XtVaSetValues (warningDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
XtUnmanageChild(XtNameToWidget(warningDialog, "Help"));
XtUnmanageChild(XtNameToWidget(warningDialog, "Cancel"));
XtManageChild(warningDialog);
}
void G4OpenInventorXtExaminerViewer::newViewPtFileCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
This->popUpFileSelDialog(This->newFileDialog, "New File", "Save",
createNewVPFileCB);
}
void G4OpenInventorXtExaminerViewer::createNewVPFileCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file;
std::string fName;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmFileSelectionBoxCallbackStruct *cbs =
(XmFileSelectionBoxCallbackStruct *) call_data;
// Get the file
if (cbs) {
if (!(file = (char *) XmStringUnparse(cbs->value,
XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
XmOUTPUT_ALL))) {
SoDebugError::post("G4OpenInventorXtExaminerViewer::createNewVPFileCB",
"Internal error during file opening");
return;
}
This->fileName = file;
fName = This->fileName.substr(This->fileName.rfind('/') + 1); // Extracts just the name of the file
This->fileIn.open(file);
if (This->fileIn.fail()) { // Filename does not exist
This->cleanUpAfterPrevFile();
This->fileOut.open(file); // Creates a new empty file
XtSetSensitive(This->nextViewPtButton, False);
XtSetSensitive(This->prevViewPtButton, False);
if (This->listsDialog)
closeListsDialogCB(w, This, NULL);
constructListsDialog(w, This, NULL);
XtUnmanageChild(w);
if (This->returnToSaveVP) {
This->returnToSaveVP = false;
saveViewPtCB(NULL, This, NULL);
}
} else { // Filename already exists
String dialogName = (char *) "Existing File";
std::string msg = "'" + fName + "' already exists. Do you want to overwrite it?";
This->warningMsgDialog(msg, dialogName, overwriteFileCB);
This->fileIn.close();
}
This->fileIn.clear();
XtFree(file);
}
}
void G4OpenInventorXtExaminerViewer::overwriteFileCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
This->cleanUpAfterPrevFile();
XtSetSensitive(This->nextViewPtButton, False);
XtSetSensitive(This->prevViewPtButton, False);
XtUnmanageChild(This->newFileDialog);
This->fileOut.open(This->fileName.c_str());
if (This->returnToSaveVP) {
This->returnToSaveVP = false;
saveViewPtCB(NULL, This, NULL);
}
}
void G4OpenInventorXtExaminerViewer::loadRefCoordsDialogCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *)client_data;
This->popUpFileSelDialog(This->loadRefCoordsDialog, "Load Ref Coords",
"Load", loadRefCoordsCB);
}
void G4OpenInventorXtExaminerViewer::loadRefCoordsCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file = NULL;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data;
XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
// Get the file
if(cbs) {
file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT,
NULL, 0, XmOUTPUT_ALL);
std::ifstream ifs(file);
if(ifs.is_open()){
This->refParticleTrajectory.clear();
float x,y,z;
while(ifs >> x >> y >> z){
This->refParticleTrajectory.push_back(SbVec3f(x,y,z));
}
ifs.close();
XtUnmanageChild(w);
}
else{
String dialogName = (char *) "Problem reading file";
std::string msg = "Problem reading file";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
}
return;
}
void G4OpenInventorXtExaminerViewer::saveRefCoordsDialogCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (!This->refParticleTrajectory.size()) {
String dialogName = (char *) "No Reference Trajectory";
std::string msg = "You need to start a run or load a reference trajectory from a file";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
int n;
Arg args[3];
Widget parent, scrollWidget;
parent = SoXt::getShellWidget(This->getParentWidget());
if (This->saveRefCoordsDialog == NULL) {
// Change the 'OK' button to whatever buttonLabel contains
XmString str = XmStringCreateLocalized((char *)"Save");
n = 0;
XtSetArg(args[n], XmNokLabelString, str); n++;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
This->saveRefCoordsDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Ref Coords", args, n);
XtAddCallback(This->saveRefCoordsDialog, XmNokCallback, saveRefCoordsCB, This);
XtAddCallback(This->saveRefCoordsDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
// Adding scrolling functionality to the widget
scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_DIR_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
XtUnmanageChild(XmSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_HELP_BUTTON));
XmStringFree(str);
}
//TODO: Auto name?
XtManageChild(This->saveRefCoordsDialog);
}
void G4OpenInventorXtExaminerViewer::saveRefCoordsCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmFileSelectionBoxCallbackStruct *cbs =
(XmFileSelectionBoxCallbackStruct *) call_data;
// Get the file
if (cbs) {
file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT,
NULL, 0, XmOUTPUT_ALL);
std::ifstream ifile(file);
if (ifile) {
//File already exists
Arg args[4];
Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
Widget confirmOverwriteDialog;
XmString msg;
confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
// If users presses OK, we want to return to this function and
// save the file. For that to work, pass it the current widget
// to be able to grab the filename.
XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveRefCoordsOverWriteCB, client_data);
XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveRefCoordsOverWriteCB, client_data);
XmStringFree (msg);
//The confirmOverwriteDialog will need this
This->saveRefCoordsFileName = file;
This->saveRefCoordsWidget = w;
XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
XtManageChild(confirmOverwriteDialog);
return;
}
else{
std::ofstream ofs(file);
if(ofs.is_open()){
float x,y,z;
for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
This->refParticleTrajectory[i].getValue(x,y,z);
ofs << x << " " << y << " " << z << "\n";
}
ofs.close();
XtUnmanageChild(w);
}
else{
String dialogName = (char *) "Error opening file";
std::string msg = "There was a problem trying to open the file '";
msg += This->saveRefCoordsFileName;
msg += "'";
This->warningMsgDialog(msg, dialogName, NULL);
}
}
}
return;
}
void G4OpenInventorXtExaminerViewer::saveRefCoordsOverWriteCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
switch (cbs->reason) {
case XmCR_OK:
{
// Overwrite confirmed, save file and dismiss both
// dialogs (file dialog and overwrite confirmation dialog)
std::ofstream ofs(This->saveRefCoordsFileName.c_str());
if(ofs.is_open()){
float x,y,z;
for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
This->refParticleTrajectory[i].getValue(x,y,z);
ofs << x << " " << y << " " << z << "\n";
}
ofs.close();
XtUnmanageChild(w);
XtUnmanageChild(This->saveRefCoordsWidget);
}
else{
String dialogName = (char *) "Error opening file";
std::string msg = "There was a problem trying to open the file '";
msg += This->saveRefCoordsFileName;
msg += "'";
This->warningMsgDialog(msg, dialogName, NULL);
}
break;
}
case XmCR_CANCEL:
{
// Overwrite refused, dismiss overwrite confirmation
// dialog and return to file dialog
// Give focus to the text field instead of the OK button
XmProcessTraversal(XtNameToWidget(This->saveRefCoordsWidget, "Text"), XmTRAVERSE_CURRENT);
XtUnmanageChild(w);
This->saveRefCoordsFileName.clear();
This->saveRefCoordsWidget = NULL;
break;
}
default:
return;
}
}
void G4OpenInventorXtExaminerViewer::loadSceneGraphDialogCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *)client_data;
This->popUpFileSelDialog(This->loadSceneGraphDialog, "Load Scene Graph",
"Load", loadSceneGraphCB);
return;
}
void G4OpenInventorXtExaminerViewer::loadSceneGraphCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file = NULL;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *)client_data;
XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
if(cbs) {
file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT,
NULL, 0, XmOUTPUT_ALL);
SoInput sceneInput;
if (!sceneInput.openFile(file)) {
String dialogName = (char *) "Problem opening file";
std::string msg = "Cannot open file ";
msg += file;
This->warningMsgDialog(msg, dialogName, NULL);
sceneInput.closeFile();
XtUnmanageChild(w);
}
// Read the whole file into the database
This->newSceneGraph = SoDB::readAll(&sceneInput);
if (This->newSceneGraph == NULL) {
String dialogName = (char *) "Problem reading file";
std::string msg = "Problem reading file";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
//This->newSceneGraph->ref();
This->setSceneGraph(This->newSceneGraph);
}
return;
}
void G4OpenInventorXtExaminerViewer::saveSceneGraphDialogCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
int n;
Arg args[3];
Widget parent, scrollWidget;
parent = SoXt::getShellWidget(This->getParentWidget());
if (This->saveSceneGraphDialog == NULL) {
// Change the 'OK' button to whatever buttonLabel contains
XmString str = XmStringCreateLocalized((char *)"Save");
n = 0;
XtSetArg(args[n], XmNokLabelString, str); n++;
XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
This->saveSceneGraphDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Scene Graph", args, n);
XtAddCallback(This->saveSceneGraphDialog, XmNokCallback, saveSceneGraphCB, This);
XtAddCallback(This->saveSceneGraphDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
// Adding scrolling functionality to the widget
scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_DIR_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_LIST);
if (scrollWidget)
xmAddMouseEventHandler(scrollWidget);
XtUnmanageChild(XmSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_HELP_BUTTON));
XmStringFree(str);
}
//TODO: Auto name?
XtManageChild(This->saveSceneGraphDialog);
}
void G4OpenInventorXtExaminerViewer::saveSceneGraphCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
char *file;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmFileSelectionBoxCallbackStruct *cbs =
(XmFileSelectionBoxCallbackStruct *) call_data;
if (cbs) {
file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT,
NULL, 0, XmOUTPUT_ALL);
std::ifstream ifile(file);
if (ifile) {
//File already exists
Arg args[4];
Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
Widget confirmOverwriteDialog;
XmString msg;
confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
// If users presses OK, we want to return to this function and
// save the file. For that to work, pass it the current widget
// to be able to grab the filename.
XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveSceneGraphOverWriteCB, client_data);
XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveSceneGraphOverWriteCB, client_data);
XmStringFree (msg);
//The confirmOverwriteDialog will need this
This->saveScenegraphFileName = file;
This->saveScenegraphWidget = w;
XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
XtManageChild(confirmOverwriteDialog);
return;
}
else{
SoWriteAction writeAction;
SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
SoOutput * out = writeAction.getOutput();
if(out->openFile(file)){
out->setBinary(FALSE);
writeAction.apply(root);
out->closeFile();
XtUnmanageChild(w);
}
else{
String dialogName = (char *) "Error opening file";
std::string msg = "There was a problem trying to open the file '";
msg += This->saveScenegraphFileName;
msg += "'";
This->warningMsgDialog(msg, dialogName, NULL);
}
}
}
return;
}
void G4OpenInventorXtExaminerViewer::saveSceneGraphOverWriteCB(Widget w,
XtPointer client_data,
XtPointer call_data)
{
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
switch (cbs->reason) {
case XmCR_OK:
{
// Overwrite confirmed, save file and dismiss both
// dialogs (file dialog and overwrite confirmation dialog)
SoWriteAction writeAction;
SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
SoOutput * out = writeAction.getOutput();
if(out->openFile(This->saveScenegraphFileName.c_str())){
out->setBinary(FALSE);
writeAction.apply(root);
out->closeFile();
XtUnmanageChild(w);
XtUnmanageChild(This->saveScenegraphWidget);
This->saveScenegraphFileName.clear();
This->saveScenegraphWidget = NULL;
}
else{
String dialogName = (char *) "Error opening file";
std::string msg = "There was a problem trying to open the file '";
msg += This->saveScenegraphFileName;
msg += "'";
This->warningMsgDialog(msg, dialogName, NULL);
This->saveScenegraphFileName.clear();
This->saveScenegraphWidget = NULL;
}
break;
}
case XmCR_CANCEL:
{
// Overwrite refused, dismiss overwrite confirmation
// dialog and return to file dialog
// Give focus to the text field instead of the OK button
XmProcessTraversal(XtNameToWidget(This->saveScenegraphWidget, "Text"), XmTRAVERSE_CURRENT);
XtUnmanageChild(w);
This->saveScenegraphFileName.clear();
This->saveScenegraphWidget = NULL;
break;
}
default:
return;
}
}
// Receives the name of the bookmark clicked and searches for it in viewPtList.
void G4OpenInventorXtExaminerViewer::loadBookmarkCB(Widget,
XtPointer client_data,
XtPointer call_data)
{
char *vpName;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
vpName = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
for (int i = 0; i < (int) This->viewPtList.size(); i++) {
if (!strcmp(This->viewPtList[i].viewPtName, vpName)) {
This->viewPtIdx = i;
break;
}
}
XmTextSetString(This->viewPtSelection, vpName);
This->writeViewPtIdx();
This->setViewPt();
XtFree(vpName);
}
void G4OpenInventorXtExaminerViewer::deleteBookmarkCB(Widget,
XtPointer client_data,
XtPointer)
{
char *vpName;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
vpName = XmTextGetString(This->viewPtSelection);
XmString vpNameStr = XmStringCreateLocalized(vpName);
if (XmListItemExists(This->myViewPtList, vpNameStr)) {
XmListDeleteItem(This->myViewPtList, vpNameStr);
This->deleteViewPt(vpName);
}
XmStringFree(vpNameStr);
XmTextSetString(This->viewPtSelection, NULL);
XtFree(vpName);
}
void G4OpenInventorXtExaminerViewer::renameBookmarkCB(Widget,
XtPointer client_data,
XtPointer)
{
std::string vpNameStr;
char *vpName;
int *pos_list, pos_cnt;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
vpName = XmTextGetString(This->viewPtSelection);
if (!strlen(vpName) || !strcmp(This->curViewPtName, vpName)) {
XtFree(vpName);
return;
}
vpNameStr = vpName;
XtFree(vpName);
int beg = vpNameStr.find_first_not_of(' '); // Remove leading/trailing spaces
int end = vpNameStr.find_last_not_of(' ');
vpNameStr = vpNameStr.substr(beg, end - beg + 1);
const int nVPName = vpNameStr.size() + 1;
vpName = new char[nVPName];
strncpy(vpName, vpNameStr.c_str(), nVPName);
int size = This->viewPtList.size();
for (int i = 0; i < size; i++) {
if (!strcmp(vpName, This->viewPtList[i].viewPtName)) {
String dialogName = (char *) "Existing Viewpoint";
std::string msg = "'";
msg += vpName;
msg += "' already exists. Choose a different name";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
}
XmString vpNameXmStr = XmStringCreateLocalized(vpName);
if (XmListGetSelectedPos(This->myViewPtList, &pos_list, &pos_cnt)) {
XmListReplaceItemsPos(This->myViewPtList, &vpNameXmStr, 1, pos_list[0]);
This->renameViewPt(vpName);
XtFree((char *) pos_list);
}
if (This->currentState == VIEWPOINT)
This->scheduleRedraw();
XmStringFree(vpNameXmStr);
}
void G4OpenInventorXtExaminerViewer::sortBookmarksCB(Widget,
XtPointer client_data,
XtPointer)
{
int size;
char *vpName;
XmString *strList, *newStrList;
std::vector<std::string> charList;
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (This->viewPtList.size() < 2)
return;
// Get current entries from the list
XtVaGetValues(This->myViewPtList, XmNitemCount, &size, XmNitems, &strList,
NULL);
for (int i = 0; i < size; i++) {
vpName = (char *) XmStringUnparse(strList[i], XmFONTLIST_DEFAULT_TAG,
XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
charList.push_back(vpName);
XtFree(vpName);
}
std::sort(charList.begin(), charList.end());
newStrList = (XmString *) XtMalloc(size * sizeof(XmString));
for (int i = 0; i < size; i++) {
// viewPtIdx has to be changed to account for a different order in viewPtList
if (!strcmp(charList[i].c_str(), This->curViewPtName))
This->viewPtIdx = i;
const int nVPName = charList[i].size() + 1;
char *vpName2 = new char[nVPName];
strncpy(vpName2, charList[i].c_str(), nVPName);
newStrList[i] = XmStringCreateLocalized(vpName2);
delete vpName2;
}
XmListDeleteAllItems(This->myViewPtList);
XmListAddItemsUnselected(This->myViewPtList, newStrList, size, 1);
This->sortViewPts(charList);
if (newStrList != NULL) {
for (int i = 0; i < size; i++)
XmStringFree(newStrList[i]);
XtFree((char *) newStrList);
}
}
void G4OpenInventorXtExaminerViewer::evenOutRefParticlePts()
{
if(this->refParticleTrajectory.empty())
return;
SbVec3f p1, p2, p3, dirNow, dirNxt, dir, p2_tmp, p_start, p_corner, p_nxt;
float avgDistBtwPts = 0;
float totalDistBtwPts = 0;
std::vector<SbVec3f> newRefParticleTrajectory;
SbVec3f refPoint;
int size = refParticleTrajectory.size() - 1;
int numOfPts = 0;
for (int i = 0; i < size; i++) {
p1 = refParticleTrajectory[i];
p2 = refParticleTrajectory[i + 1];
if (p1 == p2)
continue;
numOfPts++;
totalDistBtwPts += (p2 - p1).length();
}
avgDistBtwPts = totalDistBtwPts / numOfPts;
float minDistAllowed = 0.75 * avgDistBtwPts;
// float maxDistAllowed = 1.25 * avgDistBtwPts; // Pts tend to be close not far
float x, y, z;
int i = 0, j = 0;
while (i < size) {
p1 = refParticleTrajectory[i];
p2 = refParticleTrajectory[i + 1];
refPoint = p1;
p1.getValue(x, y, z);
newRefParticleTrajectory.push_back(refPoint);
j = i;
while ((p2 - p1).length() < minDistAllowed && j < (size - 1)) {
j++;
p1 = refParticleTrajectory[j];
p2 = refParticleTrajectory[j + 1];
}
if (j != i)
i = j + 1;
else
i++;
}
refParticleTrajectory.clear();
refParticleTrajectory = newRefParticleTrajectory;
}
// Called when the viewer is closed; closes all open widgets.
void G4OpenInventorXtExaminerViewer::closeMainWindowCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
if (This->openFileDialog)
XtUnmanageChild(This->openFileDialog);
if (This->newFileDialog)
XtUnmanageChild(This->newFileDialog);
if (This->listsDialog)
closeListsDialogCB(NULL, This, NULL);
}
void G4OpenInventorXtExaminerViewer::saveCurCamera()
{
SoCamera *cam = getCamera();
camB4Animation.viewportMapping = cam->viewportMapping.getValue();
camB4Animation.position = cam->position.getValue();
camB4Animation.orientation = cam->orientation.getValue();
camB4Animation.aspectRatio = cam->aspectRatio.getValue();
camB4Animation.nearDistance = cam->nearDistance.getValue();
camB4Animation.farDistance = cam->farDistance.getValue();
camB4Animation.focalDistance = cam->focalDistance.getValue();
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
camB4Animation.height =
((SoPerspectiveCamera *) cam)->heightAngle.getValue();
camB4Animation.camType = PERSPECTIVE;
} else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
camB4Animation.height =
((SoOrthographicCamera *) cam)->height.getValue();
camB4Animation.camType = ORTHOGRAPHIC;
}
}
void G4OpenInventorXtExaminerViewer::restoreCamera()
{
SoCamera *cam = getCamera();
cam->viewportMapping = camB4Animation.viewportMapping;
cam->position = camB4Animation.position;
cam->orientation = camB4Animation.orientation;
cam->aspectRatio = camB4Animation.aspectRatio;
cam->nearDistance = camB4Animation.nearDistance;
cam->farDistance = camB4Animation.farDistance;
cam->focalDistance = camB4Animation.focalDistance;
if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
if (camB4Animation.camType == ORTHOGRAPHIC) {
toggleCameraType();
cam = getCamera();
((SoOrthographicCamera *) cam)->height.setValue(
camB4Animation.height);
} else
((SoPerspectiveCamera *) cam)->heightAngle.setValue(
camB4Animation.height);
} else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
if (camB4Animation.camType == PERSPECTIVE) {
toggleCameraType();
cam = getCamera();
((SoPerspectiveCamera *) cam)->heightAngle.setValue(
camB4Animation.height);
} else
((SoOrthographicCamera *) cam)->height.setValue(
camB4Animation.height);
}
}
void G4OpenInventorXtExaminerViewer::animateSensorRotationCB(void *data,
SoSensor *sensor)
{
SbTime curTime = SbTime::getTimeOfDay();
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data;
SoTimerSensor *s = (SoTimerSensor *) sensor;
float t = float((curTime - s->getBaseTime()).getValue())
/ This->animateBtwPtsPeriod;
if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
t = 1.0f;
SbBool end = (t == 1.0f);
if (end) {
This->animateSensorRotation->unschedule();
if(This->rotCnt){
// rotations left
This->rotateCamera();
}
else {
// rotation over
This->currentState = This->prevState;
return;
}
}
}
// Called repeatedly during reference particle animation
void G4OpenInventorXtExaminerViewer::animateSensorCB(void *data,
SoSensor *sensor)
{
SbTime curTime = SbTime::getTimeOfDay();
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) data;
SoCamera *cam = This->getCamera();
SoTimerSensor *s = (SoTimerSensor *) sensor;
float t = float((curTime - s->getBaseTime()).getValue())
/ This->animateBtwPtsPeriod;
if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
t = 1.0f;
SbBool end = (t == 1.0f);
cam->orientation = SbRotation::slerp(This->camStartOrient, This->camEndOrient, t);
cam->position = This->camStartPos + (This->camEndPos - This->camStartPos) * t;
if (end) {
This->animateSensor->unschedule();
if (This->currentState == ANIMATION) {
if (This->refParticleIdx < (int) (This->refParticleTrajectory.size() - 1))
This->animateRefParticle();
else {
This->animateBtwPtsPeriod = MIN_SPEED;
This->speedStep = START_STEP;
}
}
if (This->currentState == REVERSED_ANIMATION) {
if (This->refParticleIdx >= 1)
This->animateRefParticle();
else {
This->animateBtwPtsPeriod = MIN_SPEED;
This->speedStep = START_STEP;
}
}
}
}
void G4OpenInventorXtExaminerViewer::setStartingPtForAnimation()
{
if (SoXtExaminerViewer::isAnimating())
stopAnimating();
SbRotation rot;
SbVec3f p1, p2, p2_tmp, camUpV, camD, camD_tmp, leftRightAxis;
float x1, y1, z1, x2, y2, z2;
if (currentState == ANIMATION) {
p1 = refParticleTrajectory[refParticleIdx];
p2 = refParticleTrajectory[++(refParticleIdx)];
} else if (currentState == REVERSED_ANIMATION) {
p2 = refParticleTrajectory[refParticleIdx];
p1 = refParticleTrajectory[--(refParticleIdx)];
} else if (currentState == PAUSED_ANIMATION) {
if (refParticleIdx < (int) refParticleTrajectory.size()) {
p1 = refParticleTrajectory[refParticleIdx];
p2 = refParticleTrajectory[refParticleIdx + 1];
} else {
p1 = refParticleTrajectory[refParticleIdx - 1];
p2 = refParticleTrajectory[refParticleIdx];
}
}
p1.getValue(x1, y1, z1);
p2.getValue(x2, y2, z2);
camD = p2 - p1;
camD.normalize();
p2_tmp.setValue(x2, y1, z2);
camD_tmp = p2_tmp - p1;
camD_tmp.normalize();
camUpV.setValue(0, 1, 0);
rot.setValue(camD_tmp, camD);
rot.multVec(camUpV, camUpV);
leftRightAxis = camD.cross(camUpV);
myCam->position = p1;
myCam->pointAt(p2, camUpV);
// Update camera position
p1 = p1 + (up_down * camUpV) + (left_right * leftRightAxis);
myCam->position = p1;
// FWJ Try look-ahead here
int idx = refParticleIdx + pathLookahead;
idx = std::min(idx, (int)refParticleTrajectory.size() - 1);
myCam->pointAt(refParticleTrajectory[idx], camUpV);
// myCam->pointAt(refParticleTrajectory[idx], camUpVec);
myCam->focalDistance = 0.1f;
}
void G4OpenInventorXtExaminerViewer::gotoRefPathStart()
{
G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(NULL, (void *)this,
NULL);
}
void G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (!This->refParticleTrajectory.size()) {
String dialogName = (char *) "No Reference Trajectory";
std::string msg = "You need to start a run or load a reference trajectory from a file";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
if (This->currentState == ROTATING)
return;
if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
|| This->currentState == PAUSED_ANIMATION) {
if (This->animateSensor->isScheduled())
This->animateSensor->unschedule();
This->setSuperimpositionEnabled(This->superimposition, FALSE);
This->maxSpeed = 0.0f;
This->scheduleRedraw();
} else {
This->saveCurCamera();
This->prevState = This->currentState;
This->prevRefIdx = This->refParticleIdx;
}
if (This->SoXtExaminerViewer::isAnimating())
This->stopAnimating();
This->up_down = 0;
This->left_right = 0;
This->step = 1;
This->refParticleIdx = 0;
This->currentState = BEAMLINE;
This->setSuperimpositionEnabled(This->superimposition, TRUE);
This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
This->scheduleRedraw();
// FWJ Disabled: this is set in moveCamera()
// Zoom in
// SoCamera *cam = This->getCamera();
// cam->focalDistance = 0.1f;
This->prevParticleDir = SbVec3f(0,0,0);
//Default zoom
SbVec3f p1 = This->refParticleTrajectory[0];
SbVec3f pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
This->distance = (pN - p1).length() / 10;
This->moveCamera(This->distance, true);
}
void G4OpenInventorXtExaminerViewer::invertRefPathCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This =
(G4OpenInventorXtExaminerViewer *) client_data;
This->invertRefPath();
}
void G4OpenInventorXtExaminerViewer::invertRefPath()
{
std::reverse(this->refParticleTrajectory.begin(),
this->refParticleTrajectory.end());
this->setReferencePathZPos();
this->sortElements();
}
void G4OpenInventorXtExaminerViewer::animateRefParticleCB(Widget,
XtPointer client_data,
XtPointer)
{
G4OpenInventorXtExaminerViewer * This = (G4OpenInventorXtExaminerViewer *) client_data;
if (!This->refParticleTrajectory.size()) {
This->returnToAnim = true;
String dialogName = (char *) "No Reference Trajectory";
std::string msg = "You need to start a run or load a reference trajectory from a file";
This->warningMsgDialog(msg, dialogName, NULL);
return;
}
if (!This->refParticleTrajectory.size())
return;
///////////////////////////////////////////////////////////////
This->setSuperimpositionEnabled(This->superimposition, TRUE);
This->maxSpeed = SPEED_INDICATOR_STEP;
This->axisSwitch->whichChild.setValue(SO_SWITCH_ALL);
This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
This->scheduleRedraw();
///////////////////////////////////////////////////////////////
SoCamera *cam = This->getCamera();
// SbVec3f camDirOld, camDirNew, camDirNew_tmp, camUpVec, P0, P1, P1_tmp;
if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
|| This->currentState == ROTATING)
return;
if (This->currentState != PAUSED_ANIMATION) {
This->saveCurCamera();
This->prevState = This->currentState;
This->prevRefIdx = This->refParticleIdx;
if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
This->toggleCameraType();
cam = This->getCamera();
}
This->refParticleIdx = 0; // Set the camera to the starting point of the animation
This->animateBtwPtsPeriod = MIN_SPEED;
This->speedStep = START_STEP;
This->left_right = This->up_down = 0;
cam->focalDistance = 0.1f;
((SoPerspectiveCamera *) cam)->heightAngle = 0.50f;
}
This->currentState = ANIMATION;
This->setStartingPtForAnimation();
cam->position = (This->myCam)->position.getValue();
cam->orientation = (This->myCam)->orientation.getValue();
This->animateRefParticle(); // Animate the camera
}
void G4OpenInventorXtExaminerViewer::animateRefParticle()
{
SoCamera *cam = getCamera();
camStartPos = cam->position.getValue();
camStartOrient = cam->orientation.getValue();
if (currentState != BEAMLINE)
setStartingPtForAnimation();
camEndPos = myCam->position.getValue();
camEndOrient = myCam->orientation.getValue();
if (animateSensor->isScheduled())
animateSensor->unschedule();
animateSensor->setBaseTime(SbTime::getTimeOfDay());
animateSensor->setInterval(SbTime(0.02));
animateSensor->schedule();
}
void G4OpenInventorXtExaminerViewer::addEscapeCallback(
void (*callback)(void *), void * object)
{
this->escapeCallback = callback;
this->examinerObject = object;
}
void G4OpenInventorXtExaminerViewer::sceneChangeCB(void *userData, SoSensor *)
{
G4OpenInventorXtExaminerViewer* This =
(G4OpenInventorXtExaminerViewer*)userData;
if(This->newEvents){
This->findAndSetRefPath();
This->newEvents = false;
}
}
HookEventProcState::HookEventProcState(G4OpenInventorXtExaminerViewer* vwr)
{
this->viewer = vwr;
}
HookEventProcState::~HookEventProcState()
{;}
G4bool HookEventProcState::Notify(G4ApplicationState requiredState)
{
if(requiredState == G4State_EventProc){
this->viewer->newEvents = true;
}
return true;
}