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