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