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