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