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