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