Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/OpenInventor/src/G4OpenInventorQtExaminerViewer.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /visualization/OpenInventor/src/G4OpenInventorQtExaminerViewer.cc (Version 11.3.0) and /visualization/OpenInventor/src/G4OpenInventorQtExaminerViewer.cc (Version 5.2)


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26                                                   
 27 // Frederick Jones TRIUMF 07 January 2018         
 28                                                   
 29 #include "G4OpenInventorQtExaminerViewer.hh"      
 30                                                   
 31 #include "ui_OIQtListsDialog.h"                   
 32                                                   
 33 #include "saveViewPt.h"                           
 34 #include "pickext.h"                              
 35 #include "pickref.h"                              
 36 #include "wireframe.h"                            
 37                                                   
 38 #include <algorithm> // For using sort on a ve    
 39                                                   
 40 #include "G4ios.hh"                               
 41 #include "G4UImanager.hh"                         
 42 #include "G4UIQt.hh"                              
 43                                                   
 44 #include <Inventor/Qt/SoQt.h>                     
 45 #include <Inventor/Qt/SoQtCursor.h>               
 46 #include <Inventor/events/SoKeyboardEvent.h>      
 47 #include <Inventor/events/SoMouseButtonEvent.h    
 48 #include <Inventor/events/SoLocation2Event.h>     
 49 #include <Inventor/nodes/SoSeparator.h>           
 50 #include <Inventor/nodes/SoOrthographicCamera.    
 51 #include <Inventor/nodes/SoPerspectiveCamera.h    
 52                                                   
 53 // FWJ moved to header file                       
 54 //#include <Inventor/nodes/SoEventCallback.h>     
 55 #include <Inventor/nodes/SoLineSet.h>             
 56 #include <Inventor/nodes/SoMaterial.h>            
 57 #include <Inventor/errors/SoDebugError.h>         
 58 #include <Inventor/SoPickedPoint.h>               
 59 #include <Inventor/actions/SoWriteAction.h>       
 60 #include <Inventor/projectors/SbPlaneProjector    
 61                                                   
 62 #include <Inventor/sensors/SoTimerSensor.h>       
 63 #include <Inventor/sensors/SoNodeSensor.h>        
 64                                                   
 65 #include "Geant4_SoPolyhedron.h"                  
 66 #include "G4TrajectoryPoint.hh"                   
 67 #include "G4AttHolder.hh"                         
 68 #include "G4AttCheck.hh"                          
 69 #if 0x060000 <= QT_VERSION                        
 70 #include "G4StateManager.hh"                      
 71 #endif                                            
 72                                                   
 73 #include <Inventor/nodes/SoCallback.h>            
 74 #include <Inventor/nodes/SoSwitch.h>              
 75 #include <Inventor/nodes/SoScale.h>               
 76 #include <Inventor/nodes/SoTranslation.h>         
 77 #include <Inventor/actions/SoSearchAction.h>      
 78 #include <Inventor/actions/SoGetBoundingBoxAct    
 79                                                   
 80 #include <Inventor/nodes/SoCoordinate3.h>         
 81 // For rendering distance during animation:       
 82 #include <Inventor/nodes/SoText2.h>               
 83 #include <Inventor/nodes/SoFont.h>                
 84 #include <Inventor/nodes/SoPointSet.h>            
 85 #include <Inventor/nodes/SoDrawStyle.h>           
 86 #include <Inventor/nodes/SoBaseColor.h>           
 87                                                   
 88 // For searching for nodes within kits:           
 89 #include <Inventor/nodekits/SoBaseKit.h>          
 90                                                   
 91 #include <QMenuBar>                               
 92 #include <QPushButton>                            
 93 #include <QRadioButton>                           
 94 #include <QToolButton>                            
 95 #include <QListWidget>                            
 96 #include <QListWidgetItem>                        
 97 #include <QInputDialog>                           
 98 #include <QMessageBox>                            
 99 #include <QFileDialog>                            
100 #include <QStyle>                                 
101 #include <QCommonStyle>                           
102 //#include <QMainWindow>                          
103                                                   
104 #ifndef G4GMAKE                                   
105 #include "moc_G4OpenInventorQtExaminerViewer.c    
106 #endif                                            
107                                                   
108 #define G4warn G4cout                             
109                                                   
110 #if QT_VERSION < 0x060000                         
111 G4OpenInventorQtExaminerViewer* G4OpenInventor    
112 #endif                                            
113                                                   
114 #define MIN_SPEED  2.1        // Lower number     
115 #define START_STEP 0.3                            
116 #define SPEED_INDICATOR_STEP 0.045                
117 #define MAX_SPEED_INDICATOR  0.81                 
118 // Number of steps 90 degree rotation around a    
119 #define ROT_CNT 6                                 
120                                                   
121                                                   
122 // Constructor                                    
123 G4OpenInventorQtExaminerViewer::                  
124 G4OpenInventorQtExaminerViewer(QWidget* parent    
125                                SoQtFullViewer:    
126                                SoQtViewer::Typ    
127    : SoQtExaminerViewer(parent, name, embed, f    
128 #if 0x060000 <= QT_VERSION                        
129      fName(name),                                 
130 #endif                                            
131      externalQtApp(0), processSoEventCount(0)     
132 {                                                 
133    // FWJ DEBUG                                   
134    //  G4cout << "G4OpenInventorQtExaminerView    
135    //  G4cout << "G4OpenInventorQtExaminerView    
136                                                   
137    // FWJ THIS DOESN'T WORK APPARENTLY NO MAIN    
138    //   QMenuBar* menubar = ((QMainWindow*)par    
139                                                   
140 #if QT_VERSION < 0x060000                         
141    fName = new QString(name);                     
142    viewer = this;                                 
143 #endif                                            
144    construct(TRUE);                               
145 }                                                 
146                                                   
147 // Destructor                                     
148 G4OpenInventorQtExaminerViewer::~G4OpenInvento    
149 {                                                 
150    //   if (superimposition != NULL) {            
151    //      removeSuperimposition(superimpositi    
152    //      superimposition->unref();              
153    //      superimposition = NULL;                
154    //   }                                         
155    //   if (animateSensor->isScheduled())         
156    //      animateSensor->unschedule();           
157    //   delete animateSensor;                     
158    //   delete sceneChangeSensor;                 
159    //   delete[] curViewPtName;                   
160    //   delete searcher;                          
161                                                   
162 #if QT_VERSION < 0x060000                         
163    viewer = 0;                                    
164 #else                                             
165    delete hookBeamOn;                             
166 #endif                                            
167 }                                                 
168                                                   
169                                                   
170 void G4OpenInventorQtExaminerViewer::construct    
171 {                                                 
172    setFeedbackSize(40);                           
173                                                   
174    hookBeamOn = new HookEventProcState(this);     
175    newEvents = false;                             
176                                                   
177    buildWidget(getParentWidget());                
178                                                   
179    fileName = "bookmarkFile"; // Default viewp    
180    viewPtIdx = -1; // index of the most recent    
181                                                   
182    animateSensor = new SoTimerSensor(animateSe    
183    animateSensorRotation = new SoTimerSensor(a    
184    animateBtwPtsPeriod = MIN_SPEED;               
185                                                   
186    currentState = GENERAL;                        
187    myCam = new SoPerspectiveCamera;               
188    MAX_VP_IDX = 3;                                
189    MAX_VP_NAME = 35; // Max length of a viewpo    
190 #if QT_VERSION < 0x060000                         
191    curViewPtName = new char[MAX_VP_NAME + 1];     
192 #else                                             
193    curViewPtName.clear();                         
194 #endif                                            
195    left_right = up_down = 0; // For movements     
196    speedStep = START_STEP; // For smoother ani    
197    rotUpVec = false; // Used during scene elem    
198    step = 1;  //By default                        
199    // Used for moving along the beam with the     
200    // mouse instead of rotating the view          
201    lshiftdown = rshiftdown = false;               
202    // Used for rotating the view with the came    
203    // staying in place                            
204    lctrldown = rctrldown = false;                 
205    // Used to send abbreviated output to the c    
206    abbrOutputFlag = false;                        
207    pickRefPathFlag = false;                       
208    prevColorField = NULL;                         
209    //   warningFlag = false; // We come from t    
210    //   myElementList = NULL;                     
211    // FWJ default path look-ahead                 
212    pathLookahead = 5;                             
213                                                   
214    newSceneGraph = NULL;                          
215    zcoordSetFlag = false;                         
216                                                   
217    //////////////////////////SUPERIMPOSED SCEN    
218    searcher = NULL;                               
219    // Used in animation; progressively scaled     
220    maxSpeed = 0.0f;                               
221                                                   
222    static const char * superimposed[] = {         
223       "#Inventor V2.1 ascii", "",                 
224       "Separator ",                               
225       "{",                                        
226       " MaterialBinding ",                        
227       " {",                                       
228       "         value OVERALL",                   
229       " }",                                       
230       "         OrthographicCamera ",             
231       " {",                                       
232       "         height 1",                        
233       "         nearDistance 0",                  
234       "         farDistance 1",                   
235       " }",                                       
236       "         DEF soxt->callback Callback {     
237       "         Separator ",                      
238       " {",                                       
239       "         DEF soxt->translation Translat    
240       "         {",                               
241       "                 translation 0 0 0",       
242       "     }",                                   
243       "     DEF soxt->scale Scale ",              
244       "         {",                               
245       "                 scaleFactor 1 1 1",       
246       "     }",                                   
247       "         DEF soxt->geometry Coordinate3    
248       "         {",                               
249       "             point ",                      
250       "                 [",                       
251       "                         -0.81   -0.04     
252       "                 -0.81   0.04    0,        
253       "                 0       0       0,  0     
254       "                 0.81    -0.04   0,  0.    
255       "                 0.81    0.04    0,",      
256       "                 0       0.02    0,", /    
257       "                 0.81    0.02    0,  0.    
258       "                 0       -0.02   0,",      
259       "                 0       0.01    0,", /    
260       "                 0.4     0.01    0,  0.    
261       "                 0       -0.01   0",       
262       "                 ]",                       
263       "         }",                               
264       // current speed indicator (outline)        
265       "         DEF soxt->animSpeedOutlineSwit    
266       "         {",                               
267       "                 whichChild -3",           
268       "                 Material ",               
269       "                 {",                       
270       "                    emissiveColor 0 0 0    
271       "             }",                           
272       "                 IndexedFaceSet ",         
273       "                 {",                       
274       "                 coordIndex ",             
275       "                         [",               
276       "                                 12, 11    
277       "                         ]",               
278       "         }",                               
279       "                  }",                      
280       // the coordinate system                    
281       "         DEF soxt->axisSwitch Switch ",    
282       "         {",                               
283       "                 whichChild -3",           
284       "                 BaseColor ",              
285       "                 {",                       
286       "                     rgb 1 1 1",           
287       "                 }",                       
288       "                 IndexedLineSet ",         
289       "                 {",                       
290       "                         coordIndex ",     
291       "                         [",               
292       "                                 0, 2,     
293       "                                 3, 5,     
294       "                                 6, 8,     
295       "                                 1, 7,     
296       "                         ]",               
297       "                     }",                   
298       "                 }",                       
299       // current speed indicator                  
300       "         DEF soxt->animSpeedSwitch Swit    
301       "         {",                               
302       "                     whichChild -3",       
303       "                 Material ",               
304       "                 {",                       
305       "                 emissiveColor 0 1 0",     
306       "         }",                               
307       "                 IndexedFaceSet ",         
308       "                 {",                       
309       "                 coordIndex ",             
310       "                         [",               
311       "                                 16, 15    
312       "                         ]",               
313       "                 }",                       
314       "         }",                               
315       "         }",                               
316       // For displaying either z position (dur    
317       " DEF soxt->curInfoSwitch Switch ",         
318       " {",                                       
319       "         whichChild -3",                   
320       "         DEF soxt->curInfoTrans Transla    
321       "         {",                               
322       "                 translation 0 0 0    "    
323       //      "                 translation 10    
324       "         }",                               
325       "         DEF soxt->curInfoFont Font ",     
326       "         {",                               
327       "                 name defaultFont:Bold"    
328       "                 size 16",                 
329       "                 }",                       
330       "         DEF soxt->curInfoText Text2 ",    
331       "         {",                               
332       "                 string Hello",            
333       "     }",                                   
334       " }",                                       
335       // Need to use different fields for mous    
336       // because newlines are ignored when the    
337       " Separator ",                              
338       " {",                                       
339       "         DEF soxt->mouseOverTransLogNam    
340       "         {",                               
341       "                 translation 0 0 0    "    
342       "         }",                               
343       "         DEF soxt->mouseOverFontLogName    
344       "         {",                               
345       "                 name defaultFont:Bold"    
346       "                 size 16",                 
347       "                 }",                       
348       "         DEF soxt->mouseOverTextLogName    
349       " }",                                       
350       " Separator ",                              
351       " {",                                       
352       "         DEF soxt->mouseOverTransSolid     
353       "         {",                               
354       "                 translation 0 0 0    "    
355       "         }",                               
356       "         DEF soxt->mouseOverFontSolid F    
357       "         {",                               
358       "                 name defaultFont:Bold"    
359       "                 size 16",                 
360       "                 }",                       
361       "         DEF soxt->mouseOverTextSolid T    
362       " }",                                       
363       " Separator ",                              
364       " {",                                       
365       "         DEF soxt->mouseOverTransMateri    
366       "         {",                               
367       "                 translation 0 0 0    "    
368       "         }",                               
369       "         DEF soxt->mouseOverFontMateria    
370       "         {",                               
371       "                 name defaultFont:Bold"    
372       "                 size 16",                 
373       "                 }",                       
374       "         DEF soxt->mouseOverTextMateria    
375       " }",                                       
376       " Separator ",                              
377       " {",                                       
378       "         DEF soxt->mouseOverTransZPos T    
379       "         {",                               
380       "                 translation 0 0 0    "    
381       "         }",                               
382       "         DEF soxt->mouseOverFontZPos Fo    
383       "         {",                               
384       "                 name defaultFont:Bold"    
385       "                 size 16",                 
386       "                 }",                       
387       "         DEF soxt->mouseOverTextZPos Te    
388       " }",                                       
389       "}", NULL                                   
390    };                                             
391                                                   
392    int i, bufsize;                                
393    for (i = bufsize = 0; superimposed[i]; i++)    
394       bufsize += strlen(superimposed[i]) + 1;     
395    char * buf = new char[bufsize + 1];            
396    for (i = bufsize = 0; superimposed[i]; i++)    
397       strcpy(buf + bufsize, superimposed[i]);     
398       bufsize += strlen(superimposed[i]);         
399       buf[bufsize] = '\n';                        
400       bufsize++;                                  
401    }                                              
402    SoInput * input = new SoInput;                 
403    input->setBuffer(buf, bufsize);                
404    SbBool ok = SoDB::read(input, superimpositi    
405    (void)ok;   // FWJ added to avoid compiler     
406    assert(ok);                                    
407    delete input;                                  
408    delete[] buf;                                  
409    superimposition->ref();                        
410                                                   
411    sscale = (SoScale *) getSuperimpositionNode    
412    stranslation = (SoTranslation *) getSuperim    
413    sgeometry = (SoCoordinate3 *) getSuperimpos    
414    axisSwitch = (SoSwitch *) getSuperimpositio    
415    animSpeedOutlineSwitch = (SoSwitch *) getSu    
416    animSpeedSwitch = (SoSwitch *) getSuperimpo    
417    curInfoSwitch = (SoSwitch *) getSuperimposi    
418    curInfoTrans = (SoTranslation *) getSuperim    
419    curInfoFont = (SoFont *) getSuperimposition    
420    curInfoText = (SoText2 *) getSuperimpositio    
421    mouseOverTransLogName = (SoTranslation*)get    
422    mouseOverFontLogName = (SoFont *) getSuperi    
423    mouseOverTextLogName = (SoText2 *) getSuper    
424    mouseOverTransSolid = (SoTranslation *) get    
425    mouseOverFontSolid = (SoFont *) getSuperimp    
426    mouseOverTextSolid = (SoText2 *) getSuperim    
427    mouseOverTransMaterial = (SoTranslation*)ge    
428    mouseOverFontMaterial = (SoFont *) getSuper    
429    mouseOverTextMaterial = (SoText2 *) getSupe    
430    mouseOverTransZPos = (SoTranslation *) getS    
431    mouseOverFontZPos = (SoFont *) getSuperimpo    
432    mouseOverTextZPos = (SoText2 *) getSuperimp    
433                                                   
434    SoCallback * cb = (SoCallback *) getSuperim    
435    cb->setCallback(superimpositionCB, this);      
436                                                   
437    addSuperimposition(superimposition);           
438    setSuperimpositionEnabled(superimposition,     
439    axisSwitch->whichChild.setValue(SO_SWITCH_N    
440    animSpeedOutlineSwitch->whichChild.setValue    
441    animSpeedSwitch->whichChild.setValue(SO_SWI    
442                                                   
443    /////////////////////\SUPERIMPOSED SCENE///    
444                                                   
445 }                                                 
446                                                   
447                                                   
448 // Adds a menu bar and menu items to the viewe    
449 void G4OpenInventorQtExaminerViewer::buildWidg    
450 {                                                 
451    if (!parent)                                   
452       SoDebugError::post("G4OpenInventorQtExam    
453                          "Error: Parent is nul    
454                                                   
455    // Common font for (almost) all widgets        
456    font = new QFont;                              
457    font->setPointSize(12);                        
458    // This font setting does not propagate to     
459    parent->setFont(*font);                        
460    // This propagates everywhere but would aff    
461    //   QApplication::setFont(*font);             
462                                                   
463 // MENU BAR                                       
464                                                   
465 #if QT_VERSION < 0x060000                         
466    menubar = new QMenuBar(getRenderAreaWidget(    
467 #else                                             
468    menubar = new QMenuBar();                      
469    menubar->setNativeMenuBar(false);              
470    addAppPushButton(menubar);                     
471 #endif                                            
472    // FWJ DEBUG                                   
473    //   G4cout << "G4OpenInventorQtExaminerVie    
474    //      menubar << G4endl;                     
475                                                   
476    filemenu = new QMenu("File");                  
477    menubar->addMenu(filemenu);                    
478                                                   
479    FileOpenBookmark = new QAction("Open Bookma    
480    FileOpenBookmark->setFont(*font);              
481    connect(FileOpenBookmark, SIGNAL(triggered(    
482            SLOT(FileOpenBookmarkCB()));           
483    filemenu->addAction(FileOpenBookmark);         
484                                                   
485    FileNewBookmark = new QAction("New Bookmark    
486    FileNewBookmark->setFont(*font);               
487    connect(FileNewBookmark, SIGNAL(triggered()    
488            SLOT(FileNewBookmarkCB()));            
489    filemenu->addAction(FileNewBookmark);          
490                                                   
491    FileLoadRefPath = new QAction("Load Referen    
492    FileLoadRefPath->setFont(*font);               
493    connect(FileLoadRefPath, SIGNAL(triggered()    
494            SLOT(FileLoadRefPathCB()));            
495    filemenu->addAction(FileLoadRefPath);          
496                                                   
497    FileSaveRefPath = new QAction("Save Referen    
498    FileSaveRefPath->setFont(*font);               
499    connect(FileSaveRefPath, SIGNAL(triggered()    
500            SLOT(FileSaveRefPathCB()));            
501    filemenu->addAction(FileSaveRefPath);          
502                                                   
503    FileLoadSceneGraph = new QAction("Load scen    
504    FileLoadSceneGraph->setFont(*font);            
505    connect(FileLoadSceneGraph, SIGNAL(triggere    
506            SLOT(FileLoadSceneGraphCB()));         
507    filemenu->addAction(FileLoadSceneGraph);       
508                                                   
509    FileSaveSceneGraph = new QAction("Save scen    
510    FileSaveSceneGraph->setFont(*font);            
511    connect(FileSaveSceneGraph, SIGNAL(triggere    
512            SLOT(FileSaveSceneGraphCB()));         
513    filemenu->addAction(FileSaveSceneGraph);       
514                                                   
515    // Rest of File menu is done in G4OpenInven    
516                                                   
517    toolsmenu = new QMenu("Tools");                
518    menubar->addMenu(toolsmenu);                   
519                                                   
520    ToolsAnimateRefParticle = new QAction("Fly     
521    ToolsAnimateRefParticle->setFont(*font);       
522    connect(ToolsAnimateRefParticle, SIGNAL(tri    
523            SLOT(ToolsAnimateRefParticleCB()));    
524    toolsmenu->addAction(ToolsAnimateRefParticl    
525                                                   
526    ToolsRefPathStart = new QAction("Go to star    
527    ToolsRefPathStart->setFont(*font);             
528    connect(ToolsRefPathStart, SIGNAL(triggered    
529            SLOT(ToolsRefPathStartCB()));          
530    toolsmenu->addAction(ToolsRefPathStart);       
531                                                   
532    ToolsRefPathInvert = new QAction("Invert Re    
533    ToolsRefPathInvert->setFont(*font);            
534    connect(ToolsRefPathInvert, SIGNAL(triggere    
535            SLOT(ToolsRefPathInvertCB()));         
536    toolsmenu->addAction(ToolsRefPathInvert);      
537                                                   
538    etcmenu = new QMenu("Etc");                    
539    menubar->addMenu(etcmenu);                     
540                                                   
541    // All Etc menu items are done in G4OpenInv    
542                                                   
543    helpmenu = new QMenu("Help");                  
544    menubar->addMenu(helpmenu);                    
545                                                   
546    HelpControls = new QAction("Controls", this    
547    HelpControls->setFont(*font);                  
548    connect(HelpControls, SIGNAL(triggered()),     
549    helpmenu->addAction(HelpControls);             
550                                                   
551 #if QT_VERSION < 0x060000                         
552    menubar->show();                               
553 #endif                                            
554                                                   
555    //   SoQtExaminerViewer::buildWidget(parent    
556                                                   
557    // APP VIEWER BUTTONS have their own box on    
558    // The built in viewer button list is PRIVA    
559                                                   
560    saveViewPtButton = new QPushButton;            
561    saveViewPtButton->setIcon(QPixmap((const ch    
562    saveViewPtButton->setIconSize(QSize(24,24))    
563    saveViewPtButton->setToolTip("Bookmark this    
564    connect(saveViewPtButton, SIGNAL(clicked())    
565            SLOT(SaveViewPtCB()));                 
566    addAppPushButton(saveViewPtButton);            
567                                                   
568    nextViewPtButton = new QPushButton;            
569    nextViewPtButton->setIconSize(QSize(24,24))    
570    QCommonStyle style;                            
571    nextViewPtButton->setIcon(style.standardIco    
572    nextViewPtButton->setToolTip("Next bookmark    
573    connect(nextViewPtButton, SIGNAL(clicked())    
574            SLOT(NextViewPtCB()));                 
575    addAppPushButton(nextViewPtButton);            
576                                                   
577    prevViewPtButton = new QPushButton;            
578    prevViewPtButton->setIconSize(QSize(24,24))    
579    prevViewPtButton->setIcon(style.standardIco    
580    prevViewPtButton->setToolTip("Previous book    
581    connect(prevViewPtButton, SIGNAL(clicked())    
582            SLOT(PrevViewPtCB()));                 
583    addAppPushButton(prevViewPtButton);            
584                                                   
585    abbrOutputButton = new QPushButton;            
586    abbrOutputButton->setCheckable(true);          
587    abbrOutputButton->setIconSize(QSize(24,24))    
588    abbrOutputButton->setIcon(QPixmap((const ch    
589    abbrOutputButton->setToolTip("Extended pick    
590    connect(abbrOutputButton, SIGNAL(toggled(bo    
591            SLOT(AbbrOutputCB(bool)));             
592    addAppPushButton(abbrOutputButton);            
593                                                   
594    pickRefPathButton = new QPushButton;           
595    pickRefPathButton->setIconSize(QSize(24,24)    
596    pickRefPathButton->setIcon(QPixmap((const c    
597    pickRefPathButton->setToolTip("Pick ref tra    
598    connect(pickRefPathButton, SIGNAL(clicked()    
599            SLOT(PickRefPathCB()));                
600    addAppPushButton(pickRefPathButton);           
601                                                   
602    switchWireFrameButton = new QPushButton;       
603    switchWireFrameButton->setCheckable(true);     
604    switchWireFrameButton->setIconSize(QSize(24    
605    switchWireFrameButton->setIcon(QPixmap((con    
606    switchWireFrameButton->setToolTip("Switch w    
607    connect(switchWireFrameButton, SIGNAL(toggl    
608            SLOT(SwitchWireFrameCB(bool)));        
609    addAppPushButton(switchWireFrameButton);       
610                                                   
611    switchAxesButton = new QPushButton;            
612    switchAxesButton->setCheckable(true);          
613    switchAxesButton->setText(QString("A"));       
614    switchAxesButton->setToolTip("Axes on/off")    
615    connect(switchAxesButton, SIGNAL(toggled(bo    
616            SLOT(SwitchAxesCB(bool)));             
617    addAppPushButton(switchAxesButton);            
618                                                   
619    detachButton = new QPushButton;                
620    detachButton->setIconSize(QSize(24,24));       
621    detachButton->setIcon(style.standardIcon(QS    
622    detachButton->setToolTip("Detach viewer win    
623    connect(detachButton, SIGNAL(clicked()), th    
624            SLOT(DetachCB()));                     
625    // Used for UIQt only so check and add late    
626    //   addAppPushButton(detachButton);           
627                                                   
628    // HELP WINDOW                                 
629                                                   
630    helpmsgbox = new QMessageBox(getParentWidge    
631    helpmsgbox->setWindowTitle("OIQt Controls")    
632    helpmsgbox->setFont(*font);                    
633    QString messagetxt =                           
634 "\nVIEWING mode (Hand cursor):\n\n\               
635    Left-button + pointer move:  rotate\n\         
636    Shift+Left-button + pointer move:  pan\n\      
637    Middle-button + pointer move:  pan\n\          
638    Ctrl+Shift+Left-button + pointer move:  zoo    
639    Mouse wheel:  zoom\n\                          
640    Right-button:  popup menu\n\n\                 
641 PICKING mode (Arrow cursor):\n\n\                 
642    Click on a volume:  geometry readout\n\        
643    Click on a trajectory:  particle & trajecto    
644    Ctrl + click on a volume:  see daughters.\n    
645    Shift + click on a volume:  see mother.\n\n    
646 EXTENDED PICKING mode (Arrow+ viewer button):\    
647    Hover the mouse over a volume or trajectory    
648    overlayed readout.\n\n\                        
649 ELEMENT NAVIGATION (requires Reference Path):\    
650    Click on element in list:  centers view on     
651    Arrow keys:  rotate in 90 degree steps arou    
652    Shift + Right Arrow:  move to next element\    
653    Shift + Left Arrow:  move to previous eleme    
654 FLY mode (requires Reference Path):\n\n\          
655    Page Up:  Increase speed\n\                    
656    Page Down:  Decrease speed (& reverse if wa    
657    Up Arrow:  raise camera above path\n\          
658    Down Arror:  lower camera below path\n\        
659    Escape:  Exit fly mode";                       
660    helpmsgbox->setText(messagetxt);               
661    helpmsgbox->setModal(false);                   
662    //   helpmsgbox->setWindowModality(Qt::NonM    
663                                                   
664    // AUXILIARY LISTS WINDOW                      
665                                                   
666    // Bypass the namespace in order to make a     
667    AuxWindowDialog = new Ui_Dialog;               
668    AuxWindow = new QDialog(parent);               
669    AuxWindowDialog->setupUi(AuxWindow);           
670                                                   
671    // SIGNALS                                     
672    connect(AuxWindowDialog->listWidget, SIGNAL    
673            this, SLOT(LoadBookmarkCB(QListWidg    
674    connect(AuxWindowDialog->listWidget1, SIGNA    
675            this, SLOT(LookAtSceneElementCB(QLi    
676    connect(AuxWindowDialog->pushButton_2, SIGN    
677            this, SLOT(DeleteBookmarkCB()));       
678    connect(AuxWindowDialog->pushButton_3, SIGN    
679            this, SLOT(RenameBookmarkCB()));       
680    connect(AuxWindowDialog->pushButton, SIGNAL    
681            this, SLOT(SortBookmarksCB()));        
682                                                   
683    // FWJ Better to do this after viewer windo    
684    //   AuxWindow->show();                        
685    //   AuxWindow->raise();                       
686    //   AuxWindow->activateWindow();              
687 }                                                 
688                                                   
689                                                   
690 #if QT_VERSION < 0x060000                         
691 // Called right after buttons and widgets get     
692 // It sets the viewpoint last accessed.           
693 void G4OpenInventorQtExaminerViewer::afterReal    
694 {                                                 
695    SoQtExaminerViewer::afterRealizeHook();        
696 #else                                             
697 void G4OpenInventorQtExaminerViewer::setupScen    
698 {                                                 
699 #endif                                            
700    // Default height is used when selecting an    
701    // FWJ Added defaultHeight for Ortho camera    
702    SoCamera *cam = getCamera();                   
703    if (cam) {                                     
704       if (cam->isOfType(SoPerspectiveCamera::g    
705          defaultHeightAngle =                     
706             ((SoPerspectiveCamera *) cam)->hei    
707          toggleCameraType();                      
708          defaultHeight =                          
709             ((SoOrthographicCamera *) cam)->he    
710          toggleCameraType();                      
711       } else {                                    
712          defaultHeight =                          
713             ((SoOrthographicCamera *) cam)->he    
714          toggleCameraType();                      
715          cam = getCamera();                       
716          if (cam->isOfType(SoPerspectiveCamera    
717             defaultHeightAngle =                  
718                ((SoPerspectiveCamera *) cam)->    
719          toggleCameraType();                      
720       }                                           
721    }                                              
722                                                   
723    // Open the default bookmark file              
724    fileIn.open(fileName.c_str());                 
725    if (!fileIn.fail()) {                          
726       if (!loadViewPts()) {                       
727          QMessageBox msgbox;                      
728          msgbox.setFont(*font);                   
729          QString messagetxt = "Error reading b    
730          messagetxt.append(QString(fileName.c_    
731          msgbox.setText(messagetxt);              
732          msgbox.exec();                           
733       } else {                                    
734          // Opens a file without erasing it       
735          fileOut.open(fileName.c_str(), std::i    
736          fileOut.seekp(0, std::ios::end); // F    
737          // FWJ DEBUG                             
738          // G4cout << "afterRealizeHook: opene    
739          //        << G4endl;                     
740          if (viewPtList.size()) {                 
741             // FWJ disabled auto-selection of     
742             // Initial view should be user-con    
743             //    setViewPt();                    
744             addViewPoints();                      
745          }                                        
746       }                                           
747       fileIn.close();                             
748    } else {                                       
749       // Creates a new default bookmark file      
750       fileOut.open(fileName.c_str());             
751       // FWJ DEBUG                                
752       // G4cout << "afterRealizeHook: Opened a    
753    }                                              
754                                                   
755    fileIn.clear();                                
756                                                   
757    SoSeparator* root = (SoSeparator*) (getScen    
758    if (root == NULL)                              
759       SoDebugError::post("G4OpenInventorQtExam    
760    else {                                         
761       root->addChild(myCam); // For position/o    
762    }                                              
763                                                   
764 #if 0x060000 <= QT_VERSION                        
765    if(root!=nullptr) {                            
766 #endif                                            
767    sceneChangeSensor = new SoNodeSensor;          
768    sceneChangeSensor->setFunction(sceneChangeC    
769    sceneChangeSensor->attach(root);               
770    sceneChangeSensor->setData(this);              
771                                                   
772    ///////////////////////////// MOUSEOVER & P    
773                                                   
774    // Monitor mouseover events for displaying     
775    // An SoEventCallback is needed instead of     
776    // because that last one does not provide u    
777    // that was picked                             
778    SoEventCallback *moCB = new SoEventCallback    
779    moCB->addEventCallback(                        
780                           SoLocation2Event::ge    
781                           mouseoverCB, static_    
782    root->addChild(moCB);                          
783                                                   
784    // Override the default picking mechanism p    
785    // because we want abbreviated output when     
786    SoEventCallback *pickCB = new SoEventCallba    
787    pickCB->addEventCallback(                      
788                             SoMouseButtonEvent    
789                             pickingCB, static_    
790    root->addChild(pickCB);                        
791 #if 0x060000 <= QT_VERSION                        
792    }                                              
793 #endif                                            
794                                                   
795    ///////////////////////////// MOUSEOVER & P    
796                                                   
797 #if QT_VERSION < 0x060000                         
798    AuxWindow->show();                             
799    AuxWindow->raise();                            
800    AuxWindow->activateWindow();                   
801                                                   
802    auto UI = G4UImanager::GetUIpointer();         
803    uiQt = dynamic_cast<G4UIQt*>(UI->GetG4UIWin    
804    // This explicitly sets the TabWidget as pa    
805    if (uiQt) {                                    
806       viewerParent = getParentWidget();           
807       viewerParent2 = viewerParent->parentWidg    
808       uiQt->AddTabWidget(getParentWidget(), *f    
809       uiQtTabIndex = uiQt->GetViewerTabWidget(    
810       //      attached = TRUE;                    
811       addAppPushButton(detachButton);             
812    }                                              
813 #else                                             
814    //G.Barrand: map the AuxWindow "at need", i    
815    //           Having one appearing for each     
816    //           Also, if "closing" the AuxWind    
817    //           way to map it again. Moreover,    
818    //           it inactivates the Apple menu     
819    //           AuxWindow per viewer, why not     
820    //           tab widget? It will go toward     
821 #endif                                            
822 }                                                 
823                                                   
824 #if 0x060000 <= QT_VERSION                        
825 void G4OpenInventorQtExaminerViewer::addInTab(    
826   auto UI = G4UImanager::GetUIpointer();          
827   uiQt = dynamic_cast<G4UIQt*>(UI->GetG4UIWind    
828   if(uiQt) {                                      
829     uiQt->AddTabWidget(getParentWidget(),fName    
830     addAppPushButton(detachButton);               
831   }                                               
832 }                                                 
833 #endif                                            
834                                                   
835 // This method locates a named node in the sup    
836 // FWJ RENAME THIS                                
837 SoNode*                                           
838 G4OpenInventorQtExaminerViewer::getSuperimposi    
839                                                   
840 {                                                 
841    if (!searcher)                                 
842       searcher = new SoSearchAction;              
843    searcher->reset();                             
844    searcher->setName(SbName(name));               
845    searcher->setInterest(SoSearchAction::FIRST    
846    searcher->setSearchingAll(TRUE);               
847    searcher->apply(root);                         
848    assert(searcher->getPath());                   
849    return searcher->getPath()->getTail();         
850 }                                                 
851                                                   
852                                                   
853 // FWJ don't know why userdata is called "clos    
854 // It contains the this pointer!                  
855 void G4OpenInventorQtExaminerViewer::superimpo    
856                                                   
857 {                                                 
858    if (closure)                                   
859       ((G4OpenInventorQtExaminerViewer*)closur    
860 }                                                 
861                                                   
862                                                   
863 // Renders and positions speed indicator and l    
864 // distance/viewpoint name on the drawing canv    
865 void G4OpenInventorQtExaminerViewer::superimpo    
866 {                                                 
867                                                   
868    if (!action->isOfType(SoGLRenderAction::get    
869       return;                                     
870    SbViewportRegion vpRegion =                    
871       ((SoGLRenderAction*)action)->getViewport    
872    SbVec2s viewportSize = vpRegion.getViewport    
873                                                   
874    // Aspect is WIDTH/HEIGHT                      
875    float aspect = float(viewportSize[0]) / flo    
876                                                   
877    // FWJ DEBUG                                   
878    //   G4cout << "SPEVENT X0 Y0 DX DY aspect:    
879    //      " " << vpRegion.getViewportOrigin()    
880    //      " " << viewportSize[0] <<              
881    //      " " << viewportSize()[1] <<            
882    //      " " << aspect << G4endl;               
883                                                   
884    // Translation and scale factor for animati    
885                                                   
886    float factorx = 1.0f / float(viewportSize[1    
887    float factory = factorx;                       
888                                                   
889    if (aspect > 1.0f) {                           
890       stranslation->translation.setValue(SbVec    
891    } else {                                       
892       stranslation->translation.setValue(SbVec    
893       factorx /= aspect;                          
894       factory /= aspect;                          
895    }                                              
896    if (viewportSize[0] > 500)                     
897       factorx *= 500.0f / 400.0f;                 
898    else                                           
899       factorx *= float(viewportSize[0]) / 400.    
900                                                   
901    sscale->scaleFactor.setValue(SbVec3f(factor    
902                                                   
903    // TEXT OVERLAY...                             
904                                                   
905    // FWJ Simplified and rewrote the following    
906    // with the overlayed text after a viewer w    
907    // Result is now readable but needs further    
908                                                   
909    float xInfo, yInfo, xLogName, yLogName, xSo    
910       xMaterial, yMaterial, xZPos, yZPos;         
911                                                   
912    // Base point for navigation distance or vi    
913    // Origin is at center of render area.         
914    xInfo = -.475;                                 
915    yInfo = .475;                                  
916    // Menu bar height in same coordinates:        
917    float mbgap = 0.03;                            
918    if (aspect > 1.) xInfo = xInfo*aspect;         
919    if (aspect < 1.) yInfo = yInfo/aspect;         
920    yInfo = yInfo - mbgap*aspect;                  
921                                                   
922    // Following are relative to above base poi    
923    xLogName = 0.0;                                
924    yLogName = -.88 + mbgap*aspect;                
925    xSolid = 0.0;                                  
926    ySolid = -.91 + mbgap*aspect;                  
927    xMaterial = 0.0;                               
928    yMaterial = -.94 + mbgap*aspect;               
929    xZPos = 0.0;                                   
930    yZPos = -.97 + mbgap*aspect;                   
931                                                   
932    // Top line                                    
933    curInfoTrans->translation.setValue(SbVec3f(    
934                                                   
935    // Bottom lines                                
936    mouseOverTransLogName->translation.setValue    
937    mouseOverTransSolid->translation.setValue(S    
938    mouseOverTransMaterial->translation.setValu    
939    mouseOverTransZPos->translation.setValue(Sb    
940                                                   
941    if (currentState == VIEWPOINT) { // Display    
942       curInfoFont->size.setValue(15);             
943       curInfoFont->name.setValue("defaultFont:    
944 #if QT_VERSION < 0x060000                         
945       curInfoText->string.setValue(SbString(cu    
946 #else                                             
947       curInfoText->string.setValue(SbString(cu    
948 #endif                                            
949    }                                              
950    else if(currentState == GENERAL) { // Displ    
951       curInfoFont->size.setValue(16);             
952       curInfoFont->name.setValue("defaultFont:    
953       curInfoText->string.setValue(SbString(""    
954    }                                              
955    else {                                         
956       if (refParticleIdx < (int) refParticleTr    
957          curInfoFont->size.setValue(16);          
958          curInfoFont->name.setValue("defaultFo    
959          char zPos[20];                           
960          // FWJ need a better format here         
961          snprintf(zPos, sizeof zPos, "%-7.2f [    
962          curInfoText->string.setValue(SbString    
963       }                                           
964    }                                              
965 }                                                 
966                                                   
967                                                   
968 //  Loads view point data from a file into a v    
969                                                   
970 bool G4OpenInventorQtExaminerViewer::loadViewP    
971 {                                                 
972    bool error = false;                            
973    viewPtData tmp;                                
974    std::string token;                             
975    SbVec3f axis;                                  
976    SbRotation orient;                             
977    float x{0.0}, y{0.0}, z{0.0}, angle{0.0};      
978                                                   
979    // Gets the last view point accessed, store    
980    fileIn >> token;                               
981    parseString<int>(viewPtIdx, token, error);     
982    getline(fileIn, token); // Remove "\n"         
983    // Converts data from string type into nece    
984    while (getline(fileIn, token)) {               
985                                                   
986       std::size_t end = token.find_last_not_of    
987       token = token.substr(0, end + 1);           
988                                                   
989 #if QT_VERSION < 0x060000                         
990       char *vpName = new char[token.size() + 1    
991       strcpy(vpName, token.c_str());              
992       tmp.viewPtName = vpName;                    
993 #else                                             
994       tmp.viewPtName = token;                     
995 #endif                                            
996       fileIn >> token;                            
997                                                   
998       parseString<float>(x, token, error);        
999       fileIn >> token;                            
1000       parseString<float>(y, token, error);       
1001       fileIn >> token;                           
1002       parseString<float>(z, token, error);       
1003       fileIn >> token;                           
1004       tmp.position = axis.setValue(x, y, z);     
1005                                                  
1006       parseString<float>(x, token, error);       
1007       fileIn >> token;                           
1008       parseString<float>(y, token, error);       
1009       fileIn >> token;                           
1010       parseString<float>(z, token, error);       
1011       fileIn >> token;                           
1012       parseString<float>(angle, token, error)    
1013       fileIn >> token;                           
1014       orient.setValue(axis.setValue(x, y, z),    
1015       tmp.orientation = orient.getValue();       
1016                                                  
1017       int camType{0};                            
1018       parseString<int>(camType, token, error)    
1019       fileIn >> token;                           
1020       tmp.camType = (CameraType) camType;        
1021                                                  
1022       parseString<float>(tmp.height, token, e    
1023       fileIn >> token;                           
1024       parseString<float>(tmp.focalDistance, t    
1025       fileIn >> token;                           
1026       parseString<float>(tmp.nearDistance, to    
1027       fileIn >> token;                           
1028       parseString<float>(tmp.farDistance, tok    
1029       fileIn >> token;                           
1030       parseString<int>(tmp.viewportMapping, t    
1031       fileIn >> token;                           
1032       parseString<float>(tmp.aspectRatio, tok    
1033                                                  
1034       getline(fileIn, token); // To remove "\    
1035       getline(fileIn, token);                    
1036                                                  
1037       if (error) {                               
1038 #if QT_VERSION < 0x060000                        
1039          viewPtIdx = 0;                          
1040 #else                                            
1041          viewPtIdx = -1;                         
1042 #endif                                           
1043          viewPtList.clear();                     
1044          return false;                           
1045       }                                          
1046       viewPtList.push_back(tmp);                 
1047    }                                             
1048                                                  
1049    return true;                                  
1050 }                                                
1051                                                  
1052                                                  
1053 // Rotates camera 90 degrees around a scene e    
1054 // Rotation is animated for smoothness.          
1055 void G4OpenInventorQtExaminerViewer::rotateCa    
1056 {                                                
1057    SoCamera *cam = getCamera();                  
1058                                                  
1059    SbRotation rot(rotAxis, M_PI / (2 * ROT_CN    
1060    rot.multVec(camDir, camDir);                  
1061    rot.multVec(camUpVec, camUpVec);              
1062                                                  
1063    SbVec3f camPosNew = prevPt - (camDir*dista    
1064    cam->position = camPosNew;                    
1065    cam->pointAt(prevPt, camUpVec);               
1066    cam->focalDistance = (prevPt - camPosNew).    
1067                                                  
1068    rotCnt--;                                     
1069                                                  
1070    if (animateSensorRotation->isScheduled())     
1071       animateSensorRotation->unschedule();       
1072    }                                             
1073                                                  
1074    animateSensorRotation->setBaseTime(SbTime:    
1075    animateSensorRotation->setInterval(SbTime(    
1076    animateSensorRotation->schedule();            
1077                                                  
1078 }                                                
1079                                                  
1080                                                  
1081 // Slides camera along the beamline.             
1082 void G4OpenInventorQtExaminerViewer::moveCame    
1083 {                                                
1084                                                  
1085    SoCamera *cam = getCamera();                  
1086    SbVec3f p1, p2;   // The particle moves fr    
1087    SbVec3f particleDir;  // Direction vector     
1088    SbVec3f camPosNew{0.0f, 0.0f, 0.0f};  // N    
1089                                                  
1090    if(refParticleTrajectory.size() == 0) {       
1091       //refParticleTrajectory hasn't been set    
1092       if(dist)                                   
1093          distance = dist;                        
1094       else                                       
1095          distance = (cam->position.getValue()    
1096                                                  
1097       cam->position.setValue(center + offsetF    
1098       cam->focalDistance = (cam->position.get    
1099       cam->pointAt(center, upVector);            
1100    }                                             
1101    else {                                        
1102                                                  
1103       // If we move forward past the last tra    
1104       // go back to the beginning                
1105       if (refParticleIdx >= (int) refParticle    
1106          prevPt = refParticleTrajectory[refPa    
1107          dist = (prevPt - cam->position.getVa    
1108          refParticleIdx = 0;                     
1109       }                                          
1110       // If we move backward past the beginni    
1111       // go to the last trajectory point         
1112       if (refParticleIdx < 0) {                  
1113          prevPt = refParticleTrajectory[refPa    
1114          dist = (prevPt - cam->position.getVa    
1115          refParticleIdx = (int) refParticleTr    
1116       }                                          
1117                                                  
1118       // Set start and end points                
1119       p1 = refParticleTrajectory[refParticleI    
1120       p2 = refParticleTrajectory[refParticleI    
1121                                                  
1122       // Get the direction from p1 to p2         
1123       particleDir = p2 - p1;                     
1124       particleDir.normalize();                   
1125                                                  
1126       if(prevParticleDir == SbVec3f(0,0,0)) {    
1127          // First time entering BEAMLINE mode    
1128          // the element from the front, with     
1129          if(lookdown)                            
1130             camDir = SbVec3f(0,0,1);             
1131          else                                    
1132             camDir = SbVec3f(1,0,0);             
1133          camUpVec = SbVec3f(0,1,0);              
1134                                                  
1135          // In case the start of the goes in     
1136          // direction other than +z, rotate t    
1137          SbRotation rot(SbVec3f(0,0,1), parti    
1138          rot.multVec(camDir, camDir);            
1139          rot.multVec(camUpVec, camUpVec);        
1140                                                  
1141       }                                          
1142       else if(particleDir != prevParticleDir)    
1143          // The beamline has changed directio    
1144                                                  
1145          SbRotation rot(prevParticleDir, part    
1146          rot.multVec(camDir, camDir);            
1147          rot.multVec(camUpVec, camUpVec);        
1148                                                  
1149       }                                          
1150                                                  
1151       if (cam->isOfType(SoPerspectiveCamera::    
1152          if (!dist)                              
1153             distance = (prevPt - cam->positio    
1154          else                                    
1155             distance = dist;                     
1156       }                                          
1157                                                  
1158       // FWJ distance not relevant -- use foc    
1159       // if (cam->isOfType(SoOrthographicCame    
1160       //    if (!dist)                           
1161       //       distance = (prevPt - cam->posi    
1162       //    else                                 
1163       //       distance = dist;                  
1164       // }                                       
1165                                                  
1166                                                  
1167       float x,y,z;                               
1168       prevPt.getValue(x,y,z);                    
1169                                                  
1170                                                  
1171       if (cam->isOfType(SoPerspectiveCamera::    
1172          camPosNew = p2 - (camDir*distance);     
1173       }                                          
1174       if (cam->isOfType(SoOrthographicCamera:    
1175          // FWJ maintain focal distance          
1176          camPosNew = p2 - (camDir*cam->focalD    
1177          //         camPosNew = p2 - (camDir)    
1178       }                                          
1179                                                  
1180       cam->position = camPosNew;                 
1181       cam->pointAt(p2, camUpVec);                
1182       cam->focalDistance = (p2 - camPosNew).l    
1183                                                  
1184       p2.getValue(x,y,z);                        
1185       camPosNew.getValue(x,y,z);                 
1186                                                  
1187       prevParticleDir = particleDir;             
1188       prevPt = p1; // For accurate distance c    
1189                                                  
1190    }                                             
1191                                                  
1192 }                                                
1193                                                  
1194                                                  
1195 void G4OpenInventorQtExaminerViewer::pickingC    
1196                                                  
1197 {                                                
1198    SoHandleEventAction* action = eventCB->get    
1199    const SoPickedPoint *pp = action->getPicke    
1200    G4OpenInventorQtExaminerViewer* This = (G4    
1201                                                  
1202    if(pp != NULL) {                              
1203                                                  
1204       SoPath* path = pp->getPath();              
1205       SoNode* node = ((SoFullPath*)path)->get    
1206                                                  
1207       if(node->getTypeId() == SoLineSet::getC    
1208                                                  
1209          if(This->pickRefPathFlag) {             
1210             This->pickRefPathFlag = false;       
1211             if(This->viewingBeforePickRef !=     
1212                This->setViewing(This->viewing    
1213             else                                 
1214                This->setComponentCursor(SoQtC    
1215                                                  
1216             // The trajectory is a set of lin    
1217             SoLineSet * trajectory = (SoLineS    
1218             // FWJ DEBUG                         
1219             // G4cout << "FOUND trajectory Li    
1220                                                  
1221        // The set of all trajectories is stor    
1222        // one level above the LineSet that wa    
1223        // seperator are as follows (in this o    
1224        // ResetTransform, MatrixTransform, Co    
1225             SoSeparator * grpNode =              
1226                (SoSeparator*)(((SoFullPath*)p    
1227                                                  
1228    // The node that contains the coordinates     
1229    // Coordinate3 node which occurs before th    
1230    // back through the nodes in the group unt    
1231             int nodeIndex = grpNode->findChil    
1232             SoNode * tmpNode;                    
1233             // FWJ needs initialization          
1234             SoCoordinate3 * coords = 0;          
1235             //            SoCoordinate3 * coo    
1236             // We allow only 100 iterations,     
1237             // (should take only a few iterat    
1238             for(int i = 0; i < 100; ++i) {       
1239                --nodeIndex;                      
1240                                                  
1241                tmpNode = grpNode->getChild(no    
1242                if(tmpNode->getTypeId() == SoC    
1243                   //node found                   
1244                   coords = (SoCoordinate3 *)t    
1245                   break;                         
1246                }                                 
1247             }                                    
1248                                                  
1249             if(coords == NULL) {                 
1250                G4warn << "Could not find the     
1251                   " for the picked trajectory    
1252                G4warn << " Reference trajecto    
1253                return;                           
1254             }                                    
1255             // FWJ DEBUG                         
1256             // G4cout << "FOUND SoCoordinate3    
1257                                                  
1258                                                  
1259             if ((This->lshiftdown)  || (This-    
1260                This->setReferencePath(traject    
1261             else                                 
1262                This->setReferencePath(traject    
1263                                                  
1264             return;                              
1265                                                  
1266          }                                       
1267          else if(This->abbrOutputFlag) {         
1268                                                  
1269             G4AttHolder* attHolder = dynamic_    
1270             if(attHolder && attHolder->GetAtt    
1271                                                  
1272                std::string strTrajPoint = "G4    
1273                std::ostringstream oss;           
1274                for (std::size_t i = 0; i < at    
1275                   G4cout << G4AttCheck(attHol    
1276                                        attHol    
1277                   oss << G4AttCheck(attHolder    
1278                                     attHolder    
1279                   if(oss.str().find(strTrajPo    
1280                                                  
1281            // Last attribute displayed was a     
1282            // want abbreviated output, displa    
1283            // (unless we're already at the la    
1284                      if(i != attHolder->GetAt    
1285                         G4cout << G4AttCheck(    
1286               attHolder->GetAttValues()[attHo    
1287               attHolder->GetAttDefs()[attHold    
1288                      }                           
1289                      break;                      
1290                   }                              
1291                }                                 
1292             } else {                             
1293                G4String name((char*)node->get    
1294                G4String cls((char*)node->getT    
1295                G4warn << "SoNode : " << node     
1296                       << " SoType : " << cls     
1297                       << " name : " << name      
1298                       << G4endl;                 
1299                G4warn << "No attributes attac    
1300             }                                    
1301                                                  
1302             return;                              
1303          }                                       
1304          else{                                   
1305             //Go to default behavior             
1306          }                                       
1307       }                                          
1308       else {                                     
1309          //Go to default behavior                
1310       }                                          
1311                                                  
1312       // Default behavior in G4OpenInventorVi    
1313       G4AttHolder* attHolder = dynamic_cast<G    
1314       if(attHolder && attHolder->GetAttDefs()    
1315          for (std::size_t i = 0; i < attHolde    
1316             G4cout << G4AttCheck(attHolder->G    
1317                                  attHolder->G    
1318          }                                       
1319       } else {                                   
1320          G4String name((char*)node->getName()    
1321          G4String cls((char*)node->getTypeId(    
1322          G4warn << "SoNode : " << node           
1323                 << " SoType : " << cls           
1324                 << " name : " << name            
1325                 << G4endl;                       
1326          G4warn << "No attributes attached."     
1327       }                                          
1328                                                  
1329       //Suppress other event handlers            
1330       eventCB->setHandled();                     
1331    }                                             
1332 }                                                
1333                                                  
1334                                                  
1335 void G4OpenInventorQtExaminerViewer::mouseove    
1336 {                                                
1337    SoHandleEventAction* action = eventCB->get    
1338    const SoPickedPoint* pp = action->getPicke    
1339    G4OpenInventorQtExaminerViewer* This = (G4    
1340                                                  
1341    if(!This->abbrOutputFlag)                     
1342       return;                                    
1343                                                  
1344    if(pp != NULL) {                              
1345                                                  
1346       const SbViewportRegion & viewportRegion    
1347                                                  
1348       std::string sLogName;                      
1349       float x,y,z;                               
1350       std::stringstream ssZPos;                  
1351       std::stringstream ssSolids;                
1352       std::stringstream ssMaterials;             
1353       SoPath * path = pp->getPath();             
1354       SoNode* node = ((SoFullPath*)path)->get    
1355                                                  
1356       if(node->getTypeId() == Geant4_SoPolyhe    
1357                                                  
1358          sLogName = "Logical Volume:  ";         
1359          sLogName += ((Geant4_SoPolyhedron *)    
1360                                                  
1361          SoGetBoundingBoxAction bAction(viewp    
1362          bAction.apply((SoFullPath*)path);       
1363          SbBox3f bBox = bAction.getBoundingBo    
1364          SbVec3f centr = bBox.getCenter();       
1365          centr.getValue(x,y,z);                  
1366          ssZPos << "Pos:  " << x << "  " << y    
1367                                                  
1368          G4AttHolder* attHolder = dynamic_cas    
1369          if(attHolder && attHolder->GetAttDef    
1370                                                  
1371             std::vector<const std::map<G4Stri    
1372                attHolder->GetAttDefs();          
1373             std::vector<const std::vector<G4A    
1374                attHolder->GetAttValues();        
1375             for (std::size_t i = 0; i < vecDe    
1376                const std::vector<G4AttValue>     
1377                                                  
1378                std::vector<G4AttValue>::const    
1379                                                  
1380                for (iValue = vals->begin(); i    
1381                   const G4String& valueName =    
1382                   const G4String& value = iVa    
1383                                                  
1384                   if(valueName == "Solid") {     
1385                      if(ssSolids.str() == "")    
1386                         ssSolids << "Solid Na    
1387                      else                        
1388                         ssSolids << ", " << v    
1389                   }                              
1390                                                  
1391                   if(valueName == "Material")    
1392                      if(ssMaterials.str() ==     
1393                         ssMaterials << "Mater    
1394                      else                        
1395                         ssMaterials << ", " <    
1396                   }                              
1397                }                                 
1398             }                                    
1399          }                                       
1400       }                                          
1401       // FWJ Mouseover for trajectories          
1402       else if(node->getTypeId() == SoLineSet:    
1403          // G4cout << "Trajectory!!!!!!!!!!!!    
1404          G4AttHolder* attHolder = dynamic_cas    
1405          if(attHolder && attHolder->GetAttDef    
1406             std::string strTrajPoint = "G4Tra    
1407             std::ostringstream oss;              
1408             G4String t1, t1Ch, t2, t3, t4;       
1409             for (std::size_t i = 0; i < attHo    
1410                // G4cout << "Getting index "     
1411                // No, returns a vector!          
1412                //   G4AttValue* attValue = at    
1413                const std::vector<G4AttValue>*    
1414                std::vector<G4AttValue>::const    
1415                for (iValue = vals->begin(); i    
1416                   const G4String& valueName =    
1417                   const G4String& value = iVa    
1418                   // G4cout << "  valueName =    
1419                   // G4cout << "  value = " <    
1420                   // LINE 1                      
1421                   if (valueName == "PN") t1 =    
1422                   if (valueName == "Ch") {       
1423                      if (atof(value.c_str())     
1424                         t1Ch = "    +";          
1425                      else                        
1426                         t1Ch = "    ";           
1427                      t1Ch += value;              
1428                   }                              
1429                   if (valueName == "PDG") {      
1430                      t1 += "    ";               
1431                      t1 += value;                
1432                      t1 += t1Ch;                 
1433                      This->mouseOverTextLogNa    
1434                   }                              
1435                   //                  G4cout     
1436                   // LINE 2                      
1437                   if (valueName == "EventID")    
1438                   if (valueName == "ID") t2 +    
1439                   if (valueName == "PID") {      
1440                      t2 += "    Prt " + value    
1441                      This->mouseOverTextSolid    
1442                   }                              
1443                   // LINE 3                      
1444                   if (valueName == "IKE") t3     
1445                   if (valueName == "IMom") {     
1446                      // Remove units             
1447                      std::size_t ipos = value    
1448                      G4String value1 = value;    
1449                      value1.erase(ipos);         
1450                      t3 += "    P (" + value1    
1451                   }                              
1452                   if (valueName == "IMag") {     
1453                      t3 += " " + value + "/c"    
1454                      //                     t    
1455                      This->mouseOverTextMater    
1456                   }                              
1457                   // LINE 4                      
1458                   if (valueName == "NTP") {      
1459                      std::ostringstream t4oss    
1460                      t4oss << "TrjPts " <<  v    
1461                      t4oss << "    Pos " << p    
1462                         " " << pp->getPoint()    
1463                      This->mouseOverTextZPos-    
1464                   }                              
1465                }                                 
1466 //             G4cout << "  NOW CALLING G4Att    
1467 //             G4cout << G4AttCheck(attHolder    
1468 //                                     attHol    
1469 //             oss << G4AttCheck(attHolder->G    
1470 //                                  attHolder    
1471 //             if(oss.str().find(strTrajPoint    
1472 //                // Last attribute displayed    
1473 //                // want abbreviated output,    
1474 //                // (unless we're already at    
1475 //                if(i != attHolder->GetAttDe    
1476 //                   G4cout << G4AttCheck(       
1477 //                      attHolder->GetAttValu    
1478 //                      attHolder->GetAttDefs    
1479 //                   }                           
1480 //                   break;                      
1481 //                }                              
1482             }                                    
1483          }                                       
1484          This->setSuperimpositionEnabled(This    
1485          This->scheduleRedraw();                 
1486          eventCB->setHandled();                  
1487          return;                                 
1488       }                                          
1489                                                  
1490       bool redraw = false;                       
1491       if(std::string(This->mouseOverTextLogNa    
1492          This->mouseOverTextLogName->string.s    
1493          redraw = true;                          
1494       }                                          
1495       if(std::string(This->mouseOverTextSolid    
1496          This->mouseOverTextSolid->string.set    
1497          redraw = true;                          
1498       }                                          
1499       if(std::string(This->mouseOverTextMater    
1500          This->mouseOverTextMaterial->string.    
1501          redraw = true;                          
1502       }                                          
1503       if(std::string(This->mouseOverTextZPos-    
1504          This->mouseOverTextZPos->string.setV    
1505          redraw = true;                          
1506       }                                          
1507                                                  
1508       if(redraw) {                               
1509          This->setSuperimpositionEnabled(This    
1510          This->scheduleRedraw();                 
1511       }                                          
1512                                                  
1513       eventCB->setHandled();                     
1514    }                                             
1515    else {                                        
1516       if(std::string(This->mouseOverTextLogNa    
1517          This->mouseOverTextLogName->string.s    
1518          This->scheduleRedraw();                 
1519       }                                          
1520       if(std::string(This->mouseOverTextSolid    
1521          This->mouseOverTextSolid->string.set    
1522          This->scheduleRedraw();                 
1523       }                                          
1524       if(std::string(This->mouseOverTextMater    
1525          This->mouseOverTextMaterial->string.    
1526          This->scheduleRedraw();                 
1527       }                                          
1528       if(std::string(This->mouseOverTextZPos-    
1529          This->mouseOverTextZPos->string.setV    
1530          This->scheduleRedraw();                 
1531       }                                          
1532    }                                             
1533 }                                                
1534                                                  
1535                                                  
1536 // Called by hitting PageUp during animation.    
1537 void G4OpenInventorQtExaminerViewer::incSpeed    
1538    if (std::ceil(animateBtwPtsPeriod * 100) >    
1539       if (speedStep > 0.08)                      
1540          speedStep -= 0.02;                      
1541       else                                       
1542          speedStep = 0.02;                       
1543       animateBtwPtsPeriod -= speedStep;          
1544    } else                                        
1545       animateBtwPtsPeriod = 0.0;                 
1546                                                  
1547    if (currentState != PAUSED_ANIMATION) {       
1548       int lastIdx = (int) refParticleTrajecto    
1549       if (refParticleIdx < lastIdx && !animat    
1550          animateRefParticle();                   
1551    }                                             
1552 }                                                
1553                                                  
1554 // Called by hitting PageDown during animatio    
1555 void G4OpenInventorQtExaminerViewer::decSpeed    
1556    animateBtwPtsPeriod += speedStep;             
1557    if (animateBtwPtsPeriod < MIN_SPEED) {        
1558       if (std::floor(animateBtwPtsPeriod * 10    
1559     speedStep = 0.08;                            
1560       } else if (animateBtwPtsPeriod > 0.12)     
1561          speedStep += 0.02;                      
1562    } else {                                      
1563       animateBtwPtsPeriod = MIN_SPEED;           
1564       speedStep = START_STEP;                    
1565       maxSpeed = 0.0f;                           
1566       if (animateSensor->isScheduled())          
1567          animateSensor->unschedule();            
1568    }                                             
1569 }                                                
1570                                                  
1571                                                  
1572 // Based on the user's interaction the speed     
1573                                                  
1574 void G4OpenInventorQtExaminerViewer::updateSp    
1575 {                                                
1576    assert(this->sgeometry != NULL);              
1577                                                  
1578    SbVec3f * points = this->sgeometry->point.    
1579                                                  
1580    if (points[10][0] == 0.0f)                    
1581       this->animSpeedOutlineSwitch->whichChil    
1582    if (points[14][0] == 0.0f)                    
1583       this->animSpeedSwitch->whichChild.setVa    
1584    points[10][0] = this->maxSpeed;               
1585    points[11][0] = this->maxSpeed;               
1586    points[14][0] = this->maxSpeed;               
1587    points[15][0] = this->maxSpeed;               
1588    this->sgeometry->point.finishEditing();       
1589                                                  
1590    if (this->maxSpeed == 0.0f) {                 
1591       this->animSpeedOutlineSwitch->whichChil    
1592       this->animSpeedSwitch->whichChild.setVa    
1593    }                                             
1594 }                                                
1595                                                  
1596                                                  
1597 void G4OpenInventorQtExaminerViewer::actualRe    
1598   switch (currentState) {                        
1599   case ANIMATION:                                
1600   case REVERSED_ANIMATION:                       
1601   case PAUSED_ANIMATION:                         
1602     updateSpeedIndicator();                      
1603     SoQtExaminerViewer::actualRedraw();          
1604     break;                                       
1605   default:                                       
1606     SoQtExaminerViewer::actualRedraw();          
1607     break;                                       
1608   }                                              
1609 }                                                
1610                                                  
1611                                                  
1612 void G4OpenInventorQtExaminerViewer::setRefer    
1613        SoCoordinate3 *coords, bool append)       
1614 {                                                
1615    // TODO:  Color the reference path            
1616    // Disable the color stuff for now: change    
1617    // FWJ See G4OpenInventorXtExaminerViewer.    
1618                                                  
1619    // The trajectory is composed of all the p    
1620    // multiple value field (SoMFInt32) numVer    
1621    // For each of the numVertices.getNum()* p    
1622    // retrieve the points from the SoCoordina    
1623                                                  
1624    SbVec3f refParticlePt;                        
1625                                                  
1626    if(!append)                                   
1627       refParticleTrajectory.clear();             
1628                                                  
1629    for(int i = 0; i < lineset->numVertices.ge    
1630       for(int j = 0; j < lineset->numVertices    
1631          refParticlePt = coords->point[j];       
1632          refParticleTrajectory.push_back(refP    
1633       }                                          
1634    }                                             
1635    // Remove points that are too close to eac    
1636    evenOutRefParticlePts();                      
1637    setReferencePathZPos();                       
1638    getSceneElements();                           
1639    sortElements();                               
1640 }                                                
1641                                                  
1642                                                  
1643 void G4OpenInventorQtExaminerViewer::setRefer    
1644 {                                                
1645    refZPositions.clear();                        
1646    refZPositions.push_back(0);                   
1647    float dist;                                   
1648    for(unsigned int i=0; i < refParticleTraje    
1649       dist = (refParticleTrajectory[i] -         
1650               refParticleTrajectory[i + 1]).l    
1651       refZPositions.push_back(refZPositions[i    
1652    }                                             
1653 }                                                
1654                                                  
1655                                                  
1656 void G4OpenInventorQtExaminerViewer::findAndS    
1657 {                                                
1658    SoSearchAction action;                        
1659    action.setType(SoLineSet::getClassTypeId()    
1660    action.setInterest(SoSearchAction::ALL);      
1661    action.apply(getSceneGraph());                
1662                                                  
1663    SoPathList &pathList = action.getPaths();     
1664                                                  
1665    if(pathList.getLength() != 0) {               
1666                                                  
1667       SoCoordinate3 * coords = NULL;             
1668       std::vector<SoCoordinate3 *> coordvec;     
1669       std::vector<SoLineSet *> linevec;          
1670                                                  
1671       bool refPathFound = false;                 
1672       for(int i = 0; i < pathList.getLength()    
1673          SoFullPath *path = (SoFullPath *)pat    
1674                                                  
1675          G4AttHolder* attHolder = dynamic_cas    
1676          if(attHolder != nullptr)                
1677          {                                       
1678          for (std::size_t j = 0; j < attHolde    
1679             std::ostringstream oss;              
1680             oss << G4AttCheck(attHolder->GetA    
1681                               attHolder->GetA    
1682                                                  
1683             std::string findStr = "Type of tr    
1684             std::string compareValue = "REFER    
1685             std::size_t idx = oss.str().find(    
1686                                                  
1687             if(idx != std::string::npos) {       
1688                if(oss.str().substr(idx + find    
1689                                    compareVal    
1690                   coords = getCoordsNode(path    
1691                   if(coords != NULL) {           
1692                      refPathFound = true;        
1693                      coordvec.push_back(coord    
1694                      linevec.push_back((SoLin    
1695                   }                              
1696                   break;                         
1697                }                                 
1698             }                                    
1699                                                  
1700             findStr = "Track ID (ID): ";         
1701             idx = oss.str().find(findStr);       
1702             if(idx != std::string::npos) {       
1703                //index all primary tracks        
1704                std::string tmpstr = oss.str()    
1705                std::istringstream buffer(tmps    
1706                int num;                          
1707                buffer >> num;                    
1708                if(num == 1) {                    
1709                                                  
1710                   // Check if next character     
1711                   // in which case we don't h    
1712                   // FWJ attempt to fix Cover    
1713                   char nextChar = oss.str().a    
1714                   // const char * nextChar =     
1715                   // oss.str().substr(idx + f    
1716                   if(std::isdigit(nextChar))     
1717                      break; //Not a primary t    
1718                                                  
1719                   coords = getCoordsNode(path    
1720                   if(coords != NULL) {           
1721                      coordvec.push_back(coord    
1722                      linevec.push_back((SoLin    
1723                      break; //Found coords no    
1724                   }                              
1725                }                                 
1726                else                              
1727                   break;  //Not a primary tra    
1728             }                                    
1729             else{                                
1730                //Not a Track ID attribute, fa    
1731             }                                    
1732          }                                       
1733          }                                       
1734                                                  
1735          if(refPathFound)                        
1736             break;                               
1737       }                                          
1738                                                  
1739       if(coordvec.empty())                       
1740          return;    //No track with a Coordin    
1741                                                  
1742       if(refPathFound) {                         
1743          //set ref path to last traj, coord i    
1744          setReferencePath(linevec.back(), coo    
1745          return;                                 
1746       }                                          
1747       //else                                     
1748                                                  
1749       int longestIdx = 0;                        
1750       float longestLength = 0.0;                 
1751       // For all paths                           
1752       for(unsigned int i=0;i < linevec.size()    
1753                                                  
1754          //First generate a vector with all t    
1755          std::vector<SbVec3f> trajectory;        
1756          // For all lines in the i path          
1757          for(int j=0; j < linevec[i]->numVert    
1758             // For all points in line j          
1759             for(int k=0; k < linevec[i]->numV    
1760                trajectory.push_back(coordvec[    
1761             }                                    
1762          }                                       
1763                                                  
1764          // Then calculate the total length      
1765          float tmpLength=0.0;                    
1766          for(unsigned int j=0; j < trajectory    
1767             tmpLength += (trajectory[j] - tra    
1768          }                                       
1769                                                  
1770          if(tmpLength > longestLength) {         
1771             longestIdx = i;                      
1772             longestLength = tmpLength;           
1773          }                                       
1774       }                                          
1775                                                  
1776       // Set the longest path as the referenc    
1777       setReferencePath(linevec[longestIdx], c    
1778    }                                             
1779 }                                                
1780                                                  
1781                                                  
1782 SoCoordinate3 * G4OpenInventorQtExaminerViewe    
1783 {                                                
1784    SoLineSet *trajectory = (SoLineSet *)path-    
1785    SoSeparator * grpNode = (SoSeparator*)(((S    
1786    int nodeIndex = grpNode->findChild(traject    
1787    SoNode * tmpNode;                             
1788                                                  
1789    // We allow only 100 iterations, in case t    
1790    // (should take only a few iterations)        
1791    for (int i = 0; i < 100; ++i) {               
1792       --nodeIndex;                               
1793                                                  
1794       tmpNode = grpNode->getChild(nodeIndex);    
1795       if(tmpNode->getTypeId() == SoCoordinate    
1796          //node found                            
1797          return (SoCoordinate3 *)tmpNode;        
1798       }                                          
1799    }                                             
1800    return NULL; //coords node not found          
1801 }                                                
1802                                                  
1803                                                  
1804 // Displays scene elements on the right side     
1805 // else: scene graph is searched for Geant4_S    
1806 void G4OpenInventorQtExaminerViewer::getScene    
1807 {                                                
1808    std::string field, eltName;                   
1809                                                  
1810    std::map<std::string, int> duplicates;        
1811    std::map<std::string, int> sceneElts;         
1812    SoSearchAction search;                        
1813    Geant4_SoPolyhedron *node;                    
1814    SoGroup *root = (SoGroup *)getSceneManager    
1815                                                  
1816    SoBaseKit::setSearchingChildren(TRUE);        
1817                                                  
1818    search.reset();                               
1819    search.setSearchingAll(TRUE);                 
1820    search.setInterest(SoSearchAction::ALL);      
1821    search.setType(Geant4_SoPolyhedron::getCla    
1822                                                  
1823    // FWJ DEBUG                                  
1824    //   G4cout << "Searching for elements....    
1825    search.apply(root);                           
1826                                                  
1827    SoPathList &pl = search.getPaths();           
1828                                                  
1829                                                  
1830    // First find which names occur more than     
1831    for (int i = 0; i < pl.getLength(); i++) {    
1832       SoFullPath *path = (SoFullPath *)pl[i];    
1833       node = (Geant4_SoPolyhedron *)path->get    
1834       eltName = node->getName();                 
1835       //      G4cout << "  FOUND " << i << "     
1836       if(duplicates.count(eltName))              
1837          duplicates[eltName]++;                  
1838       else                                       
1839          duplicates[eltName] = 1;                
1840    }                                             
1841                                                  
1842    for(int i = 0; i < pl.getLength(); i++) {     
1843       float x,y,z;                               
1844       std::stringstream ssCount;                 
1845       SoFullPath *path = (SoFullPath *)pl[i];    
1846       node = (Geant4_SoPolyhedron *)path->get    
1847       eltName = node->getName();                 
1848       field = eltName;                           
1849       if(duplicates[eltName] == 1)               
1850          ssCount << "";//duplicates[field]       
1851       else {                                     
1852          if(sceneElts.count(eltName))            
1853             sceneElts[eltName]++;                
1854          else                                    
1855             sceneElts[eltName] = 1;              
1856                                                  
1857          ssCount << sceneElts[eltName];          
1858          field += "_";                           
1859       }                                          
1860                                                  
1861       field += ssCount.str();                    
1862                                                  
1863       SoGetBoundingBoxAction bAction(getViewp    
1864       bAction.apply(path);                       
1865       SbBox3f bBox = bAction.getBoundingBox()    
1866                                                  
1867       SbVec3f centr = bBox.getCenter();          
1868       centr.getValue(x,y,z);                     
1869                                                  
1870       path->ref();                               
1871       sceneElement el = { field, path, centr,    
1872       sceneElements.push_back(el);               
1873    }                                             
1874 }                                                
1875                                                  
1876                                                  
1877 float G4OpenInventorQtExaminerViewer::sqrlen(    
1878 {                                                
1879    float x,y,z;                                  
1880    a.getValue(x,y,z);                            
1881    return x*x + y*y + z*z;                       
1882 }                                                
1883                                                  
1884                                                  
1885 void G4OpenInventorQtExaminerViewer::distance    
1886                                                  
1887                                                  
1888                                                  
1889 {                                                
1890    // a : Previous point on trajectory           
1891    // b : Next point on trajectory               
1892    // q : the point in space                     
1893    // dab, daq, dbq: distance between a & b,     
1894    //                                            
1895    // Theory:  A point p on a line ab is defi    
1896    //                                            
1897    //         p(t) = a+t?(b?a)                   
1898    //                                            
1899    //       note: All are vectors except the     
1900    //                                            
1901    // When t is between 0 and 1 the point p i    
1902    // The point p is defined in terms of the     
1903    // the distance from the query point q to     
1904    // of that distance we differentiate it an    
1905    //                                            
1906    //       diff(Norm(p(t)- q)) = 0              
1907    //                                            
1908    //     note: diff means taking the derivat    
1909    //                                            
1910    // The resulting t is given in the code be    
1911    // between p and q is given by:               
1912    //                                            
1913    //       d^2 = (Norm(p(t)-q))^2               
1914    //                                            
1915    // The expression found is given in the co    
1916    //                                            
1917    // Ref: http://programmizm.sourceforge.net    
1918    //           distance-from-a-point-to-a-po    
1919    //                                            
1920    //    --PLG                                   
1921                                                  
1922    const std::size_t count = refParticleTraje    
1923    assert(count>0);                              
1924                                                  
1925    SbVec3f b = refParticleTrajectory[0];         
1926    SbVec3f dbq = b - q;                          
1927    float sqrDist = sqrlen(dbq);                  
1928    closestPoint = b;                             
1929    index = 0;                                    
1930    for (std::size_t i = 1; i < count; ++i) {     
1931       const SbVec3f a = b;                       
1932       const SbVec3f daq = dbq;                   
1933       b = refParticleTrajectory[i];              
1934       dbq = b - q;                               
1935       const SbVec3f dab = a - b;                 
1936                                                  
1937       float dab_x, dab_y, dab_z;                 
1938       dab.getValue(dab_x,dab_y,dab_z);           
1939       float daq_x, daq_y, daq_z;                 
1940       daq.getValue(daq_x, daq_y, daq_z);         
1941       float dbq_x, dbq_y, dbq_z;                 
1942       dbq.getValue(dbq_x, dbq_y, dbq_z);         
1943                                                  
1944       const float inv_sqrlen = 1./sqrlen(dab)    
1945       const float t = (dab_x*daq_x + dab_y*da    
1946                                                  
1947       if (t<0.) {                                
1948          // The trajectory point occurs befor    
1949          // Go to the next point                 
1950          continue;                               
1951       }                                          
1952       float current_dist;                        
1953       if (t<=1.) {                               
1954          // The trajectory point occurs betwe    
1955          // Compute the distance to that poin    
1956          current_dist = daq_x*daq_x + daq_y*d    
1957             - t*(daq_x*dab_x + daq_y*dab_y +     
1958             + t*t*(dab_x*dab_x + dab_y*dab_y     
1959       }                                          
1960       else { //t>1.                              
1961          // The trajectory point occurs after    
1962          // Get the distance to point b          
1963          current_dist = sqrlen(dbq);             
1964       }                                          
1965                                                  
1966       if (current_dist < sqrDist) {              
1967          sqrDist = current_dist;                 
1968          closestPoint = a + t*(b-a);             
1969          index = (int) i;                        
1970       }                                          
1971    }                                             
1972                                                  
1973    dist = std::sqrt(sqrDist);                    
1974 }                                                
1975                                                  
1976                                                  
1977 void G4OpenInventorQtExaminerViewer::sortElem    
1978 {                                                
1979    if(refParticleTrajectory.empty())             
1980       return;                                    
1981                                                  
1982    float * trajLength = new float[refParticle    
1983    typedef std::map<elementForSorting, sceneE    
1984    sortedMap sorted;                             
1985                                                  
1986    // For every point on the reference trajec    
1987    // the total length from the start            
1988    SbVec3f prevPoint;                            
1989    std::vector<SbVec3f>::iterator itRef = ref    
1990    int trajIndex = 0;                            
1991    prevPoint = *itRef;                           
1992    trajLength[trajIndex] = 0.0;                  
1993    ++itRef;                                      
1994    ++trajIndex;                                  
1995    for(; itRef != refParticleTrajectory.end()    
1996       trajLength[trajIndex] = trajLength[traj    
1997       prevPoint = *itRef;                        
1998    }                                             
1999                                                  
2000    // Compute the smallest distance between t    
2001    // and the reference trajectory (find the     
2002    // then map the element to the trajectory     
2003    // point (calculated above)                   
2004    SoGetBoundingBoxAction bAction(getViewport    
2005    SbVec3f elementCoord;                         
2006    std::vector<sceneElement>::iterator itEl;     
2007    int elementIndex;                             
2008    elementForSorting el;                         
2009    for(itEl = sceneElements.begin(), elementI    
2010        itEl != sceneElements.end(); ++itEl, +    
2011       bAction.apply(itEl->path);                 
2012                                                  
2013       // FWJ sceneElement already has a cente    
2014       elementCoord = itEl->center;               
2015       // ... and this sometimes returns an em    
2016       //      elementCoord = bAction.getBound    
2017       //      if (bAction.getBoundingBox().is    
2018       //         G4cout << "sortElements: Box    
2019       //         G4cout << "   element name="    
2020       //      }                                  
2021                                                  
2022       int index;                                 
2023       distanceToTrajectory(elementCoord, el.s    
2024       itEl->closestPointZCoord = el.closestPo    
2025       el.distanceToBeamlineStart = (itEl->cen    
2026                                                  
2027       // This map of the scene elements (or t    
2028       // is automatically sorted by trajector    
2029       // by the distance between the element     
2030       // is the same as another element.  Thi    
2031       // an element structure which implement    
2032       sorted.insert(std::make_pair(el,*itEl))    
2033    }                                             
2034                                                  
2035    // store the sorted elements into the vect    
2036    sceneElements.clear();                        
2037                                                  
2038    sortedMap::iterator itSorted = sorted.begi    
2039    for(; itSorted != sorted.end(); itSorted++    
2040       sceneElements.push_back(itSorted->secon    
2041                                                  
2042    zcoordSetFlag = true;                         
2043                                                  
2044    createElementsList();                         
2045                                                  
2046    delete[] trajLength;                          
2047 }                                                
2048                                                  
2049                                                  
2050 void G4OpenInventorQtExaminerViewer::createEl    
2051 {                                                
2052    // FWJ DEBUG                                  
2053    //   G4cout << "Populating ELEMENT LIST...    
2054                                                  
2055    AuxWindowDialog->listWidget1->clear();        
2056    //   int size = sceneElements.size();         
2057                                                  
2058    std::vector<sceneElement>::const_iterator     
2059    std::stringstream ss;                         
2060                                                  
2061    for(it=sceneElements.begin(); it!=sceneEle    
2062       ss << it->name;                            
2063       if(zcoordSetFlag)                          
2064          ss << " [" << it->closestPointZCoord    
2065                                                  
2066       new QListWidgetItem(ss.str().c_str(), A    
2067       ss.str("");                                
2068    }                                             
2069 }                                                
2070                                                  
2071                                                  
2072 // Called when user clicks a scene element in    
2073 // Zooms onto that element.                      
2074 void                                             
2075 G4OpenInventorQtExaminerViewer::LookAtSceneEl    
2076 {                                                
2077    // FWJ DEBUG                                  
2078    //   G4cout << "AuxWindow: listWidget1 sel    
2079                                                  
2080    SoCamera * cam = getCamera();                 
2081                                                  
2082    if (SoQtExaminerViewer::isAnimating())        
2083       stopAnimating();                           
2084                                                  
2085    if (currentState == ANIMATION || currentSt    
2086        || currentState == PAUSED_ANIMATION )     
2087       if (animateSensor->isScheduled())          
2088          animateSensor->unschedule();            
2089       setSuperimpositionEnabled(superimpositi    
2090       maxSpeed = 0.0f;                           
2091       scheduleRedraw();                          
2092       restoreCamera();                           
2093       currentState = prevState;                  
2094    } else if (currentState == VIEWPOINT)         
2095       setSuperimpositionEnabled(superimpositi    
2096                                                  
2097    std::string elementField = qPrintable(item    
2098                                                  
2099    std::size_t idx = elementField.find_last_o    
2100    if(idx == std::string::npos)                  
2101       idx = elementField.size(); //if "[" not    
2102    else                                          
2103       idx--; // To get rid of the space that     
2104                                                  
2105    bool error = false;                           
2106    SoFullPath *path;                             
2107    SoSearchAction search;                        
2108    SoNode *root = getSceneManager()->getScene    
2109    int counter = 0;                              
2110    std::size_t idxUnderscore = elementField.f    
2111                                                  
2112    parseString<int>(counter,                     
2113                           elementField.substr    
2114                                                  
2115    SoBaseKit::setSearchingChildren(TRUE);        
2116    search.reset();                               
2117    search.setSearchingAll(TRUE);                 
2118                                                  
2119    // G4cout << "  Starting search for elemen    
2120    //        << G4endl;                          
2121                                                  
2122    if(error) { // No counter is present => el    
2123       curEltName = elementField.substr(0, idx    
2124       search.setName(curEltName.c_str());        
2125       search.apply(root);                        
2126                                                  
2127       path = (SoFullPath *)search.getPath();     
2128    }                                             
2129    else {                                        
2130       curEltName = elementField.substr(0, idx    
2131       search.setInterest(SoSearchAction::ALL)    
2132       search.setName(curEltName.c_str());        
2133       search.apply(root);                        
2134                                                  
2135       SoPathList &pl = search.getPaths();        
2136       path = (SoFullPath *)pl[counter - 1]; /    
2137    }                                             
2138                                                  
2139    G4ThreeVector global;                         
2140                                                  
2141    // FWJ FLIP THIS                              
2142    if ((idx > 0) && (path)) {                    
2143                                                  
2144       if(!refParticleTrajectory.empty()) {       
2145                                                  
2146          SoGetBoundingBoxAction bAction(getVi    
2147          bAction.apply(path);                    
2148          SbBox3f bBox = bAction.getBoundingBo    
2149          SbVec3f elementCoord = bBox.getCente    
2150                                                  
2151          refParticleIdx = 0;                     
2152          SbVec3f p;                              
2153                                                  
2154          float absLengthNow, absLengthMin;       
2155          int maxIdx = (int) refParticleTrajec    
2156          int targetIdx = 0;                      
2157          SbVec3f dir;                            
2158                                                  
2159          p = refParticleTrajectory[refParticl    
2160          absLengthMin = (p - elementCoord).le    
2161          refParticleIdx++;                       
2162                                                  
2163          // Find a ref. particle's point clos    
2164          while (refParticleIdx < maxIdx) {       
2165             p = refParticleTrajectory[refPart    
2166             absLengthNow = (p - elementCoord)    
2167                                                  
2168             if (absLengthNow < absLengthMin)     
2169                absLengthMin = absLengthNow;      
2170                targetIdx = refParticleIdx;       
2171             }                                    
2172             refParticleIdx++;                    
2173          }                                       
2174                                                  
2175          if (currentState != BEAMLINE) { // S    
2176             SbVec3f p1, pN;                      
2177             currentState = BEAMLINE;             
2178             prevParticleDir = SbVec3f(0,0,0);    
2179                                                  
2180             p1 = prevPt = refParticleTrajecto    
2181             pN = refParticleTrajectory[refPar    
2182             distance = (pN - p1).length() / 1    
2183                                                  
2184             // FWJ Rather than switching to a    
2185             // to keep the same height(magnif    
2186             // if (cam->isOfType(SoOrthograph    
2187             //    ((SoOrthographicCamera *) c    
2188             // // FWJ Restore the default hei    
2189             // // ((SoOrthographicCamera *) c    
2190             // }                                 
2191             // else if (cam->isOfType(SoPersp    
2192                                                  
2193             // FWJ required to avoid extreme     
2194             if (cam->isOfType(SoPerspectiveCa    
2195                ((SoPerspectiveCamera*)cam)->h    
2196                                                  
2197          } else {                                
2198             if (cam->isOfType(SoPerspectiveCa    
2199                distance = (prevPt - cam->posi    
2200          }                                       
2201          refParticleIdx = targetIdx;             
2202                                                  
2203          ////////////////////////////////////    
2204          setSuperimpositionEnabled(superimpos    
2205          axisSwitch->whichChild.setValue(SO_S    
2206          animSpeedOutlineSwitch->whichChild.s    
2207          animSpeedSwitch->whichChild.setValue    
2208          scheduleRedraw();                       
2209          ////////////////////////////////////    
2210                                                  
2211          moveCamera(distance);                   
2212                                                  
2213       }                                          
2214                                                  
2215       else {                                     
2216          offsetFromCenter.setValue(0, 0, 1);     
2217          distance = 50;// small number since     
2218          upVector.setValue(0, 1, 0);             
2219          moveCamera(distance);                   
2220          cam->viewAll(path, getViewportRegion    
2221       }                                          
2222    }                                             
2223                                                  
2224 }                                                
2225                                                  
2226                                                  
2227 void G4OpenInventorQtExaminerViewer::FileLoad    
2228 {                                                
2229    //   G4cout << "File: Load Ref Path CALLBA    
2230                                                  
2231    QFileDialog filedialog(getParentWidget(),     
2232    filedialog.setFileMode(QFileDialog::AnyFil    
2233    filedialog.setFont(*font);                    
2234    if (!filedialog.exec()) return;               
2235    QStringList filenameinlist = filedialog.se    
2236    QString filenamein = filenameinlist[0];       
2237                                                  
2238    std::ifstream ifs(qPrintable(filenamein));    
2239    if(ifs.is_open()) {                           
2240       refParticleTrajectory.clear();             
2241       float x,y,z;                               
2242       while(ifs >> x >> y >> z) {                
2243          refParticleTrajectory.push_back(SbVe    
2244       }                                          
2245       ifs.close();                               
2246    } else {                                      
2247       QMessageBox msgbox;                        
2248       msgbox.setFont(*font);                     
2249       QString messagetxt = "Reference Path fi    
2250       messagetxt.append(filenamein);             
2251       msgbox.setText(messagetxt);                
2252       msgbox.exec();                             
2253       return;                                    
2254    }                                             
2255    if (refParticleTrajectory.size() < 2) {       
2256       QMessageBox msgbox;                        
2257       msgbox.setFont(*font);                     
2258       QString messagetxt = "Invalid Reference    
2259       msgbox.setText(messagetxt);                
2260       msgbox.exec();                             
2261       return;                                    
2262    }                                             
2263    // Following setReferencePath() ...           
2264    evenOutRefParticlePts();                      
2265    setReferencePathZPos();                       
2266    getSceneElements();                           
2267    sortElements();                               
2268 }                                                
2269                                                  
2270                                                  
2271 void G4OpenInventorQtExaminerViewer::FileSave    
2272 {                                                
2273    //   G4cout << "File: Save Ref Path CALLBA    
2274                                                  
2275    QFileDialog filedialog(getParentWidget(),     
2276    filedialog.setFileMode(QFileDialog::AnyFil    
2277    // To enable confirmation of overwriting      
2278    filedialog.setAcceptMode(QFileDialog::Acce    
2279    filedialog.setFont(*font);                    
2280    if (!filedialog.exec()) return;               
2281    QStringList filenameinlist = filedialog.se    
2282    QString filenamein = filenameinlist[0];       
2283                                                  
2284    std::ofstream ofs(qPrintable(filenamein));    
2285    if (ofs.is_open()) {                          
2286       float x,y,z;                               
2287       for (unsigned int i=0; i < refParticleT    
2288          refParticleTrajectory[i].getValue(x,    
2289          ofs << x << " " << y << " " << z <<     
2290       }                                          
2291       ofs.close();                               
2292    } else {                                      
2293       QMessageBox msgbox;                        
2294       msgbox.setFont(*font);                     
2295       QString messagetxt = "Error opening fil    
2296       messagetxt.append(filenamein);             
2297       msgbox.setText(messagetxt);                
2298       msgbox.exec();                             
2299    }                                             
2300                                                  
2301 }                                                
2302                                                  
2303 void G4OpenInventorQtExaminerViewer::evenOutR    
2304 {                                                
2305    if(refParticleTrajectory.empty())             
2306       return;                                    
2307                                                  
2308    SbVec3f p1, p2, p3, dirNow, dirNxt, dir, p    
2309    float avgDistBtwPts = 0;                      
2310    float totalDistBtwPts = 0;                    
2311    std::vector<SbVec3f> newRefParticleTraject    
2312    SbVec3f refPoint;                             
2313    std::size_t size = refParticleTrajectory.s    
2314    int numOfPts = 0;                             
2315    for (std::size_t i = 0; i < size; ++i) {      
2316       p1 = refParticleTrajectory[i];             
2317       p2 = refParticleTrajectory[i + 1];         
2318       if (p1 == p2)                              
2319          continue;                               
2320       numOfPts++;                                
2321       totalDistBtwPts += (p2 - p1).length();     
2322    }                                             
2323    // Nothing useful to do (and fix Coverity)    
2324    if (numOfPts <= 2) return;                    
2325                                                  
2326    avgDistBtwPts = totalDistBtwPts / numOfPts    
2327    float minDistAllowed = 0.75 * avgDistBtwPt    
2328    // float maxDistAllowed = 1.25 * avgDistBt    
2329                                                  
2330    float x, y, z;                                
2331    std::size_t i = 0, j = 0;                     
2332    while (i < size) {                            
2333       p1 = refParticleTrajectory[i];             
2334       p2 = refParticleTrajectory[i + 1];         
2335                                                  
2336       refPoint = p1;                             
2337       p1.getValue(x, y, z);                      
2338                                                  
2339       newRefParticleTrajectory.push_back(refP    
2340                                                  
2341       j = i;                                     
2342       while ((p2 - p1).length() < minDistAllo    
2343          j++;                                    
2344                                                  
2345          p1 = refParticleTrajectory[j];          
2346          p2 = refParticleTrajectory[j + 1];      
2347       }                                          
2348       if (j != i)                                
2349          i = j + 1;                              
2350       else                                       
2351          i++;                                    
2352    }                                             
2353                                                  
2354    refParticleTrajectory.clear();                
2355    refParticleTrajectory = newRefParticleTraj    
2356 }                                                
2357                                                  
2358                                                  
2359 void G4OpenInventorQtExaminerViewer::saveCurC    
2360 {                                                
2361    SoCamera *cam = getCamera();                  
2362    camB4Animation.viewportMapping = cam->view    
2363    camB4Animation.position = cam->position.ge    
2364    camB4Animation.orientation = cam->orientat    
2365    camB4Animation.aspectRatio = cam->aspectRa    
2366    camB4Animation.nearDistance = cam->nearDis    
2367    camB4Animation.farDistance = cam->farDista    
2368    camB4Animation.focalDistance = cam->focalD    
2369                                                  
2370    if (cam->isOfType(SoPerspectiveCamera::get    
2371       camB4Animation.height =                    
2372          ((SoPerspectiveCamera *) cam)->heigh    
2373       camB4Animation.camType = PERSPECTIVE;      
2374    } else if (cam->isOfType(SoOrthographicCam    
2375       camB4Animation.height =                    
2376          ((SoOrthographicCamera *) cam)->heig    
2377       camB4Animation.camType = ORTHOGRAPHIC;     
2378    }                                             
2379 }                                                
2380                                                  
2381                                                  
2382 void G4OpenInventorQtExaminerViewer::restoreC    
2383 {                                                
2384    SoCamera *cam = getCamera();                  
2385                                                  
2386    cam->viewportMapping = camB4Animation.view    
2387    cam->position = camB4Animation.position;      
2388    cam->orientation = camB4Animation.orientat    
2389    cam->aspectRatio = camB4Animation.aspectRa    
2390    cam->nearDistance = camB4Animation.nearDis    
2391    cam->farDistance = camB4Animation.farDista    
2392    cam->focalDistance = camB4Animation.focalD    
2393                                                  
2394    if (cam->isOfType(SoPerspectiveCamera::get    
2395       if (camB4Animation.camType == ORTHOGRAP    
2396          toggleCameraType();                     
2397          cam = getCamera();                      
2398          ((SoOrthographicCamera *) cam)->heig    
2399                                                  
2400       } else                                     
2401          ((SoPerspectiveCamera *) cam)->heigh    
2402                                                  
2403    } else if (cam->isOfType(SoOrthographicCam    
2404       if (camB4Animation.camType == PERSPECTI    
2405          toggleCameraType();                     
2406          cam = getCamera();                      
2407          ((SoPerspectiveCamera *) cam)->heigh    
2408                                                  
2409       } else                                     
2410          ((SoOrthographicCamera *) cam)->heig    
2411                                                  
2412    }                                             
2413 }                                                
2414                                                  
2415                                                  
2416 void G4OpenInventorQtExaminerViewer::animateS    
2417                                                  
2418 {                                                
2419    SbTime curTime = SbTime::getTimeOfDay();      
2420    G4OpenInventorQtExaminerViewer* This = (G4    
2421                                                  
2422    SoTimerSensor* s = (SoTimerSensor*) sensor    
2423                                                  
2424    float t = float((curTime - s->getBaseTime(    
2425       / This->animateBtwPtsPeriod;               
2426                                                  
2427    if ((t > 1.0f) || (t + s->getInterval().ge    
2428       t = 1.0f;                                  
2429    SbBool end = (t == 1.0f);                     
2430                                                  
2431    if (end) {                                    
2432       This->animateSensorRotation->unschedule    
2433       if(This->rotCnt) {                         
2434          // rotations left                       
2435          This->rotateCamera();                   
2436       }                                          
2437       else {                                     
2438          // rotation over                        
2439          This->currentState = This->prevState    
2440          return;                                 
2441       }                                          
2442    }                                             
2443                                                  
2444 }                                                
2445                                                  
2446                                                  
2447 // Called repeatedly during reference particl    
2448                                                  
2449 void G4OpenInventorQtExaminerViewer::animateS    
2450                                                  
2451 {                                                
2452    SbTime curTime = SbTime::getTimeOfDay();      
2453    G4OpenInventorQtExaminerViewer* This = (G4    
2454    SoCamera *cam = This->getCamera();            
2455    SoTimerSensor* s = (SoTimerSensor*) sensor    
2456                                                  
2457    float t = float((curTime - s->getBaseTime(    
2458       / This->animateBtwPtsPeriod;               
2459                                                  
2460    if ((t > 1.0f) || (t + s->getInterval().ge    
2461       t = 1.0f;                                  
2462    SbBool end = (t == 1.0f);                     
2463                                                  
2464    cam->orientation = SbRotation::slerp(This-    
2465    cam->position = This->camStartPos + (This-    
2466                                                  
2467    if (end) {                                    
2468       This->animateSensor->unschedule();         
2469                                                  
2470       if (This->currentState == ANIMATION) {     
2471          if (This->refParticleIdx < (int) (Th    
2472             This->animateRefParticle();          
2473          else {                                  
2474             This->animateBtwPtsPeriod = MIN_S    
2475             This->speedStep = START_STEP;        
2476          }                                       
2477       }                                          
2478       if (This->currentState == REVERSED_ANIM    
2479          if (This->refParticleIdx >= 1)          
2480             This->animateRefParticle();          
2481          else {                                  
2482             This->animateBtwPtsPeriod = MIN_S    
2483             This->speedStep = START_STEP;        
2484          }                                       
2485       }                                          
2486    }                                             
2487 }                                                
2488                                                  
2489                                                  
2490 void G4OpenInventorQtExaminerViewer::setStart    
2491 {                                                
2492    if (SoQtExaminerViewer::isAnimating())        
2493       stopAnimating();                           
2494                                                  
2495    SbRotation rot;                               
2496    SbVec3f p1{0.0, 0.0, 0.0}, p2{0.0, 0.0, 0.    
2497    float x1, y1, z1, x2, y2, z2;                 
2498                                                  
2499    if (currentState == ANIMATION) {              
2500       p1 = refParticleTrajectory[refParticleI    
2501       p2 = refParticleTrajectory[++(refPartic    
2502    } else if (currentState == REVERSED_ANIMAT    
2503       p2 = refParticleTrajectory[refParticleI    
2504       p1 = refParticleTrajectory[--(refPartic    
2505    } else if (currentState == PAUSED_ANIMATIO    
2506       if (refParticleIdx < (int) refParticleT    
2507          p1 = refParticleTrajectory[refPartic    
2508          p2 = refParticleTrajectory[refPartic    
2509       } else {                                   
2510          p1 = refParticleTrajectory[refPartic    
2511          p2 = refParticleTrajectory[refPartic    
2512       }                                          
2513    }                                             
2514    p1.getValue(x1, y1, z1);                      
2515    p2.getValue(x2, y2, z2);                      
2516                                                  
2517    camD = p2 - p1;                               
2518    camD.normalize();                             
2519                                                  
2520    p2_tmp.setValue(x2, y1, z2);                  
2521    camD_tmp = p2_tmp - p1;                       
2522    camD_tmp.normalize();                         
2523                                                  
2524    camUpV.setValue(0, 1, 0);                     
2525    rot.setValue(camD_tmp, camD);                 
2526    rot.multVec(camUpV, camUpV);                  
2527                                                  
2528    leftRightAxis = camD.cross(camUpV);           
2529                                                  
2530    myCam->position = p1;                         
2531    myCam->pointAt(p2, camUpV);                   
2532                                                  
2533    // Update camera position                     
2534    p1 = p1 + (up_down * camUpV) + (left_right    
2535    myCam->position = p1;                         
2536    // FWJ Try look-ahead here                    
2537    int idx = refParticleIdx + pathLookahead;     
2538    idx = std::min(idx, (int)refParticleTrajec    
2539    myCam->pointAt(refParticleTrajectory[idx],    
2540    //   myCam->pointAt(refParticleTrajectory[    
2541    myCam->focalDistance = 0.1f;                  
2542 }                                                
2543                                                  
2544                                                  
2545 void G4OpenInventorQtExaminerViewer::gotoRefP    
2546 {                                                
2547    G4OpenInventorQtExaminerViewer::ToolsRefPa    
2548 }                                                
2549                                                  
2550                                                  
2551 void G4OpenInventorQtExaminerViewer::ToolsRef    
2552 {                                                
2553    if (!refParticleTrajectory.size()) {          
2554       QMessageBox msgbox;                        
2555       msgbox.setFont(*font);                     
2556       QString messagetxt = "No current refere    
2557       msgbox.setText(messagetxt);                
2558       msgbox.exec();                             
2559       return;                                    
2560    }                                             
2561                                                  
2562    if (currentState == ROTATING)                 
2563       return;                                    
2564    if (currentState == ANIMATION || currentSt    
2565        || currentState == PAUSED_ANIMATION) {    
2566       if (animateSensor->isScheduled())          
2567          animateSensor->unschedule();            
2568       setSuperimpositionEnabled(superimpositi    
2569       maxSpeed = 0.0f;                           
2570       scheduleRedraw();                          
2571    } else {                                      
2572       saveCurCamera();                           
2573       prevState = currentState;                  
2574       prevRefIdx = refParticleIdx;               
2575    }                                             
2576                                                  
2577    if (SoQtExaminerViewer::isAnimating())        
2578       stopAnimating();                           
2579                                                  
2580    up_down = 0;                                  
2581    left_right = 0;                               
2582    step = 1;                                     
2583                                                  
2584    refParticleIdx = 0;                           
2585    currentState = BEAMLINE;                      
2586    setSuperimpositionEnabled(superimposition,    
2587    axisSwitch->whichChild.setValue(SO_SWITCH_    
2588    animSpeedOutlineSwitch->whichChild.setValu    
2589    animSpeedSwitch->whichChild.setValue(SO_SW    
2590    scheduleRedraw();                             
2591                                                  
2592    // FWJ Disabled: this is set in moveCamera    
2593    // Zoom in                                    
2594    //   SoCamera *cam = getCamera();             
2595    //   cam->focalDistance = 0.1f;               
2596                                                  
2597    prevParticleDir = SbVec3f(0,0,0);             
2598                                                  
2599    //Default zoom                                
2600    SbVec3f p1 = refParticleTrajectory[0];        
2601    SbVec3f pN = refParticleTrajectory[refPart    
2602    distance = (pN - p1).length() / 10;           
2603                                                  
2604    moveCamera(distance, true);                   
2605 }                                                
2606                                                  
2607                                                  
2608 void G4OpenInventorQtExaminerViewer::ToolsRef    
2609 {                                                
2610    invertRefPath();                              
2611 }                                                
2612                                                  
2613                                                  
2614 void G4OpenInventorQtExaminerViewer::invertRe    
2615 {                                                
2616    std::reverse(refParticleTrajectory.begin()    
2617                 refParticleTrajectory.end());    
2618    setReferencePathZPos();                       
2619    sortElements();                               
2620 }                                                
2621                                                  
2622                                                  
2623 void G4OpenInventorQtExaminerViewer::animateR    
2624 {                                                
2625    SoCamera *cam = getCamera();                  
2626                                                  
2627    camStartPos = cam->position.getValue();       
2628    camStartOrient = cam->orientation.getValue    
2629                                                  
2630    if (currentState != BEAMLINE)                 
2631       setStartingPtForAnimation();               
2632                                                  
2633    camEndPos = myCam->position.getValue();       
2634    camEndOrient = myCam->orientation.getValue    
2635                                                  
2636    if (animateSensor->isScheduled())             
2637       animateSensor->unschedule();               
2638                                                  
2639    animateSensor->setBaseTime(SbTime::getTime    
2640    animateSensor->setInterval(SbTime(0.02));     
2641                                                  
2642    animateSensor->schedule();                    
2643 }                                                
2644                                                  
2645                                                  
2646 #if QT_VERSION < 0x060000                        
2647 void G4OpenInventorQtExaminerViewer::addEscap    
2648 {                                                
2649    escapeCallback = callback;                    
2650 }                                                
2651 #endif                                           
2652                                                  
2653 void G4OpenInventorQtExaminerViewer::sceneCha    
2654 {                                                
2655    // FWJ DEBUG                                  
2656    //   G4cout << "SCENE CHANGE callback" <<     
2657    // NOTE: could/should be disabled during a    
2658                                                  
2659    G4OpenInventorQtExaminerViewer* This =        
2660       (G4OpenInventorQtExaminerViewer*)userDa    
2661    if(This->newEvents) {                         
2662       This->findAndSetRefPath();                 
2663       This->newEvents = false;                   
2664    }                                             
2665 }                                                
2666                                                  
2667                                                  
2668 //////////////////////////////////// BOOKMARK    
2669                                                  
2670 // Adds bookmarks to listsDialog.                
2671                                                  
2672 void G4OpenInventorQtExaminerViewer::addViewP    
2673 {                                                
2674    std::size_t size = viewPtList.size();         
2675    if (!size) return;                            
2676                                                  
2677    for (std::size_t i = 0; i < size; ++i) {      
2678 #if QT_VERSION < 0x060000                        
2679       new QListWidgetItem(viewPtList[i].viewP    
2680                           AuxWindowDialog->li    
2681 #else                                            
2682       new QListWidgetItem(viewPtList[i].viewP    
2683                           AuxWindowDialog->li    
2684 #endif                                           
2685    }                                             
2686 }                                                
2687                                                  
2688                                                  
2689 // Converts a string type word into a float t    
2690                                                  
2691 template<class T>                                
2692 void G4OpenInventorQtExaminerViewer::parseStr    
2693                                                  
2694 {                                                
2695    std::istringstream str(s);                    
2696    if ((str >> t).fail())                        
2697       error = true;                              
2698 }                                                
2699                                                  
2700                                                  
2701 void                                             
2702 G4OpenInventorQtExaminerViewer::FileOpenBookm    
2703 {                                                
2704    // FWJ DEBUG                                  
2705    //   G4cout << "File: Open Bookmark File C    
2706    QFileDialog filedialog(getParentWidget(),     
2707    filedialog.setFileMode(QFileDialog::Existi    
2708    filedialog.setFont(*font);                    
2709    if (!filedialog.exec()) return;               
2710    QStringList filenameinlist = filedialog.se    
2711    QString filenamein = filenameinlist[0];       
2712                                                  
2713    fileIn.close();                               
2714    fileIn.open(qPrintable(filenamein));          
2715    if (fileIn.fail()) {                          
2716       QMessageBox msgbox;                        
2717       msgbox.setFont(*font);                     
2718       QString messagetxt = "Error opening fil    
2719       messagetxt.append(filenamein);             
2720       msgbox.setText(messagetxt);                
2721       msgbox.exec();                             
2722       //      G4cout << "ERROR opening file "    
2723       fileIn.clear();                            
2724       return;                                    
2725    }                                             
2726    // Opens a file without erasing it            
2727    cleanUpAfterPrevFile();                       
2728                                                  
2729    if (!loadViewPts()) {                         
2730       QMessageBox msgbox;                        
2731       msgbox.setFont(*font);                     
2732       QString messagetxt = "Error reading boo    
2733       messagetxt.append(filenamein);             
2734       msgbox.setText(messagetxt);                
2735       msgbox.exec();                             
2736       //      G4cout << "ERROR reading bookma    
2737       fileIn.clear();                            
2738       return;                                    
2739    }                                             
2740                                                  
2741    fileName = qPrintable(filenamein);            
2742    fileOut.open(fileName.c_str(), std::ios::i    
2743    fileOut.seekp(0, std::ios::end);              
2744                                                  
2745    addViewPoints();                              
2746                                                  
2747    // LATER: display filename in lists window    
2748                                                  
2749    fileIn.close();                               
2750    fileIn.clear();                               
2751 }                                                
2752                                                  
2753 // Called before loading a new viewpoint file    
2754 // Resets member fields to default values.       
2755                                                  
2756 void G4OpenInventorQtExaminerViewer::cleanUpA    
2757 {                                                
2758    viewPtIdx = -1;                               
2759    viewPtList.clear();                           
2760    //   setSuperimpositionEnabled(superimposi    
2761    //   scheduleRedraw();                        
2762    currentState = GENERAL;                       
2763    if (fileOut.is_open()) fileOut.close();       
2764                                                  
2765    AuxWindowDialog->listWidget->clear();         
2766    AuxWindowDialog->lineEdit->setText(QString    
2767 }                                                
2768                                                  
2769                                                  
2770 void                                             
2771 G4OpenInventorQtExaminerViewer::FileNewBookma    
2772 {                                                
2773    //   G4cout << "File: Open New Bookmark Fi    
2774    QFileDialog filedialog(getParentWidget(),     
2775    filedialog.setFileMode(QFileDialog::AnyFil    
2776    // To enable confirmation of overwriting      
2777    filedialog.setAcceptMode(QFileDialog::Acce    
2778    // But change the "Save" button text          
2779    filedialog.setLabelText(QFileDialog::Accep    
2780    filedialog.setFont(*font);                    
2781    if (!filedialog.exec()) return;               
2782    QStringList filenameinlist = filedialog.se    
2783    QString filenamein = filenameinlist[0];       
2784                                                  
2785    cleanUpAfterPrevFile();                       
2786    fileName = qPrintable(filenamein);            
2787    fileOut.open(fileName.c_str());               
2788    if (fileOut.fail()) {                         
2789       QMessageBox msgbox;                        
2790       msgbox.setFont(*font);                     
2791       QString messagetxt = "Error opening new    
2792       messagetxt.append(filenamein);             
2793       msgbox.setText(messagetxt);                
2794       msgbox.exec();                             
2795       // G4cout << "ERROR opening new bookmar    
2796    }                                             
2797 }                                                
2798                                                  
2799                                                  
2800 void                                             
2801 G4OpenInventorQtExaminerViewer::ToolsAnimateR    
2802 {                                                
2803    //   G4cout << "Tools: Animate Ref Particl    
2804    if (!refParticleTrajectory.size()) {          
2805       returnToAnim = true;                       
2806       G4warn << "No Reference Trajectory" <<     
2807       return;                                    
2808    }                                             
2809                                                  
2810    //////////////////////////////////////////    
2811    setSuperimpositionEnabled(superimposition,    
2812    maxSpeed = SPEED_INDICATOR_STEP;              
2813    axisSwitch->whichChild.setValue(SO_SWITCH_    
2814    animSpeedOutlineSwitch->whichChild.setValu    
2815    animSpeedSwitch->whichChild.setValue(SO_SW    
2816    scheduleRedraw();                             
2817    //////////////////////////////////////////    
2818                                                  
2819    SoCamera *cam = getCamera();                  
2820    //   SbVec3f camDirOld, camDirNew, camDirN    
2821                                                  
2822    if (currentState == ANIMATION || currentSt    
2823        || currentState == ROTATING)              
2824       return;                                    
2825                                                  
2826    if (currentState != PAUSED_ANIMATION) {       
2827                                                  
2828       saveCurCamera();                           
2829       prevState = currentState;                  
2830       prevRefIdx = refParticleIdx;               
2831                                                  
2832       if (cam->isOfType(SoOrthographicCamera:    
2833          toggleCameraType();                     
2834          cam = getCamera();                      
2835       }                                          
2836                                                  
2837       refParticleIdx = 0; // Set the camera t    
2838       animateBtwPtsPeriod = MIN_SPEED;           
2839       speedStep = START_STEP;                    
2840       left_right = up_down = 0;                  
2841                                                  
2842       cam->focalDistance = 0.1f;                 
2843       ((SoPerspectiveCamera *) cam)->heightAn    
2844    }                                             
2845                                                  
2846    currentState = ANIMATION;                     
2847    setStartingPtForAnimation();                  
2848                                                  
2849    cam->position = (myCam)->position.getValue    
2850    cam->orientation = (myCam)->orientation.ge    
2851    animateRefParticle(); // Animate the camer    
2852 }                                                
2853                                                  
2854                                                  
2855 void                                             
2856 G4OpenInventorQtExaminerViewer::SaveViewPtCB(    
2857 {                                                
2858    //   G4cout << "AppButton: Save Viewpoint     
2859    // First get viewpoint name ...               
2860    // EMULATING getViewPtNameCB ...              
2861    //   bool ok;                                 
2862    // Note QString() returns an empty string     
2863 #if 0x060000 <= QT_VERSION                       
2864    //G.Barrand: map the AuxWindow here. Then     
2865    //           and not systematically when c    
2866    //           Moreover, if "closing" the Au    
2867    //           it permits to map it back.       
2868    AuxWindow->show();                            
2869    AuxWindow->raise();                           
2870    AuxWindow->activateWindow();                  
2871 #endif                                           
2872                                                  
2873    // NONE OF THE FOLLOWING CHANGES THE FONT:    
2874    QInputDialog* inputdialog = new QInputDial    
2875    inputdialog->setFont(*font);                  
2876    inputdialog->setWindowTitle(tr("Enter a na    
2877    inputdialog->setLabelText("Bookmark name")    
2878    //   inputdialog->setTextEchoMode(QLineEdi    
2879    inputdialog->adjustSize();                    
2880    QString namein;                               
2881    if (inputdialog->exec() == QDialog::Accept    
2882       namein=inputdialog->textValue().trimmed    
2883    else                                          
2884       return;                                    
2885    if (namein.isEmpty()) return;                 
2886                                                  
2887    // This easier approach failed: unable to     
2888    //   QString namein =                         
2889    //      QInputDialog::getText(getParentWid    
2890    //                            tr("Enter a     
2891    //                            tr("Bookmark    
2892    //                            QString(), &    
2893                                                  
2894    namein.truncate(MAX_VP_NAME);                 
2895                                                  
2896    char* name = strdup(qPrintable(namein));      
2897                                                  
2898    // FWJ DEBUG                                  
2899    //   G4cout << "QString is " << qPrintable    
2900    //   G4cout << "char[] is  " << name << G4    
2901                                                  
2902    for (int i = 0; i < (int)viewPtList.size()    
2903 #if QT_VERSION < 0x060000                        
2904       if (!strcmp(name, viewPtList[i].viewPtN    
2905 #else                                            
2906       if (!strcmp(name, viewPtList[i].viewPtN    
2907 #endif                                           
2908          QMessageBox msgbox;                     
2909          msgbox.setText("Bookmark name is alr    
2910          msgbox.exec();                          
2911          free(name);                             
2912          return;                                 
2913       }                                          
2914    }                                             
2915                                                  
2916    if (viewPtIdx == -1) viewPtIdx = 0;           
2917    saveViewPt(name);                             
2918                                                  
2919    saveViewPtItem = new QListWidgetItem(namei    
2920                                         AuxWi    
2921    AuxWindowDialog->listWidget->setCurrentIte    
2922    AuxWindowDialog->lineEdit->setText(namein)    
2923    free(name);                                   
2924 }                                                
2925                                                  
2926                                                  
2927 // Saves current camera parameters to a viewp    
2928                                                  
2929 void G4OpenInventorQtExaminerViewer::saveView    
2930 {                                                
2931    SbVec3f axis;                                 
2932    viewPtData tmp;                               
2933    float x, y, z, angle;                         
2934    SoCamera* camera = getCamera();               
2935                                                  
2936    // NOTE: Xt VSN increments this at end of     
2937    //   viewPtIdx++;                             
2938                                                  
2939    //  FWJ DEBUG                                 
2940    //   G4cout << "saveViewPt: saving bookmar    
2941    //          << G4endl;                        
2942                                                  
2943    if (viewPtList.size() == 0) {                 
2944       writeViewPtIdx();                          
2945    }                                             
2946                                                  
2947 #if QT_VERSION < 0x060000                        
2948    tmp.viewPtName = name;                        
2949 #else                                            
2950    tmp.viewPtName = std::string(name);           
2951 #endif                                           
2952    tmp.viewportMapping = camera->viewportMapp    
2953    tmp.position = camera->position.getValue()    
2954    tmp.orientation = camera->orientation.getV    
2955    tmp.aspectRatio = camera->aspectRatio.getV    
2956    tmp.nearDistance = camera->nearDistance.ge    
2957    tmp.farDistance = camera->farDistance.getV    
2958    tmp.focalDistance = camera->focalDistance.    
2959                                                  
2960    // Save camera height (changed by zooming)    
2961    if (camera->isOfType(SoPerspectiveCamera::    
2962       tmp.height = ((SoPerspectiveCamera *) c    
2963       tmp.camType = PERSPECTIVE;                 
2964    } else if (camera->isOfType(SoOrthographic    
2965       tmp.height = ((SoOrthographicCamera *)     
2966       tmp.camType = ORTHOGRAPHIC;                
2967    } else {                                      
2968       SoDebugError::post("G4OpenInventorQtExa    
2969                          "Only Perspective an    
2970       return;                                    
2971    }                                             
2972                                                  
2973    viewPtList.push_back(tmp);                    
2974                                                  
2975    // Now save the view point to a .txt file     
2976    // FWJ DEBUG                                  
2977    // G4cout << "saveViewPt: writing to Bookm    
2978                                                  
2979    std::string vpName = name;                    
2980                                                  
2981    while ((int) vpName.size() <= MAX_VP_NAME)    
2982       vpName += " ";                             
2983                                                  
2984    fileOut << vpName << std::endl;               
2985    tmp.position.getValue(x, y, z);               
2986    fileOut << x << " " << y << " " << z << st    
2987                                                  
2988    // Reusing x, y and z for storing the axis    
2989    tmp.orientation.getValue(axis, angle);        
2990    axis.getValue(x, y, z);                       
2991    fileOut << x << " " << y << " " << z << "     
2992                                                  
2993    fileOut << tmp.camType << " " << tmp.heigh    
2994    fileOut << tmp.focalDistance << " ";          
2995    fileOut << tmp.nearDistance << " ";           
2996    fileOut << tmp.farDistance << std::endl;      
2997    fileOut << tmp.viewportMapping << " ";        
2998    fileOut << tmp.aspectRatio << "\n" << std:    
2999    fileOut.flush();                              
3000                                                  
3001    viewPtIdx++;                                  
3002                                                  
3003    // FWJ DEBUG                                  
3004    //   G4cout << "saveViewPt: finished writi    
3005    //      "  Next viewPtIdx is " << viewPtId    
3006 }                                                
3007                                                  
3008                                                  
3009 // Updates the viewPtIdx in a viewpoint file.    
3010                                                  
3011 void G4OpenInventorQtExaminerViewer::writeVie    
3012 {                                                
3013    std::string idxStr;                           
3014    std::stringstream out;                        
3015                                                  
3016    out << viewPtIdx;                             
3017    idxStr = out.str();                           
3018    fileOut.seekp(0, std::ios::beg);              
3019                                                  
3020    while ((int) idxStr.length() < MAX_VP_IDX)    
3021       idxStr += " ";                             
3022    }                                             
3023                                                  
3024    // FWJ DEBUG                                  
3025    //   G4cout << "writeViewPtIdx: " << viewP    
3026    fileOut << idxStr << "\n";                    
3027    fileOut.flush();                              
3028    fileOut.seekp(0, std::ios::end);              
3029 }                                                
3030                                                  
3031                                                  
3032 // Receives the name of the bookmark clicked     
3033                                                  
3034 void G4OpenInventorQtExaminerViewer::LoadBook    
3035 {                                                
3036    // FWJ DEBUG                                  
3037    //   G4cout << "AuxWindow: listWidget Load    
3038                                                  
3039    for (int i = 0; i < (int)viewPtList.size()    
3040 #if QT_VERSION < 0x060000                        
3041       if (!strcmp(viewPtList[i].viewPtName, q    
3042 #else                                            
3043       if (!strcmp(viewPtList[i].viewPtName.c_    
3044 #endif                                           
3045          viewPtIdx = i;                          
3046          break;                                  
3047       }                                          
3048    }                                             
3049    //   G4cout << "  FOUND viewPtIdx " << vie    
3050                                                  
3051    writeViewPtIdx();                             
3052    setViewPt();                                  
3053    AuxWindowDialog->lineEdit->setText(item->t    
3054 }                                                
3055                                                  
3056                                                  
3057 // Sets the viewpoint based on camera data th    
3058                                                  
3059 void G4OpenInventorQtExaminerViewer::setViewP    
3060 {                                                
3061    if (currentState == ANIMATION || currentSt    
3062        || currentState == ROTATING) {            
3063       if (animateSensor->isScheduled()) anima    
3064       setSuperimpositionEnabled(superimpositi    
3065       maxSpeed = 0.0f;                           
3066       scheduleRedraw();                          
3067    }                                             
3068                                                  
3069    SoCamera * camera = getCamera();              
3070    if (camera == NULL) {                         
3071       G4warn << "setViewPt: Camera is null. U    
3072          G4endl;                                 
3073       //      String dialogName = (char *) "M    
3074       //      std::string msg = "Camera is nu    
3075       //      warningMsgDialog(msg, dialogNam    
3076       return;                                    
3077    }                                             
3078                                                  
3079    if (!viewPtList.size()) {                     
3080       G4warn << "setViewPt: There are no view    
3081       //      String dialogName = (char *) "M    
3082       //      std::string msg = "There are no    
3083       //      warningMsgDialog(msg, dialogNam    
3084       return;                                    
3085    }                                             
3086                                                  
3087    if (SoQtExaminerViewer::isAnimating()) sto    
3088                                                  
3089    if (currentState != VIEWPOINT) {              
3090       currentState = VIEWPOINT;                  
3091       ///////////////////////////////////////    
3092       setSuperimpositionEnabled(superimpositi    
3093       axisSwitch->whichChild.setValue(SO_SWIT    
3094       animSpeedOutlineSwitch->whichChild.setV    
3095       animSpeedSwitch->whichChild.setValue(SO    
3096       scheduleRedraw();                          
3097       ///////////////////////////////////////    
3098    }                                             
3099                                                  
3100 #if QT_VERSION < 0x060000                        
3101 #else                                            
3102    if((viewPtIdx<0)||(viewPtIdx>=int(viewPtLi    
3103      G4warn << "setViewPt: inconsitent viewPt    
3104      return;                                     
3105    }                                             
3106 #endif                                           
3107                                                  
3108    curViewPtName = viewPtList[viewPtIdx].view    
3109    camera->viewportMapping = viewPtList[viewP    
3110    camera->position = viewPtList[viewPtIdx].p    
3111    camera->orientation = viewPtList[viewPtIdx    
3112    camera->aspectRatio = viewPtList[viewPtIdx    
3113    camera->nearDistance = viewPtList[viewPtId    
3114    camera->farDistance = viewPtList[viewPtIdx    
3115    camera->focalDistance = viewPtList[viewPtI    
3116                                                  
3117    // Restore camera height (changed by zoomi    
3118    if (camera->isOfType(SoPerspectiveCamera::    
3119       if (viewPtList[viewPtIdx].camType == OR    
3120          toggleCameraType();                     
3121          camera = getCamera();                   
3122          ((SoOrthographicCamera *) camera)->h    
3123                                                  
3124       } else                                     
3125          ((SoPerspectiveCamera *) camera)->he    
3126                                                  
3127    } else if (camera->isOfType(SoOrthographic    
3128       if (viewPtList[viewPtIdx].camType == PE    
3129          toggleCameraType();                     
3130          camera = getCamera();                   
3131          ((SoPerspectiveCamera *) camera)->he    
3132                                                  
3133       } else                                     
3134          ((SoOrthographicCamera *) camera)->h    
3135                                                  
3136    } else {                                      
3137       SoDebugError::post("G4OpenInventorQtExa    
3138                          "Only Perspective an    
3139       return;                                    
3140    }                                             
3141                                                  
3142 }                                                
3143                                                  
3144                                                  
3145 void G4OpenInventorQtExaminerViewer::NextView    
3146 {                                                
3147    // FWJ DEBUG                                  
3148    //   G4cout << "App Button: nextViewPt CAL    
3149                                                  
3150    if (!viewPtList.size()) return;               
3151    if (viewPtIdx >= (int)viewPtList.size() -     
3152       viewPtIdx = 0;                             
3153 #if 0x060000 <= QT_VERSION                       
3154    else if (viewPtIdx<0)                         
3155       viewPtIdx = 0;                             
3156 #endif                                           
3157    else                                          
3158       viewPtIdx++;                               
3159                                                  
3160    writeViewPtIdx();                             
3161    setViewPt();                                  
3162 #if QT_VERSION < 0x060000                        
3163    char* viewptname = viewPtList[viewPtIdx].v    
3164    AuxWindowDialog->lineEdit->setText(QString    
3165 #else                                            
3166    AuxWindowDialog->lineEdit->setText(QString    
3167 #endif                                           
3168 }                                                
3169                                                  
3170 void G4OpenInventorQtExaminerViewer::PrevView    
3171 {                                                
3172    // FWJ DEBUG                                  
3173    //   G4cout << "App Button: prevViewPt CAL    
3174                                                  
3175    if (!viewPtList.size()) return;               
3176 #if QT_VERSION < 0x060000                        
3177    if (viewPtIdx == 0)                           
3178 #else                                            
3179    if (viewPtIdx <= 0)                           
3180 #endif                                           
3181       viewPtIdx = (int) viewPtList.size() - 1    
3182    else                                          
3183       viewPtIdx--;                               
3184                                                  
3185    writeViewPtIdx();                             
3186    setViewPt();                                  
3187 #if QT_VERSION < 0x060000                        
3188    char* viewptname = viewPtList[viewPtIdx].v    
3189    AuxWindowDialog->lineEdit->setText(QString    
3190 #else                                            
3191    AuxWindowDialog->lineEdit->setText(QString    
3192 #endif                                           
3193 }                                                
3194                                                  
3195                                                  
3196 void G4OpenInventorQtExaminerViewer::AbbrOutp    
3197 {                                                
3198    // FWJ DEBUG                                  
3199    //   G4cout << "App Button: abbrOutput CAL    
3200                                                  
3201    abbrOutputFlag = checked;                     
3202 }                                                
3203                                                  
3204                                                  
3205 void G4OpenInventorQtExaminerViewer::PickRefP    
3206 {                                                
3207    // FWJ DEBUG                                  
3208    //   G4cout << "App Button: pickRefPath CA    
3209                                                  
3210    // Save viewing state and go to picking mo    
3211    viewingBeforePickRef = isViewing();           
3212    if(isViewing())                               
3213       setViewing(false);                         
3214    setComponentCursor(SoQtCursor(SoQtCursor::    
3215    pickRefPathFlag = true;                       
3216 }                                                
3217                                                  
3218                                                  
3219 void G4OpenInventorQtExaminerViewer::SwitchWi    
3220 {                                                
3221    // FWJ DEBUG                                  
3222    //   G4cout << "App Button: switchWireFram    
3223                                                  
3224    //   if (switchWireFrameButton->isDown())     
3225    if (checked) {                                
3226       setDrawStyle(SoQtViewer::STILL, SoQtVie    
3227       setDrawStyle(SoQtViewer::INTERACTIVE, S    
3228    } else {                                      
3229       setDrawStyle(SoQtViewer::STILL, SoQtVie    
3230       setDrawStyle(SoQtViewer::INTERACTIVE,      
3231                          SoQtViewer::VIEW_SAM    
3232    }                                             
3233 }                                                
3234                                                  
3235                                                  
3236 void G4OpenInventorQtExaminerViewer::SwitchAx    
3237 {                                                
3238    // FWJ DEBUG                                  
3239    //   G4cout << "App Button: switchAxes CAL    
3240    setFeedbackVisibility(checked);               
3241    //   if (checked) {                           
3242    //      setFeedbackVisibility(TRUE);          
3243    //   } else {                                 
3244    //      setFeedbackVisibility(FALSE);         
3245    //   }                                        
3246 }                                                
3247                                                  
3248                                                  
3249 void G4OpenInventorQtExaminerViewer::DetachCB    
3250 {                                                
3251 #if QT_VERSION < 0x060000                        
3252    //   FWJ DEBUG                                
3253    //   G4cout << "App Button: detach CALLBAC    
3254    uiQt->GetViewerTabWidget()->removeTab(uiQt    
3255    viewerParent->setParent(viewerParent2);       
3256    removeAppPushButton(detachButton);            
3257    show();                                       
3258 #else                                            
3259    //G.Barrand: have the viewer in a detached    
3260    //           We have the title window refl    
3261    //           it comes from, then "Detached    
3262    //           Ask to destroy the detached v    
3263    //           of closing the window with th    
3264    //           we have a dandling hidden vie    
3265    //           to map it again.                 
3266    G4int index = -1;                             
3267   {int tabn = uiQt->GetViewerTabWidget()->cou    
3268    for (G4int c = 0; c < tabn; ++c) {            
3269      if (uiQt->GetViewerTabWidget()->tabText(    
3270        index = c;                                
3271      }                                           
3272    }}                                            
3273    if(index==(-1)) return;                       
3274    removeAppPushButton(detachButton);            
3275    uiQt->GetViewerTabWidget()->removeTab(inde    
3276   {short w,h;                                    
3277    getSize().getValue(w,h);                      
3278    QWidget* dialog = new QDialog();              
3279    dialog->setWindowTitle(QString("Detached "    
3280    dialog->setAttribute(Qt::WA_DeleteOnClose)    
3281   {QHBoxLayout* layout = new QHBoxLayout();      
3282    layout->setContentsMargins(0,0,0,0);          
3283    layout->setSpacing(0);                        
3284    layout->addWidget(getParentWidget());         
3285    dialog->setLayout(layout);}                   
3286    dialog->resize(w,h);                          
3287    getParentWidget()->show();                    
3288    dialog->show();                               
3289   }                                              
3290 #endif                                           
3291 }                                                
3292                                                  
3293                                                  
3294 void G4OpenInventorQtExaminerViewer::DeleteBo    
3295 {                                                
3296    // FWJ DEBUG                                  
3297    //   G4cout << "Delete Button: DeleteBookm    
3298                                                  
3299    // Maybe nothing selected yet                 
3300    QListWidgetItem* listitem = AuxWindowDialo    
3301    if (!listitem) return;                        
3302    if (!(listitem->isSelected())) return;        
3303                                                  
3304    QString vpnamein = listitem->text();          
3305                                                  
3306    char* vpName = strdup(qPrintable(vpnamein)    
3307    //   G4cout << "DELETING bookmark " << vpN    
3308                                                  
3309    deleteViewPt(vpName);                         
3310    delete listitem;                              
3311    free(vpName);                                 
3312 }                                                
3313                                                  
3314 // Deletes current viewpoint the user is look    
3315 // Updates the input file and bookmarks as we    
3316                                                  
3317 void G4OpenInventorQtExaminerViewer::deleteVi    
3318 {                                                
3319    std::string line;                             
3320    std::size_t end;                              
3321    fileIn.open(fileName.c_str());                
3322    std::ofstream out("temporaryFile.txt");       
3323                                                  
3324 #if QT_VERSION < 0x060000                        
3325    if (!vpName)                                  
3326       vpName = viewPtList[viewPtIdx].viewPtNa    
3327 #endif                                           
3328                                                  
3329    getline(fileIn, line); // Printing the vie    
3330    out << line << "\n";                          
3331                                                  
3332    while (getline(fileIn, line)) {               
3333       end = line.find_last_not_of(' ');          
3334       line = line.substr(0, end + 1);            
3335       if (!strcmp(line.c_str(), vpName)) { //    
3336          while (line.size()) {                   
3337             getline(fileIn, line);               
3338          }                                       
3339                                                  
3340          while (getline(fileIn, line))           
3341             out << line << "\n";                 
3342       } else {                                   
3343          while (line.size()) {                   
3344             out << line << "\n";                 
3345             getline(fileIn, line);               
3346          }                                       
3347          out << "\n";                            
3348       }                                          
3349    }                                             
3350                                                  
3351    std::size_t idx = 0; // Remove viewpoint f    
3352    std::size_t size = viewPtList.size();         
3353    while (idx < size) {                          
3354 #if QT_VERSION < 0x060000                        
3355       if (!strcmp(viewPtList[idx].viewPtName,    
3356 #else                                            
3357       if (!strcmp(viewPtList[idx].viewPtName.    
3358 #endif                                           
3359          viewPtList.erase(viewPtList.begin()     
3360          break;                                  
3361       }                                          
3362       idx++;                                     
3363    }                                             
3364                                                  
3365    out.close();                                  
3366    fileOut.close();                              
3367    fileIn.clear();                               
3368    fileIn.close();                               
3369                                                  
3370    // FWJ check return status: error popups n    
3371    int istat = remove(fileName.c_str());         
3372    if (istat == -1) {                            
3373       QMessageBox msgbox;                        
3374       msgbox.setFont(*font);                     
3375       QString messagetxt = "Error removing bo    
3376       //      messagetxt.append(filenamein);     
3377       msgbox.setText(messagetxt);                
3378       msgbox.exec();                             
3379       //      G4cout << "Error removing bookm    
3380    }                                             
3381    istat = rename("temporaryFile.txt", fileNa    
3382    if (istat == -1) {                            
3383       QMessageBox msgbox;                        
3384       msgbox.setFont(*font);                     
3385       QString messagetxt = "Error renaming bo    
3386       //      messagetxt.append(filenamein);     
3387       msgbox.setText(messagetxt);                
3388       msgbox.exec();                             
3389       //      G4cout << "Error renaming bookm    
3390    }                                             
3391    fileOut.open(fileName.c_str(), std::ios::i    
3392    fileOut.seekp(0, std::ios::end);              
3393                                                  
3394    if (!viewPtList.size()) { // viewPtList is    
3395 #if QT_VERSION < 0x060000                        
3396       curViewPtName = (char *) empty.c_str();    
3397 #else                                            
3398       curViewPtName.clear();                     
3399 #endif                                           
3400       scheduleRedraw();                          
3401    } else {                                      
3402       if (viewPtIdx >= (int) viewPtList.size(    
3403          viewPtIdx--;                            
3404       writeViewPtIdx();                          
3405       setViewPt();                               
3406    }                                             
3407 }                                                
3408                                                  
3409                                                  
3410 void G4OpenInventorQtExaminerViewer::RenameBo    
3411 {                                                
3412    // FWJ DEBUG                                  
3413    //   G4cout << "Rename Button: RenameBookm    
3414    // Maybe nothing selected yet                 
3415    QListWidgetItem* listitem = AuxWindowDialo    
3416    if (!listitem) return;                        
3417    if (!(listitem->isSelected())) return;        
3418                                                  
3419    QString vpnamein = listitem->text();          
3420                                                  
3421    QInputDialog* inputdialog = new QInputDial    
3422    inputdialog->setFont(*font);                  
3423    inputdialog->setWindowTitle(tr("Enter"));     
3424    inputdialog->setLabelText("New bookmark na    
3425    inputdialog->adjustSize();                    
3426    QString newnamein;                            
3427    if (inputdialog->exec() == QDialog::Accept    
3428       newnamein=inputdialog->textValue().trim    
3429    else                                          
3430       return;                                    
3431    if (newnamein.isEmpty()) return;              
3432                                                  
3433    char* newname = strdup(qPrintable(newnamei    
3434                                                  
3435    std::size_t size = viewPtList.size();         
3436    for (std::size_t i = 0; i < size; ++i) {      
3437 #if QT_VERSION < 0x060000                        
3438       if (!strcmp(newname, viewPtList[i].view    
3439 #else                                            
3440       if (!strcmp(newname, viewPtList[i].view    
3441 #endif                                           
3442          QMessageBox msgbox;                     
3443          msgbox.setFont(*font);                  
3444          msgbox.setText("Bookmark name is alr    
3445          msgbox.exec();                          
3446       }                                          
3447    }                                             
3448                                                  
3449    //   G4cout << "RENAMING to " << newname <    
3450    renameViewPt(newname);                        
3451    listitem->setText(QString(newname));          
3452    AuxWindowDialog->lineEdit->setText(newname    
3453    //   if (currentState == VIEWPOINT)           
3454    //      scheduleRedraw();                     
3455                                                  
3456    free(newname);                                
3457 }                                                
3458                                                  
3459 // Renames currently selected viewpoint.         
3460                                                  
3461 void G4OpenInventorQtExaminerViewer::renameVi    
3462 {                                                
3463    std::size_t idx = 0, end, pos;                
3464    std::size_t size = viewPtList.size();         
3465    std::string line, newName;                    
3466    fileIn.open(fileName.c_str());                
3467                                                  
3468    newName = vpName;                             
3469    while ((int) newName.size() < MAX_VP_NAME)    
3470       newName += " ";                            
3471                                                  
3472    getline(fileIn, line);                        
3473    pos = fileIn.tellg();                         
3474    while (getline(fileIn, line)) {               
3475       end = line.find_last_not_of(' ');          
3476       line = line.substr(0, end + 1);            
3477 #if QT_VERSION < 0x060000                        
3478       if (!strcmp(line.c_str(), curViewPtName    
3479 #else                                            
3480       if (!strcmp(line.c_str(), curViewPtName    
3481 #endif                                           
3482          fileOut.seekp(pos);                     
3483          fileOut << newName;                     
3484          fileOut.seekp(0, std::ios::end); //     
3485          break;                                  
3486       }                                          
3487       while (line.size())                        
3488          getline(fileIn, line);                  
3489       pos = fileIn.tellg();                      
3490    }                                             
3491                                                  
3492    fileIn.close();                               
3493    fileIn.clear();                               
3494                                                  
3495    while (idx < size) {                          
3496 #if QT_VERSION < 0x060000                        
3497       if (!strcmp(viewPtList[idx].viewPtName,    
3498          strcpy(viewPtList[idx].viewPtName, v    
3499 #else                                            
3500       if (!strcmp(viewPtList[idx].viewPtName.    
3501          viewPtList[idx].viewPtName = std::st    
3502 #endif                                           
3503          break;                                  
3504       }                                          
3505       idx++;                                     
3506    }                                             
3507 }                                                
3508                                                  
3509                                                  
3510 void G4OpenInventorQtExaminerViewer::SortBook    
3511 {                                                
3512    // FWJ NOTE: Xt version of this does not w    
3513                                                  
3514    //   G4cout << "Sort Button: SortBookmarks    
3515                                                  
3516    // FWJ List for sorting                       
3517    // The dialog list and bookmark file will     
3518    // Simpler to populate this list from the     
3519                                                  
3520    std::vector<std::string> charList;            
3521                                                  
3522    if (viewPtList.size() < 2) return;            
3523                                                  
3524    // Get current entries from the list          
3525                                                  
3526    for (int i = 0; i < (int)viewPtList.size()    
3527                                                  
3528       charList.push_back(viewPtList[i].viewPt    
3529       //      G4cout << "  Pushed " << i << "    
3530    }                                             
3531                                                  
3532    std::sort(charList.begin(), charList.end()    
3533                                                  
3534    // FWJ POPULATE the new dialog list           
3535    //   G4cout << "  Populating Bookmark list    
3536    AuxWindowDialog->listWidget->clear();         
3537                                                  
3538    for (int i = 0; i < (int)viewPtList.size()    
3539       // viewPtIdx has to be changed to accou    
3540 #if QT_VERSION < 0x060000                        
3541       if (!strcmp(charList[i].c_str(), curVie    
3542 #else                                            
3543       if (!strcmp(charList[i].c_str(), curVie    
3544 #endif                                           
3545          viewPtIdx = i;                          
3546       new QListWidgetItem(charList[i].c_str()    
3547                                                  
3548    }                                             
3549                                                  
3550    sortViewPts(charList);                        
3551                                                  
3552 }                                                
3553                                                  
3554 // Rewrites entire viewpoint file with sorted    
3555                                                  
3556 void G4OpenInventorQtExaminerViewer::sortView    
3557 {                                                
3558    SbVec3f axis;                                 
3559    float x, y, z, angle;                         
3560    std::size_t sortIdx = 0, unsortIdx = 0;       
3561                                                  
3562    if (fileOut.is_open())                        
3563       fileOut.close();                           
3564                                                  
3565    fileOut.open(fileName.c_str()); // Erase c    
3566                                                  
3567    writeViewPtIdx();                             
3568                                                  
3569    std::size_t size = sortedViewPts.size();      
3570    while (sortIdx < size) {                      
3571       while (strcmp(sortedViewPts[sortIdx].c_    
3572 #if QT_VERSION < 0x060000                        
3573                     viewPtList[unsortIdx].vie    
3574 #else                                            
3575                     viewPtList[unsortIdx].vie    
3576 #endif                                           
3577          unsortIdx++;                            
3578                                                  
3579       std::string vpName = viewPtList[unsortI    
3580                                                  
3581       while ((int) vpName.size() < MAX_VP_NAM    
3582          vpName += " ";                          
3583       fileOut << vpName << std::endl;            
3584       viewPtList[unsortIdx].position.getValue    
3585       fileOut << x << " " << y << " " << z <<    
3586                                                  
3587       // Reusing x, y and z for storing the a    
3588       viewPtList[unsortIdx].orientation.getVa    
3589       axis.getValue(x, y, z);                    
3590       fileOut << x << " " << y << " " << z <<    
3591                                                  
3592       fileOut << viewPtList[unsortIdx].camTyp    
3593               << viewPtList[unsortIdx].height    
3594       fileOut << viewPtList[unsortIdx].focalD    
3595                                                  
3596       fileOut << viewPtList[unsortIdx].nearDi    
3597                                                  
3598       fileOut << viewPtList[unsortIdx].farDis    
3599                                                  
3600       fileOut << viewPtList[unsortIdx].viewpo    
3601       fileOut << viewPtList[unsortIdx].aspect    
3602       fileOut.flush();                           
3603                                                  
3604       unsortIdx = 0;                             
3605       sortIdx++;                                 
3606    }                                             
3607 }                                                
3608                                                  
3609 // Needed to implement mouse wheel zoom direc    
3610 // Does not work with MacOS trackpad: use Coi    
3611 // Emulating private method SoGuiFullViewerP:    
3612 #ifndef __APPLE__                                
3613 void                                             
3614 G4OpenInventorQtExaminerViewer::zoom(const fl    
3615 {                                                
3616    float multiplicator = float(std::exp(diffv    
3617    SoCamera *cam = getCamera();                  
3618                                                  
3619    if (cam->isOfType(SoPerspectiveCamera::get    
3620       const float oldfocaldist = cam->focalDi    
3621       const float newfocaldist = oldfocaldist    
3622                                                  
3623       SbVec3f direction;                         
3624       cam->orientation.getValue().multVec(SbV    
3625                                                  
3626       const SbVec3f oldpos = cam->position.ge    
3627       const SbVec3f newpos = oldpos + (newfoc    
3628       cam->position = newpos;                    
3629       cam->focalDistance = newfocaldist;         
3630    } else if (cam->isOfType(SoOrthographicCam    
3631       SoOrthographicCamera * oc = (SoOrthogra    
3632       oc->height = oc->height.getValue() * mu    
3633    }                                             
3634 }                                                
3635 #endif                                           
3636                                                  
3637 // Handling mouse and keyboard events            
3638                                                  
3639 SbBool                                           
3640 G4OpenInventorQtExaminerViewer::processSoEven    
3641 {                                                
3642                                                  
3643    // FWJ DEBUG                                  
3644    //   G4cout << "processSoEvent ###########    
3645                                                  
3646    SoCamera *cam = getCamera();                  
3647    const SoType type(ev->getTypeId());           
3648                                                  
3649 // Needed to implement mouse wheel zoom direc    
3650 // Does not work with MacOS trackpad: use Coi    
3651 #ifndef __APPLE__                                
3652    if (type.isDerivedFrom(SoMouseButtonEvent:    
3653       SoMouseButtonEvent * me = (SoMouseButto    
3654                                                  
3655       //      if (currentState == ANIMATION |    
3656       //          || currentState == PAUSED_A    
3657                                                  
3658       switch (me->getButton()) {                 
3659                                                  
3660          case SoMouseButtonEvent::BUTTON4: //    
3661             if (me->getState() == SoButtonEve    
3662                //               G4cout << "SC    
3663                zoom(-0.1f);                      
3664                return TRUE;                      
3665             }                                    
3666             break;                               
3667                                                  
3668          case SoMouseButtonEvent::BUTTON5: //    
3669             if (me->getState() == SoButtonEve    
3670                //               G4cout << "SC    
3671                zoom(0.1f);                       
3672                return TRUE;                      
3673             }                                    
3674             break;                               
3675                                                  
3676          default:                                
3677             break;                               
3678       }                                          
3679          //      }                               
3680       if (currentState == GENERAL) {             
3681                                                  
3682       }                                          
3683    }                                             
3684 #endif                                           
3685                                                  
3686    if (type.isDerivedFrom(SoKeyboardEvent::ge    
3687       SoKeyboardEvent* ke = (SoKeyboardEvent*    
3688                                                  
3689       if (SoKeyboardEvent::isKeyPressEvent(ev    
3690          switch (ke->getKey()) {                 
3691          case SoKeyboardEvent::E:                
3692             if (externalQtApp) {                 
3693                // G4cout << "E KEY PRESSED" <    
3694                return TRUE;                      
3695             } else {                             
3696                G4cout <<                         
3697                   "E KEY PRESSED, EXITING OIQ    
3698                   G4endl;                        
3699                SoQt::exitMainLoop();             
3700             //            escapeCallback();      
3701                return TRUE;                      
3702             }                                    
3703          case SoKeyboardEvent::LEFT_SHIFT:       
3704             this->lshiftdown = true;             
3705             return TRUE;                         
3706          case SoKeyboardEvent::RIGHT_SHIFT:      
3707             this->rshiftdown = true;             
3708             return TRUE;                         
3709          case SoKeyboardEvent::LEFT_CONTROL:     
3710             this->lctrldown = true;              
3711             return TRUE;                         
3712          case SoKeyboardEvent::RIGHT_CONTROL:    
3713             this->rctrldown = true;              
3714             return TRUE;                         
3715          case SoKeyboardEvent::SPACE:            
3716             if (currentState == ANIMATION        
3717                 || currentState == REVERSED_A    
3718                beforePausing = currentState;     
3719                currentState = PAUSED_ANIMATIO    
3720                if (animateSensor->isScheduled    
3721                   animateSensor->unschedule()    
3722                return TRUE;                      
3723             } else if (currentState == PAUSED    
3724                if (maxSpeed) {                   
3725                   if ((beforePausing == ANIMA    
3726                        && refParticleIdx         
3727                        < (int) refParticleTra    
3728                       || (beforePausing == RE    
3729                           && refParticleIdx >    
3730                      currentState = beforePau    
3731                      animateRefParticle();       
3732                   }                              
3733                }                                 
3734                return TRUE;                      
3735             }                                    
3736             break;                               
3737          case SoKeyboardEvent::ESCAPE:           
3738             if (currentState == ANIMATION        
3739                 || currentState == REVERSED_A    
3740                 || currentState == PAUSED_ANI    
3741                                                  
3742                if (animateSensor->isScheduled    
3743                   animateSensor->unschedule()    
3744                currentState = prevState;         
3745                refParticleIdx = prevRefIdx;      
3746                setSuperimpositionEnabled(supe    
3747                maxSpeed = 0.0f;                  
3748                step = 1;                         
3749                                                  
3750                scheduleRedraw();                 
3751                if (currentState == VIEWPOINT)    
3752                   setSuperimpositionEnabled(s    
3753                   axisSwitch->whichChild.setV    
3754                   animSpeedOutlineSwitch->whi    
3755                                                  
3756                   animSpeedSwitch->whichChild    
3757                                                  
3758                   scheduleRedraw();              
3759                }                                 
3760                restoreCamera();                  
3761                return TRUE;                      
3762             }                                    
3763             break;                               
3764          case SoKeyboardEvent::DELETE:           
3765             if (viewPtList.size()                
3766                 && (currentState != ANIMATION    
3767                     && currentState != REVERS    
3768                     && currentState != PAUSED    
3769                // FWJ IMPLEMENT LATER            
3770                // String dialogName = (char *    
3771                // std::string msg = "Are you     
3772                // warningMsgDialog(msg, dialo    
3773                return TRUE;                      
3774             }                                    
3775             break;                               
3776          case SoKeyboardEvent::LEFT_ARROW:       
3777             switch (currentState) {              
3778             case BEAMLINE:                       
3779                if ((this->lshiftdown)   || (t    
3780                   refParticleIdx -= step;        
3781                   moveCamera();                  
3782                }                                 
3783                else if ((this->lctrldown)        
3784                   if (SoQtExaminerViewer::isA    
3785                      stopAnimating();            
3786                   prevState = currentState;      
3787                   currentState = ROTATING;       
3788                   animateBtwPtsPeriod = 0.08f    
3789                                                  
3790                   SbVec3f tmp = camDir;          
3791                   tmp.negate();                  
3792                   rotAxis = tmp;                 
3793                                                  
3794                   rotCnt = ROT_CNT;              
3795                   moveCamera(); // To make su    
3796                   rotateCamera();                
3797                }                                 
3798                else {                            
3799                   if (SoQtExaminerViewer::isA    
3800                      stopAnimating();            
3801                   prevState = currentState;      
3802                   currentState = ROTATING;       
3803                   animateBtwPtsPeriod = 0.08f    
3804                                                  
3805                   SbVec3f tmp = camUpVec;        
3806                   tmp.negate();                  
3807                   rotAxis = tmp;                 
3808                                                  
3809                   rotCnt = ROT_CNT;              
3810                   moveCamera(); // To make su    
3811                   rotateCamera();                
3812                                                  
3813                }                                 
3814                return TRUE;                      
3815                                                  
3816             case ANIMATION:                      
3817             case REVERSED_ANIMATION:             
3818                left_right -= 1.5f;               
3819                return TRUE;                      
3820             case PAUSED_ANIMATION:               
3821                left_right -= 1.5f;               
3822                setStartingPtForAnimation();      
3823                cam->position = myCam->positio    
3824                return TRUE;                      
3825             case GENERAL:                        
3826             case VIEWPOINT:                      
3827                if ((!this->lshiftdown) && (!t    
3828                   // Using this allows us to     
3829                   // changing the camera para    
3830                   this->bottomWheelMotion(       
3831                                           thi    
3832                                                  
3833                   return TRUE;                   
3834                }                                 
3835                break;                            
3836             case ROTATING:                       
3837                // For this state, let the key    
3838                // be handled by superclass       
3839                break;                            
3840             default:                             
3841                SoDebugError::post("G4OpenInve    
3842                                   "Unhandled     
3843                break;                            
3844             }                                    
3845             break;                               
3846                                                  
3847          case SoKeyboardEvent::RIGHT_ARROW:      
3848             switch(currentState) {               
3849             case BEAMLINE:                       
3850                if ((this->lshiftdown)   || (t    
3851                   refParticleIdx += step;        
3852                   moveCamera();                  
3853                }                                 
3854                else if ((this->lctrldown)        
3855                   if (SoQtExaminerViewer::isA    
3856                      stopAnimating();            
3857                   prevState = currentState;      
3858                   currentState = ROTATING;       
3859                   animateBtwPtsPeriod = 0.08f    
3860                                                  
3861                   rotAxis = camDir;              
3862                                                  
3863                   rotCnt = ROT_CNT;              
3864                   moveCamera(); // To make su    
3865                   rotateCamera();                
3866                }                                 
3867                else{                             
3868                   if (SoQtExaminerViewer::isA    
3869                      stopAnimating();            
3870                   prevState = currentState;      
3871                   currentState = ROTATING;       
3872                   animateBtwPtsPeriod = 0.08f    
3873                                                  
3874                   rotAxis = camUpVec;            
3875                                                  
3876                   rotCnt = ROT_CNT;              
3877                   moveCamera(); // To make su    
3878                   rotateCamera();                
3879                }                                 
3880                return TRUE;                      
3881                                                  
3882             case ANIMATION:                      
3883             case REVERSED_ANIMATION:             
3884                left_right += 1.5f;               
3885                return TRUE;                      
3886             case PAUSED_ANIMATION:               
3887                left_right += 1.5f;               
3888                setStartingPtForAnimation();      
3889                cam->position = myCam->positio    
3890                return TRUE;                      
3891             case GENERAL:                        
3892             case VIEWPOINT:                      
3893                if ((!this->lshiftdown) && (!t    
3894                   // Using this allows us to     
3895                   // changing the camera para    
3896                   this->bottomWheelMotion(       
3897                                           thi    
3898                   return TRUE;                   
3899                }                                 
3900                break;                            
3901             case ROTATING:                       
3902                // For this state, let the key    
3903                // be handled by superclass       
3904                break;                            
3905             default:                             
3906                SoDebugError::post("G4OpenInve    
3907                                   "Unhandled     
3908                break;                            
3909             }                                    
3910             break;                               
3911                                                  
3912          case SoKeyboardEvent::DOWN_ARROW:       
3913             switch(currentState) {               
3914             case BEAMLINE:                       
3915                                                  
3916                if ((this->lshiftdown)   || (t    
3917                   refParticleIdx -= step;        
3918                   moveCamera();                  
3919                }                                 
3920                else{                             
3921                   if (SoQtExaminerViewer::isA    
3922                      stopAnimating();            
3923                   prevState = currentState;      
3924                   currentState = ROTATING;       
3925                   animateBtwPtsPeriod = 0.08f    
3926                                                  
3927                   rotAxis = camDir.cross(camU    
3928                                                  
3929                   rotCnt = ROT_CNT;              
3930                   moveCamera(); // To make su    
3931                   rotateCamera();                
3932                                                  
3933                }                                 
3934                return TRUE;                      
3935                                                  
3936             case ANIMATION:                      
3937             case REVERSED_ANIMATION:             
3938                up_down -= 1.5f;                  
3939                return TRUE;                      
3940             case PAUSED_ANIMATION:               
3941                up_down -= 1.5f;                  
3942                setStartingPtForAnimation();      
3943                cam->position = myCam->positio    
3944                return TRUE;                      
3945             case GENERAL:                        
3946             case VIEWPOINT:                      
3947                // Using this allows us to loo    
3948                // changing the camera paramet    
3949                if ((!this->lshiftdown) && (!t    
3950                   this->leftWheelMotion(this-    
3951                   return TRUE;                   
3952                }                                 
3953                break;                            
3954             case ROTATING:                       
3955                // For this state, let the key    
3956                // be handled by superclass       
3957                break;                            
3958             default:                             
3959                SoDebugError::post("G4OpenInve    
3960                                   "Unhandled     
3961                break;                            
3962             }                                    
3963             break;                               
3964                                                  
3965          case SoKeyboardEvent::UP_ARROW:         
3966             switch(currentState) {               
3967             case BEAMLINE:                       
3968                if ((this->lshiftdown)   || (t    
3969                   refParticleIdx -= step;        
3970                   moveCamera();                  
3971                }                                 
3972                else{                             
3973                   if (SoQtExaminerViewer::isA    
3974                      stopAnimating();            
3975                   prevState = currentState;      
3976                   currentState = ROTATING;       
3977                   animateBtwPtsPeriod = 0.08f    
3978                                                  
3979                   rotAxis = camUpVec.cross(ca    
3980                                                  
3981                   rotCnt = ROT_CNT;              
3982                   moveCamera();                  
3983                                                  
3984                   rotateCamera();                
3985                                                  
3986                                                  
3987                }                                 
3988                return TRUE;                      
3989             case ANIMATION:                      
3990             case REVERSED_ANIMATION:             
3991                up_down += 1.5f;                  
3992                return TRUE;                      
3993             case PAUSED_ANIMATION:               
3994                up_down += 1.5f;                  
3995                setStartingPtForAnimation();      
3996                cam->position = myCam->positio    
3997                return TRUE;                      
3998             case GENERAL:                        
3999             case VIEWPOINT:                      
4000                // Using this allows us to loo    
4001                // changing the camera paramet    
4002                if ((!this->lshiftdown) && (!t    
4003                   this->leftWheelMotion(this-    
4004                   return TRUE;                   
4005                }                                 
4006                break;                            
4007             case ROTATING:                       
4008                // For this state, let the key    
4009                // be handled by superclass       
4010                break;                            
4011             default:                             
4012                SoDebugError::post("G4OpenInve    
4013                                   "Unhandled     
4014                break;                            
4015             }                                    
4016             break;                               
4017                                                  
4018          case SoKeyboardEvent::PAGE_UP:          
4019             switch(currentState) {               
4020             case BEAMLINE:                       
4021                if (step < (int) refParticleTr    
4022                   step++;                        
4023                return TRUE;                      
4024             case ANIMATION:                      
4025                incSpeed();                       
4026                maxSpeed += SPEED_INDICATOR_ST    
4027                if (maxSpeed > 0.8)               
4028                   maxSpeed = MAX_SPEED_INDICA    
4029                scheduleRedraw();                 
4030                                                  
4031                return TRUE;                      
4032             case REVERSED_ANIMATION:             
4033                if(!animateSensor->isScheduled    
4034                   currentState = ANIMATION;      
4035                   if (refParticleIdx             
4036                       < (int) refParticleTraj    
4037                      refParticleIdx++;           
4038                      maxSpeed = SPEED_INDICAT    
4039                      scheduleRedraw();           
4040                      animateRefParticle();       
4041                   }                              
4042                }                                 
4043                else{                             
4044                   maxSpeed += SPEED_INDICATOR    
4045                   decSpeed();                    
4046                   scheduleRedraw();              
4047                }                                 
4048                return TRUE;                      
4049             case PAUSED_ANIMATION:               
4050                maxSpeed += SPEED_INDICATOR_ST    
4051                if (maxSpeed > 0.8)               
4052                   maxSpeed = MAX_SPEED_INDICA    
4053                                                  
4054                if (beforePausing == ANIMATION    
4055                   incSpeed();                    
4056                } else {                          
4057                   decSpeed();                    
4058                   if (animateBtwPtsPeriod >=     
4059                      beforePausing = ANIMATIO    
4060                }                                 
4061                                                  
4062                scheduleRedraw();                 
4063                return TRUE;                      
4064             default:    //fall through           
4065                break;                            
4066             }                                    
4067             break;                               
4068                                                  
4069          case SoKeyboardEvent::PAGE_DOWN:        
4070             switch(currentState) {               
4071             case BEAMLINE:                       
4072                if (step > 1)                     
4073                   step--;                        
4074                return TRUE;                      
4075             case ANIMATION:                      
4076                if(!animateSensor->isScheduled    
4077                   currentState = REVERSED_ANI    
4078                   if (refParticleIdx > 1) {      
4079                      refParticleIdx--;           
4080                      maxSpeed = -SPEED_INDICA    
4081                      scheduleRedraw();           
4082                      animateRefParticle();       
4083                   }                              
4084                }                                 
4085                else{                             
4086                   maxSpeed -= SPEED_INDICATOR    
4087                   decSpeed();                    
4088                   scheduleRedraw();              
4089                }                                 
4090                return TRUE;                      
4091             case REVERSED_ANIMATION:             
4092                incSpeed();                       
4093                maxSpeed -= SPEED_INDICATOR_ST    
4094                if (maxSpeed < -0.8)              
4095                   maxSpeed = -MAX_SPEED_INDIC    
4096                scheduleRedraw();                 
4097                return TRUE;                      
4098             case PAUSED_ANIMATION:               
4099                maxSpeed -= SPEED_INDICATOR_ST    
4100                if (maxSpeed < -0.8)              
4101                   maxSpeed = -MAX_SPEED_INDIC    
4102                if (beforePausing == REVERSED_    
4103                   incSpeed();                    
4104                } else {                          
4105                   decSpeed();                    
4106                   if (animateBtwPtsPeriod >=     
4107                      beforePausing = REVERSED    
4108                }                                 
4109                scheduleRedraw();                 
4110                return TRUE;                      
4111             default:                             
4112                //fall through                    
4113                break;                            
4114             }                                    
4115             break;                               
4116                                                  
4117             // FROM XT VIEWER                    
4118             //         case SoKeyboardEvent::    
4119             //            this->escapeCallbac    
4120             //            break;                 
4121                                                  
4122          default:                                
4123             break; // To get rid of compiler     
4124          }                                       
4125       }                                          
4126       if (SoKeyboardEvent::isKeyReleaseEvent(    
4127          switch (ke->getKey()) {                 
4128          case SoKeyboardEvent::LEFT_SHIFT:       
4129             this->lshiftdown = false;            
4130             return TRUE;                         
4131          case SoKeyboardEvent::RIGHT_SHIFT:      
4132             this->rshiftdown = false;            
4133             return TRUE;                         
4134          case SoKeyboardEvent::LEFT_CONTROL:     
4135             this->lctrldown = false;             
4136             return TRUE;                         
4137          case SoKeyboardEvent::RIGHT_CONTROL:    
4138             this->rctrldown = false;             
4139             return TRUE;                         
4140          default:                                
4141             break;                               
4142          }                                       
4143       }                                          
4144    }                                             
4145                                                  
4146    // Pass the event on to the viewer            
4147    // Need some checks here as in Xt viewer?     
4148                                                  
4149    if (currentState == ANIMATION || currentSt    
4150        || currentState == ROTATING)              
4151       return FALSE;                              
4152    else                                          
4153       return SoQtExaminerViewer::processSoEve    
4154 }                                                
4155                                                  
4156                                                  
4157 // REMAINDER OF MENU BAR FUNCTIONS...            
4158                                                  
4159                                                  
4160 void G4OpenInventorQtExaminerViewer::FileLoad    
4161 {                                                
4162    //   G4cout << "File: Load scene graph CAL    
4163                                                  
4164    QFileDialog filedialog(getParentWidget(),     
4165    filedialog.setFileMode(QFileDialog::AnyFil    
4166    filedialog.setFont(*font);                    
4167    if (!filedialog.exec()) return;               
4168    QStringList filenameinlist = filedialog.se    
4169    QString filenamein = filenameinlist[0];       
4170                                                  
4171    SoInput sceneInput;                           
4172                                                  
4173    if (sceneInput.openFile(qPrintable(filenam    
4174       // Read the whole file into the databas    
4175       newSceneGraph = SoDB::readAll(&sceneInp    
4176       if (newSceneGraph == NULL) {               
4177          QMessageBox msgbox;                     
4178          msgbox.setFont(*font);                  
4179          QString messagetxt = "Error reading     
4180          messagetxt.append(filenamein);          
4181          msgbox.setText(messagetxt);             
4182          msgbox.exec();                          
4183          sceneInput.closeFile();                 
4184          return;                                 
4185       }                                          
4186    } else {                                      
4187       QMessageBox msgbox;                        
4188       msgbox.setFont(*font);                     
4189       QString messagetxt = "Error opening sce    
4190       messagetxt.append(filenamein);             
4191       msgbox.setText(messagetxt);                
4192       msgbox.exec();                             
4193       return;                                    
4194    }                                             
4195                                                  
4196    SoSeparator* root = (SoSeparator*)getScene    
4197    root->unref();                                
4198    newSceneGraph->ref();                         
4199    setSceneGraph(newSceneGraph);                 
4200 }                                                
4201                                                  
4202 void G4OpenInventorQtExaminerViewer::FileSave    
4203 {                                                
4204    //   G4cout << "File: Save scene graph CAL    
4205                                                  
4206    QFileDialog filedialog(getParentWidget(),     
4207    filedialog.setFileMode(QFileDialog::AnyFil    
4208    // To enable confirmation of overwriting      
4209    filedialog.setAcceptMode(QFileDialog::Acce    
4210    filedialog.setFont(*font);                    
4211    if (!filedialog.exec()) return;               
4212    QStringList filenameinlist = filedialog.se    
4213    QString filenamein = filenameinlist[0];       
4214                                                  
4215    SoWriteAction writeAction;                    
4216    SoSeparator* root = (SoSeparator*)getScene    
4217                                                  
4218    SoOutput* out = writeAction.getOutput();      
4219                                                  
4220    if (out->openFile(qPrintable(filenamein)))    
4221       out->setBinary(FALSE);                     
4222       writeAction.apply(root);                   
4223       out->closeFile();                          
4224    } else {                                      
4225       QMessageBox msgbox;                        
4226       msgbox.setFont(*font);                     
4227       QString messagetxt = "Error opening fil    
4228       messagetxt.append(filenamein);             
4229       msgbox.setText(messagetxt);                
4230       msgbox.exec();                             
4231    }                                             
4232 }                                                
4233                                                  
4234                                                  
4235 void G4OpenInventorQtExaminerViewer::HelpCont    
4236 {                                                
4237    //   G4cout << "Help: Help Controls CALLBA    
4238    helpmsgbox->show();                           
4239 }                                                
4240                                                  
4241                                                  
4242 HookEventProcState::HookEventProcState(G4Open    
4243 {                                                
4244    viewer = vwr;                                 
4245 }                                                
4246                                                  
4247 HookEventProcState::~HookEventProcState()        
4248 {;}                                              
4249                                                  
4250 G4bool HookEventProcState::Notify(G4Applicati    
4251 {                                                
4252 #if QT_VERSION < 0x060000                        
4253    if (requestedState == G4State_EventProc) v    
4254 #else                                            
4255 #ifdef G4MULTITHREADED                           
4256    //G.Barrand: on the master thread, we are     
4257    //           we raise the newEvents flag o    
4258    G4StateManager* stateManager = G4StateMana    
4259    G4ApplicationState previousState = stateMa    
4260  //if (previousState == G4State_Idle       &&    
4261  //if (previousState == G4State_GeomClosed &&    
4262  //if (previousState == G4State_EventProc  &&    
4263    if (previousState == G4State_GeomClosed &&    
4264      viewer->newEvents = true;                   
4265    }                                             
4266 #else                                            
4267    if (requestedState == G4State_EventProc) v    
4268 #endif                                           
4269 #endif                                           
4270    return true;                                  
4271 }                                                
4272