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