4897 lines
168 KiB
C++
4897 lines
168 KiB
C++
//
|
||
// ********************************************************************
|
||
// * License and Disclaimer *
|
||
// * *
|
||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||
// * conditions of the Geant4 Software License, included in the file *
|
||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||
// * include a list of copyright holders. *
|
||
// * *
|
||
// * Neither the authors of this software system, nor their employing *
|
||
// * institutes,nor the agencies providing financial support for this *
|
||
// * work make any representation or warranty, express or implied, *
|
||
// * regarding this software system or assume any liability for its *
|
||
// * use. Please see the license in the file LICENSE and URL above *
|
||
// * for the full disclaimer and the limitation of liability. *
|
||
// * *
|
||
// * This code implementation is the result of the scientific and *
|
||
// * technical work of the GEANT4 collaboration. *
|
||
// * By using, copying, modifying or distributing the software (or *
|
||
// * any work based on the software) you agree to acknowledge its *
|
||
// * use in resulting scientific publications, and indicate your *
|
||
// * acceptance of all terms of the Geant4 Software license. *
|
||
// ********************************************************************
|
||
//
|
||
//
|
||
// 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 "pickext.h"
|
||
#include "pickref.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 pickextxpm, pickextxpm_ins;
|
||
pickextxpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
|
||
pickext_xpm);
|
||
pickextxpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
|
||
pickext_xpm, TRUE);
|
||
XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
|
||
pickextxpm, XmNselectPixmap, pickextxpm, XmNlabelInsensitivePixmap,
|
||
pickextxpm_ins, XmNselectInsensitivePixmap, pickextxpm_ins, NULL);
|
||
// 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 pickrefxpm, pickrefxpm_ins;
|
||
pickrefxpm = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
|
||
pickref_xpm);
|
||
pickrefxpm_ins = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
|
||
pickref_xpm, TRUE);
|
||
XtVaSetValues(pickRefPathButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
|
||
pickrefxpm, XmNselectPixmap, pickrefxpm, XmNlabelInsensitivePixmap,
|
||
pickrefxpm_ins, XmNselectInsensitivePixmap, pickrefxpm_ins, NULL);
|
||
// 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, t1Ch, 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)
|
||
t1Ch = " +";
|
||
else
|
||
t1Ch = " ";
|
||
t1Ch += value;
|
||
}
|
||
if (valueName == "PDG") {
|
||
t1 += " ";
|
||
t1 += value;
|
||
t1 += t1Ch;
|
||
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 + "/c";
|
||
// 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
|
||
// FWJ attempt to fix Coverity issue.
|
||
char nextChar = oss.str().at(idx+findStr.size()+1);
|
||
// const char * nextChar =
|
||
// oss.str().substr(idx + findStr.size() + 1,1).c_str();
|
||
if(std::isdigit(nextChar))
|
||
// 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⋅(b–a)
|
||
//
|
||
// 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);
|
||
|
||
// FWJ sceneElement already has a center
|
||
elementCoord = itEl->center;
|
||
// ... and this sometimes returns an empty box!
|
||
// elementCoord = bAction.getBoundingBox().getCenter();
|
||
// if (bAction.getBoundingBox().isEmpty()) {
|
||
// G4cout << "sortElements: Box is empty!" << G4endl;
|
||
// G4cout << " element name=" << itEl->name << G4endl;
|
||
// }
|
||
|
||
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();
|
||
|
||
// FWJ check return status
|
||
int istat = remove(fileName.c_str());
|
||
if (istat == -1) {
|
||
char dialogName[] = "Warning";
|
||
warningMsgDialog("Error removing bookmarks file", dialogName,
|
||
NULL);
|
||
}
|
||
istat = rename("temporaryFile.txt", fileName.c_str());
|
||
if (istat == -1) {
|
||
char dialogName[] = "Warning";
|
||
warningMsgDialog("Error renaming bookmarks file", dialogName,
|
||
NULL);
|
||
}
|
||
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;
|
||
char* vpName1 = new char[nVPName];
|
||
strncpy(vpName1, vpNameStr.c_str(), nVPName);
|
||
|
||
int size = This->viewPtList.size();
|
||
for (int i = 0; i < size; i++) {
|
||
if (!strcmp(vpName1, This->viewPtList[i].viewPtName)) {
|
||
|
||
String dialogName = (char *) "Existing Viewpoint";
|
||
std::string msg = "'";
|
||
msg += vpName1;
|
||
msg += "' already exists. Choose a different name";
|
||
|
||
This->warningMsgDialog(msg, dialogName, NULL);
|
||
delete[] vpName1;
|
||
return;
|
||
}
|
||
}
|
||
|
||
XmString vpNameXmStr = XmStringCreateLocalized(vpName1);
|
||
|
||
if (XmListGetSelectedPos(This->myViewPtList, &pos_list, &pos_cnt)) {
|
||
XmListReplaceItemsPos(This->myViewPtList, &vpNameXmStr, 1, pos_list[0]);
|
||
This->renameViewPt(vpName1);
|
||
XtFree((char *) pos_list);
|
||
}
|
||
|
||
if (This->currentState == VIEWPOINT)
|
||
This->scheduleRedraw();
|
||
|
||
XmStringFree(vpNameXmStr);
|
||
delete[] vpName1;
|
||
}
|
||
|
||
|
||
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;
|
||
}
|