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