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