Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4OpenInventorXtExaminerViewer.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // Open Inventor Xt Extended Viewer - 30 Oct 2012
28 // Rastislav Ondrasek, Pierre-Luc Gagnon, Frederick Jones TRIUMF
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <string>
33 #include <sstream>
34 #include <cmath>
35 #include <iostream>
36 #include <iomanip>
37 #include <algorithm> // For using sort on a vector
38 #include <X11/keysym.h>
39 
40 #include <Xm/Xm.h>
41 #include <Xm/Text.h>
42 #include <Xm/List.h>
43 #include <Xm/MessageB.h>
44 #include <Xm/PushB.h>
45 #include <Xm/ToggleB.h>
46 #include <Xm/CascadeB.h>
47 #include <Xm/ArrowBG.h>
48 #include <Xm/Form.h>
49 #include <Xm/RowColumn.h>
50 #include <Xm/FileSB.h>
51 #include <Xm/SelectioB.h>
52 #include <Xm/Protocols.h>
53 #include <Xm/SeparatoG.h>
54 #include <Xm/DialogS.h>
55 #include <Xm/PanedW.h>
56 #include <Xm/LabelG.h>
57 #include <Xm/Scale.h>
58 #include <Xm/DrawingA.h>
59 
60 #include <Inventor/Xt/SoXt.h>
61 //#include <Inventor/Xt/SoXtInternal.h>
62 #include <Inventor/Xt/SoXtCursor.h>
63 #include <Inventor/events/SoKeyboardEvent.h>
64 #include <Inventor/events/SoMouseButtonEvent.h>
65 #include <Inventor/events/SoLocation2Event.h>
66 #include <Inventor/nodes/SoSeparator.h>
67 #include <Inventor/nodes/SoOrthographicCamera.h>
68 #include <Inventor/nodes/SoPerspectiveCamera.h>
69 #include <Inventor/nodes/SoEventCallback.h>
70 #include <Inventor/nodes/SoLineSet.h>
71 #include <Inventor/nodes/SoMaterial.h>
72 #include <Inventor/errors/SoDebugError.h>
73 #include <Inventor/SoPickedPoint.h>
74 #include <Inventor/actions/SoWriteAction.h>
75 
77 #include "wheelmouse.h" // To use mouse scrolling in dialogs
78 #include "SoXtInternal.h"
79 #include <Inventor/sensors/SoTimerSensor.h> // Animation
80 #include <Inventor/sensors/SoNodeSensor.h> // Detect start of run
81 #include "saveViewPt.h"
82 #include "console.h"
83 #include "favorites.h"
84 
85 #include "Geant4_SoPolyhedron.h"
86 //#include "G4RunManager.hh"
87 //#include "G4Run.hh"
88 #include "G4TrajectoryPoint.hh"
89 #include "G4AttHolder.hh"
90 #include "G4AttCheck.hh"
91 
92 #include <Inventor/nodes/SoCallback.h>
93 #include <Inventor/nodes/SoSwitch.h>
94 #include <Inventor/nodes/SoScale.h>
95 #include <Inventor/nodes/SoTranslation.h>
96 #include <Inventor/actions/SoSearchAction.h>
97 #include <Inventor/actions/SoGetBoundingBoxAction.h>
98 
99 #include <Inventor/nodes/SoCoordinate3.h>
100 // For rendering distance during animation:
101 #include <Inventor/nodes/SoText2.h>
102 #include <Inventor/nodes/SoFont.h>
103 #include <Inventor/nodes/SoPointSet.h>
104 #include <Inventor/nodes/SoDrawStyle.h>
105 #include <Inventor/nodes/SoBaseColor.h>
106 
107 // For searching for nodes within kits:
108 #include <Inventor/nodekits/SoBaseKit.h>
109 
110 G4OpenInventorXtExaminerViewer* G4OpenInventorXtExaminerViewer::viewer = 0;
111 
112 static const char* thisClassName = "G4OpenInventorXtExaminerViewer";
113 
114 #define MIN_SPEED 2.1 // Lower number means faster
115 #define START_STEP 0.3
116 #define SPEED_INDICATOR_STEP 0.045
117 #define MAX_SPEED_INDICATOR 0.81
118 // Number of steps 90 degree rotation around an element is split into
119 #define ROT_CNT 6
120 
121 // Public constructor
123  const char *name, SbBool embed,
124  SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type) :
125  SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
126 {
127 // Tell GLWidget not to build just yet
128  this->constructor(TRUE);
129 }
130 
131 // Protected constructor for classes deriving from this viewer.
133  const char *name, SbBool embed,
134  SoXtFullViewer::BuildFlag flag, SoXtViewer::Type type,
135  SbBool build) :
136  SoXtExaminerViewer(parent, name, embed, flag, type, FALSE)
137 {
138  this->constructor(build);
139 }
140 
141 // Called by all constructors to set up widgets and initialize member fields.
142 void G4OpenInventorXtExaminerViewer::constructor(const SbBool build)
143 {
144  setClassName(thisClassName);
145 
146  hookBeamOn = new HookEventProcState(this);
147  this->newEvents = false;
148 
149  fileName = ".bookmarkFile"; // Default viewpoint file name
150  viewPtIdx = -1; // index of the most recent viewpoint in viewPtList vector
151  animateSensor = new SoTimerSensor(
152  G4OpenInventorXtExaminerViewer::animateSensorCB, this);
153  animateSensorRotation = new SoTimerSensor(
154  G4OpenInventorXtExaminerViewer::animateSensorRotationCB, this);
155  animateBtwPtsPeriod = MIN_SPEED;
156  currentState = GENERAL;
157  myCam = new SoPerspectiveCamera;
158  MAX_VP_IDX = 3;
159  MAX_VP_NAME = 35; // Max length of a viewpoint name, padded with spaces
160  rotCnt = ROT_CNT; // For 90 degree rotations
161  curViewPtName = new char[MAX_VP_NAME + 1];
162  left_right = up_down = 0; // For movements around the beam during animation
163  speedStep = START_STEP; // For smoother animation speed increase/decrease
164  rotUpVec = false; // Used during scene element rotations
165  step = 1; //By default
166  // Used for moving along the beam with the
167  // mouse instead of rotating the view
168  lshiftdown = rshiftdown = false;
169  // Used for rotating the view with the camera
170  // staying in place
171  lctrldown = rctrldown = false;
172  // Used to send abbreviated output to the console when
173  abbrOutputFlag = false;
174  pickRefPathFlag = false;
175  prevColorField = NULL;
176  warningFlag = false; // We come from the warning dialog
177  viewer = this;
178  openFileDialog = newFileDialog = listsDialog = (Widget) NULL;
179  loadRefCoordsDialog = saveRefCoordsDialog = NULL;
180  loadSceneGraphDialog = saveSceneGraphDialog = NULL;
181  myElementList = NULL;
182 
183  newSceneGraph = NULL;
184  zcoordSetFlag = false;
185 
187  searcher = NULL;
188  // Used in animation; progressively scaled for gradual speed change
189  maxSpeed = 0.0f;
190 
191  static const char * superimposed[] = {
192  "#Inventor V2.1 ascii", "",
193  "Separator ",
194  "{",
195  " MaterialBinding ",
196  " {",
197  " value OVERALL",
198  " }",
199  " OrthographicCamera ",
200  " {",
201  " height 1",
202  " nearDistance 0",
203  " farDistance 1",
204  " }",
205  " DEF soxt->callback Callback { }",
206  " Separator ",
207  " {",
208  " DEF soxt->translation Translation ",
209  " {",
210  " translation 0 0 0",
211  " }",
212  " DEF soxt->scale Scale ",
213  " {",
214  " scaleFactor 1 1 1",
215  " }",
216  " DEF soxt->geometry Coordinate3 ",
217  " {",
218  " point ",
219  " [",
220  " -0.81 -0.04 0, -0.81 0 0,",
221  " -0.81 0.04 0, 0 -0.04 0,",
222  " 0 0 0, 0 0.04 0,",
223  " 0.81 -0.04 0, 0.81 0 0,",
224  " 0.81 0.04 0,",
225  " 0 0.02 0,", // idx 9
226  " 0.81 0.02 0, 0.81 -0.02 0,",
227  " 0 -0.02 0,",
228  " 0 0.01 0,", // idx 13
229  " 0.4 0.01 0, 0.4 -0.01 0,",
230  " 0 -0.01 0",
231  " ]",
232  " }",
233  // current speed indicator (outline)
234  " DEF soxt->animSpeedOutlineSwitch Switch ",
235  " {",
236  " whichChild -3",
237  " Material ",
238  " {",
239  " emissiveColor 0 0 0",
240  " }",
241  " IndexedFaceSet ",
242  " {",
243  " coordIndex ",
244  " [",
245  " 12, 11, 10, 9, -1",
246  " ]",
247  " }",
248  " }",
249  // the coordinate system
250  " DEF soxt->axisSwitch Switch ",
251  " {",
252  " whichChild -3",
253  " BaseColor ",
254  " {",
255  " rgb 1 1 1",
256  " }",
257  " IndexedLineSet ",
258  " {",
259  " coordIndex ",
260  " [",
261  " 0, 2, -1,",
262  " 3, 5, -1,",
263  " 6, 8, -1,",
264  " 1, 7, -1",
265  " ]",
266  " }",
267  " }",
268  // current speed indicator
269  " DEF soxt->animSpeedSwitch Switch ",
270  " {",
271  " whichChild -3",
272  " Material ",
273  " {",
274  " emissiveColor 0 1 0",
275  " }",
276  " IndexedFaceSet ",
277  " {",
278  " coordIndex ",
279  " [",
280  " 16, 15, 14, 13, -1",
281  " ]",
282  " }",
283  " }",
284  " }",
285  // For displaying either z position (during animation) or current viewpoint name
286  " DEF soxt->curInfoSwitch Switch ",
287  " {",
288  " whichChild -3",
289  " DEF soxt->curInfoTrans Translation ",
290  " {",
291  " translation 10 20 30 ",
292  " }",
293  " DEF soxt->curInfoFont Font ",
294  " {",
295  " name defaultFont:Bold",
296  " size 16",
297  " }",
298  " DEF soxt->curInfoText Text2 ",
299  " {",
300  " string Hello",
301  " }",
302  " }",
303  // Need to use different fields for mouseover
304  // because newlines are ignored when the scene is rendered
305  " Separator ",
306  " {",
307  " DEF soxt->mouseOverTransLogName Translation ",
308  " {",
309  " translation 0 0 0 ",
310  " }",
311  " DEF soxt->mouseOverFontLogName Font ",
312  " {",
313  " name defaultFont:Bold",
314  " size 16",
315  " }",
316  " DEF soxt->mouseOverTextLogName Text2 { } ",
317  " }",
318  " Separator ",
319  " {",
320  " DEF soxt->mouseOverTransSolid Translation ",
321  " {",
322  " translation 0 0 0 ",
323  " }",
324  " DEF soxt->mouseOverFontSolid Font ",
325  " {",
326  " name defaultFont:Bold",
327  " size 16",
328  " }",
329  " DEF soxt->mouseOverTextSolid Text2 { } ",
330  " }",
331  " Separator ",
332  " {",
333  " DEF soxt->mouseOverTransMaterial Translation ",
334  " {",
335  " translation 0 0 0 ",
336  " }",
337  " DEF soxt->mouseOverFontMaterial Font ",
338  " {",
339  " name defaultFont:Bold",
340  " size 16",
341  " }",
342  " DEF soxt->mouseOverTextMaterial Text2 { } ",
343  " }",
344  " Separator ",
345  " {",
346  " DEF soxt->mouseOverTransZPos Translation ",
347  " {",
348  " translation 0 0 0 ",
349  " }",
350  " DEF soxt->mouseOverFontZPos Font ",
351  " {",
352  " name defaultFont:Bold",
353  " size 16",
354  " }",
355  " DEF soxt->mouseOverTextZPos Text2 { } ",
356  " }",
357  "}", NULL
358  };
359 
360  int i, bufsize;
361  for (i = bufsize = 0; superimposed[i]; i++)
362  bufsize += strlen(superimposed[i]) + 1;
363  char * buf = new char[bufsize + 1];
364  for (i = bufsize = 0; superimposed[i]; i++) {
365  strcpy(buf + bufsize, superimposed[i]);
366  bufsize += strlen(superimposed[i]);
367  buf[bufsize] = '\n';
368  bufsize++;
369  }
370  SoInput * input = new SoInput;
371  input->setBuffer(buf, bufsize);
372  SbBool ok = SoDB::read(input, this->superimposition);
373  (void)ok; // FWJ added to avoid compiler warning
374  assert(ok);
375  delete input;
376  delete[] buf;
377  this->superimposition->ref();
378 
379  this->sscale = (SoScale *) this->getSuperimpositionNode(
380  this->superimposition, "soxt->scale");
381  this->stranslation = (SoTranslation *) this->getSuperimpositionNode(
382  this->superimposition, "soxt->translation");
383  this->sgeometry = (SoCoordinate3 *) this->getSuperimpositionNode(
384  this->superimposition, "soxt->geometry");
385  this->axisSwitch = (SoSwitch *) this->getSuperimpositionNode(
386  this->superimposition, "soxt->axisSwitch");
387  this->animSpeedOutlineSwitch = (SoSwitch *) this->getSuperimpositionNode(
388  this->superimposition, "soxt->animSpeedOutlineSwitch");
389  this->animSpeedSwitch = (SoSwitch *) this->getSuperimpositionNode(
390  this->superimposition, "soxt->animSpeedSwitch");
391  this->curInfoSwitch = (SoSwitch *) this->getSuperimpositionNode(
392  this->superimposition, "soxt->curInfoSwitch");
393  this->curInfoTrans = (SoTranslation *) this->getSuperimpositionNode(
394  this->superimposition, "soxt->curInfoTrans");
395  this->curInfoFont = (SoFont *) this->getSuperimpositionNode(
396  this->superimposition, "soxt->curInfoFont");
397  this->curInfoText = (SoText2 *) this->getSuperimpositionNode(
398  this->superimposition, "soxt->curInfoText");
399  this->mouseOverTransLogName = (SoTranslation*)this->getSuperimpositionNode(
400  this->superimposition, "soxt->mouseOverTransLogName");
401  this->mouseOverFontLogName = (SoFont *) this->getSuperimpositionNode(
402  this->superimposition, "soxt->mouseOverFontLogName");
403  this->mouseOverTextLogName = (SoText2 *) this->getSuperimpositionNode(
404  this->superimposition, "soxt->mouseOverTextLogName");
405  this->mouseOverTransSolid = (SoTranslation *) this->getSuperimpositionNode(
406  this->superimposition, "soxt->mouseOverTransSolid");
407  this->mouseOverFontSolid = (SoFont *) this->getSuperimpositionNode(
408  this->superimposition, "soxt->mouseOverFontSolid");
409  this->mouseOverTextSolid = (SoText2 *) this->getSuperimpositionNode(
410  this->superimposition, "soxt->mouseOverTextSolid");
411  this->mouseOverTransMaterial = (SoTranslation*)this->getSuperimpositionNode(
412  this->superimposition, "soxt->mouseOverTransMaterial");
413  this->mouseOverFontMaterial = (SoFont *) this->getSuperimpositionNode(
414  this->superimposition, "soxt->mouseOverFontMaterial");
415  this->mouseOverTextMaterial = (SoText2 *) this->getSuperimpositionNode(
416  this->superimposition, "soxt->mouseOverTextMaterial");
417  this->mouseOverTransZPos = (SoTranslation *) this->getSuperimpositionNode(
418  this->superimposition, "soxt->mouseOverTransZPos");
419  this->mouseOverFontZPos = (SoFont *) this->getSuperimpositionNode(
420  this->superimposition, "soxt->mouseOverFontZPos");
421  this->mouseOverTextZPos = (SoText2 *) this->getSuperimpositionNode(
422  this->superimposition, "soxt->mouseOverTextZPos");
423 
424  SoCallback * cb = (SoCallback *) this->getSuperimpositionNode(
425  this->superimposition, "soxt->callback");
426  cb->setCallback(superimpositionCB, this);
427 
428  this->addSuperimposition(this->superimposition);
429  this->setSuperimpositionEnabled(this->superimposition, FALSE);
430  axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
431  animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
432  animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
433 
435 
436  // Build everything else like the parent viewer does
437  if (build) {
438  Widget w = buildWidget(getParentWidget());
439  setBaseWidget(w);
440 
441  // Make this window a little bigger because of the extra buttons
442  // FWJ but it is already set to 600x600 by vis/open
443  // setSize(SbVec2s(500, 550));
444  }
445 
446 }
447 
448 
449 // Static function that returns the pointer to G4OpenInventorXtExaminerViewer
450 G4OpenInventorXtExaminerViewer *G4OpenInventorXtExaminerViewer::getObject()
451 {
452  if (!viewer)
454  return viewer;
455 }
456 
457 
458 // This method locates a named node in the superimposed or original scene.
459 SoNode *
460 G4OpenInventorXtExaminerViewer::getSuperimpositionNode(SoNode *root,
461  const char * name)
462 {
463  if (!this->searcher)
464  this->searcher = new SoSearchAction;
465  searcher->reset();
466  searcher->setName(SbName(name));
467  searcher->setInterest(SoSearchAction::FIRST);
468  searcher->setSearchingAll(TRUE);
469  searcher->apply(root);
470  assert(searcher->getPath());
471  return searcher->getPath()->getTail();
472 }
473 
474 
475 void G4OpenInventorXtExaminerViewer::superimpositionCB(void * closure,
476  SoAction * action)
477 {
478  if (closure)
479  ((G4OpenInventorXtExaminerViewer*)closure)->superimpositionEvent(action);
480 }
481 
482 
483 // Renders and positions speed indicator and longitudinal
484 // distance/viewpoint name on the drawing canvas
485 void G4OpenInventorXtExaminerViewer::superimpositionEvent(SoAction * action)
486 {
487 
488  if (!action->isOfType(SoGLRenderAction::getClassTypeId()))
489  return;
490  SbViewportRegion vpRegion =
491  ((SoGLRenderAction *) action)->getViewportRegion();
492  SbVec2s viewportSize = vpRegion.getViewportSizePixels();
493 
494  float aspect = float(viewportSize[0]) / float(viewportSize[1]);
495  float factorx = 1.0f / float(viewportSize[1]) * 220.0f;
496  float factory = factorx;
497 
498  if (aspect > 1.0f) {
499  this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
500  } else {
501  this->stranslation->translation.setValue(
502  SbVec3f(0.0f, -0.4f / aspect, 0.0f));
503  factorx /= aspect;
504  factory /= aspect;
505  }
506  if (viewportSize[0] > 500)
507  factorx *= 500.0f / 400.0f;
508  else
509  factorx *= float(viewportSize[0]) / 400.0f;
510  this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
511 
512  float xInfo, yInfo, xMouseLogName, yMouseLogName, xMouseSolid, yMouseSolid,
513  xMouseMaterial, yMouseMaterial, xMouseZPos, yMouseZPos;
514  xInfo = -.45;
515  yInfo = .45;
516  xMouseLogName = 0.0;
517  yMouseLogName = -.75;
518  xMouseSolid = 0.0;
519  yMouseSolid = -.78;
520  xMouseMaterial = 0.0;
521  yMouseMaterial = -.81;
522  xMouseZPos = 0.0;
523  yMouseZPos = -.84;
524 
525  if (aspect > 1.0f) {
526  xInfo *= aspect;
527  xMouseSolid *= aspect;
528  xMouseMaterial *= aspect;
529  this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
530  this->mouseOverTransLogName->translation.setValue(
531  SbVec3f(xMouseLogName, yMouseLogName, 0.0));
532  this->mouseOverTransSolid->translation.setValue(
533  SbVec3f(xMouseSolid, yMouseSolid, 0.0));
534  this->mouseOverTransMaterial->translation.setValue(
535  SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
536  this->mouseOverTransZPos->translation.setValue(
537  SbVec3f(xMouseZPos, yMouseZPos, 0.0));
538  } else {
539  yInfo /= aspect;
540  yMouseSolid /= aspect;
541  yMouseMaterial /= aspect;
542  this->curInfoTrans->translation.setValue(SbVec3f(xInfo, yInfo, 0.0));
543  this->mouseOverTransLogName->translation.setValue(
544  SbVec3f(xMouseLogName, yMouseLogName, 0.0));
545  this->mouseOverTransSolid->translation.setValue(
546  SbVec3f(xMouseSolid, yMouseSolid, 0.0));
547  this->mouseOverTransMaterial->translation.setValue(
548  SbVec3f(xMouseMaterial, yMouseMaterial, 0.0));
549  this->mouseOverTransZPos->translation.setValue(
550  SbVec3f(xMouseZPos, yMouseZPos, 0.0));
551  }
552 
553  if (currentState == VIEWPOINT) { // Displaying viewpoint name
554  this->curInfoFont->size.setValue(15);
555  this->curInfoFont->name.setValue("defaultFont:Italic");
556  this->curInfoText->string.setValue(SbString(curViewPtName));
557  }
558  else if(currentState == GENERAL) { // Displaying longitudinal distance
559  this->curInfoFont->size.setValue(16);
560  this->curInfoFont->name.setValue("defaultFont:Bold");
561  this->curInfoText->string.setValue(SbString(""));
562  }
563  else {
564  if (refParticleIdx < (int) refParticleTrajectory.size() - 1) {
565  this->curInfoFont->size.setValue(16);
566  this->curInfoFont->name.setValue("defaultFont:Bold");
567 
568  char zPos[20];
569  sprintf(zPos, "%7.2f [m]", refZPositions[refParticleIdx] / 1000);
570 
571  this->curInfoText->string.setValue(SbString(zPos));
572  }
573  }
574 }
575 
576 
578 {
579  if (superimposition != NULL) {
580  removeSuperimposition(superimposition);
581  superimposition->unref();
582  superimposition = NULL;
583  }
584  if (animateSensor->isScheduled())
585  animateSensor->unschedule();
586  delete animateSensor;
587  delete sceneChangeSensor;
588 
589  delete[] curViewPtName;
590  delete searcher;
591 
592  viewer = 0;
593 }
594 
595 
596 // Adds a menu bar and a few menu items to the viewer.
598 {
599  Widget shell;
600  Atom WM_DELETE_WINDOW;
601 
602  if (!parent)
603  SoDebugError::post("G4OpenInventorXtExaminerViewer::buildWidget", "Error: Parent is null.");
604 
605  Arg args[10];
606  XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
607  XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
608  XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
609  XtSetArg(args[3], XmNbottomAttachment, XmATTACH_FORM);
610  Widget form = XmCreateForm(parent, (char *) "Form", args, 4);
611  XtManageChild(form);
612 
613  shell = XtParent(form);
614  WM_DELETE_WINDOW = XInternAtom(XtDisplay(parent), "WM_DELETE_WINDOW",
615  False);
616  XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW,
617  (XtCallbackProc)closeMainWindowCB, this);
618 
619  XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
620  XtSetArg(args[1], XmNleftAttachment, XmATTACH_FORM);
621  XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
622  menuBar = XmCreateMenuBar(form, (char *) "MenuBar", args, 3);
623  XtManageChild(menuBar);
624 
625  fileMenu = addMenu("File");
626  this->addButton(fileMenu, "Open Viewpoint File...", openViewPtFileCB);
627  addButton(fileMenu, "New Viewpoint File", newViewPtFileCB);
628  addButton(fileMenu, "Load Ref. Coords", loadRefCoordsDialogCB);
629  addButton(fileMenu, "Save Ref. Coords", saveRefCoordsDialogCB);
630  addButton(fileMenu, "Load Scene Graph", loadSceneGraphDialogCB);
631  addButton(fileMenu, "Save Scene Graph", saveSceneGraphDialogCB);
632  XtManageChild(
633  XmCreateSeparatorGadget(fileMenu, (char *) "Separator", NULL, 0));
634 
635  Widget menu = addMenu("Tools");
636  addButton(menu, "Animate Ref. Particle", animateRefParticleCB);
637  addButton(menu, "Go to start of Ref path", gotoRefPathStartCB);
638  addButton(menu, "Invert Ref path", invertRefPathCB);
639 
640  Widget viewerBase = SoXtFullViewer::buildWidget(form);
641 
642  XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
643  XtSetArg(args[1], XmNtopWidget, menuBar);
644  XtSetArg(args[2], XmNleftAttachment, XmATTACH_FORM);
645  XtSetArg(args[3], XmNrightAttachment, XmATTACH_FORM);
646  XtSetArg(args[4], XmNbottomAttachment, XmATTACH_FORM);
647  XtSetValues(viewerBase, args, 5);
648 
649  return viewerBase;
650 }
651 
652 
653 // Adds a new menu to menuBar
655 {
656  Arg args[1];
657  Widget menu = XmCreatePulldownMenu(menuBar, (char *) name.c_str(), NULL, 0);
658 
659  XtSetArg(args[0], XmNsubMenuId, menu);
660  Widget w = XmCreateCascadeButton(menuBar, (char *) name.c_str(), args, 1);
661  XtManageChild(w);
662 
663  return menu;
664 }
665 
666 
667 // Adds a new button to menu
668 void G4OpenInventorXtExaminerViewer::addButton(Widget menu, std::string name,
669  XtCallbackProc cb)
670 {
671  Widget button = XmCreatePushButton(menu, (char *) name.c_str(), NULL, 0);
672  XtManageChild(button);
673  XtAddCallback(button, XmNactivateCallback, cb, this);
674 }
675 
676 
677 // Overloaded for saving of and browsing through viewpoints.
679  SbPList * buttonlist)
680 {
681  int n;
682  Arg args[6];
683  Widget saveViewPtButton, abbrOutputButton, pickRefPathButton;
684 
685  // Create original buttons
686  SoXtExaminerViewer::createViewerButtons(parent, buttonlist);
687 
688  // Handle disappearing button caused by SoXtExaminerViewer::setCamera
689  Widget emptyButton = XtVaCreateManagedWidget("", xmPushButtonWidgetClass,
690  parent, NULL);
691  buttonlist->append(emptyButton);
692 
693  // Left arrow that goes back one view point on click
694  n = 0;
695  XtSetArg(args[n], XmNtopPosition, 1); n++;
696  XtSetArg(args[n], XmNbottomPosition, 2); n++;
697  XtSetArg(args[n], XmNleftPosition, 0); n++;
698  XtSetArg(args[n], XmNrightPosition, 1); n++;
699  XtSetArg(args[n], XmNarrowDirection, XmARROW_LEFT); n++;
700  XtSetArg(args[n], XmNsensitive, False); n++;
701  prevViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowL",
702  args, n);
703  XtManageChild(prevViewPtButton);
704  XtAddCallback(prevViewPtButton, XmNactivateCallback,
705  G4OpenInventorXtExaminerViewer::prevViewPtCB, this);
706  buttonlist->append(prevViewPtButton);
707 
708  // Right arrow that goes forward one view point on click
709  n = 0;
710  XtSetArg(args[n], XmNtopPosition, 1); n++;
711  XtSetArg(args[n], XmNbottomPosition, 2); n++;
712  XtSetArg(args[n], XmNleftPosition, 0); n++;
713  XtSetArg(args[n], XmNrightPosition, 1); n++;
714  XtSetArg(args[n], XmNarrowDirection, XmARROW_RIGHT); n++;
715  XtSetArg(args[n], XmNsensitive, False); n++;
716  nextViewPtButton = XmCreateArrowButtonGadget(parent, (char *) "ArrowR",
717  args, n);
718  XtManageChild(nextViewPtButton);
719  XtAddCallback(nextViewPtButton, XmNactivateCallback,
720  G4OpenInventorXtExaminerViewer::nextViewPtCB, this);
721  buttonlist->append(nextViewPtButton);
722 
723  // Save button for storing current camera parameters
724  saveViewPtButton = XtVaCreateManagedWidget("Save", xmPushButtonWidgetClass,
725  parent, NULL);
726  XtAddCallback(saveViewPtButton, XmNactivateCallback,
727  G4OpenInventorXtExaminerViewer::saveViewPtCB, this);
728  Pixmap saveVP, saveVP_ins;
729  saveVP = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
730  saveViewPt_xpm);
731  saveVP_ins = SoXtInternal::createPixmapFromXpm(saveViewPtButton,
732  saveViewPt_xpm, TRUE);
733  XtVaSetValues(saveViewPtButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
734  saveVP, XmNselectPixmap, saveVP, XmNlabelInsensitivePixmap,
735  saveVP_ins, XmNselectInsensitivePixmap, saveVP_ins, NULL);
736  buttonlist->append(saveViewPtButton);
737 
738  // Toggle button to get abbreviated output
739  abbrOutputButton = XtVaCreateManagedWidget("Abbr",
740  xmToggleButtonWidgetClass, parent, XmNindicatorOn, False, NULL);
741  XtAddCallback(abbrOutputButton, XmNdisarmCallback, G4OpenInventorXtExaminerViewer::abbrOutputCB,
742  this);
743  Pixmap consolexpm, consolexpm_ins;
744  consolexpm = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
745  console_xpm);
746  consolexpm_ins = SoXtInternal::createPixmapFromXpm(abbrOutputButton,
747  console_xpm, TRUE);
748  XtVaSetValues(abbrOutputButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
749  consolexpm, XmNselectPixmap, consolexpm, XmNlabelInsensitivePixmap,
750  consolexpm_ins, XmNselectInsensitivePixmap, consolexpm_ins, NULL);
751  buttonlist->append(abbrOutputButton);
752 
753  // Button for selecting the beam that will act as reference path
754  pickRefPathButton = XtVaCreateManagedWidget("Refpath", xmPushButtonWidgetClass,
755  parent, NULL);
756  XtAddCallback(pickRefPathButton, XmNactivateCallback,
757  G4OpenInventorXtExaminerViewer::pickRefPathCB, this);
758  Pixmap favoritesxpm, favoritesxpm_ins;
759  favoritesxpm = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
760  favorites_xpm);
761  favoritesxpm_ins = SoXtInternal::createPixmapFromXpm(pickRefPathButton,
762  favorites_xpm, TRUE);
763  XtVaSetValues(pickRefPathButton, XmNlabelType, XmPIXMAP, XmNlabelPixmap,
764  favoritesxpm, XmNselectPixmap, favoritesxpm, XmNlabelInsensitivePixmap,
765  favoritesxpm_ins, XmNselectInsensitivePixmap, favoritesxpm_ins, NULL);
766  buttonlist->append(pickRefPathButton);
767 
768 }
769 
770 
771 // Called right after buttons and widgets get realized.
772 // It sets the viewpoint last accessed.
774 {
775  SoXtExaminerViewer::afterRealizeHook();
776 
777  // Default height is used when selecting and viewing scene elements
778  // FWJ Added defaultHeight for Ortho camera
779  SoCamera *cam = getCamera();
780  if (cam) {
781  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
782  defaultHeightAngle =
783  ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
784  toggleCameraType();
785  defaultHeight =
786  ((SoOrthographicCamera *) cam)->height.getValue();
787  toggleCameraType();
788  } else {
789  defaultHeight =
790  ((SoOrthographicCamera *) cam)->height.getValue();
791  toggleCameraType();
792  cam = getCamera();
793  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
794  defaultHeightAngle =
795  ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
796  toggleCameraType();
797  }
798  }
799 
800  // Open the default bookmark file
801  fileIn.open(fileName.c_str());
802  if (!fileIn.fail()) {
803  if (!loadViewPts()) {
804  String dialogName = (char *) "Error Loading File";
805  std::string msg = "Wrong or corrupted input file.";
806  warningMsgDialog(msg, dialogName, NULL);
807  } else {
808  // Opens a file without erasing it
809  fileOut.open(fileName.c_str(), std::ios::in);
810  fileOut.seekp(0, std::ios::end); // For appending new data to the end
811  constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
812 
813  if (viewPtList.size()) {
814  // FWJ disabled auto-selection of first viewpoint.
815  // Initial view should be user-controllable & not forced
816  // setViewPt();
817  XtSetSensitive(nextViewPtButton, True);
818  XtSetSensitive(prevViewPtButton, True);
819  }
820  }
821 
822  fileIn.close();
823  } else {
824  // Creates a new default bookmark file
825  fileOut.open(fileName.c_str());
826  constructListsDialog(getParentWidget(), this, NULL); // Pop up listsDialog
827  }
828 
829  fileIn.clear();
830 
831  SoSeparator *root = (SoSeparator *) (getSceneManager()->getSceneGraph());
832  if (root == NULL)
833  SoDebugError::post("G4OpenInventorXtExaminerViewer::afterRealizeHook", "Root is null.");
834  else {
835  root->addChild(myCam); // For position/orientation calculation during animation
836  }
837 
838  sceneChangeSensor = new SoNodeSensor;
839  sceneChangeSensor->setFunction(sceneChangeCB);
840  sceneChangeSensor->attach(root);
841  sceneChangeSensor->setData(this);
842 
843  // Monitor mouseover events for displaying the name of scene elements
844  // An SoEventCallback is needed instead of using the default processSoEvent
845  // because that last one does not provide us with an SoPath to the object
846  // that was picked
847  SoEventCallback *moCB = new SoEventCallback;
848  moCB->addEventCallback(
849  SoLocation2Event::getClassTypeId(),
850  mouseoverCB, static_cast<void *>(this));
851  root->addChild(moCB);
852 
853  // Override the default picking mechanism present in G4OpenInventorViewer
854  // because we want abbreviated output when picking a trajectory
855  SoEventCallback *pickCB = new SoEventCallback;
856  pickCB->addEventCallback(
857  SoMouseButtonEvent::getClassTypeId(),
858  pickingCB, static_cast<void *>(this));
859  root->addChild(pickCB);
860 
861 }
862 
863 
864 // Rotates camera 90 degrees around a scene element.
865 // Rotation is animated for smoothness.
867 {
868  SoCamera *cam = getCamera();
869 
870  SbRotation rot(rotAxis, M_PI / (2 * ROT_CNT));
871  rot.multVec(camDir, camDir);
872  rot.multVec(camUpVec, camUpVec);
873 
874  SbVec3f camPosNew = prevPt - (camDir*distance);
875  cam->position = camPosNew;
876  cam->pointAt(prevPt, camUpVec);
877  cam->focalDistance = (prevPt - camPosNew).length();
878 
879  rotCnt--;
880 
881  if (animateSensorRotation->isScheduled()) {
882  animateSensorRotation->unschedule();
883  }
884 
885  animateSensorRotation->setBaseTime(SbTime::getTimeOfDay());
886  animateSensorRotation->setInterval(SbTime(0.02));
887  animateSensorRotation->schedule();
888 
889 }
890 
891 
892 // Slides camera along the beamline.
893 void G4OpenInventorXtExaminerViewer::moveCamera(float dist, bool lookdown)
894 {
895 
896  SoCamera *cam = getCamera();
897  SbVec3f p1, p2; // The particle moves from p1 to p2
898  SbVec3f particleDir; // Direction vector from p1 to p2
899  SbVec3f camPosNew; // New position of the camera
900 
901  if(refParticleTrajectory.size() == 0) {
902  //refParticleTrajectory hasn't been set yet
903  if(dist)
904  distance = dist;
905  else
906  distance = (cam->position.getValue() - center).length();
907 
908  cam->position.setValue(center + offsetFromCenter*distance);
909  cam->focalDistance = (cam->position.getValue() - center).length();
910  cam->pointAt(center, upVector);
911  }
912  else{
913 
914  // If we move forward past the last trajectory point,
915  // go back to the beginning
916  if (refParticleIdx >= (int) refParticleTrajectory.size() - 1) {
917  prevPt = refParticleTrajectory[refParticleIdx - step];
918  dist = (prevPt - cam->position.getValue()).length();
919  refParticleIdx = 0;
920  }
921  // If we move backward past the beginning,
922  // go to the last trajectory point
923  if (refParticleIdx < 0) {
924  prevPt = refParticleTrajectory[refParticleIdx + step];
925  dist = (prevPt - cam->position.getValue()).length();
926  refParticleIdx = refParticleTrajectory.size() - 2;
927  }
928 
929  // Set start and end points
930  p1 = refParticleTrajectory[refParticleIdx];
931  p2 = refParticleTrajectory[refParticleIdx + step];
932 
933  // Get the direction from p1 to p2
934  particleDir = p2 - p1;
935  particleDir.normalize();
936 
937  if(prevParticleDir == SbVec3f(0,0,0)){
938  // First time entering BEAMLINE mode, look at
939  // the element from the front, with camera upright
940  if(lookdown)
941  camDir = SbVec3f(0,0,1);
942  else
943  camDir = SbVec3f(1,0,0);
944  camUpVec = SbVec3f(0,1,0);
945 
946  // In case the start of the goes in a
947  // direction other than +z, rotate the camera accordingly
948  SbRotation rot(SbVec3f(0,0,1), particleDir);
949  rot.multVec(camDir, camDir);
950  rot.multVec(camUpVec, camUpVec);
951 
952  }
953  else if(particleDir != prevParticleDir) {
954  // The beamline has changed direction
955 
956  SbRotation rot(prevParticleDir, particleDir);
957  rot.multVec(camDir, camDir);
958  rot.multVec(camUpVec, camUpVec);
959 
960  }
961 
962  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
963  if (!dist)
964  distance = (prevPt - cam->position.getValue()).length();
965  else
966  distance = dist;
967  }
968 
969  if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
970  if (!dist)
971  distance = (prevPt - cam->position.getValue()).length();
972  else
973  distance = dist;
974  }
975 
976 
977  float x,y,z;
978  prevPt.getValue(x,y,z);
979 
980 
981  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
982  camPosNew = p2 - (camDir*distance);
983  }
984  if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
985  camPosNew = p2 - (camDir);
986  }
987 
988  cam->position = camPosNew;
989  cam->pointAt(p2, camUpVec);
990  // FWJ Disabled: zooms out the Persp camera much too far
991  // and can't recover by zooming in!
992  // cam->focalDistance = (p2 - camPosNew).length();
993 
994  p2.getValue(x,y,z);
995  camPosNew.getValue(x,y,z);
996 
997  prevParticleDir = particleDir;
998  prevPt = p1; // For accurate distance calculation
999 
1000  }
1001 
1002 }
1003 
1004 
1005 void G4OpenInventorXtExaminerViewer::pickingCB(void *aThis,
1006  SoEventCallback *eventCB)
1007 {
1008  SoHandleEventAction* action = eventCB->getAction();
1009  const SoPickedPoint *pp = action->getPickedPoint();
1011 
1012  if(pp != NULL) {
1013 
1014  SoPath* path = pp->getPath();
1015  SoNode* node = ((SoFullPath*)path)->getTail();
1016 
1017  if(node->getTypeId() == SoLineSet::getClassTypeId()){
1018 
1019  if(This->pickRefPathFlag){
1020  This->pickRefPathFlag = false;
1021  if(This->viewingBeforePickRef != This->isViewing())
1022  This->setViewing(This->viewingBeforePickRef);
1023  else
1024  This->setComponentCursor(SoXtCursor(SoXtCursor::DEFAULT));
1025 
1026  // The trajectory is a set of lines stored in a LineSet
1027  SoLineSet * trajectory = (SoLineSet *)node;
1028 
1029  // The set of all trajectories is stored in a Seperator group node
1030  // one level above the LineSet that was picked. The nodes under that
1031  // seperator are as follows (in this order): Material, LightModel,
1032  // ResetTransform, MatrixTransform, Coordinate3, DrawStyle, LineSet
1033  SoSeparator * grpNode =
1034  (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
1035 
1036  // The node that contains the coordinates for the trajectory is a
1037  // Coordinate3 node which occurs before the LineSet node. We iterate
1038  // back through the nodes in the group until we find the Coordinate3 node
1039  int nodeIndex = grpNode->findChild(trajectory);
1040  SoNode * tmpNode;
1041  // FWJ needs initialization
1042  SoCoordinate3 * coords = 0;
1043  // SoCoordinate3 * coords;
1044  // We allow only 100 iterations, in case the node isn't found
1045  // (should take only a few iterations)
1046  for(int i = 0; i < 100; ++i) {
1047  --nodeIndex;
1048 
1049  tmpNode = grpNode->getChild(nodeIndex);
1050  if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
1051  //node found
1052  coords = (SoCoordinate3 *)tmpNode;
1053  break;
1054  }
1055  }
1056 
1057  if(coords == NULL){
1058  String dialogName = (char *) "No coordinates";
1059  std::string msg = "Could not find the coordinates node"
1060  " for the picked trajectory."
1061  " Reference trajectory not set";
1062  This->warningMsgDialog(msg, dialogName, NULL);
1063  return;
1064  }
1065 
1066 
1067  if ((This->lshiftdown) || (This->rshiftdown))
1068  This->setReferencePath(trajectory, coords, true);
1069  else
1070  This->setReferencePath(trajectory, coords, false);
1071 
1072  return;
1073 
1074  }
1075  else if(This->abbrOutputFlag) {
1076 
1077  G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
1078  if(attHolder && attHolder->GetAttDefs().size()) {
1079 
1080  std::string strTrajPoint = "G4TrajectoryPoint:";
1081  std::ostringstream oss;
1082  for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
1083  G4cout << G4AttCheck(attHolder->GetAttValues()[i],
1084  attHolder->GetAttDefs()[i]);
1085  oss << G4AttCheck(attHolder->GetAttValues()[i],
1086  attHolder->GetAttDefs()[i]);
1087  if(oss.str().find(strTrajPoint) != std::string::npos) {
1088 
1089  // Last attribute displayed was a trajectory point. Since we
1090  // want abbreviated output, display the last one and exit
1091  // (unless we're already at the last (and only) trajectory point)
1092  if(i != attHolder->GetAttDefs().size()-1) {
1093  G4cout << G4AttCheck(
1094  attHolder->GetAttValues()[attHolder->GetAttDefs().size()-1],
1095  attHolder->GetAttDefs()[attHolder->GetAttDefs().size()-1]);
1096  }
1097  break;
1098  }
1099  }
1100  } else {
1101  G4String name((char*)node->getName().getString());
1102  G4String cls((char*)node->getTypeId().getName().getString());
1103  G4cout << "SoNode : " << node
1104  << " SoType : " << cls
1105  << " name : " << name
1106  << G4endl;
1107  G4cout << "No attributes attached." << G4endl;
1108  }
1109 
1110  return;
1111  }
1112  else{
1113  //Go to default behavior
1114  }
1115  }
1116  else {
1117  //Go to default behavior
1118  }
1119 
1120  // Default behavior in G4OpenInventorViewer::SelectionCB
1121  G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
1122  if(attHolder && attHolder->GetAttDefs().size()) {
1123  for (size_t i = 0; i < attHolder->GetAttDefs().size(); ++i) {
1124  G4cout << G4AttCheck(attHolder->GetAttValues()[i],
1125  attHolder->GetAttDefs()[i]);
1126  }
1127  } else {
1128  G4String name((char*)node->getName().getString());
1129  G4String cls((char*)node->getTypeId().getName().getString());
1130  G4cout << "SoNode : " << node
1131  << " SoType : " << cls
1132  << " name : " << name
1133  << G4endl;
1134  G4cout << "No attributes attached." << G4endl;
1135  }
1136 
1137  //Suppress other event handlers
1138  eventCB->setHandled();
1139  }
1140 }
1141 
1142 
1143 void G4OpenInventorXtExaminerViewer::mouseoverCB(void *aThis, SoEventCallback *eventCB)
1144 {
1145  SoHandleEventAction* action = eventCB->getAction();
1146  const SoPickedPoint *pp = action->getPickedPoint();
1148 
1149  if(!This->abbrOutputFlag)
1150  return;
1151 
1152  if(pp != NULL) {
1153 
1154  const SbViewportRegion & viewportRegion = action->getViewportRegion();
1155 
1156  std::string sLogName;
1157  float x,y,z;
1158  std::stringstream ssZPos;
1159  std::stringstream ssSolids;
1160  std::stringstream ssMaterials;
1161  SoPath * path = pp->getPath();
1162  SoNode* node = ((SoFullPath*)path)->getTail();
1163 
1164  if(node->getTypeId() == Geant4_SoPolyhedron::getClassTypeId()) {
1165 
1166  sLogName = "Logical Volume: ";
1167  sLogName += ((Geant4_SoPolyhedron *)node)->getName().getString();
1168 
1169  SoGetBoundingBoxAction bAction(viewportRegion);
1170  bAction.apply((SoFullPath*)path);
1171  SbBox3f bBox = bAction.getBoundingBox();
1172  SbVec3f center = bBox.getCenter();
1173  center.getValue(x,y,z);
1174  ssZPos << "Pos: " << x << " " << y << " " << z;
1175 
1176  G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(node);
1177  if(attHolder && attHolder->GetAttDefs().size()) {
1178 
1179  std::vector<const std::map<G4String,G4AttDef>*> vecDefs =
1180  attHolder->GetAttDefs();
1181  std::vector<const std::vector<G4AttValue>*> vecVals =
1182  attHolder->GetAttValues();
1183  for (size_t i = 0; i < vecDefs.size(); ++i) {
1184  const std::vector<G4AttValue> * vals = vecVals[i];
1185 
1186  std::vector<G4AttValue>::const_iterator iValue;
1187 
1188  for (iValue = vals->begin(); iValue != vals->end(); ++iValue) {
1189  const G4String& valueName = iValue->GetName();
1190  const G4String& value = iValue->GetValue();
1191 
1192  if(valueName == "Solid") {
1193  if(ssSolids.str() == "")
1194  ssSolids << "Solid Name: " << value;
1195  else
1196  ssSolids << ", " << value;
1197  }
1198 
1199  if(valueName == "Material") {
1200  if(ssMaterials.str() == "")
1201  ssMaterials << "Material Name: " << value;
1202  else
1203  ssMaterials << ", " << value;
1204  }
1205  }
1206  }
1207  }
1208  }
1209 
1210  bool redraw = false;
1211  if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != sLogName) {
1212  This->mouseOverTextLogName->string.setValue(SbString(sLogName.c_str()));
1213  redraw = true;
1214  }
1215  if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != ssSolids.str()) {
1216  This->mouseOverTextSolid->string.setValue(SbString(ssSolids.str().c_str()));
1217  redraw = true;
1218  }
1219  if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != ssMaterials.str()){
1220  This->mouseOverTextMaterial->string.setValue(SbString(ssMaterials.str().c_str()));
1221  redraw = true;
1222  }
1223  if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != ssZPos.str()) {
1224  This->mouseOverTextZPos->string.setValue(SbString(ssZPos.str().c_str()));
1225  redraw = true;
1226  }
1227 
1228  if(redraw) {
1229  This->setSuperimpositionEnabled(This->superimposition, TRUE);
1230  This->scheduleRedraw();
1231  }
1232 
1233  eventCB->setHandled();
1234  }
1235  else {
1236  if(std::string(This->mouseOverTextLogName->string.getValues(0)->getString()) != "") {
1237  This->mouseOverTextLogName->string.setValue(SbString(""));
1238  This->scheduleRedraw();
1239  }
1240  if(std::string(This->mouseOverTextSolid->string.getValues(0)->getString()) != "") {
1241  This->mouseOverTextSolid->string.setValue(SbString(""));
1242  This->scheduleRedraw();
1243  }
1244  if(std::string(This->mouseOverTextMaterial->string.getValues(0)->getString()) != "") {
1245  This->mouseOverTextMaterial->string.setValue(SbString(""));
1246  This->scheduleRedraw();
1247  }
1248  if(std::string(This->mouseOverTextZPos->string.getValues(0)->getString()) != "") {
1249  This->mouseOverTextZPos->string.setValue(SbString(""));
1250  This->scheduleRedraw();
1251  }
1252  }
1253 }
1254 
1255 
1256 SbBool G4OpenInventorXtExaminerViewer::processSoEvent(const SoEvent * const ev) {
1257  SoCamera *cam = getCamera();
1258  const SoType type(ev->getTypeId());
1259 
1260  if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
1261  SoMouseButtonEvent * me = (SoMouseButtonEvent *) ev;
1262 
1263  if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
1264  || currentState == PAUSED_ANIMATION) {
1265  switch (me->getButton()) {
1266  case SoMouseButtonEvent::BUTTON4: // Scroll wheel up
1267  if (me->getState() == SoButtonEvent::DOWN) {
1268  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
1269  float hAngle =
1270  ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
1271  ((SoPerspectiveCamera *) cam)->heightAngle = hAngle
1272  + 0.01f;
1273  return TRUE;
1274  } else if (cam->isOfType(
1275  SoOrthographicCamera::getClassTypeId())) {
1276  float height =
1277  ((SoOrthographicCamera *) cam)->height.getValue();
1278  ((SoOrthographicCamera *) cam)->height = height + 5;
1279  return TRUE;
1280  }
1281  }
1282  break;
1283  case SoMouseButtonEvent::BUTTON5: // Scroll wheel down
1284  if (me->getState() == SoButtonEvent::DOWN) {
1285  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
1286  float hAngle =
1287  ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
1288  if (hAngle > 0.01)
1289  ((SoPerspectiveCamera *) cam)->heightAngle = hAngle
1290  - 0.01f;
1291  return TRUE;
1292  } else if (cam->isOfType(
1293  SoOrthographicCamera::getClassTypeId())) {
1294  float height =
1295  ((SoOrthographicCamera *) cam)->height.getValue();
1296  if (height > 5)
1297  ((SoOrthographicCamera *) cam)->height = height - 5;
1298  return TRUE;
1299  }
1300  }
1301  break;
1302  default:
1303  break;
1304  }
1305  }
1306  if (currentState == GENERAL) {
1307 
1308  }
1309  }
1310 
1311  if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
1312  SoKeyboardEvent * ke = (SoKeyboardEvent *) ev;
1313 
1314  if (SoKeyboardEvent::isKeyPressEvent(ev, ke->getKey())) {
1315  switch (ke->getKey()) {
1316  case SoKeyboardEvent::LEFT_SHIFT:
1317  this->lshiftdown = true;
1318  return TRUE;
1319  case SoKeyboardEvent::RIGHT_SHIFT:
1320  this->rshiftdown = true;
1321  return TRUE;
1322  case SoKeyboardEvent::LEFT_CONTROL:
1323  this->lctrldown = true;
1324  return TRUE;
1325  case SoKeyboardEvent::RIGHT_CONTROL:
1326  this->rctrldown = true;
1327  return TRUE;
1328  case SoKeyboardEvent::SPACE:
1329  if (currentState == ANIMATION
1330  || currentState == REVERSED_ANIMATION) {
1331  beforePausing = currentState;
1332  currentState = PAUSED_ANIMATION;
1333  if (animateSensor->isScheduled())
1334  animateSensor->unschedule();
1335  return TRUE;
1336  } else if (currentState == PAUSED_ANIMATION) {
1337  if (maxSpeed) {
1338  if ((beforePausing == ANIMATION
1339  && refParticleIdx
1340  < (int) refParticleTrajectory.size() - 1)
1341  || (beforePausing == REVERSED_ANIMATION
1342  && refParticleIdx > 0)) {
1343  currentState = beforePausing;
1344  animateRefParticle();
1345  }
1346  }
1347  return TRUE;
1348  }
1349  break;
1350  case SoKeyboardEvent::ESCAPE:
1351  if (currentState == ANIMATION
1352  || currentState == REVERSED_ANIMATION
1353  || currentState == PAUSED_ANIMATION) {
1354 
1355  if (animateSensor->isScheduled())
1356  animateSensor->unschedule();
1357  currentState = prevState;
1358  refParticleIdx = prevRefIdx;
1359  setSuperimpositionEnabled(superimposition, FALSE);
1360  maxSpeed = 0.0f;
1361  step = 1;
1362 
1363  scheduleRedraw();
1364  if (currentState == VIEWPOINT) {
1365  setSuperimpositionEnabled(superimposition, TRUE);
1366  axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
1367  animSpeedOutlineSwitch->whichChild.setValue(
1368  SO_SWITCH_NONE);
1369  animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
1370 
1371  scheduleRedraw();
1372  }
1373  restoreCamera();
1374  return TRUE;
1375  }
1376  break;
1377  case SoKeyboardEvent::DELETE:
1378  if (viewPtList.size()
1379  && (currentState != ANIMATION
1380  || currentState != REVERSED_ANIMATION
1381  || currentState != PAUSED_ANIMATION)) {
1382  String dialogName = (char *) "Delete Viewpoint";
1383  std::string msg = "Are you sure you want to delete current viewpoint?";
1384  warningMsgDialog(msg, dialogName, deleteViewPtCB);
1385  return TRUE;
1386  }
1387  break;
1388  case SoKeyboardEvent::LEFT_ARROW:
1389  switch (currentState) {
1390  case BEAMLINE:
1391  if ((this->lshiftdown) || (this->rshiftdown)){
1392  refParticleIdx -= step;
1393  moveCamera();
1394  }
1395  else if ((this->lctrldown) || (this->rctrldown)){
1396  if (SoXtExaminerViewer::isAnimating())
1397  stopAnimating();
1398  prevState = currentState;
1399  currentState = ROTATING;
1400  animateBtwPtsPeriod = 0.08f;
1401 
1402  SbVec3f tmp = camDir;
1403  tmp.negate();
1404  rotAxis = tmp;
1405 
1406  rotCnt = ROT_CNT;
1407  moveCamera(); // To make sure camera is perpendicular to the beamline
1408 
1409  rotateCamera();
1410  }
1411  else{
1412  if (SoXtExaminerViewer::isAnimating())
1413  stopAnimating();
1414  prevState = currentState;
1415  currentState = ROTATING;
1416  animateBtwPtsPeriod = 0.08f;
1417 
1418  SbVec3f tmp = camUpVec;
1419  tmp.negate();
1420  rotAxis = tmp;
1421 
1422  rotCnt = ROT_CNT;
1423  moveCamera(); // To make sure camera is perpendicular to the beamline
1424 
1425  rotateCamera();
1426 
1427  }
1428  return TRUE;
1429 
1430  case ANIMATION:
1431  case REVERSED_ANIMATION:
1432  left_right -= 1.5f;
1433  return TRUE;
1434  case PAUSED_ANIMATION:
1435  left_right -= 1.5f;
1436  setStartingPtForAnimation();
1437  cam->position = myCam->position;
1438  return TRUE;
1439  case GENERAL:
1440  case VIEWPOINT:
1441  if ((!this->lshiftdown) && (!this->rshiftdown)) {
1442  // Using this allows us to look around without
1443  // changing the camera parameters (camDir, camUpVec)
1444  this->bottomWheelMotion(
1445  this->getBottomWheelValue() + 0.1f);
1446 
1447  return TRUE;
1448  }
1449  break;
1450  case ROTATING:
1451  // For this state, let the keyboard event
1452  // be handled by superclass
1453  break;
1454  default:
1455  SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
1456  "Unhandled viewer state");
1457  break;
1458  }
1459  break;
1460 
1461  case SoKeyboardEvent::RIGHT_ARROW:
1462  switch(currentState){
1463  case BEAMLINE:
1464  if ((this->lshiftdown) || (this->rshiftdown)){
1465  refParticleIdx += step;
1466  moveCamera();
1467  }
1468  else if ((this->lctrldown) || (this->rctrldown)){
1469  if (SoXtExaminerViewer::isAnimating())
1470  stopAnimating();
1471  prevState = currentState;
1472  currentState = ROTATING;
1473  animateBtwPtsPeriod = 0.08f;
1474 
1475  rotAxis = camDir;
1476 
1477  rotCnt = ROT_CNT;
1478  moveCamera(); // To make sure camera is perpendicular to the beamline
1479 
1480  rotateCamera();
1481  }
1482  else{
1483  if (SoXtExaminerViewer::isAnimating())
1484  stopAnimating();
1485  prevState = currentState;
1486  currentState = ROTATING;
1487  animateBtwPtsPeriod = 0.08f;
1488 
1489  rotAxis = camUpVec;
1490 
1491  rotCnt = ROT_CNT;
1492  moveCamera(); // To make sure camera is perpendicular to the beamline
1493 
1494  rotateCamera();
1495  }
1496  return TRUE;
1497 
1498  case ANIMATION:
1499  case REVERSED_ANIMATION:
1500  left_right += 1.5f;
1501  return TRUE;
1502  case PAUSED_ANIMATION:
1503  left_right += 1.5f;
1504  setStartingPtForAnimation();
1505  cam->position = myCam->position;
1506  return TRUE;
1507  case GENERAL:
1508  case VIEWPOINT:
1509  if ((!this->lshiftdown) && (!this->rshiftdown)) {
1510  // Using this allows us to look around without
1511  // changing the camera parameters (camDir, camUpVec)
1512  this->bottomWheelMotion(
1513  this->getBottomWheelValue() - 0.1f);
1514  return TRUE;
1515  }
1516  break;
1517  case ROTATING:
1518  // For this state, let the keyboard event
1519  // be handled by superclass
1520  break;
1521  default:
1522  SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
1523  "Unhandled viewer state");
1524  break;
1525  }
1526  break;
1527 
1528  case SoKeyboardEvent::DOWN_ARROW:
1529  switch(currentState){
1530  case BEAMLINE:
1531 
1532  if ((this->lshiftdown) || (this->rshiftdown)){
1533  refParticleIdx -= step;
1534  moveCamera();
1535  }
1536  else{
1537  if (SoXtExaminerViewer::isAnimating())
1538  stopAnimating();
1539  prevState = currentState;
1540  currentState = ROTATING;
1541  animateBtwPtsPeriod = 0.08f;
1542 
1543  rotAxis = camDir.cross(camUpVec);
1544 
1545  rotCnt = ROT_CNT;
1546  moveCamera(); // To make sure camera is perpendicular to the beamline
1547 
1548  rotateCamera();
1549 
1550  }
1551  return TRUE;
1552 
1553  case ANIMATION:
1554  case REVERSED_ANIMATION:
1555  up_down -= 1.5f;
1556  return TRUE;
1557  case PAUSED_ANIMATION:
1558  up_down -= 1.5f;
1559  setStartingPtForAnimation();
1560  cam->position = myCam->position;
1561  return TRUE;
1562  case GENERAL:
1563  case VIEWPOINT:
1564  // Using this allows us to look around without
1565  // changing the camera parameters (camDir, camUpVec)
1566  if ((!this->lshiftdown) && (!this->rshiftdown)) {
1567  this->leftWheelMotion(this->getLeftWheelValue() - 0.1f);
1568  return TRUE;
1569  }
1570  break;
1571  case ROTATING:
1572  // For this state, let the keyboard event
1573  // be handled by superclass
1574  break;
1575  default:
1576  SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
1577  "Unhandled viewer state");
1578  break;
1579  }
1580  break;
1581 
1582  case SoKeyboardEvent::UP_ARROW:
1583  switch(currentState){
1584  case BEAMLINE:
1585  if ((this->lshiftdown) || (this->rshiftdown)){
1586  refParticleIdx -= step;
1587  moveCamera();
1588  }
1589  else{
1590  if (SoXtExaminerViewer::isAnimating())
1591  stopAnimating();
1592  prevState = currentState;
1593  currentState = ROTATING;
1594  animateBtwPtsPeriod = 0.08f;
1595 
1596  rotAxis = camUpVec.cross(camDir);
1597 
1598  rotCnt = ROT_CNT;
1599  moveCamera();
1600 
1601  rotateCamera();
1602 
1603 
1604  }
1605  return TRUE;
1606  case ANIMATION:
1607  case REVERSED_ANIMATION:
1608  up_down += 1.5f;
1609  return TRUE;
1610  case PAUSED_ANIMATION:
1611  up_down += 1.5f;
1612  setStartingPtForAnimation();
1613  cam->position = myCam->position;
1614  return TRUE;
1615  case GENERAL:
1616  case VIEWPOINT:
1617  // Using this allows us to look around without
1618  // changing the camera parameters (camDir, camUpVec)
1619  if ((!this->lshiftdown) && (!this->rshiftdown)) {
1620  this->leftWheelMotion(this->getLeftWheelValue() + 0.1f);
1621  return TRUE;
1622  }
1623  break;
1624  case ROTATING:
1625  // For this state, let the keyboard event
1626  // be handled by superclass
1627  break;
1628  default:
1629  SoDebugError::post("G4OpenInventorXtExaminerViewer::processSoEvent",
1630  "Unhandled viewer state");
1631  break;
1632  }
1633  break;
1634 
1635  case SoKeyboardEvent::PAGE_UP:
1636  switch(currentState){
1637  case BEAMLINE:
1638  if (step < (int) refParticleTrajectory.size() / 5) // Magic number
1639  step++;
1640  return TRUE;
1641  case ANIMATION:
1642  incSpeed();
1643  maxSpeed += SPEED_INDICATOR_STEP;
1644  if (maxSpeed > 0.8)
1645  maxSpeed = MAX_SPEED_INDICATOR;
1646  scheduleRedraw();
1647 
1648  return TRUE;
1649  case REVERSED_ANIMATION:
1650  if(!animateSensor->isScheduled()){
1651  currentState = ANIMATION;
1652  if (refParticleIdx
1653  < (int) refParticleTrajectory.size() - 1) {
1654  refParticleIdx++;
1655  maxSpeed = SPEED_INDICATOR_STEP;
1656  scheduleRedraw();
1657  animateRefParticle();
1658  }
1659  }
1660  else{
1661  maxSpeed += SPEED_INDICATOR_STEP;
1662  decSpeed();
1663  scheduleRedraw();
1664  }
1665  return TRUE;
1666  case PAUSED_ANIMATION:
1667  maxSpeed += SPEED_INDICATOR_STEP;
1668  if (maxSpeed > 0.8)
1669  maxSpeed = MAX_SPEED_INDICATOR;
1670 
1671  if (beforePausing == ANIMATION) {
1672  incSpeed();
1673  } else {
1674  decSpeed();
1675  if (animateBtwPtsPeriod >= MIN_SPEED)
1676  beforePausing = ANIMATION;
1677  }
1678 
1679  scheduleRedraw();
1680  return TRUE;
1681  default: //fall through
1682  break;
1683  }
1684  break;
1685 
1686  case SoKeyboardEvent::PAGE_DOWN:
1687  switch(currentState){
1688  case BEAMLINE:
1689  if (step > 1)
1690  step--;
1691  return TRUE;
1692  case ANIMATION:
1693  if(!animateSensor->isScheduled()){
1694  currentState = REVERSED_ANIMATION;
1695  if (refParticleIdx > 1) {
1696  refParticleIdx--;
1697  maxSpeed = -SPEED_INDICATOR_STEP;
1698  scheduleRedraw();
1699  animateRefParticle();
1700  }
1701  }
1702  else{
1703  maxSpeed -= SPEED_INDICATOR_STEP;
1704  decSpeed();
1705  scheduleRedraw();
1706  }
1707  return TRUE;
1708  case REVERSED_ANIMATION:
1709  incSpeed();
1710  maxSpeed -= SPEED_INDICATOR_STEP;
1711  if (maxSpeed < -0.8)
1712  maxSpeed = -MAX_SPEED_INDICATOR;
1713  scheduleRedraw();
1714  return TRUE;
1715  case PAUSED_ANIMATION:
1716  maxSpeed -= SPEED_INDICATOR_STEP;
1717  if (maxSpeed < -0.8)
1718  maxSpeed = -MAX_SPEED_INDICATOR;
1719  if (beforePausing == REVERSED_ANIMATION) {
1720  incSpeed();
1721  } else {
1722  decSpeed();
1723  if (animateBtwPtsPeriod >= MIN_SPEED)
1724  beforePausing = REVERSED_ANIMATION;
1725  }
1726  scheduleRedraw();
1727  return TRUE;
1728  default:
1729  //fall through
1730  break;
1731  }
1732  break;
1733 
1734  case SoKeyboardEvent::E:
1735  this->escapeCallback(this->examinerObject);
1736  break;
1737 
1738  default:
1739  break; // To get rid of compiler warnings
1740  }
1741  }
1742  if (SoKeyboardEvent::isKeyReleaseEvent(ev, ke->getKey())) {
1743  switch (ke->getKey()) {
1744  case SoKeyboardEvent::LEFT_SHIFT:
1745  this->lshiftdown = false;
1746  return TRUE;
1747  case SoKeyboardEvent::RIGHT_SHIFT:
1748  this->rshiftdown = false;
1749  return TRUE;
1750  case SoKeyboardEvent::LEFT_CONTROL:
1751  this->lctrldown = false;
1752  return TRUE;
1753  case SoKeyboardEvent::RIGHT_CONTROL:
1754  this->rctrldown = false;
1755  return TRUE;
1756  default:
1757  break;
1758  }
1759  }
1760  }
1761 
1762  if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
1763  || currentState == ROTATING)
1764  return FALSE;
1765  else
1766  return SoXtExaminerViewer::processSoEvent(ev);
1767 }
1768 
1769 // Called by hitting PageUp during animation.
1770 void G4OpenInventorXtExaminerViewer::incSpeed() {
1771  if (std::ceil(animateBtwPtsPeriod * 100) >= 4) {
1772  if (speedStep > 0.08)
1773  speedStep -= 0.02;
1774  else
1775  speedStep = 0.02;
1776  animateBtwPtsPeriod -= speedStep;
1777  } else
1778  animateBtwPtsPeriod = 0.0;
1779 
1780  if (currentState != PAUSED_ANIMATION) {
1781  int lastIdx = refParticleTrajectory.size() - 1;
1782  if (refParticleIdx < lastIdx && !animateSensor->isScheduled())
1783  animateRefParticle();
1784  }
1785 }
1786 
1787 // Called by hitting PageDown during animation.
1788 void G4OpenInventorXtExaminerViewer::decSpeed() {
1789  animateBtwPtsPeriod += speedStep;
1790  if (animateBtwPtsPeriod < MIN_SPEED) {
1791  if (std::floor(animateBtwPtsPeriod * 100) == 12) { // Errors in double representation
1792  speedStep = 0.08;
1793  } else if (animateBtwPtsPeriod > 0.12)
1794  speedStep += 0.02;
1795  } else {
1796  animateBtwPtsPeriod = MIN_SPEED;
1797  speedStep = START_STEP;
1798  maxSpeed = 0.0f;
1799  if (animateSensor->isScheduled())
1800  animateSensor->unschedule();
1801  }
1802 }
1803 
1804 // Based on the user's interaction the speed indicator bar needs to be adjusted.
1805 void G4OpenInventorXtExaminerViewer::updateSpeedIndicator(void) {
1806  assert(this->sgeometry != NULL);
1807 
1808  SbVec3f * points = this->sgeometry->point.startEditing();
1809 
1810  if (points[10][0] == 0.0f)
1811  this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
1812  if (points[14][0] == 0.0f)
1813  this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
1814  points[10][0] = this->maxSpeed;
1815  points[11][0] = this->maxSpeed;
1816  points[14][0] = this->maxSpeed;
1817  points[15][0] = this->maxSpeed;
1818  this->sgeometry->point.finishEditing();
1819 
1820  if (this->maxSpeed == 0.0f) {
1821  this->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
1822  this->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
1823  }
1824 }
1825 
1826 void G4OpenInventorXtExaminerViewer::actualRedraw(void) {
1827  switch (currentState) {
1828  case ANIMATION:
1829  case REVERSED_ANIMATION:
1830  case PAUSED_ANIMATION:
1831  updateSpeedIndicator();
1832  SoXtExaminerViewer::actualRedraw();
1833  break;
1834  default:
1835  SoXtExaminerViewer::actualRedraw();
1836  break;
1837  }
1838 }
1839 
1840 void G4OpenInventorXtExaminerViewer::setReferencePath(SoLineSet *lineset, SoCoordinate3 *coords, bool append)
1841 {
1842  // TODO: Color the reference path
1843  // Disable the color stuff for now: changes all trajectories
1844 
1845 // // We change the color of the trajectory too, so we get its material
1846 // nodeIndex = grpNode->findChild(trajectory);
1847 // SoMaterial * mat;
1848 // for(int i = 0; i < 100; ++i){
1849 // --nodeIndex;
1850 //
1851 // tmpNode = grpNode->getChild(nodeIndex);
1852 // if(tmpNode->getTypeId() == SoMaterial::getClassTypeId()){
1853 // //node found
1854 // mat = (SoMaterial *)tmpNode;
1855 //
1856 // break;
1857 // }
1858 // }
1859 //
1860 //
1861 // // Restore default color for previously picked trajectory
1862 // // and set different color for current pick
1863 // if(This->prevColorField)
1864 // ((SoMFColor *)This->prevColorField)->setValue(0.0, 1.0, 0.0);
1865 // This->prevColorField = (void *)&mat->diffuseColor;
1866 //
1867 //
1868 // if(mat->diffuseColor.isConnected())
1869 // std::cout << "connected" << std::endl;
1870 //
1871 // mat->diffuseColor.setValue(41.0/255.0, 230.0/255.0, 230.0/255.0);
1872 //
1873 // std::cout << "R: " << mat->diffuseColor[0][0] << " ";
1874 // std::cout << "G: " << mat->diffuseColor[0][1] << " ";
1875 // std::cout << "B: " << mat->diffuseColor[0][2] << std::endl;
1876 
1877  // The trajectory is composed of all the polyline segments in the
1878  // multiple value field (SoMFInt32) numVertices.
1879  // For each of the numVertices.getNum()* polyline segments,
1880  // retrieve the points from the SoCoordinate3 node
1881  SbVec3f refParticlePt;
1882 
1883  if(!append)
1884  this->refParticleTrajectory.clear();
1885 
1886  for(int i = 0; i < lineset->numVertices.getNum(); ++i){
1887  for(int j = 0; j < lineset->numVertices[i]; ++j){
1888  refParticlePt = coords->point[j];
1889  this->refParticleTrajectory.push_back(refParticlePt);
1890  }
1891  }
1892  // Remove points that are too close to each other
1893  this->evenOutRefParticlePts();
1894  this->setReferencePathZPos();
1895  this->sortElements();
1896 }
1897 
1898 
1899 void G4OpenInventorXtExaminerViewer::setReferencePathZPos()
1900 {
1901  refZPositions.clear();
1902  refZPositions.push_back(0);
1903  float dist;
1904  for(unsigned int i=0; i < this->refParticleTrajectory.size() - 1; ++i){
1905  dist = (refParticleTrajectory[i] -
1906  refParticleTrajectory[i + 1]).length();
1907  refZPositions.push_back(refZPositions[i] + dist);
1908  }
1909 }
1910 
1911 
1912 void G4OpenInventorXtExaminerViewer::findAndSetRefPath()
1913 {
1914  SoSearchAction action;
1915  action.setType(SoLineSet::getClassTypeId(),false);
1916  action.setInterest(SoSearchAction::ALL);
1917  action.apply(this->getSceneGraph());
1918 
1919  SoPathList &pathList = action.getPaths();
1920 
1921  if(pathList.getLength() != 0){
1922 
1923  SoCoordinate3 * coords = NULL;
1924  std::vector<SoCoordinate3 *> coordvec;
1925  std::vector<SoLineSet *> linevec;
1926 
1927  bool refPathFound = false;
1928  for(int i = 0; i < pathList.getLength(); ++i) {
1929  SoFullPath *path = (SoFullPath *)pathList[i];
1930 
1931  G4AttHolder* attHolder = dynamic_cast<G4AttHolder*>(path->getTail());
1932  for (size_t j = 0; j < attHolder->GetAttDefs().size(); ++j) {
1933  std::ostringstream oss;
1934  oss << G4AttCheck(attHolder->GetAttValues()[j], attHolder->GetAttDefs()[j]);
1935 
1936  std::string findStr = "Type of trajectory (Type): ";
1937  std::string compareValue = "REFERENCE";
1938  size_t idx = oss.str().find(findStr);
1939 
1940  if(idx != std::string::npos) {
1941  if(oss.str().substr(idx + findStr.size(), compareValue.size()) == compareValue) {
1942  coords = this->getCoordsNode(path);
1943  if(coords != NULL){
1944  refPathFound = true;
1945  coordvec.push_back(coords);
1946  linevec.push_back((SoLineSet *)path->getTail());
1947  }
1948  break;
1949  }
1950  }
1951 
1952  findStr = "Track ID (ID): ";
1953  idx = oss.str().find(findStr);
1954  if(idx != std::string::npos) {
1955  //index all primary tracks
1956  std::string tmpstr = oss.str().substr(idx + findStr.size(),1);
1957  std::istringstream buffer(tmpstr);
1958  int num;
1959  buffer >> num;
1960  if(num == 1) {
1961 
1962  // Check if next character is a number,
1963  // in which case we don't have Track ID 1
1964  const char * nextChar =
1965  oss.str().substr(idx + findStr.size() + 1,1).c_str();
1966  if(std::isdigit(nextChar[0]))
1967  break; //Not a primary track, continue with next track
1968 
1969  coords = this->getCoordsNode(path);
1970  if(coords != NULL){
1971  coordvec.push_back(coords);
1972  linevec.push_back((SoLineSet *)path->getTail());
1973  break; //Found coords node, continue with next track
1974  }
1975  }
1976  else
1977  break; //Not a primary track, continue with next track
1978  }
1979  else{
1980  //Not a Track ID attribute, fall through
1981  }
1982  }
1983 
1984  if(refPathFound)
1985  break;
1986  }
1987 
1988  if(coordvec.empty())
1989  return; //No track with a Coordinate3 node found
1990 
1991  if(refPathFound){
1992  //set ref path to last traj, coord in the vecs
1993  this->setReferencePath(linevec.back(), coordvec.back());
1994  return;
1995  }
1996  //else
1997 
1998  int longestIdx = 0;
1999  float longestLength = 0.0;
2000  // For all paths
2001  for(unsigned int i=0;i < linevec.size(); ++i){
2002 
2003  //First generate a vector with all the points in this lineset
2004  std::vector<SbVec3f> trajectory;
2005  // For all lines in the i path
2006  for(int j=0; j < linevec[i]->numVertices.getNum(); ++j){
2007  // For all points in line j
2008  for(int k=0; k < linevec[i]->numVertices[j]; ++k){
2009  trajectory.push_back(coordvec[i]->point[k]);
2010  }
2011  }
2012 
2013  // Then calculate the total length
2014  float tmpLength=0.0;
2015  for(unsigned int j=0; j < trajectory.size() - 1; ++j){
2016  tmpLength += (trajectory[j] - trajectory[j + 1]).length();
2017  }
2018 
2019  if(tmpLength > longestLength){
2020  longestIdx = i;
2021  longestLength = tmpLength;
2022  }
2023  }
2024 
2025  // Set the longest path as the reference path
2026  this->setReferencePath(linevec[longestIdx], coordvec[longestIdx]);
2027  }
2028 }
2029 
2030 
2031 SoCoordinate3 * G4OpenInventorXtExaminerViewer::getCoordsNode(SoFullPath *path)
2032 {
2033  SoLineSet *trajectory = (SoLineSet *)path->getTail();
2034  SoSeparator * grpNode = (SoSeparator*)(((SoFullPath*)path)->getNodeFromTail(1));
2035  int nodeIndex = grpNode->findChild(trajectory);
2036  SoNode * tmpNode;
2037 
2038  // We allow only 100 iterations, in case the node isn't found
2039  // (should take only a few iterations)
2040  for(int i = 0; i < 100; ++i){
2041  --nodeIndex;
2042 
2043  tmpNode = grpNode->getChild(nodeIndex);
2044  if(tmpNode->getTypeId() == SoCoordinate3::getClassTypeId()){
2045  //node found
2046  return (SoCoordinate3 *)tmpNode;
2047  }
2048  }
2049  return NULL; //coords node not found
2050 }
2051 
2052 
2053 // Displays scene elements on the right side of listsDialog.
2054 // else: scene graph is searched for Geant4_SoPolyhedron type nodes
2055 void G4OpenInventorXtExaminerViewer::getSceneElements()
2056 {
2057  std::string field, eltName;
2058 
2059  std::map<std::string, int> duplicates;
2060  std::map<std::string, int> sceneElts;
2061  SoSearchAction search;
2062  Geant4_SoPolyhedron *node;
2063  SoGroup *root = (SoGroup *)getSceneManager()->getSceneGraph();
2064 
2065  SoBaseKit::setSearchingChildren(TRUE);
2066 
2067  search.reset();
2068  search.setSearchingAll(TRUE);
2069  search.setInterest(SoSearchAction::ALL);
2070  search.setType(Geant4_SoPolyhedron::getClassTypeId(), 0);
2071  search.apply(root);
2072 
2073  SoPathList &pl = search.getPaths();
2074 
2075 
2076  // First find which names occur more than once so we can append a counter to them
2077  for(int i = 0; i < pl.getLength(); i++) {
2078  SoFullPath *path = (SoFullPath *)pl[i];
2079  node = (Geant4_SoPolyhedron *)path->getTail();
2080  eltName = node->getName();
2081  if(duplicates.count(eltName))
2082  duplicates[eltName]++;
2083  else
2084  duplicates[eltName] = 1;
2085  }
2086 
2087  for(int i = 0; i < pl.getLength(); i++) {
2088  float x,y,z;
2089  std::stringstream ssCount;
2090  SoFullPath *path = (SoFullPath *)pl[i];
2091  node = (Geant4_SoPolyhedron *)path->getTail();
2092  eltName = node->getName();
2093  field = eltName;
2094  if(duplicates[eltName] == 1)
2095  ssCount << "";//duplicates[field]
2096  else {
2097  if(sceneElts.count(eltName))
2098  sceneElts[eltName]++;
2099  else
2100  sceneElts[eltName] = 1;
2101 
2102  ssCount << sceneElts[eltName];
2103  field += "_";
2104  }
2105 
2106  field += ssCount.str();
2107 
2108  SoGetBoundingBoxAction bAction(getViewportRegion());
2109  bAction.apply(path);
2110  SbBox3f bBox = bAction.getBoundingBox();
2111 
2112  SbVec3f centr = bBox.getCenter();
2113  centr.getValue(x,y,z);
2114 
2115  path->ref();
2116  sceneElement el = { field, path, centr, 0.0 };
2117  this->sceneElements.push_back(el);
2118  }
2119 }
2120 
2121 
2122 float G4OpenInventorXtExaminerViewer::sqrlen(const SbVec3f &a)
2123 {
2124  float x,y,z;
2125  a.getValue(x,y,z);
2126  return x*x + y*y + z*z;
2127 }
2128 
2129 
2130 void G4OpenInventorXtExaminerViewer::distanceToTrajectory(const SbVec3f &q,
2131  float &dist,
2132  SbVec3f &closestPoint,
2133  int &index)
2134 {
2135  // a : Previous point on trajectory
2136  // b : Next point on trajectory
2137  // q : the point in space
2138  // dab, daq, dbq: distance between a & b, a & q, b & q
2139  //
2140  // Theory: A point p on a line ab is defined as:
2141  //
2142  // p(t) = a+tâ‹…(b–a)
2143  //
2144  // note: All are vectors except the parameter t
2145  //
2146  // When t is between 0 and 1 the point p is situated between a and b on ab.
2147  // The point p is defined in terms of the parameter t, subsequently so does
2148  // the distance from the query point q to the point p. To find the minimum
2149  // of that distance we differentiate it and set equal to zero:
2150  //
2151  // diff(Norm(p(t)- q)) = 0
2152  //
2153  // note: diff means taking the derivative with regard to t
2154  //
2155  // The resulting t is given in the code below. The square of the distance
2156  // between p and q is given by:
2157  //
2158  // d^2 = (Norm(p(t)-q))^2
2159  //
2160  // The expression found is given in the code below (current_dist)
2161  //
2162  // Ref: http://programmizm.sourceforge.net/blog/2012/
2163  // distance-from-a-point-to-a-polyline
2164  //
2165  // --PLG
2166 
2167  const size_t count = this->refParticleTrajectory.size();
2168  assert(count>0);
2169 
2170  SbVec3f b = this->refParticleTrajectory[0];
2171  SbVec3f dbq = b - q;
2172  float sqrDist = sqrlen(dbq);
2173  closestPoint = b;
2174  index = 0;
2175  for (size_t i = 1; i < count; ++i) {
2176  const SbVec3f a = b;
2177  const SbVec3f daq = dbq;
2178  b = this->refParticleTrajectory[i];
2179  dbq = b - q;
2180  const SbVec3f dab = a - b;
2181 
2182  float dab_x, dab_y, dab_z;
2183  dab.getValue(dab_x,dab_y,dab_z);
2184  float daq_x, daq_y, daq_z;
2185  daq.getValue(daq_x, daq_y, daq_z);
2186  float dbq_x, dbq_y, dbq_z;
2187  dbq.getValue(dbq_x, dbq_y, dbq_z);
2188 
2189  const float inv_sqrlen = 1./sqrlen(dab);
2190  const float t = (dab_x*daq_x + dab_y*daq_y + dab_z*daq_z)*inv_sqrlen;
2191 
2192  if (t<0.){
2193  // The trajectory point occurs before point a
2194  // Go to the next point
2195  continue;
2196  }
2197  float current_dist;
2198  if (t<=1.){
2199  // The trajectory point occurs between a and b.
2200  // Compute the distance to that point
2201  current_dist = daq_x*daq_x + daq_y*daq_y + daq_z*daq_z
2202  - t*(daq_x*dab_x + daq_y*dab_y + daq_z*dab_z)
2203  + t*t*(dab_x*dab_x + dab_y*dab_y + dab_z*dab_z);
2204  }
2205  else { //t>1.
2206  // The trajectory point occurs after b.
2207  // Get the distance to point b
2208  current_dist = sqrlen(dbq);
2209  }
2210 
2211  if (current_dist < sqrDist){
2212  sqrDist = current_dist;
2213  closestPoint = a + t*(b-a);
2214  index = i;
2215  }
2216  }
2217 
2218  dist = std::sqrt(sqrDist);
2219 }
2220 
2221 
2222 void G4OpenInventorXtExaminerViewer::sortElements()
2223 {
2224  if(this->refParticleTrajectory.empty())
2225  return;
2226 
2227  float * trajLength = new float[this->refParticleTrajectory.size()];
2228  typedef std::map<elementForSorting, sceneElement> sortedMap;
2229  sortedMap sorted;
2230 
2231  // For every point on the reference trajectory, compute
2232  // the total length from the start
2233  SbVec3f prevPoint;
2234  std::vector<SbVec3f>::iterator itRef = this->refParticleTrajectory.begin();
2235  int trajIndex = 0;
2236  prevPoint = *itRef;
2237  trajLength[trajIndex] = 0.0;
2238  ++itRef;
2239  ++trajIndex;
2240  for(; itRef != this->refParticleTrajectory.end(); ++itRef, ++trajIndex){
2241  trajLength[trajIndex] = trajLength[trajIndex-1] + (*itRef - prevPoint).length();
2242  prevPoint = *itRef;
2243  }
2244 
2245  // Compute the smallest distance between the element
2246  // and the reference trajectory (find the closest point),
2247  // then map the element to the trajectory length of that
2248  // point (calculated above)
2249  SoGetBoundingBoxAction bAction(this->getViewportRegion());
2250  SbVec3f elementCoord;
2251  std::vector<sceneElement>::iterator itEl;
2252  int elementIndex;
2253  elementForSorting el;
2254  for(itEl = this->sceneElements.begin(), elementIndex = 0;
2255  itEl != this->sceneElements.end(); ++itEl, ++elementIndex){
2256  bAction.apply(itEl->path);
2257  elementCoord = bAction.getBoundingBox().getCenter();
2258 
2259  int index;
2260  distanceToTrajectory(elementCoord, el.smallestDistance, el.closestPoint, index);
2261  itEl->closestPointZCoord = el.closestPointZCoord = trajLength[index];
2262  el.distanceToBeamlineStart = (itEl->center - this->refParticleTrajectory[0]).length();
2263 
2264  // This map of the scene elements (or their coordinates rather)
2265  // is automatically sorted by trajectory length (Z coord), then
2266  // by the distance between the element and the point in case the Z coord
2267  // is the same as another element. This is done by using as a key
2268  // an element structure which implements the operator for weak ordering
2269  sorted.insert(std::make_pair(el,*itEl));
2270  }
2271 
2272  // store the sorted elements into the vector field
2273  this->sceneElements.clear();
2274 
2275  sortedMap::iterator itSorted = sorted.begin();
2276  for(; itSorted != sorted.end(); itSorted++)
2277  this->sceneElements.push_back(itSorted->second);
2278 
2279  this->zcoordSetFlag = true;
2280 
2281 
2282  Widget formTop = XtNameToWidget(this->listsDialog, "FormTop");
2283  Widget formTopRight = XtNameToWidget(formTop, "FormTopRight");
2284 
2285  this->createElementsList(formTopRight);
2286 
2287  delete[] trajLength;
2288 }
2289 
2290 
2291 void G4OpenInventorXtExaminerViewer::createElementsList(Widget formTopRight)
2292 {
2293  if(this->myElementList != NULL)
2294  XtUnmanageChild(this->myElementList);
2295 
2296  int size = this->sceneElements.size();
2297  XmString *elements = (XmString *) XtMalloc(size * sizeof(XmString));
2298 
2299  std::vector<sceneElement>::const_iterator it;
2300  int count = 0;
2301  std::stringstream ss;
2302  for(it=this->sceneElements.begin(); it!=this->sceneElements.end(); ++it) {
2303  ss << it->name;
2304  if(zcoordSetFlag)
2305  ss << " [" << it->closestPointZCoord << "]";
2306  elements[count] = XmStringCreateLocalized((char *)ss.str().c_str());
2307  ++count;
2308  ss.str("");
2309  }
2310 
2311  Arg args[10];
2312  int n;
2313 
2314  // Label Right
2315  n = 0;
2316  Widget labelRight;
2317  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
2318 
2319  labelRight = XmCreateLabelGadget(formTopRight, (char*)"Element [S mm]",
2320  args, n);
2321  XtManageChild(labelRight);
2322 
2323  // List Right
2324  n = 0;
2325  XtSetArg(args[n], XmNvisibleItemCount, 7); n++;
2326  XtSetArg(args[n], XmNitemCount, size); n++;
2327  XtSetArg(args[n], XmNitems, elements); n++;
2328  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
2329  XtSetArg(args[n], XmNtopWidget, labelRight); n++;
2330  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
2331  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
2332  XtSetArg(args[n], XmNwidth, 280); n++;
2333  // XtSetArg(args[n], XmNwidth, 300); n++;
2334 
2335  this->myElementList = XmCreateScrolledList(formTopRight, (char *) "ListRight", args, n);
2336 
2337  XtAddCallback(this->myElementList, XmNbrowseSelectionCallback,
2338  (XtCallbackProc) lookAtSceneElementCB, this);
2339  xmAddMouseEventHandler(this->myElementList); // Add scrolling functionality
2340  XtManageChild(this->myElementList);
2341 
2342  if (elements != NULL) {
2343  for (int i = 0; i < size; i++)
2344  XmStringFree(elements[i]);
2345  XtFree((char *) elements);
2346  }
2347 }
2348 
2349 
2350 // Pops up a custom dialog listsDialog containing
2351 // scene elements and viewpoints.
2352 
2353 void G4OpenInventorXtExaminerViewer::constructListsDialog(Widget w,
2354  XtPointer client_data,
2355  XtPointer)
2356 {
2358  if (This->listsDialog) {
2359  return;
2360  }
2361 
2362  if (This->currentState == ANIMATION || This->currentState == PAUSED_ANIMATION) {
2363  if (This->animateSensor->isScheduled())
2364  This->animateSensor->unschedule();
2365  This->refParticleIdx = This->prevRefIdx;
2366  This->restoreCamera();
2367  This->currentState = This->prevState;
2368  }
2369 
2370  This->step = 1; // Default values
2371  This->refParticleIdx = 0;
2372  if (This->refParticleTrajectory.size()){
2373  This->prevPt = This->refParticleTrajectory[0]; // For calculating distance
2374  }
2375 
2376  This->getSceneElements();
2377 
2378  int n = 0;
2379  Arg args[10];
2380  Atom WM_DELETE_WINDOW;
2381 
2383 
2384  Widget topShell;
2385  topShell = SoXt::getShellWidget(This->getParentWidget());
2386 
2387  // Shell Dialog
2388  std::string dialogNameStr = This->fileName.substr(This->fileName.rfind('/') + 1);
2389  char *dialogName = new char[dialogNameStr.size() + 1];
2390  strcpy(dialogName, dialogNameStr.c_str());
2391 
2392  n = 0;
2393  XtSetArg(args[n], XmNx, 610); n++;
2394  This->myShellDialog = XmCreateDialogShell(topShell, dialogName, args, n);
2395 
2396  delete[] dialogName;
2397  WM_DELETE_WINDOW = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", False);
2398  XmAddWMProtocolCallback(This->myShellDialog, WM_DELETE_WINDOW,
2399  (XtCallbackProc)closeListsDialogCB, This);
2400 
2401  // Main Pane(listsDialog)
2402  n = 0;
2403  XtSetArg(args[n], XmNsashWidth, 1); n++;
2404  XtSetArg(args[n], XmNsashHeight, 1); n++;
2405  XtSetArg(args[n], XmNseparatorOn, False); n++;
2406  This->listsDialog = XmCreatePanedWindow(This->myShellDialog, (char *) "MainPane",
2407  args, n);
2408 
2409 
2411  n = 0;
2412  Widget formTop = XmCreateForm(This->listsDialog, (char *) "FormTop", args, n);
2413 
2414  n = 0;
2415  XtSetArg(args[n], XmNmarginWidth, 8); n++;
2416  XtSetArg(args[n], XmNmarginHeight, 8); n++;
2417  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
2418  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
2419  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
2420  Widget formTopRight = XmCreateForm(formTop, (char *) "FormTopRight", args,
2421  n);
2422 
2423  n = 0;
2424  XtSetArg(args[n], XmNmarginWidth, 8); n++;
2425  XtSetArg(args[n], XmNmarginHeight, 8); n++;
2426  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
2427  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2428  XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
2429  XtSetArg(args[n], XmNrightWidget, formTopRight); n++;
2430  XtSetArg(args[n], XmNrightOffset, 10); n++;
2431  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
2432  Widget formTopLeft = XmCreateForm(formTop, (char *) "FormTopLeft", args, n);
2433 
2435 
2436  This->createElementsList(formTopRight);
2437  XtManageChild(formTopRight);
2438 
2440 
2441  // Label Left
2442  n = 0;
2443  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
2444  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2445  Widget labelLeft = XmCreateLabelGadget(formTopLeft, (char *) "ViewPoints",
2446  args, n);
2447  XtManageChild(labelLeft);
2448 
2449  // List Left
2450  n = 0;
2451  XtSetArg(args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
2452  XtSetArg(args[n], XmNvisibleItemCount, 7); n++;
2453  // XtSetArg(args[n], XmNwidth, 140); n++;
2454  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
2455  XtSetArg(args[n], XmNtopWidget, labelLeft); n++;
2456  XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
2457  XtSetArg(args[n], XmNrightWidget, This->myElementList); n++;
2458  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2459  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
2460  XtSetArg(args[n], XmNwidth, 200); n++;
2461 
2462  This->myViewPtList = XmCreateScrolledList(formTopLeft, (char *) "ListLeft",
2463  args, n);
2464  if (This->viewPtList.size())
2465  This->addViewPoints();
2466  XtAddCallback(This->myViewPtList, XmNbrowseSelectionCallback,
2467  (XtCallbackProc) loadBookmarkCB, This);
2468  xmAddMouseEventHandler(This->myViewPtList); // Add scrolling functionality
2469 
2470  XtManageChild(This->myViewPtList);
2471 
2472  XtManageChild(formTopLeft);
2473 
2474  XtManageChild(formTop);
2475 
2477  n = 0;
2478  XtSetArg(args[n], XmNmarginWidth, 6); n++;
2479  Widget formMiddle = XmCreateForm(This->listsDialog, (char *) "MiddleForm", args,
2480  n);
2481 
2482  // Label
2483  n = 0;
2484  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2485  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
2486  XtSetArg(args[n], XmNtopWidget, This->myViewPtList); n++;
2487  Widget label = XmCreateLabelGadget(formMiddle, (char *) "Selection", args,
2488  n);
2489  XtManageChild(label);
2490 
2491  // Text
2492  n = 0;
2493  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2494  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
2495  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
2496  XtSetArg(args[n], XmNtopWidget, label); n++;
2497  XtSetArg(args[n], XmNtopOffset, 3); n++;
2498  XtSetArg(args[n], XmNmaxLength, This->MAX_VP_NAME); n++;
2499  This->viewPtSelection = XmCreateText(formMiddle, (char *) "Txt", args, n);
2500  XtManageChild(This->viewPtSelection);
2501 
2502  Dimension h1, h2, h;
2503  XtVaGetValues(label, XmNheight, &h1, NULL);
2504  XtVaGetValues(This->viewPtSelection, XmNheight, &h2, NULL);
2505 
2506  h = (Dimension) (1.1 * (h1 + h2));
2507 
2508  XtVaSetValues(formMiddle, XmNpaneMaximum, h, XmNpaneMinimum, h, NULL);
2509  XtManageChild(formMiddle);
2510 
2512  // Action Area Form
2513  n = 0;
2514  XtSetArg(args[n], XmNfractionBase, 4); n++;
2515  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
2516  XtSetArg(args[n], XmNtopWidget, This->viewPtSelection); n++;
2517  Widget formAction = XmCreateForm(This->listsDialog, (char *) "ActionForm", args,
2518  n);
2519 
2520  n = 0;
2521  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2522  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
2523  XtSetArg(args[n], XmNtopOffset, 3); n++;
2524  XtSetArg(args[n], XmNbottomOffset, 5); n++;
2525  Widget separator = XmCreateSeparatorGadget(formAction, (char *) "Sep", args, n);
2526 
2527  XtManageChild(separator);
2528 
2529  Widget button = XmCreatePushButton(formAction, (char *) "Delete", NULL, 0);
2530  XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
2531  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
2532  XmATTACH_POSITION, XmNleftPosition, 0, XmNrightAttachment,
2533  XmATTACH_POSITION, XmNrightPosition, 1,
2534  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
2535  NULL);
2536 
2537  XtAddCallback(button, XmNactivateCallback,
2538  (XtCallbackProc) deleteBookmarkCB, This);
2539  XtManageChild(button);
2540 
2541  button = XmCreatePushButton(formAction, (char *) "Rename", NULL, 0);
2542  XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
2543  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
2544  XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment,
2545  XmATTACH_POSITION, XmNrightPosition, 2,
2546  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
2547  NULL);
2548 
2549  XtAddCallback(button, XmNactivateCallback,
2550  (XtCallbackProc) renameBookmarkCB, This);
2551  XtManageChild(button);
2552 
2553  button = XmCreatePushButton(formAction, (char *) "Sort", NULL, 0);
2554  XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
2555  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
2556  XmATTACH_POSITION, XmNleftPosition, 2, XmNrightAttachment,
2557  XmATTACH_POSITION, XmNrightPosition, 3,
2558  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
2559  NULL);
2560 
2561  XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) sortBookmarksCB, This);
2562  XtManageChild(button);
2563 
2564  button = XmCreatePushButton(formAction, (char *) "Close", NULL, 0);
2565  XtVaSetValues(button, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget,
2566  separator, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
2567  XmATTACH_POSITION, XmNleftPosition, 3, XmNrightAttachment,
2568  XmATTACH_POSITION, XmNrightPosition, 4,
2569  XmNdefaultButtonShadowThickness, 2, XmNwidth, 40, XmNheight, 30,
2570  NULL);
2571 
2572  XtAddCallback(button, XmNactivateCallback, (XtCallbackProc) closeListsDialogCB, This);
2573  XtManageChild(button);
2574 
2575  XtManageChild(formAction);
2576  XtVaGetValues(button, XmNheight, &h1, NULL);
2577  XtVaSetValues(formAction, XmNpaneMaximum, h1, XmNpaneMinimum, h1, NULL);
2578 
2579  XtManageChild(This->listsDialog);
2580 
2582 }
2583 
2584 
2585 // Called when user clicks a scene element in listsDialog.
2586 // Zooms onto that element.
2587 void G4OpenInventorXtExaminerViewer::lookAtSceneElementCB(Widget,
2588  XtPointer client_data,
2589  XtPointer call_data)
2590 {
2591  char *value;
2592  std::string elementField;
2594  SoCamera * cam = This->getCamera();
2595 
2596  if (This->SoXtExaminerViewer::isAnimating())
2597  This->stopAnimating();
2598 
2599  XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
2600 
2601  value = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
2602  XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
2603  if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
2604  || This->currentState == PAUSED_ANIMATION ) {
2605  if (This->animateSensor->isScheduled())
2606  This->animateSensor->unschedule();
2607  This->setSuperimpositionEnabled(This->superimposition, FALSE);
2608  This->maxSpeed = 0.0f;
2609  This->scheduleRedraw();
2610  This->restoreCamera();
2611  This->currentState = This->prevState;
2612  } else if (This->currentState == VIEWPOINT)
2613  This->setSuperimpositionEnabled(This->superimposition, FALSE);
2614 
2615  elementField = value;
2616 
2617  int idx = elementField.find_last_of("[");
2618  if(idx == -1)
2619  idx = elementField.size(); //if "[" not found for whatever reason (list not sorted)
2620  else
2621  idx--; // To get rid of the space that is between the name and '['
2622 
2623  bool error = false;
2624  SoFullPath *path;
2625  SoSearchAction search;
2626  SoNode *root = This->getSceneManager()->getSceneGraph();
2627  int counter, idxUnderscore = elementField.find_last_of("_");
2628 
2629  This->parseString<int>(counter, elementField.substr(idxUnderscore + 1, idx), error);
2630 
2631  SoBaseKit::setSearchingChildren(TRUE);
2632  search.reset();
2633  search.setSearchingAll(TRUE);
2634 
2635  if(error) { // No counter is present => element name was not modified
2636  This->curEltName = elementField.substr(0, idx);
2637  search.setName(This->curEltName.c_str());
2638  search.apply(root);
2639 
2640  path = (SoFullPath *)search.getPath();
2641  }
2642  else {
2643  This->curEltName = elementField.substr(0, idxUnderscore);
2644  search.setInterest(SoSearchAction::ALL);
2645  search.setName(This->curEltName.c_str());
2646  search.apply(root);
2647 
2648  SoPathList &pl = search.getPaths();
2649  path = (SoFullPath *)pl[counter - 1]; // Since counter starts at 1, not 0
2650  }
2651 
2652  G4ThreeVector global;
2653 
2654  if ((idx > 0) && (path)) {
2655 
2656  if(!This->refParticleTrajectory.empty()){
2657 
2658  SoGetBoundingBoxAction bAction(This->getViewportRegion());
2659  bAction.apply(path);
2660  SbBox3f bBox = bAction.getBoundingBox();
2661  SbVec3f elementCoord = bBox.getCenter();
2662 
2663  This->refParticleIdx = 0;
2664  SbVec3f p;
2665 
2666  float absLengthNow, absLengthMin;
2667  int maxIdx = This->refParticleTrajectory.size() - 2;
2668  int targetIdx = 0;
2669  SbVec3f dir;
2670 
2671  p = This->refParticleTrajectory[This->refParticleIdx];
2672  absLengthMin = (p - elementCoord).length();
2673  This->refParticleIdx++;
2674 
2675  // Find a ref. particle's point closest to element's global coords
2676  while (This->refParticleIdx < maxIdx) {
2677  p = This->refParticleTrajectory[This->refParticleIdx];
2678  absLengthNow = (p - elementCoord).length();
2679 
2680  if (absLengthNow < absLengthMin) {
2681  absLengthMin = absLengthNow;
2682  targetIdx = This->refParticleIdx;
2683  }
2684  This->refParticleIdx++;
2685  }
2686 
2687  if (This->currentState != BEAMLINE) { // Set up default zoom
2688  SbVec3f p1, pN;
2689  This->currentState = BEAMLINE;
2690  This->prevParticleDir = SbVec3f(0,0,0); //so that moveCamera() knows sets default parameters
2691 
2692  p1 = This->prevPt = This->refParticleTrajectory[0];
2693  pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
2694  This->distance = (pN - p1).length() / 10;
2695 
2696  // FWJ Restore the default height instead of hard-wired value
2697  if (cam->isOfType(SoOrthographicCamera::getClassTypeId()))
2698  ((SoOrthographicCamera *) cam)->height.setValue(This->defaultHeight);
2699  // ((SoOrthographicCamera *) cam)->height.setValue(10000.0f);
2700  else if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
2701  ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
2702  This->defaultHeightAngle);
2703  } else {
2704  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId()))
2705  This->distance = (This->prevPt - cam->position.getValue()).length();
2706  }
2707  This->refParticleIdx = targetIdx;
2708 
2710  This->setSuperimpositionEnabled(This->superimposition, TRUE);
2711  This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
2712  This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
2713  This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
2714  This->scheduleRedraw();
2716 
2717  This->moveCamera(This->distance);
2718  XtFree(value);
2719 
2720  }
2721  else{
2722  This->offsetFromCenter.setValue(0, 0, 1);
2723  This->distance = 50;// small number since using viewAll() for default zoom
2724  This->upVector.setValue(0, 1, 0);
2725 
2726  This->moveCamera(This->distance);
2727  cam->viewAll(path, This->getViewportRegion());
2728  }
2729  }
2730 
2731  XmTextSetString(This->viewPtSelection, NULL);
2732 }
2733 
2734 
2735 // Destroyes listsDialog and resets necessary member fields.
2736 
2737 void G4OpenInventorXtExaminerViewer::closeListsDialogCB(Widget,
2738  XtPointer client_data,
2739  XtPointer)
2740 {
2742 
2743  This->sceneElements.clear();
2744  This->refParticleTrajectory.clear();
2745 
2746  This->currentState = GENERAL;
2747  XtDestroyWidget(This->myShellDialog);
2748  This->listsDialog = NULL;
2749 }
2750 
2751 // Called when user clicks left arrow button. Loads previous viewpoint.
2752 void G4OpenInventorXtExaminerViewer::prevViewPtCB(Widget, XtPointer client_data,
2753  XtPointer) {
2755 
2756  if (This->viewPtIdx == 0)
2757  This->viewPtIdx = This->viewPtList.size() - 1;
2758  else
2759  This->viewPtIdx--;
2760 
2761  This->writeViewPtIdx();
2762  This->setViewPt();
2763 }
2764 
2765 // Called when user clicks right arrow button. Loads next viewpoint.
2766 void G4OpenInventorXtExaminerViewer::nextViewPtCB(Widget, XtPointer client_data,
2767  XtPointer) {
2769 
2770  if (This->viewPtIdx >= (int) This->viewPtList.size() - 1)
2771  This->viewPtIdx = 0;
2772  else
2773  This->viewPtIdx++;
2774 
2775  This->writeViewPtIdx();
2776  This->setViewPt();
2777 }
2778 
2779 
2780 // Updates the viewPtIdx in a viewpoint file.
2781 
2782 void G4OpenInventorXtExaminerViewer::writeViewPtIdx()
2783 {
2784  std::string idxStr;
2785  std::stringstream out;
2786  out << viewPtIdx;
2787  idxStr = out.str();
2788  fileOut.seekp(0, std::ios::beg);
2789 
2790  while ((int) idxStr.length() < MAX_VP_IDX) {
2791  idxStr += " ";
2792  }
2793 
2794  fileOut << idxStr << "\n";
2795  fileOut.flush();
2796  fileOut.seekp(0, std::ios::end);
2797 }
2798 
2799 
2800 // Sets the viewpoint based on camera data that viewPtIdx is pointing to.
2801 
2802 void G4OpenInventorXtExaminerViewer::setViewPt()
2803 {
2804  if (currentState == ANIMATION || currentState == REVERSED_ANIMATION
2805  || currentState == ROTATING) {
2806 
2807  if (animateSensor->isScheduled())
2808  animateSensor->unschedule();
2809  setSuperimpositionEnabled(superimposition, FALSE);
2810  maxSpeed = 0.0f;
2811  scheduleRedraw();
2812  }
2813 
2814  SoCamera * camera = getCamera();
2815  if (camera == NULL) {
2816  String dialogName = (char *) "Missing Camera Node";
2817  std::string msg = "Camera is null. Unable to set the viewpoint.";
2818  warningMsgDialog(msg, dialogName, NULL);
2819  return;
2820  }
2821 
2822  if (!viewPtList.size()) {
2823  String dialogName = (char *) "Missing Viewpoints";
2824  std::string msg = "There are no viewpoints to load.";
2825  warningMsgDialog(msg, dialogName, NULL);
2826  return;
2827  }
2828 
2829  if (SoXtExaminerViewer::isAnimating())
2830  stopAnimating();
2831 
2832  if (currentState != VIEWPOINT) {
2833  currentState = VIEWPOINT;
2835  setSuperimpositionEnabled(superimposition, TRUE);
2836  axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
2837  animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
2838  animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
2839 
2840  scheduleRedraw();
2842  }
2843 
2844  curViewPtName = viewPtList[viewPtIdx].viewPtName;
2845  camera->viewportMapping = viewPtList[viewPtIdx].viewportMapping;
2846  camera->position = viewPtList[viewPtIdx].position;
2847  camera->orientation = viewPtList[viewPtIdx].orientation;
2848  camera->aspectRatio = viewPtList[viewPtIdx].aspectRatio;
2849  camera->nearDistance = viewPtList[viewPtIdx].nearDistance;
2850  camera->farDistance = viewPtList[viewPtIdx].farDistance;
2851  camera->focalDistance = viewPtList[viewPtIdx].focalDistance;
2852 
2853  // Restore camera height (changed by zooming)
2854  if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
2855  if (viewPtList[viewPtIdx].camType == ORTHOGRAPHIC) {
2856  toggleCameraType();
2857  camera = getCamera();
2858  ((SoOrthographicCamera *) camera)->height.setValue(
2859  viewPtList[viewPtIdx].height);
2860  } else
2861  ((SoPerspectiveCamera *) camera)->heightAngle.setValue(
2862  viewPtList[viewPtIdx].height);
2863  } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
2864  if (viewPtList[viewPtIdx].camType == PERSPECTIVE) {
2865  toggleCameraType();
2866  camera = getCamera();
2867  ((SoPerspectiveCamera *) camera)->heightAngle.setValue(
2868  viewPtList[viewPtIdx].height);
2869  } else
2870  ((SoOrthographicCamera *) camera)->height.setValue(
2871  viewPtList[viewPtIdx].height);
2872  } else {
2873  SoDebugError::post("G4OpenInventorXtExaminerViewer::setViewPt",
2874  "Only Perspective and Orthographic cameras are supported.");
2875  return;
2876  }
2877 
2878 }
2879 
2880 
2881 // Pops up a prompt asking for a new viewpoint name.
2882 
2883 void G4OpenInventorXtExaminerViewer::saveViewPtCB(Widget w,
2884  XtPointer client_data,
2885  XtPointer)
2886 {
2888 
2889  if (This->fileName.empty()) {
2890  newViewPtFileCB(w, This, NULL);
2891  This->returnToSaveVP = true;
2892  return; // Need to return and call this fn again from newViewPtFileCB since flow of control does not stall here but keeps going
2893  }
2894 
2895  int n = 0;
2896  Arg args[4];
2897  Widget nameViewPtDialog;
2898  Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
2899  XmString label = XmStringCreateLocalized((char *) "Name the viewpoint:");
2900 
2901  XtSetArg(args[n], XmNselectionLabelString, label); n++;
2902  XtSetArg(args[n], XmNautoUnmanage, False); n++; //prevent the dialog from closing
2903  //automatically, in case the name
2904  //is wrong
2905 
2906  nameViewPtDialog = XmCreatePromptDialog(parent, (char *) "Save Viewpoint",
2907  args, n);
2908 
2909  XmStringFree(label);
2910  XtAddCallback(nameViewPtDialog, XmNokCallback, getViewPtNameCB, This);
2911  XtAddCallback(nameViewPtDialog, XmNcancelCallback,
2912  (XtCallbackProc) XtDestroyWidget, NULL);
2913 
2914  Widget text = XtNameToWidget(nameViewPtDialog, "Text");
2915  XtVaSetValues(text, XmNmaxLength, This->MAX_VP_NAME, NULL);
2916  std::string autoName = "";
2917  if (!This->warningFlag) { //leave the TextField as it is if coming back from warning dialog
2918  autoName = This->viewPtAutoName();
2919  }
2920  This->warningFlag = false;
2921  XmTextSetString(text, (char *) autoName.c_str());
2922  XmTextSetInsertionPosition(text, autoName.length());
2923 
2924  XtUnmanageChild(XtNameToWidget(nameViewPtDialog, "Help"));
2925  XtManageChild(nameViewPtDialog);
2926 }
2927 
2928 
2929 std::string G4OpenInventorXtExaminerViewer::viewPtAutoName()
2930 {
2931  std::string viewPt;
2932  std::stringstream sstream;
2933  std::vector<int> existingViewPts;
2934  int tmp;
2935 
2936  //Build the list of names of the form viewpoint_* already present
2937  for (unsigned int i = 0; i < this->viewPtList.size(); ++i) {
2938  viewPt = this->viewPtList[i].viewPtName;
2939  if (viewPt.find("viewpoint_") != std::string::npos) {
2940  tmp = atoi(viewPt.substr(10).c_str());
2941  if (tmp == 0) {
2942  //0 means couldn't convert to integer OR viewpoint_0
2943  if (!viewPt.compare("viewpoint_0"))
2944  existingViewPts.push_back(0);
2945  } else
2946  existingViewPts.push_back(tmp);
2947  }
2948  }
2949 
2950  sstream.str("");
2951  sstream.clear();
2952 
2953  //Return the view viewpoint_* name available
2954  if (existingViewPts.size() > 0) {
2955  int vpNum = 0;
2956  while (true) {
2957  if (std::find(existingViewPts.begin(), existingViewPts.end(), vpNum)
2958  == existingViewPts.end()) {
2959  sstream << "viewpoint_" << vpNum;
2960  return sstream.str();
2961  }
2962  ++vpNum;
2963  }
2964  } else {
2965  return "viewpoint_0";
2966  }
2967  return "";
2968 }
2969 
2970 
2971 void G4OpenInventorXtExaminerViewer::abbrOutputCB(Widget,
2972  XtPointer client_data,
2973  XtPointer)
2974 {
2976  (G4OpenInventorXtExaminerViewer *) client_data;
2977  This->abbrOutputFlag = !(This->abbrOutputFlag);
2978 }
2979 
2980 
2981 void G4OpenInventorXtExaminerViewer::pickRefPathCB(Widget,
2982  XtPointer client_data,
2983  XtPointer)
2984 {
2986 
2987  // Save viewing state and go to picking mode
2988  This->viewingBeforePickRef = This->isViewing();
2989  if(This->isViewing())
2990  This->setViewing(false);
2991  This->setComponentCursor(SoXtCursor(SoXtCursor::CROSSHAIR));
2992  This->pickRefPathFlag = true;
2993 }
2994 
2995 
2996 // Examines new viewpoint name and if OK calls saveViewPt.
2997 
2998 void G4OpenInventorXtExaminerViewer::getViewPtNameCB(Widget w,
2999  XtPointer client_data,
3000  XtPointer call_data)
3001 {
3002  char *name = NULL;
3003  std::string strName;
3005  XmSelectionBoxCallbackStruct *cbs =
3006  (XmSelectionBoxCallbackStruct *) call_data;
3007  XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &name);
3008 
3009  if (!name) {
3010  return;
3011  }
3012  if (!*name) {
3013  XtFree(name);
3014  return;
3015  }
3016 
3017  strName = name;
3018  XtFree(name);
3019 
3020  int beg = strName.find_first_not_of(' '); // Remove leading/trailing spaces
3021  int end = strName.find_last_not_of(' ');
3022  strName = strName.substr(beg, end - beg + 1);
3023 
3024  bool nameExists = false;
3025  int size = This->viewPtList.size();
3026  for (int i = 0; i < size; i++) {
3027  if (!strcmp(This->viewPtList[i].viewPtName, strName.c_str())) {
3028  nameExists = true;
3029  break;
3030  }
3031  }
3032 
3033  if (!nameExists) {
3034  name = new char[This->MAX_VP_NAME + 1];
3035  strcpy(name, strName.c_str());
3036  if (This->viewPtIdx == -1)
3037  This->viewPtIdx = 0;
3038  This->saveViewPt(name);
3039  if (This->listsDialog) {
3040  XmListAddItemUnselected(This->myViewPtList, cbs->value, 0); // vpName
3041  }
3042  //Dismiss the nameViewPtDialog dialog
3043  XtUnmanageChild(w);
3044  } else {
3045  String dialogName = (char *) "Existing Viewpoint";
3046  std::string msg = "The viewpoint already exists.";
3047  This->warningMsgDialog(msg, dialogName, NULL);
3048 
3049  }
3050 }
3051 
3052 
3053 // Saves current camera parameters to a viewpoint file.
3054 
3055 void G4OpenInventorXtExaminerViewer::saveViewPt(char *name)
3056 {
3057  SbVec3f axis;
3058  viewPtData tmp;
3059  float x, y, z, angle;
3060  SoCamera * camera = getCamera();
3061 
3062  if (viewPtList.size() == 0) {
3063  writeViewPtIdx();
3064  XtSetSensitive(nextViewPtButton, True); // Makes arrow buttons clickable
3065  XtSetSensitive(prevViewPtButton, True);
3066  }
3067 
3068  tmp.viewPtName = name;
3069  tmp.viewportMapping = camera->viewportMapping.getValue();
3070  tmp.position = camera->position.getValue();
3071  tmp.orientation = camera->orientation.getValue();
3072  tmp.aspectRatio = camera->aspectRatio.getValue();
3073  tmp.nearDistance = camera->nearDistance.getValue();
3074  tmp.farDistance = camera->farDistance.getValue();
3075  tmp.focalDistance = camera->focalDistance.getValue();
3076 
3077  // Save camera height (changed by zooming)
3078  if (camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
3079  tmp.height = ((SoPerspectiveCamera *) camera)->heightAngle.getValue();
3080  tmp.camType = PERSPECTIVE;
3081  } else if (camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
3082  tmp.height = ((SoOrthographicCamera *) camera)->height.getValue();
3083  tmp.camType = ORTHOGRAPHIC;
3084  } else {
3085  SoDebugError::post("G4OpenInventorXtExaminerViewer::saveViewPtCB",
3086  "Only Perspective and Orthographic cameras are supported.");
3087  return;
3088  }
3089 
3090  viewPtList.push_back(tmp);
3091 
3092  // Now save the view point to a .txt file
3093  std::string vpName = name;
3094 
3095  while ((int) vpName.size() <= MAX_VP_NAME)
3096  vpName += " ";
3097 
3098  fileOut << vpName << std::endl;
3099  tmp.position.getValue(x, y, z);
3100  fileOut << x << " " << y << " " << z << std::endl;
3101 
3102  // Reusing x, y and z for storing the axis
3103  tmp.orientation.getValue(axis, angle);
3104  axis.getValue(x, y, z);
3105  fileOut << x << " " << y << " " << z << " " << angle << std::endl;
3106 
3107  fileOut << tmp.camType << " " << tmp.height << std::endl;
3108  fileOut << tmp.focalDistance << " ";
3109  fileOut << tmp.nearDistance << " ";
3110  fileOut << tmp.farDistance << std::endl;
3111  fileOut << tmp.viewportMapping << " ";
3112  fileOut << tmp.aspectRatio << "\n" << std::endl;
3113  fileOut.flush();
3114  viewPtIdx++;
3115 }
3116 
3117 
3118 void G4OpenInventorXtExaminerViewer::deleteViewPtCB(Widget,
3119  XtPointer client_data,
3120  XtPointer)
3121 {
3123  (G4OpenInventorXtExaminerViewer *) client_data;
3124  This->deleteViewPt();
3125 }
3126 
3127 
3128 // Deletes current viewpoint the user is looking at.
3129 // Updates the input file and bookmarks as well.
3130 
3131 void G4OpenInventorXtExaminerViewer::deleteViewPt(char *vpName)
3132 {
3133  std::string line;
3134  int end;
3135  fileIn.open(fileName.c_str());
3136  std::ofstream out("temporaryFile.txt");
3137 
3138  if (!vpName)
3139  vpName = viewPtList[viewPtIdx].viewPtName;
3140 
3141  if (listsDialog) {
3142  XmString vpNameStr = XmStringCreateLocalized(vpName);
3143 
3144  XmListDeleteItem(myViewPtList, vpNameStr);
3145  XmStringFree(vpNameStr);
3146  }
3147 
3148  getline(fileIn, line); // Printing the viewpoint idx
3149  out << line << "\n";
3150 
3151  while (getline(fileIn, line)) {
3152  end = line.find_last_not_of(' ');
3153  line = line.substr(0, end + 1);
3154  if (!strcmp(line.c_str(), vpName)) { // Equal
3155  while (line.size()) {
3156  getline(fileIn, line);
3157  }
3158 
3159  while (getline(fileIn, line))
3160  out << line << "\n";
3161  } else {
3162  while (line.size()) {
3163  out << line << "\n";
3164  getline(fileIn, line);
3165  }
3166  out << "\n";
3167  }
3168  }
3169 
3170  int idx = 0; // Remove viewpoint from the vector
3171  int size = viewPtList.size();
3172  while (idx < size) {
3173  if (!strcmp(viewPtList[idx].viewPtName, vpName)) {
3174  viewPtList.erase(viewPtList.begin() + idx);
3175  break;
3176  }
3177  idx++;
3178  }
3179 
3180  out.close();
3181  fileOut.close();
3182  fileIn.clear();
3183  fileIn.close();
3184 
3185  remove(fileName.c_str());
3186  rename("temporaryFile.txt", fileName.c_str());
3187 
3188  fileOut.open(fileName.c_str(), std::ios::in);
3189  fileOut.seekp(0, std::ios::end);
3190 
3191  if (!viewPtList.size()) { // viewPtList is empty
3192  curViewPtName = (char *) "";
3193  scheduleRedraw();
3194  XtSetSensitive(nextViewPtButton, False);
3195  XtSetSensitive(prevViewPtButton, False);
3196  } else {
3197  if (viewPtIdx >= (int) viewPtList.size())
3198  viewPtIdx--;
3199  writeViewPtIdx();
3200  setViewPt();
3201  }
3202 }
3203 
3204 
3205 // Renames currently selected viewpoint.
3206 
3207 void G4OpenInventorXtExaminerViewer::renameViewPt(char *vpName)
3208 {
3209  int idx = 0, end, pos;
3210  int size = viewPtList.size();
3211  std::string line, newName;
3212  fileIn.open(fileName.c_str());
3213 
3214  newName = vpName;
3215  while ((int) newName.size() < MAX_VP_NAME)
3216  newName += " ";
3217 
3218  getline(fileIn, line);
3219  pos = fileIn.tellg();
3220  while (getline(fileIn, line)) {
3221  end = line.find_last_not_of(' ');
3222  line = line.substr(0, end + 1);
3223  if (!strcmp(line.c_str(), curViewPtName)) {
3224  fileOut.seekp(pos);
3225  fileOut << newName;
3226  fileOut.seekp(0, std::ios::end); // Set the file pointer to the end of the file
3227  break;
3228  }
3229  while (line.size())
3230  getline(fileIn, line);
3231  pos = fileIn.tellg();
3232  }
3233 
3234  fileIn.close();
3235  fileIn.clear();
3236 
3237  while (idx < size) {
3238  if (!strcmp(viewPtList[idx].viewPtName, curViewPtName)) {
3239  strcpy(viewPtList[idx].viewPtName, vpName);
3240  break;
3241  }
3242  idx++;
3243  }
3244 }
3245 
3246 
3247 // Rewrites entire viewpoint file with sorted viewpoints.
3248 
3249 void G4OpenInventorXtExaminerViewer::sortViewPts(std::vector<std::string> sortedViewPts)
3250 {
3251  SbVec3f axis;
3252  float x, y, z, angle;
3253  int sortIdx = 0, unsortIdx = 0;
3254 
3255  if (fileOut.is_open())
3256  fileOut.close();
3257 
3258  fileOut.open(fileName.c_str()); // Erase current viewpoint file
3259 
3260  writeViewPtIdx();
3261 
3262  int size = sortedViewPts.size();
3263  while (sortIdx < size) {
3264  while (strcmp(sortedViewPts[sortIdx].c_str(),
3265  viewPtList[unsortIdx].viewPtName))
3266  unsortIdx++;
3267 
3268  std::string vpName = viewPtList[unsortIdx].viewPtName;
3269 
3270  while ((int) vpName.size() < MAX_VP_NAME)
3271  vpName += " ";
3272  fileOut << vpName << std::endl;
3273  viewPtList[unsortIdx].position.getValue(x, y, z);
3274  fileOut << x << " " << y << " " << z << std::endl;
3275 
3276  // Reusing x, y and z for storing the axis
3277  viewPtList[unsortIdx].orientation.getValue(axis, angle);
3278  axis.getValue(x, y, z);
3279  fileOut << x << " " << y << " " << z << " " << angle << std::endl;
3280 
3281  fileOut << viewPtList[unsortIdx].camType << " "
3282  << viewPtList[unsortIdx].height << std::endl;
3283  fileOut << viewPtList[unsortIdx].focalDistance << " ";
3284 
3285  fileOut << viewPtList[unsortIdx].nearDistance << " ";
3286 
3287  fileOut << viewPtList[unsortIdx].farDistance << std::endl;
3288 
3289  fileOut << viewPtList[unsortIdx].viewportMapping << " ";
3290  fileOut << viewPtList[unsortIdx].aspectRatio << "\n" << std::endl;
3291  fileOut.flush();
3292 
3293  unsortIdx = 0;
3294  sortIdx++;
3295  }
3296 }
3297 
3298 
3299 // Loads view point data from a file into a vector.
3300 
3302 {
3303  bool error = false;
3304  viewPtData tmp;
3305  std::string token;
3306  SbVec3f axis;
3307  SbRotation orient;
3308  float x, y, z, angle;
3309 
3310  // Gets the last view point accessed, stored in the first line of the data file.
3311  fileIn >> token;
3312  parseString<int>(viewPtIdx, token, error);
3313  getline(fileIn, token); // Remove "\n"
3314  // Converts data from string type into necessary types
3315  while (getline(fileIn, token)) {
3316 
3317  int end = token.find_last_not_of(' '); // Remove padded spaces
3318  token = token.substr(0, end + 1);
3319 
3320  char *vpName = new char[token.size() + 1];
3321  strcpy(vpName, token.c_str());
3322  tmp.viewPtName = vpName;
3323  fileIn >> token;
3324 
3325  parseString<float>(x, token, error);
3326  fileIn >> token;
3327  parseString<float>(y, token, error);
3328  fileIn >> token;
3329  parseString<float>(z, token, error);
3330  fileIn >> token;
3331  tmp.position = axis.setValue(x, y, z);
3332 
3333  parseString<float>(x, token, error);
3334  fileIn >> token;
3335  parseString<float>(y, token, error);
3336  fileIn >> token;
3337  parseString<float>(z, token, error);
3338  fileIn >> token;
3339  parseString<float>(angle, token, error);
3340  fileIn >> token;
3341  orient.setValue(axis.setValue(x, y, z), angle);
3342  tmp.orientation = orient.getValue();
3343 
3344  int camType;
3345  parseString<int>(camType, token, error);
3346  fileIn >> token;
3347  tmp.camType = (CameraType) camType;
3348 
3349  parseString<float>(tmp.height, token, error);
3350  fileIn >> token;
3351  parseString<float>(tmp.focalDistance, token, error);
3352  fileIn >> token;
3353  parseString<float>(tmp.nearDistance, token, error);
3354  fileIn >> token;
3355  parseString<float>(tmp.farDistance, token, error);
3356  fileIn >> token;
3357  parseString<int>(tmp.viewportMapping, token, error);
3358  fileIn >> token;
3359  parseString<float>(tmp.aspectRatio, token, error);
3360 
3361  getline(fileIn, token); // To remove "\n" characters
3362  getline(fileIn, token);
3363 
3364  if (error) {
3365  viewPtIdx = 0;
3366  viewPtList.clear();
3367  return false;
3368  }
3369  viewPtList.push_back(tmp);
3370  }
3371 
3372  return true;
3373 }
3374 
3375 
3376 // Converts a string type word into a float type.
3377 
3378 template<class T>
3379 void G4OpenInventorXtExaminerViewer::parseString(T &t, const std::string &s,
3380  bool &error)
3381 {
3382  std::istringstream str(s);
3383  if ((str >> t).fail())
3384  error = true;
3385 }
3386 
3387 
3388 // Generic fileSelectionDialog creation.
3389 
3390 void G4OpenInventorXtExaminerViewer::popUpFileSelDialog(Widget &dialog,
3391  std::string dialogName,
3392  std::string buttonLabel,
3393  XtCallbackProc cbOK)
3394 {
3395  int n;
3396  Arg args[3];
3397  Widget parent, scrollWidget;
3398  parent = SoXt::getShellWidget(getParentWidget());
3399 
3400  if (dialog == NULL) {
3401 
3402  // Change the 'OK' button to whatever buttonLabel contains
3403  XmString str = XmStringCreateLocalized((char *) buttonLabel.c_str());
3404 
3405  n = 0;
3406  XtSetArg(args[n], XmNokLabelString, str); n++;
3407  XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
3408 
3409  dialog = XmCreateFileSelectionDialog(parent,
3410  (char *) dialogName.c_str(), args, n);
3411 
3412  XtAddCallback(dialog, XmNokCallback, cbOK, this);
3413  XtAddCallback(dialog, XmNcancelCallback, cancelFileSelDialogCB, this);
3414 
3415  // Adding scrolling functionality to the widget
3416  scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_DIR_LIST);
3417  if (scrollWidget)
3418  xmAddMouseEventHandler(scrollWidget);
3419  scrollWidget = XmFileSelectionBoxGetChild(dialog, XmDIALOG_LIST);
3420  if (scrollWidget)
3421  xmAddMouseEventHandler(scrollWidget);
3422 
3423  XtUnmanageChild(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
3424  XmStringFree(str);
3425  }
3426  XtManageChild(dialog);
3427 }
3428 
3429 
3430 // Generic fileSelectionDialog cancelation.
3431 
3432 void G4OpenInventorXtExaminerViewer::cancelFileSelDialogCB(Widget w,
3433  XtPointer,
3434  XtPointer)
3435 {
3436  XtUnmanageChild(w);
3437 }
3438 
3439 
3440 // Displays a file selection dialog that allows to open a new viewpoint file.
3441 
3442 void G4OpenInventorXtExaminerViewer::openViewPtFileCB(Widget,
3443  XtPointer client_data,
3444  XtPointer)
3445 {
3447  (G4OpenInventorXtExaminerViewer *) client_data;
3448  This->popUpFileSelDialog(This->openFileDialog, "Open File", "Load",
3449  viewPtFileSelectedCB);
3450 }
3451 
3452 
3453 void G4OpenInventorXtExaminerViewer::viewPtFileSelectedCB(Widget w,
3454  XtPointer client_data,
3455  XtPointer call_data)
3456 {
3457  char *file = NULL;
3459  XmFileSelectionBoxCallbackStruct *cbs =
3460  (XmFileSelectionBoxCallbackStruct *) call_data;
3461 
3462  // Get the file
3463  if (cbs) {
3464  if (!(file = (char *) XmStringUnparse(cbs->value,
3465  XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
3466  XmOUTPUT_ALL))) {
3467  SoDebugError::post("G4OpenInventorXtExaminerViewer::fileSelectedCB",
3468  "Internal error during file opening");
3469  return;
3470  }
3471 
3472  This->fileIn.open(file);
3473  if (!This->fileIn.fail()) {
3474  // Opens a file without erasing it
3475  This->cleanUpAfterPrevFile();
3476  if (!This->loadViewPts()) {
3477  String dialogName = (char *) "Error Loading File";
3478  std::string msg = "Wrong or corrupted input file.";
3479  This->warningMsgDialog(msg, dialogName, NULL);
3480  } else {
3481  This->fileName = file;
3482  This->fileOut.open(This->fileName.c_str(), std::ios::in);
3483  This->fileOut.seekp(0, std::ios::end);
3484 
3485  if (!This->listsDialog)
3486  constructListsDialog(w, This, NULL); // Pop up listsDialog
3487  else
3488  This->addViewPoints();
3489 
3490  std::string newDialogName = This->fileName.substr(
3491  This->fileName.rfind('/') + 1);
3492  XtVaSetValues(This->myShellDialog, XmNtitle,
3493  (char *) newDialogName.c_str(), NULL);
3494 
3495  if (This->viewPtList.size()) {
3496  This->setViewPt();
3497  XmTextSetString(This->viewPtSelection, NULL);
3498  XtSetSensitive(This->nextViewPtButton, True);
3499  XtSetSensitive(This->prevViewPtButton, True);
3500  } else {
3501  XtSetSensitive(This->nextViewPtButton, False);
3502  XtSetSensitive(This->prevViewPtButton, False);
3503  }
3504 
3505  XtUnmanageChild(w);
3506  }
3507 
3508  This->fileIn.close();
3509  } else {
3510  String dialogName = (char *) "Nonexistent File";
3511  std::string msg = "Unable to open file.";
3512  This->warningMsgDialog(msg, dialogName, NULL);
3513  }
3514  }
3515 
3516  This->fileIn.clear();
3517  XtFree(file);
3518 }
3519 
3520 
3521 // Adds bookmarks to listsDialog.
3522 
3523 void G4OpenInventorXtExaminerViewer::addViewPoints()
3524 {
3525  int size = viewPtList.size();
3526  if (!size)
3527  return;
3528 
3529  XmString *viewPts;
3530 
3531  viewPts = (XmString *) XtMalloc(size * sizeof(XmString));
3532  for (int i = 0; i < size; i++)
3533  viewPts[i] = XmStringCreateLocalized(viewPtList[i].viewPtName);
3534 
3535  XmListAddItemsUnselected(myViewPtList, viewPts, size, 1);
3536 
3537  if (viewPts != NULL) {
3538  for (int i = 0; i < size; i++)
3539  XmStringFree(viewPts[i]);
3540  XtFree((char *) viewPts);
3541  }
3542 }
3543 
3544 
3545 // Called before loading a new viewpoint file.
3546 // Resets member fields to default values.
3547 
3548 void G4OpenInventorXtExaminerViewer::cleanUpAfterPrevFile()
3549 {
3550  viewPtIdx = -1;
3551  viewPtList.clear();
3552  setSuperimpositionEnabled(superimposition, FALSE);
3553  scheduleRedraw();
3554  currentState = GENERAL;
3555  if (fileOut.is_open())
3556  fileOut.close();
3557  if (listsDialog) // Clear viewpoints
3558  XmListDeleteAllItems(myViewPtList);
3559 }
3560 
3561 
3562 // Generic function for displaying a warning dialog.
3563 
3565  String dialogName,
3566  XtCallbackProc cb)
3567 {
3568  Arg args[5];
3569  unsigned int n;
3570  XmString warningMsg;
3571 
3572  warningMsg = XmStringCreateLocalized((char *)msg.c_str());
3573 
3574  n = 0;
3575  XtSetArg(args[n], XmNmessageString, warningMsg); n++;
3576  Widget warningDialog = XmCreateWarningDialog(getParentWidget(), dialogName, args, n);
3577  if (cb)
3578  XtAddCallback(warningDialog, XmNokCallback, cb, this);
3579 
3580  XmStringFree(warningMsg);
3581 
3582  XtVaSetValues (warningDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
3583  XtUnmanageChild(XtNameToWidget(warningDialog, "Help"));
3584  XtUnmanageChild(XtNameToWidget(warningDialog, "Cancel"));
3585 
3586  XtManageChild(warningDialog);
3587 }
3588 
3589 
3590 void G4OpenInventorXtExaminerViewer::newViewPtFileCB(Widget,
3591  XtPointer client_data,
3592  XtPointer)
3593 {
3595  (G4OpenInventorXtExaminerViewer *) client_data;
3596  This->popUpFileSelDialog(This->newFileDialog, "New File", "Save",
3597  createNewVPFileCB);
3598 }
3599 
3600 
3601 void G4OpenInventorXtExaminerViewer::createNewVPFileCB(Widget w,
3602  XtPointer client_data,
3603  XtPointer call_data)
3604 {
3605  char *file;
3606  std::string fName;
3608  XmFileSelectionBoxCallbackStruct *cbs =
3609  (XmFileSelectionBoxCallbackStruct *) call_data;
3610 
3611  // Get the file
3612  if (cbs) {
3613  if (!(file = (char *) XmStringUnparse(cbs->value,
3614  XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0,
3615  XmOUTPUT_ALL))) {
3616  SoDebugError::post("G4OpenInventorXtExaminerViewer::createNewVPFileCB",
3617  "Internal error during file opening");
3618  return;
3619  }
3620 
3621  This->fileName = file;
3622  fName = This->fileName.substr(This->fileName.rfind('/') + 1); // Extracts just the name of the file
3623  This->fileIn.open(file);
3624  if (This->fileIn.fail()) { // Filename does not exist
3625  This->cleanUpAfterPrevFile();
3626  This->fileOut.open(file); // Creates a new empty file
3627  XtSetSensitive(This->nextViewPtButton, False);
3628  XtSetSensitive(This->prevViewPtButton, False);
3629  if (This->listsDialog)
3630  closeListsDialogCB(w, This, NULL);
3631  constructListsDialog(w, This, NULL);
3632  XtUnmanageChild(w);
3633  if (This->returnToSaveVP) {
3634  This->returnToSaveVP = false;
3635  saveViewPtCB(NULL, This, NULL);
3636  }
3637  } else { // Filename already exists
3638  String dialogName = (char *) "Existing File";
3639  std::string msg = "'" + fName + "' already exists. Do you want to overwrite it?";
3640  This->warningMsgDialog(msg, dialogName, overwriteFileCB);
3641  This->fileIn.close();
3642  }
3643  This->fileIn.clear();
3644  XtFree(file);
3645  }
3646 }
3647 
3648 
3649 void G4OpenInventorXtExaminerViewer::overwriteFileCB(Widget,
3650  XtPointer client_data,
3651  XtPointer)
3652 {
3654  This->cleanUpAfterPrevFile();
3655  XtSetSensitive(This->nextViewPtButton, False);
3656  XtSetSensitive(This->prevViewPtButton, False);
3657 
3658  XtUnmanageChild(This->newFileDialog);
3659 
3660  This->fileOut.open(This->fileName.c_str());
3661 
3662  if (This->returnToSaveVP) {
3663  This->returnToSaveVP = false;
3664  saveViewPtCB(NULL, This, NULL);
3665  }
3666 }
3667 
3668 
3669 void G4OpenInventorXtExaminerViewer::loadRefCoordsDialogCB(Widget,
3670  XtPointer client_data,
3671  XtPointer)
3672 {
3674  (G4OpenInventorXtExaminerViewer *)client_data;
3675  This->popUpFileSelDialog(This->loadRefCoordsDialog, "Load Ref Coords",
3676  "Load", loadRefCoordsCB);
3677 }
3678 
3679 
3680 void G4OpenInventorXtExaminerViewer::loadRefCoordsCB(Widget w,
3681  XtPointer client_data,
3682  XtPointer call_data)
3683 {
3684  char *file = NULL;
3686  XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
3687 
3688  // Get the file
3689  if(cbs) {
3690 
3691  file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
3692  XmCHARSET_TEXT, XmCHARSET_TEXT,
3693  NULL, 0, XmOUTPUT_ALL);
3694 
3695  std::ifstream ifs(file);
3696  if(ifs.is_open()){
3697  This->refParticleTrajectory.clear();
3698  float x,y,z;
3699  while(ifs >> x >> y >> z){
3700  This->refParticleTrajectory.push_back(SbVec3f(x,y,z));
3701  }
3702  ifs.close();
3703  XtUnmanageChild(w);
3704  }
3705  else{
3706  String dialogName = (char *) "Problem reading file";
3707  std::string msg = "Problem reading file";
3708  This->warningMsgDialog(msg, dialogName, NULL);
3709  return;
3710 
3711  }
3712  }
3713 
3714  return;
3715 }
3716 
3717 
3718 void G4OpenInventorXtExaminerViewer::saveRefCoordsDialogCB(Widget,
3719  XtPointer client_data,
3720  XtPointer)
3721 {
3723 
3724  if (!This->refParticleTrajectory.size()) {
3725  String dialogName = (char *) "No Reference Trajectory";
3726  std::string msg = "You need to start a run or load a reference trajectory from a file";
3727  This->warningMsgDialog(msg, dialogName, NULL);
3728  return;
3729  }
3730 
3731  int n;
3732  Arg args[3];
3733  Widget parent, scrollWidget;
3734  parent = SoXt::getShellWidget(This->getParentWidget());
3735 
3736  if (This->saveRefCoordsDialog == NULL) {
3737 
3738  // Change the 'OK' button to whatever buttonLabel contains
3739  XmString str = XmStringCreateLocalized((char *)"Save");
3740 
3741  n = 0;
3742  XtSetArg(args[n], XmNokLabelString, str); n++;
3743  XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
3744 
3745  This->saveRefCoordsDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Ref Coords", args, n);
3746 
3747  XtAddCallback(This->saveRefCoordsDialog, XmNokCallback, saveRefCoordsCB, This);
3748  XtAddCallback(This->saveRefCoordsDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
3749 
3750  // Adding scrolling functionality to the widget
3751  scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_DIR_LIST);
3752  if (scrollWidget)
3753  xmAddMouseEventHandler(scrollWidget);
3754  scrollWidget = XmFileSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_LIST);
3755  if (scrollWidget)
3756  xmAddMouseEventHandler(scrollWidget);
3757 
3758  XtUnmanageChild(XmSelectionBoxGetChild(This->saveRefCoordsDialog, XmDIALOG_HELP_BUTTON));
3759  XmStringFree(str);
3760  }
3761 
3762  //TODO: Auto name?
3763 
3764  XtManageChild(This->saveRefCoordsDialog);
3765 
3766 }
3767 
3768 
3769 void G4OpenInventorXtExaminerViewer::saveRefCoordsCB(Widget w,
3770  XtPointer client_data,
3771  XtPointer call_data)
3772 {
3773  char *file;
3775  XmFileSelectionBoxCallbackStruct *cbs =
3776  (XmFileSelectionBoxCallbackStruct *) call_data;
3777 
3778  // Get the file
3779  if (cbs) {
3780 
3781  file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
3782  XmCHARSET_TEXT, XmCHARSET_TEXT,
3783  NULL, 0, XmOUTPUT_ALL);
3784 
3785  std::ifstream ifile(file);
3786  if (ifile) {
3787  //File already exists
3788 
3789  Arg args[4];
3790  Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
3791  Widget confirmOverwriteDialog;
3792  XmString msg;
3793 
3794  confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
3795  msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
3796  XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
3797 
3798  // If users presses OK, we want to return to this function and
3799  // save the file. For that to work, pass it the current widget
3800  // to be able to grab the filename.
3801  XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
3802  XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveRefCoordsOverWriteCB, client_data);
3803  XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveRefCoordsOverWriteCB, client_data);
3804 
3805  XmStringFree (msg);
3806 
3807  //The confirmOverwriteDialog will need this
3808  This->saveRefCoordsFileName = file;
3809  This->saveRefCoordsWidget = w;
3810 
3811  XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
3812  XtManageChild(confirmOverwriteDialog);
3813 
3814  return;
3815  }
3816  else{
3817 
3818  std::ofstream ofs(file);
3819  if(ofs.is_open()){
3820  float x,y,z;
3821  for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
3822  This->refParticleTrajectory[i].getValue(x,y,z);
3823  ofs << x << " " << y << " " << z << "\n";
3824  }
3825  ofs.close();
3826  XtUnmanageChild(w);
3827  }
3828  else{
3829  String dialogName = (char *) "Error opening file";
3830  std::string msg = "There was a problem trying to open the file '";
3831  msg += This->saveRefCoordsFileName;
3832  msg += "'";
3833 
3834  This->warningMsgDialog(msg, dialogName, NULL);
3835  }
3836  }
3837  }
3838 
3839  return;
3840 }
3841 
3842 
3843 void G4OpenInventorXtExaminerViewer::saveRefCoordsOverWriteCB(Widget w,
3844  XtPointer client_data,
3845  XtPointer call_data)
3846 {
3847  XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
3849 
3850  switch (cbs->reason) {
3851  case XmCR_OK:
3852  {
3853  // Overwrite confirmed, save file and dismiss both
3854  // dialogs (file dialog and overwrite confirmation dialog)
3855  std::ofstream ofs(This->saveRefCoordsFileName.c_str());
3856  if(ofs.is_open()){
3857  float x,y,z;
3858  for(unsigned int i=0; i < This->refParticleTrajectory.size(); ++i){
3859  This->refParticleTrajectory[i].getValue(x,y,z);
3860  ofs << x << " " << y << " " << z << "\n";
3861  }
3862  ofs.close();
3863  XtUnmanageChild(w);
3864  XtUnmanageChild(This->saveRefCoordsWidget);
3865  }
3866  else{
3867  String dialogName = (char *) "Error opening file";
3868  std::string msg = "There was a problem trying to open the file '";
3869  msg += This->saveRefCoordsFileName;
3870  msg += "'";
3871 
3872  This->warningMsgDialog(msg, dialogName, NULL);
3873  }
3874  break;
3875  }
3876  case XmCR_CANCEL:
3877  {
3878  // Overwrite refused, dismiss overwrite confirmation
3879  // dialog and return to file dialog
3880 
3881  // Give focus to the text field instead of the OK button
3882  XmProcessTraversal(XtNameToWidget(This->saveRefCoordsWidget, "Text"), XmTRAVERSE_CURRENT);
3883 
3884  XtUnmanageChild(w);
3885  This->saveRefCoordsFileName.clear();
3886  This->saveRefCoordsWidget = NULL;
3887  break;
3888  }
3889  default:
3890  return;
3891  }
3892 }
3893 
3894 
3895 void G4OpenInventorXtExaminerViewer::loadSceneGraphDialogCB(Widget,
3896  XtPointer client_data,
3897  XtPointer)
3898 {
3900  (G4OpenInventorXtExaminerViewer *)client_data;
3901  This->popUpFileSelDialog(This->loadSceneGraphDialog, "Load Scene Graph",
3902  "Load", loadSceneGraphCB);
3903  return;
3904 }
3905 
3906 
3907 void G4OpenInventorXtExaminerViewer::loadSceneGraphCB(Widget w,
3908  XtPointer client_data,
3909  XtPointer call_data)
3910 {
3911  char *file = NULL;
3913  XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)call_data;
3914 
3915  if(cbs) {
3916 
3917  file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
3918  XmCHARSET_TEXT, XmCHARSET_TEXT,
3919  NULL, 0, XmOUTPUT_ALL);
3920 
3921  SoInput sceneInput;
3922  if (!sceneInput.openFile(file)) {
3923  String dialogName = (char *) "Problem opening file";
3924  std::string msg = "Cannot open file ";
3925  msg += file;
3926  This->warningMsgDialog(msg, dialogName, NULL);
3927 
3928  sceneInput.closeFile();
3929  XtUnmanageChild(w);
3930  }
3931  // Read the whole file into the database
3932  This->newSceneGraph = SoDB::readAll(&sceneInput);
3933  if (This->newSceneGraph == NULL) {
3934  String dialogName = (char *) "Problem reading file";
3935  std::string msg = "Problem reading file";
3936  This->warningMsgDialog(msg, dialogName, NULL);
3937  return;
3938  }
3939 
3940  //This->newSceneGraph->ref();
3941  This->setSceneGraph(This->newSceneGraph);
3942  }
3943 
3944  return;
3945 }
3946 
3947 
3948 void G4OpenInventorXtExaminerViewer::saveSceneGraphDialogCB(Widget,
3949  XtPointer client_data,
3950  XtPointer)
3951 {
3953 
3954  int n;
3955  Arg args[3];
3956  Widget parent, scrollWidget;
3957  parent = SoXt::getShellWidget(This->getParentWidget());
3958 
3959  if (This->saveSceneGraphDialog == NULL) {
3960 
3961  // Change the 'OK' button to whatever buttonLabel contains
3962  XmString str = XmStringCreateLocalized((char *)"Save");
3963 
3964  n = 0;
3965  XtSetArg(args[n], XmNokLabelString, str); n++;
3966  XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
3967 
3968  This->saveSceneGraphDialog = XmCreateFileSelectionDialog(parent,(char *)"Save Scene Graph", args, n);
3969 
3970  XtAddCallback(This->saveSceneGraphDialog, XmNokCallback, saveSceneGraphCB, This);
3971  XtAddCallback(This->saveSceneGraphDialog, XmNcancelCallback, cancelFileSelDialogCB, This);
3972 
3973  // Adding scrolling functionality to the widget
3974  scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_DIR_LIST);
3975  if (scrollWidget)
3976  xmAddMouseEventHandler(scrollWidget);
3977  scrollWidget = XmFileSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_LIST);
3978  if (scrollWidget)
3979  xmAddMouseEventHandler(scrollWidget);
3980 
3981  XtUnmanageChild(XmSelectionBoxGetChild(This->saveSceneGraphDialog, XmDIALOG_HELP_BUTTON));
3982  XmStringFree(str);
3983  }
3984 
3985  //TODO: Auto name?
3986 
3987  XtManageChild(This->saveSceneGraphDialog);
3988 
3989 }
3990 
3991 
3992 
3993 void G4OpenInventorXtExaminerViewer::saveSceneGraphCB(Widget w,
3994  XtPointer client_data,
3995  XtPointer call_data)
3996 {
3997  char *file;
3999  XmFileSelectionBoxCallbackStruct *cbs =
4000  (XmFileSelectionBoxCallbackStruct *) call_data;
4001 
4002  if (cbs) {
4003 
4004  file = (char *)XmStringUnparse(cbs->value, XmFONTLIST_DEFAULT_TAG,
4005  XmCHARSET_TEXT, XmCHARSET_TEXT,
4006  NULL, 0, XmOUTPUT_ALL);
4007 
4008  std::ifstream ifile(file);
4009  if (ifile) {
4010  //File already exists
4011 
4012  Arg args[4];
4013  Widget parent = This->getParentWidget(); //gets the dialogshell of the ExaminerViewer widget
4014  Widget confirmOverwriteDialog;
4015  XmString msg;
4016 
4017  confirmOverwriteDialog = XmCreateQuestionDialog (parent, (char *)"Confirm overwrite", args, 0);
4018  msg = XmStringCreateLocalized ((char *)"File exists. Overwrite?");
4019  XtVaSetValues (confirmOverwriteDialog, XmNmessageString, msg, NULL);
4020 
4021  // If users presses OK, we want to return to this function and
4022  // save the file. For that to work, pass it the current widget
4023  // to be able to grab the filename.
4024  XtVaSetValues (confirmOverwriteDialog, XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL, NULL);
4025  XtAddCallback (confirmOverwriteDialog, XmNokCallback, saveSceneGraphOverWriteCB, client_data);
4026  XtAddCallback (confirmOverwriteDialog, XmNcancelCallback, saveSceneGraphOverWriteCB, client_data);
4027 
4028  XmStringFree (msg);
4029 
4030  //The confirmOverwriteDialog will need this
4031  This->saveScenegraphFileName = file;
4032  This->saveScenegraphWidget = w;
4033 
4034  XtUnmanageChild(XtNameToWidget(confirmOverwriteDialog, "Help"));
4035  XtManageChild(confirmOverwriteDialog);
4036 
4037  return;
4038  }
4039  else{
4040 
4041  SoWriteAction writeAction;
4042  SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
4043 
4044  SoOutput * out = writeAction.getOutput();
4045 
4046  if(out->openFile(file)){
4047  out->setBinary(FALSE);
4048  writeAction.apply(root);
4049  out->closeFile();
4050 
4051  XtUnmanageChild(w);
4052  }
4053  else{
4054  String dialogName = (char *) "Error opening file";
4055  std::string msg = "There was a problem trying to open the file '";
4056  msg += This->saveScenegraphFileName;
4057  msg += "'";
4058 
4059  This->warningMsgDialog(msg, dialogName, NULL);
4060  }
4061 
4062  }
4063  }
4064 
4065  return;
4066 }
4067 
4068 
4069 
4070 void G4OpenInventorXtExaminerViewer::saveSceneGraphOverWriteCB(Widget w,
4071  XtPointer client_data,
4072  XtPointer call_data)
4073 {
4074  XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
4076 
4077  switch (cbs->reason) {
4078  case XmCR_OK:
4079  {
4080  // Overwrite confirmed, save file and dismiss both
4081  // dialogs (file dialog and overwrite confirmation dialog)
4082  SoWriteAction writeAction;
4083  SoSeparator *root = (SoSeparator *) (This->getSceneGraph());
4084 
4085  SoOutput * out = writeAction.getOutput();
4086  if(out->openFile(This->saveScenegraphFileName.c_str())){
4087  out->setBinary(FALSE);
4088  writeAction.apply(root);
4089  out->closeFile();
4090 
4091  XtUnmanageChild(w);
4092  XtUnmanageChild(This->saveScenegraphWidget);
4093  This->saveScenegraphFileName.clear();
4094  This->saveScenegraphWidget = NULL;
4095  }
4096  else{
4097  String dialogName = (char *) "Error opening file";
4098  std::string msg = "There was a problem trying to open the file '";
4099  msg += This->saveScenegraphFileName;
4100  msg += "'";
4101 
4102  This->warningMsgDialog(msg, dialogName, NULL);
4103  This->saveScenegraphFileName.clear();
4104  This->saveScenegraphWidget = NULL;
4105  }
4106  break;
4107  }
4108  case XmCR_CANCEL:
4109  {
4110  // Overwrite refused, dismiss overwrite confirmation
4111  // dialog and return to file dialog
4112 
4113  // Give focus to the text field instead of the OK button
4114  XmProcessTraversal(XtNameToWidget(This->saveScenegraphWidget, "Text"), XmTRAVERSE_CURRENT);
4115 
4116  XtUnmanageChild(w);
4117  This->saveScenegraphFileName.clear();
4118  This->saveScenegraphWidget = NULL;
4119  break;
4120  }
4121  default:
4122  return;
4123  }
4124 }
4125 
4126 
4127 // Receives the name of the bookmark clicked and searches for it in viewPtList.
4128 
4129 void G4OpenInventorXtExaminerViewer::loadBookmarkCB(Widget,
4130  XtPointer client_data,
4131  XtPointer call_data)
4132 {
4133  char *vpName;
4135  XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
4136 
4137  vpName = (char *) XmStringUnparse(cbs->item, XmFONTLIST_DEFAULT_TAG,
4138  XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
4139 
4140  for (int i = 0; i < (int) This->viewPtList.size(); i++) {
4141  if (!strcmp(This->viewPtList[i].viewPtName, vpName)) {
4142  This->viewPtIdx = i;
4143  break;
4144  }
4145  }
4146  XmTextSetString(This->viewPtSelection, vpName);
4147 
4148  This->writeViewPtIdx();
4149  This->setViewPt();
4150  XtFree(vpName);
4151 }
4152 
4153 
4154 
4155 void G4OpenInventorXtExaminerViewer::deleteBookmarkCB(Widget,
4156  XtPointer client_data,
4157  XtPointer)
4158 {
4159  char *vpName;
4161 
4162  vpName = XmTextGetString(This->viewPtSelection);
4163 
4164  XmString vpNameStr = XmStringCreateLocalized(vpName);
4165 
4166  if (XmListItemExists(This->myViewPtList, vpNameStr)) {
4167  XmListDeleteItem(This->myViewPtList, vpNameStr);
4168  This->deleteViewPt(vpName);
4169  }
4170 
4171  XmStringFree(vpNameStr);
4172  XmTextSetString(This->viewPtSelection, NULL);
4173  XtFree(vpName);
4174 }
4175 
4176 
4177 void G4OpenInventorXtExaminerViewer::renameBookmarkCB(Widget,
4178  XtPointer client_data,
4179  XtPointer)
4180 {
4181  std::string vpNameStr;
4182  char *vpName;
4183  int *pos_list, pos_cnt;
4185 
4186  vpName = XmTextGetString(This->viewPtSelection);
4187 
4188  if (!strlen(vpName) || !strcmp(This->curViewPtName, vpName)) {
4189  XtFree(vpName);
4190  return;
4191  }
4192 
4193  vpNameStr = vpName;
4194  XtFree(vpName);
4195  int beg = vpNameStr.find_first_not_of(' '); // Remove leading/trailing spaces
4196  int end = vpNameStr.find_last_not_of(' ');
4197  vpNameStr = vpNameStr.substr(beg, end - beg + 1);
4198  vpName = new char[vpNameStr.size() + 1];
4199  strcpy(vpName, vpNameStr.c_str());
4200 
4201  int size = This->viewPtList.size();
4202  for (int i = 0; i < size; i++) {
4203  if (!strcmp(vpName, This->viewPtList[i].viewPtName)) {
4204 
4205  String dialogName = (char *) "Existing Viewpoint";
4206  std::string msg = "'";
4207  msg += vpName;
4208  msg += "' already exists. Choose a different name";
4209 
4210  This->warningMsgDialog(msg, dialogName, NULL);
4211  return;
4212  }
4213  }
4214 
4215  XmString vpNameXmStr = XmStringCreateLocalized(vpName);
4216 
4217  if (XmListGetSelectedPos(This->myViewPtList, &pos_list, &pos_cnt)) {
4218  XmListReplaceItemsPos(This->myViewPtList, &vpNameXmStr, 1, pos_list[0]);
4219  This->renameViewPt(vpName);
4220  XtFree((char *) pos_list);
4221  }
4222 
4223  if (This->currentState == VIEWPOINT)
4224  This->scheduleRedraw();
4225 
4226  XmStringFree(vpNameXmStr);
4227 }
4228 
4229 
4230 void G4OpenInventorXtExaminerViewer::sortBookmarksCB(Widget,
4231  XtPointer client_data,
4232  XtPointer)
4233 {
4234  int size;
4235  char *vpName;
4236  XmString *strList, *newStrList;
4237  std::vector<std::string> charList;
4239 
4240  if (This->viewPtList.size() < 2)
4241  return;
4242 
4243  // Get current entries from the list
4244  XtVaGetValues(This->myViewPtList, XmNitemCount, &size, XmNitems, &strList,
4245  NULL);
4246 
4247  for (int i = 0; i < size; i++) {
4248  vpName = (char *) XmStringUnparse(strList[i], XmFONTLIST_DEFAULT_TAG,
4249  XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
4250  charList.push_back(vpName);
4251  XtFree(vpName);
4252  }
4253 
4254  std::sort(charList.begin(), charList.end());
4255 
4256  newStrList = (XmString *) XtMalloc(size * sizeof(XmString));
4257  for (int i = 0; i < size; i++) {
4258  // viewPtIdx has to be changed to account for a different order in viewPtList
4259  if (!strcmp(charList[i].c_str(), This->curViewPtName))
4260  This->viewPtIdx = i;
4261  char *vpName2 = new char[charList[i].size() + 1];
4262  strcpy(vpName2, charList[i].c_str());
4263  newStrList[i] = XmStringCreateLocalized(vpName2);
4264  delete vpName2;
4265  }
4266 
4267  XmListDeleteAllItems(This->myViewPtList);
4268  XmListAddItemsUnselected(This->myViewPtList, newStrList, size, 1);
4269 
4270  This->sortViewPts(charList);
4271 
4272  if (newStrList != NULL) {
4273  for (int i = 0; i < size; i++)
4274  XmStringFree(newStrList[i]);
4275  XtFree((char *) newStrList);
4276  }
4277 }
4278 
4279 
4280 void G4OpenInventorXtExaminerViewer::evenOutRefParticlePts()
4281 {
4282  if(this->refParticleTrajectory.empty())
4283  return;
4284 
4285  SbVec3f p1, p2, p3, dirNow, dirNxt, dir, p2_tmp, p_start, p_corner, p_nxt;
4286  float avgDistBtwPts = 0;
4287  float totalDistBtwPts = 0;
4288  std::vector<SbVec3f> newRefParticleTrajectory;
4289  SbVec3f refPoint;
4290  int size = refParticleTrajectory.size() - 1;
4291  int numOfPts = 0;
4292  for (int i = 0; i < size; i++) {
4293  p1 = refParticleTrajectory[i];
4294  p2 = refParticleTrajectory[i + 1];
4295  if (p1 == p2)
4296  continue;
4297  numOfPts++;
4298  totalDistBtwPts += (p2 - p1).length();
4299  }
4300 
4301  avgDistBtwPts = totalDistBtwPts / numOfPts;
4302  float minDistAllowed = 0.75 * avgDistBtwPts;
4303  // float maxDistAllowed = 1.25 * avgDistBtwPts; // Pts tend to be close not far
4304 
4305  float x, y, z;
4306  int i = 0, j = 0;
4307  while (i < size) {
4308  p1 = refParticleTrajectory[i];
4309  p2 = refParticleTrajectory[i + 1];
4310 
4311  refPoint = p1;
4312  p1.getValue(x, y, z);
4313 
4314  newRefParticleTrajectory.push_back(refPoint);
4315 
4316  j = i;
4317  while ((p2 - p1).length() < minDistAllowed && j < (size - 1)) {
4318  j++;
4319 
4320  p1 = refParticleTrajectory[j];
4321  p2 = refParticleTrajectory[j + 1];
4322  }
4323  if (j != i)
4324  i = j + 1;
4325  else
4326  i++;
4327  }
4328 
4329  refParticleTrajectory.clear();
4330  refParticleTrajectory = newRefParticleTrajectory;
4331 }
4332 
4333 
4334 // Called when the viewer is closed; closes all open widgets.
4335 
4336 void G4OpenInventorXtExaminerViewer::closeMainWindowCB(Widget,
4337  XtPointer client_data,
4338  XtPointer)
4339 {
4341  (G4OpenInventorXtExaminerViewer *) client_data;
4342 
4343  if (This->openFileDialog)
4344  XtUnmanageChild(This->openFileDialog);
4345 
4346  if (This->newFileDialog)
4347  XtUnmanageChild(This->newFileDialog);
4348 
4349  if (This->listsDialog)
4350  closeListsDialogCB(NULL, This, NULL);
4351 }
4352 
4353 
4354 void G4OpenInventorXtExaminerViewer::saveCurCamera()
4355 {
4356  SoCamera *cam = getCamera();
4357  camB4Animation.viewportMapping = cam->viewportMapping.getValue();
4358  camB4Animation.position = cam->position.getValue();
4359  camB4Animation.orientation = cam->orientation.getValue();
4360  camB4Animation.aspectRatio = cam->aspectRatio.getValue();
4361  camB4Animation.nearDistance = cam->nearDistance.getValue();
4362  camB4Animation.farDistance = cam->farDistance.getValue();
4363  camB4Animation.focalDistance = cam->focalDistance.getValue();
4364 
4365  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
4366  camB4Animation.height =
4367  ((SoPerspectiveCamera *) cam)->heightAngle.getValue();
4368  camB4Animation.camType = PERSPECTIVE;
4369  } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
4370  camB4Animation.height =
4371  ((SoOrthographicCamera *) cam)->height.getValue();
4372  camB4Animation.camType = ORTHOGRAPHIC;
4373  }
4374 }
4375 
4376 
4377 void G4OpenInventorXtExaminerViewer::restoreCamera()
4378 {
4379  SoCamera *cam = getCamera();
4380 
4381  cam->viewportMapping = camB4Animation.viewportMapping;
4382  cam->position = camB4Animation.position;
4383  cam->orientation = camB4Animation.orientation;
4384  cam->aspectRatio = camB4Animation.aspectRatio;
4385  cam->nearDistance = camB4Animation.nearDistance;
4386  cam->farDistance = camB4Animation.farDistance;
4387  cam->focalDistance = camB4Animation.focalDistance;
4388 
4389  if (cam->isOfType(SoPerspectiveCamera::getClassTypeId())) {
4390  if (camB4Animation.camType == ORTHOGRAPHIC) {
4391  toggleCameraType();
4392  cam = getCamera();
4393  ((SoOrthographicCamera *) cam)->height.setValue(
4394  camB4Animation.height);
4395  } else
4396  ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
4397  camB4Animation.height);
4398  } else if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
4399  if (camB4Animation.camType == PERSPECTIVE) {
4400  toggleCameraType();
4401  cam = getCamera();
4402  ((SoPerspectiveCamera *) cam)->heightAngle.setValue(
4403  camB4Animation.height);
4404  } else
4405  ((SoOrthographicCamera *) cam)->height.setValue(
4406  camB4Animation.height);
4407  }
4408 }
4409 
4410 
4411 void G4OpenInventorXtExaminerViewer::animateSensorRotationCB(void *data,
4412  SoSensor *sensor)
4413 {
4414  SbTime curTime = SbTime::getTimeOfDay();
4416  SoTimerSensor *s = (SoTimerSensor *) sensor;
4417 
4418  float t = float((curTime - s->getBaseTime()).getValue())
4419  / This->animateBtwPtsPeriod;
4420 
4421  if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
4422  t = 1.0f;
4423  SbBool end = (t == 1.0f);
4424 
4425  if (end) {
4426  This->animateSensorRotation->unschedule();
4427  if(This->rotCnt){
4428  // rotations left
4429  This->rotateCamera();
4430  }
4431  else {
4432  // rotation over
4433  This->currentState = This->prevState;
4434  return;
4435  }
4436  }
4437 
4438 }
4439 
4440 
4441 // Called repeatedly during reference particle animation
4442 
4443 void G4OpenInventorXtExaminerViewer::animateSensorCB(void *data,
4444  SoSensor *sensor)
4445 {
4446  SbTime curTime = SbTime::getTimeOfDay();
4448  SoCamera *cam = This->getCamera();
4449  SoTimerSensor *s = (SoTimerSensor *) sensor;
4450 
4451  float t = float((curTime - s->getBaseTime()).getValue())
4452  / This->animateBtwPtsPeriod;
4453 
4454  if ((t > 1.0f) || (t + s->getInterval().getValue() > 1.0f))
4455  t = 1.0f;
4456  SbBool end = (t == 1.0f);
4457 
4458  cam->orientation = SbRotation::slerp(This->camStartOrient, This->camEndOrient, t);
4459  cam->position = This->camStartPos + (This->camEndPos - This->camStartPos) * t;
4460 
4461  if (end) {
4462  This->animateSensor->unschedule();
4463 
4464  if (This->currentState == ANIMATION) {
4465  if (This->refParticleIdx < (int) (This->refParticleTrajectory.size() - 1))
4466  This->animateRefParticle();
4467  else {
4468  This->animateBtwPtsPeriod = MIN_SPEED;
4469  This->speedStep = START_STEP;
4470  }
4471  }
4472  if (This->currentState == REVERSED_ANIMATION) {
4473  if (This->refParticleIdx >= 1)
4474  This->animateRefParticle();
4475  else {
4476  This->animateBtwPtsPeriod = MIN_SPEED;
4477  This->speedStep = START_STEP;
4478  }
4479  }
4480  }
4481 }
4482 
4483 
4484 void G4OpenInventorXtExaminerViewer::setStartingPtForAnimation()
4485 {
4486  if (SoXtExaminerViewer::isAnimating())
4487  stopAnimating();
4488 
4489  SbRotation rot;
4490  SbVec3f p1, p2, p2_tmp, camUpV, camD, camD_tmp, leftRightAxis;
4491  float x1, y1, z1, x2, y2, z2;
4492 
4493  if (currentState == ANIMATION) {
4494  p1 = refParticleTrajectory[refParticleIdx];
4495  p2 = refParticleTrajectory[++(refParticleIdx)];
4496  } else if (currentState == REVERSED_ANIMATION) {
4497  p2 = refParticleTrajectory[refParticleIdx];
4498  p1 = refParticleTrajectory[--(refParticleIdx)];
4499  } else if (currentState == PAUSED_ANIMATION) {
4500  if (refParticleIdx < (int) refParticleTrajectory.size()) {
4501  p1 = refParticleTrajectory[refParticleIdx];
4502  p2 = refParticleTrajectory[refParticleIdx + 1];
4503  } else {
4504  p1 = refParticleTrajectory[refParticleIdx - 1];
4505  p2 = refParticleTrajectory[refParticleIdx];
4506  }
4507  }
4508  p1.getValue(x1, y1, z1);
4509  p2.getValue(x2, y2, z2);
4510 
4511  camD = p2 - p1;
4512  camD.normalize();
4513 
4514  p2_tmp.setValue(x2, y1, z2);
4515  camD_tmp = p2_tmp - p1;
4516  camD_tmp.normalize();
4517 
4518  camUpV.setValue(0, 1, 0);
4519  rot.setValue(camD_tmp, camD);
4520  rot.multVec(camUpV, camUpV);
4521 
4522  leftRightAxis = camD.cross(camUpV);
4523 
4524  myCam->position = p1;
4525  myCam->pointAt(p2, camUpV);
4526 
4527  // Update camera position
4528  p1 = p1 + (up_down * camUpV) + (left_right * leftRightAxis);
4529  myCam->position = p1;
4530 }
4531 
4532 
4533 void G4OpenInventorXtExaminerViewer::gotoRefPathStart()
4534 {
4535  G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(NULL, (void *)this,
4536  NULL);
4537 }
4538 
4539 
4540 void G4OpenInventorXtExaminerViewer::gotoRefPathStartCB(Widget,
4541  XtPointer client_data,
4542  XtPointer)
4543 {
4545 
4546  if (!This->refParticleTrajectory.size()) {
4547  String dialogName = (char *) "No Reference Trajectory";
4548  std::string msg = "You need to start a run or load a reference trajectory from a file";
4549  This->warningMsgDialog(msg, dialogName, NULL);
4550  return;
4551  }
4552 
4553  if (This->currentState == ROTATING)
4554  return;
4555  if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
4556  || This->currentState == PAUSED_ANIMATION) {
4557  if (This->animateSensor->isScheduled())
4558  This->animateSensor->unschedule();
4559  This->setSuperimpositionEnabled(This->superimposition, FALSE);
4560  This->maxSpeed = 0.0f;
4561  This->scheduleRedraw();
4562  } else {
4563  This->saveCurCamera();
4564  This->prevState = This->currentState;
4565  This->prevRefIdx = This->refParticleIdx;
4566  }
4567 
4568  if (This->SoXtExaminerViewer::isAnimating())
4569  This->stopAnimating();
4570 
4571  This->up_down = 0;
4572  This->left_right = 0;
4573  This->step = 1;
4574 
4575  This->refParticleIdx = 0;
4576  This->currentState = BEAMLINE;
4577  This->setSuperimpositionEnabled(This->superimposition, TRUE);
4578  This->axisSwitch->whichChild.setValue(SO_SWITCH_NONE);
4579  This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_NONE);
4580  This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_NONE);
4581  This->scheduleRedraw();
4582 
4583  // FWJ Disabled: this is set in moveCamera()
4584  // Zoom in
4585  // SoCamera *cam = This->getCamera();
4586  // cam->focalDistance = 0.1f;
4587 
4588  This->prevParticleDir = SbVec3f(0,0,0);
4589 
4590  //Default zoom
4591  SbVec3f p1 = This->refParticleTrajectory[0];
4592  SbVec3f pN = This->refParticleTrajectory[This->refParticleTrajectory.size() - 1];
4593  This->distance = (pN - p1).length() / 10;
4594 
4595  This->moveCamera(This->distance, true);
4596 }
4597 
4598 
4599 void G4OpenInventorXtExaminerViewer::invertRefPathCB(Widget,
4600  XtPointer client_data,
4601  XtPointer)
4602 {
4604  (G4OpenInventorXtExaminerViewer *) client_data;
4605  This->invertRefPath();
4606 }
4607 
4608 
4609 void G4OpenInventorXtExaminerViewer::invertRefPath()
4610 {
4611  std::reverse(this->refParticleTrajectory.begin(),
4612  this->refParticleTrajectory.end());
4613  this->setReferencePathZPos();
4614  this->sortElements();
4615 }
4616 
4617 
4618 void G4OpenInventorXtExaminerViewer::animateRefParticleCB(Widget,
4619  XtPointer client_data,
4620  XtPointer)
4621 {
4623 
4624  if (!This->refParticleTrajectory.size()) {
4625  This->returnToAnim = true;
4626  String dialogName = (char *) "No Reference Trajectory";
4627  std::string msg = "You need to start a run or load a reference trajectory from a file";
4628  This->warningMsgDialog(msg, dialogName, NULL);
4629  return;
4630  }
4631 
4632  if (!This->refParticleTrajectory.size())
4633  return;
4634 
4636  This->setSuperimpositionEnabled(This->superimposition, TRUE);
4637  This->maxSpeed = SPEED_INDICATOR_STEP;
4638  This->axisSwitch->whichChild.setValue(SO_SWITCH_ALL);
4639  This->animSpeedOutlineSwitch->whichChild.setValue(SO_SWITCH_ALL);
4640  This->animSpeedSwitch->whichChild.setValue(SO_SWITCH_ALL);
4641  This->scheduleRedraw();
4643 
4644  SoCamera *cam = This->getCamera();
4645  // SbVec3f camDirOld, camDirNew, camDirNew_tmp, camUpVec, P0, P1, P1_tmp;
4646 
4647  if (This->currentState == ANIMATION || This->currentState == REVERSED_ANIMATION
4648  || This->currentState == ROTATING)
4649  return;
4650 
4651  if (This->currentState != PAUSED_ANIMATION) {
4652 
4653  This->saveCurCamera();
4654  This->prevState = This->currentState;
4655  This->prevRefIdx = This->refParticleIdx;
4656 
4657  if (cam->isOfType(SoOrthographicCamera::getClassTypeId())) {
4658  This->toggleCameraType();
4659  cam = This->getCamera();
4660  }
4661 
4662  This->refParticleIdx = 0; // Set the camera to the starting point of the animation
4663  This->animateBtwPtsPeriod = MIN_SPEED;
4664  This->speedStep = START_STEP;
4665  This->left_right = This->up_down = 0;
4666 
4667  cam->focalDistance = 0.1f;
4668  ((SoPerspectiveCamera *) cam)->heightAngle = 0.50f;
4669  }
4670 
4671  This->currentState = ANIMATION;
4672  This->setStartingPtForAnimation();
4673 
4674  cam->position = (This->myCam)->position.getValue();
4675  cam->orientation = (This->myCam)->orientation.getValue();
4676  This->animateRefParticle(); // Animate the camera
4677 }
4678 
4679 
4680 void G4OpenInventorXtExaminerViewer::animateRefParticle()
4681 {
4682  SoCamera *cam = getCamera();
4683 
4684  camStartPos = cam->position.getValue();
4685  camStartOrient = cam->orientation.getValue();
4686 
4687  if (currentState != BEAMLINE)
4688  setStartingPtForAnimation();
4689 
4690  camEndPos = myCam->position.getValue();
4691  camEndOrient = myCam->orientation.getValue();
4692 
4693  if (animateSensor->isScheduled())
4694  animateSensor->unschedule();
4695 
4696  animateSensor->setBaseTime(SbTime::getTimeOfDay());
4697  animateSensor->setInterval(SbTime(0.02));
4698 
4699  animateSensor->schedule();
4700 }
4701 
4702 
4704  void (*callback)(void *), void * object)
4705 {
4706  this->escapeCallback = callback;
4707  this->examinerObject = object;
4708 }
4709 
4710 
4711 void G4OpenInventorXtExaminerViewer::sceneChangeCB(void *userData, SoSensor *)
4712 {
4714  (G4OpenInventorXtExaminerViewer*)userData;
4715  if(This->newEvents){
4716  This->findAndSetRefPath();
4717  This->newEvents = false;
4718  }
4719 }
4720 
4721 
4723 {
4724  this->viewer = vwr;
4725 }
4726 
4727 
4729 {;}
4730 
4731 
4733 {
4734  if(requiredState == G4State_EventProc){
4735  this->viewer->newEvents = true;
4736  }
4737  return true;
4738 }