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