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