]> Creatis software - clitk.git/blob - vv/vvSlicerManagerCommand.cxx
- improve (?) speed render for contours
[clitk.git] / vv / vvSlicerManagerCommand.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
18 #include "vvSlicerManagerCommand.h"
19 #include "vvSlicerManager.h"
20
21 #include <vtkTextProperty.h>
22 #include <vtkRenderer.h>
23 #include <vtkImageActor.h>
24 #include <vtkRenderWindowInteractor.h>
25 #include <vtkPropPicker.h>
26 #include <vtkCamera.h>
27 #include <vtkImageMapToWindowLevelColors.h>
28 #include <vtkLookupTable.h>
29 #include <vtkMath.h>
30 #include <vtkAbstractPropPicker.h>
31 #include <vtkAssemblyPath.h>
32 #include <vtkCornerAnnotation.h>
33 #include <vtkRenderWindow.h>
34 #include <vvImage.h>
35 #include <vtkImageReslice.h>
36 #include "vvSlicer.h"
37 #include "vvInteractorStyleNavigator.h"
38 #include "vtkTransform.h"
39
40 #include <cmath>
41
42 //------------------------------------------------------------------------------
43 vvSlicerManagerCommand::vvSlicerManagerCommand()
44 {
45     mStartSlicer = -1;
46     mSlicerNumber=-1;
47 }
48 //------------------------------------------------------------------------------
49
50
51 //------------------------------------------------------------------------------
52 //return the num of the current slicer if visible (-1 else)
53 int vvSlicerManagerCommand::FindSlicerNumber(vtkRenderWindow* renwin)
54 {
55     int rvalue;
56     if (renwin != SM->GetSlicer(mSlicerNumber)->GetRenderWindow() ||
57             !SM->GetSlicer(mSlicerNumber)->GetRenderer()->GetDraw())
58         rvalue = -1;
59     else rvalue = mSlicerNumber;
60     //std::cerr << this << ":" << mSlicerNumber << ": " << rvalue << endl;
61     return rvalue;
62 }
63 //------------------------------------------------------------------------------
64
65
66 //------------------------------------------------------------------------------
67 void vvSlicerManagerCommand::Execute(vtkObject *caller,
68                                      unsigned long event,
69                                      void *vtkNotUsed(callData))
70 {
71     //KeyPress event
72     vvInteractorStyleNavigator *isi =
73         dynamic_cast<vvInteractorStyleNavigator *>(caller);
74     if (isi)
75     {
76         double x = isi->GetInteractor()->GetEventPosition()[0];
77         double y = isi->GetInteractor()->GetEventPosition()[1];
78         double z;
79
80         int VisibleInWindow = this->FindSlicerNumber(isi->GetInteractor()->GetRenderWindow());
81         vtkRenderer* renderer=NULL;
82         if (VisibleInWindow>-1)
83             renderer=this->SM->GetSlicer(VisibleInWindow)->GetRenderer();
84         newLandmark = false;
85         
86
87
88         if (event == vtkCommand::StartPickEvent && VisibleInWindow == -1)
89         {
90             for (int i = 0; i < this->SM->NumberOfSlicers(); i++)
91             {
92                 if (this->SM->GetSlicer(i)->GetCursorVisibility())
93                 {
94                     this->SM->GetSlicer(i)->SetCursorVisibility(0);
95                     this->SM->GetSlicer(i)->Render();
96                 }
97             }
98         }
99         if ( VisibleInWindow > -1 )
100         {
101             if (event == vtkCommand::KeyPressEvent)
102             {
103                 std::string KeyPress = isi->GetInteractor()->GetKeySym();
104                 if (KeyPress == "Tab")
105                 {
106                     if(isi->GetInteractor()->GetShiftKey())
107                         this->SM->PrevImage(VisibleInWindow);
108                     else
109                         this->SM->NextImage(VisibleInWindow);
110                     return;
111                 }
112                 if (KeyPress == "f" || KeyPress == "F")
113                 {
114                     FlyToPosition(isi->GetInteractor(),this->SM->GetSlicer(VisibleInWindow));
115                     return;
116                 }
117                 if (KeyPress == "w")
118                 {
119                     this->SM->SetLocalColorWindowing(VisibleInWindow);
120                     return;
121                 }
122                 if (KeyPress == "0")
123                 {
124                     this->SM->SetPreset(0);
125                     this->SM->UpdateWindowLevel();
126                     return;
127                 }
128                 if (KeyPress == "1")
129                 {
130                     this->SM->SetPreset(1);
131                     this->SM->UpdateWindowLevel();
132                     return;
133                 }
134                 if (KeyPress == "2")
135                 {
136                     this->SM->SetPreset(2);
137                     this->SM->UpdateWindowLevel();
138
139                     return;
140                 }
141                 if (KeyPress == "3")
142                 {
143                     this->SM->SetPreset(3);
144                     this->SM->UpdateWindowLevel();
145                     return;
146                 }
147                 if (KeyPress == "4")
148                 {
149                     this->SM->SetPreset(4);
150                     this->SM->UpdateWindowLevel();
151                     return;
152                 }
153                 if (KeyPress == "5")
154                 {
155                     this->SM->SetPreset(5);
156                     this->SM->UpdateWindowLevel();
157                     return;
158                 }
159                 if (KeyPress == "6")
160                 {
161                     this->SM->SetColorMap(0);
162                     this->SM->UpdateWindowLevel();
163                     return;
164                 }
165                 if (KeyPress == "7")
166                 {
167                     this->SM->SetColorMap(1);
168                     this->SM->UpdateWindowLevel();
169                     return;
170                 }
171                 if (KeyPress == "8")
172                 {
173                     this->SM->SetColorMap(2);
174                     this->SM->UpdateWindowLevel();
175                     return;
176                 }
177                 if (KeyPress == "9")
178                 {
179                     this->SM->SetColorMap(3);
180                     this->SM->UpdateWindowLevel();
181                     return;
182                 }
183                 if (KeyPress == "equal") //keycodes are in vtkWin32RenderWindowInteractor
184                 {
185                     this->SM->SetPreset(7);
186                     //this->SM->SetColorMap(1);
187                     this->SM->UpdateWindowLevel();
188                     return;
189                 }
190                 if (KeyPress == "minus")
191                 {
192                     this->SM->SetColorWindow(-this->SM->GetColorWindow());
193                     this->SM->SetColorMap(-1);
194                     this->SM->UpdateWindowLevel();
195                     return;
196                 }
197                 if (KeyPress == "c")
198                 {
199                     this->SM->ToggleContourSuperposition();
200                     this->SM->Render();
201                     return;
202                 }
203                 if (KeyPress == "l")
204                 {
205                     this->SM->ToggleInterpolation();
206                     this->SM->Render();
207                     return;
208                 }
209                 if (KeyPress == "h")
210                 {
211                     this->SM->SetCursorVisibility(0);
212                     this->SM->Render();
213                     return;
214                 }
215                 if (KeyPress == "u")
216                 {
217                     this->SM->Reload();
218                     this->SM->Render();
219                     return;
220                 }
221                 if (KeyPress == "r" || KeyPress=="R")
222                 {
223                     this->SM->GetSlicer(VisibleInWindow)->ResetCamera();
224                     this->SM->GetSlicer(VisibleInWindow)->Render();
225                     return;
226                 }
227                 if (KeyPress == "g")
228                 {
229                     double* cursorPos = this->SM->GetSlicer(VisibleInWindow)->GetCursorPosition();
230                     this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(
231                             cursorPos[0],cursorPos[1],cursorPos[2],cursorPos[3]);
232                     this->SM->UpdateViews(1,VisibleInWindow);
233                     this->SM->UpdateLinked(VisibleInWindow);
234                     return;
235                 }
236                 if (KeyPress == "F5")
237                 {
238                     this->SM->GetSlicer(VisibleInWindow)->FlipHorizontalView();
239                     this->SM->GetSlicer(VisibleInWindow)->Render();
240                     return;
241                 }
242                 if (KeyPress == "F6")
243                 {
244                     this->SM->GetSlicer(VisibleInWindow)->FlipVerticalView();
245                     this->SM->GetSlicer(VisibleInWindow)->Render();
246                     return;
247                 }
248                 if (KeyPress == "Up")
249                 {
250                   DD("------------ up");
251                   this->SM->GetSlicer(VisibleInWindow)->SetSlice(this->SM->GetSlicer(VisibleInWindow)->GetSlice()+1);
252                   DD("------------ after set slice");
253                   this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
254                   DD("------------ after UpdateInfoOnCursorPosition");
255                   this->SM->UpdateSlice(VisibleInWindow);
256                   DD("------------ after updateslice");
257                 }
258                 if (KeyPress == "Down")
259                 {
260                     this->SM->GetSlicer(VisibleInWindow)->SetSlice(this->SM->GetSlicer(VisibleInWindow)->GetSlice()-1);
261                     this->SM->UpdateSlice(VisibleInWindow);
262                     this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
263                 }
264                 if (KeyPress == "space")
265                 {
266                     newLandmark = true;
267                 }
268                 if (KeyPress == "Left")
269                     this->SM->SetPreviousTSlice(VisibleInWindow);
270                 if (KeyPress == "Right")
271                     this->SM->SetNextTSlice(VisibleInWindow);
272
273                 if (KeyPress == "F2")
274                 {
275                     this->SM->GetSlicer(VisibleInWindow)->GetAnnotation()->SetText(2,"Sagital\n<slice>");
276                     this->SM->GetSlicer(VisibleInWindow)->SetSliceOrientation(0);
277                     this->SM->UpdateSliceRange(VisibleInWindow);
278                     this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
279                 }
280                 if (KeyPress == "F3")
281                 {
282                     this->SM->GetSlicer(VisibleInWindow)->GetAnnotation()->SetText(2,"Coronal\n<slice>");
283                     this->SM->GetSlicer(VisibleInWindow)->SetSliceOrientation(1);
284                     this->SM->UpdateSliceRange(VisibleInWindow);
285                     this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
286                 }
287                 if (KeyPress == "F4")
288                 {
289                     this->SM->GetSlicer(VisibleInWindow)->GetAnnotation()->SetText(2,"Axial\n<slice>");
290                     this->SM->GetSlicer(VisibleInWindow)->SetSliceOrientation(2);
291                     this->SM->UpdateSliceRange(VisibleInWindow);
292                     this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
293                 }
294                 
295             }
296
297             //All type of mouse events
298             if (event == vtkCommand::LeaveEvent)
299             {
300                 this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,
301                         -VTK_DOUBLE_MAX,this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
302                 this->SM->GetSlicer(VisibleInWindow)->Render();
303                 return;
304             }
305
306             //DD(event);
307             // Mouse release HERE 
308             if (event == vtkCommand::EndPickEvent) {
309               //              DD(VisibleInWindow);
310               if (VisibleInWindow > -1)
311                 this->SM->LeftButtonReleaseEvent(VisibleInWindow);
312               return; // no return !!!! ???
313             }
314
315             if (event == vtkCommand::StartWindowLevelEvent)
316             {
317                 mStartSlicer = -1;
318                 this->InitialWindow = this->SM->GetColorWindow();
319                 this->InitialLevel = this->SM->GetColorLevel();
320
321                 if (VisibleInWindow > -1)
322                 {
323                     mStartSlicer = VisibleInWindow;
324                 }
325                 return;
326             }
327
328             if (event == vtkCommand::EndWindowLevelEvent)
329             {
330                 mStartSlicer = -1;
331             }
332
333         }
334         if (VisibleInWindow > -1)
335         {
336             this->SM->Activated();
337             //if(!this->SM->GetSlicer(VisibleInWindow)->GetAnnotation()->GetVisibility())
338             this->SM->GetSlicer(VisibleInWindow)->GetAnnotation()->SetVisibility(1);
339
340             if (event == vtkCommand::MouseWheelForwardEvent && !isi->GetInteractor()->GetControlKey())
341             {
342                 this->SM->GetSlicer(VisibleInWindow)->SetSlice(this->SM->GetSlicer(VisibleInWindow)->GetSlice()+1);
343                 this->SM->UpdateSlice(VisibleInWindow);
344                 this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
345             }
346             else if (event == vtkCommand::MouseWheelForwardEvent && isi->GetInteractor()->GetControlKey())
347             {
348                 double factor = 2;
349                 this->Dolly(pow((double)1.1, factor),isi->GetInteractor());
350             }
351             else if (event == vtkCommand::MouseWheelBackwardEvent && !isi->GetInteractor()->GetControlKey())
352             {
353                 this->SM->GetSlicer(VisibleInWindow)->SetSlice(this->SM->GetSlicer(VisibleInWindow)->GetSlice()-1);
354                 this->SM->UpdateSlice(VisibleInWindow);
355                 this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
356             }
357             else if (event == vtkCommand::MouseWheelBackwardEvent && isi->GetInteractor()->GetControlKey())
358             {
359                 double factor = -2;
360                 this->Dolly(pow((double)1.1, factor),isi->GetInteractor());
361             }
362             double xWorld=0; double yWorld=0; double zWorld=0;
363
364             //Move into World Coordinate
365             renderer->DisplayToNormalizedDisplay(x,y);
366             renderer->NormalizedDisplayToViewport(x,y);
367             renderer->ViewportToNormalizedViewport(x,y);
368             renderer->NormalizedViewportToView(x,y,z);
369             renderer->ViewToWorld(x,y,z);
370             switch (this->SM->GetSlicer(VisibleInWindow)->GetSliceOrientation())
371             {
372                 case vtkImageViewer2::SLICE_ORIENTATION_XY:
373                     xWorld = x;
374                     yWorld = y;
375                     zWorld = this->SM->GetSlicer(VisibleInWindow)->GetSlice()*
376                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetSpacing()[2] +
377                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetOrigin()[2];
378                     break;
379
380                 case vtkImageViewer2::SLICE_ORIENTATION_XZ:
381                     xWorld = x;
382                     yWorld = this->SM->GetSlicer(VisibleInWindow)->GetSlice()*
383                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetSpacing()[1] +
384                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetOrigin()[1];
385                     zWorld = z;
386                     break;
387
388                 case vtkImageViewer2::SLICE_ORIENTATION_YZ:
389                     xWorld = this->SM->GetSlicer(VisibleInWindow)->GetSlice()*
390                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetSpacing()[0] +
391                         this->SM->GetSlicer(VisibleInWindow)->GetInput()->GetOrigin()[0];
392                     yWorld = y;
393                     zWorld = z;
394                     break;
395             }
396             this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(xWorld,yWorld,zWorld,
397                     this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
398             if (newLandmark)
399             {
400                 this->SM->AddLandmark(xWorld,yWorld,zWorld,
401                                       this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
402                 this->SM->GetSlicer(VisibleInWindow)->UpdateLandmarks();
403                 this->SM->Render();
404             }
405             if (event == vtkCommand::PickEvent || event == vtkCommand::StartPickEvent)
406             {
407                 this->SM->UpdateViews(1,VisibleInWindow);
408                 this->SM->UpdateLinked(VisibleInWindow);
409                 this->SM->UpdateInfoOnCursorPosition(VisibleInWindow);
410             }
411             else
412             {
413                 this->SM->GetSlicer(VisibleInWindow)->Render();
414             }
415             //this->SM->GetSlicer(VisibleInWindow)->SetCurrentPosition(-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,
416             //-VTK_DOUBLE_MAX,this->SM->GetSlicer(VisibleInWindow)->GetTSlice());
417             //this->SM->GetSlicer(VisibleInWindow)->Render();
418         }
419
420         if (event == vtkCommand::WindowLevelEvent && mStartSlicer > -1)
421         {
422             this->SM->GetSlicer(mStartSlicer)->GetAnnotation()->SetVisibility(1);
423             // Adjust the window level here
424             int *size = isi->GetInteractor()->GetRenderWindow()->GetSize();
425             double window = this->InitialWindow;
426             double level = this->InitialLevel;
427             double range[2];
428             this->SM->GetImage()->GetScalarRange(range);
429
430             // Compute normalized delta
431             double dx = static_cast<double>(isi->GetWindowLevelCurrentPosition()[0] -
432                                             isi->GetWindowLevelStartPosition()[0]) / size[0];
433             double dy = static_cast<double>(isi->GetWindowLevelStartPosition()[1] -
434                                             isi->GetWindowLevelCurrentPosition()[1]) / size[1];
435             //Window is exponential in nature, use exponential to avoid falling into negative numbers
436             dx = std::exp(1.0 * (dx*fabs(dx) + dx)) ; //Quadratic behavior for more reactive interface
437             dy = 0.15 * (dy*fabs(dy) + dy) * (range[1]-range[0]);//Quadratic behavior for more reactive interface
438
439             this->SM->SetColorWindow(window*dx);
440             this->SM->SetColorLevel(level-dy);
441             this->SM->SetPreset(6);
442             this->SM->UpdateWindowLevel();
443             this->SM->Render();
444             return;
445         }
446     }
447 }
448 //------------------------------------------------------------------------------
449
450
451 //------------------------------------------------------------------------------
452 void vvSlicerManagerCommand::Dolly(double factor, vtkRenderWindowInteractor *interactor)
453 {
454     int VisibleInWindow = this->FindSlicerNumber(interactor->GetRenderWindow());
455     vtkRenderer* renderer;
456     if (VisibleInWindow>-1)
457         renderer=this->SM->GetSlicer(VisibleInWindow)->GetRenderer();
458     else
459     {
460         return;
461     }
462
463     double viewFocus[4],viewPoint[4],motionVector[3], focalDepth;
464     double oldPos[3], newPos[3], distance[2];
465     vtkCamera *camera = renderer->GetActiveCamera();
466     camera->GetFocalPoint(viewFocus);
467
468     renderer->SetWorldPoint(viewFocus[0], viewFocus[0], viewFocus[0], 1.0);
469     renderer->WorldToDisplay();
470     renderer->GetDisplayPoint(viewFocus);
471
472     focalDepth = viewFocus[2];
473
474     oldPos[0] = renderer->GetCenter()[0];
475     oldPos[1] = renderer->GetCenter()[1];
476     oldPos[2] = focalDepth;
477
478     distance[0] = 1/factor*
479         (interactor->GetEventPosition()[0]-renderer->GetCenter()[0]);
480     distance[1] = 1/factor*
481         (interactor->GetEventPosition()[1]-renderer->GetCenter()[1]);
482
483     newPos[0] = interactor->GetEventPosition()[0] - distance[0];
484     newPos[1] = interactor->GetEventPosition()[1] - distance[1];
485     newPos[2] = focalDepth;
486
487     renderer->DisplayToNormalizedDisplay(oldPos[0],oldPos[1]);
488     renderer->NormalizedDisplayToViewport(oldPos[0],oldPos[1]);
489     renderer->ViewportToNormalizedViewport(oldPos[0],oldPos[1]);
490     renderer->NormalizedViewportToView(oldPos[0],oldPos[1],oldPos[2]);
491     renderer->ViewToWorld(oldPos[0],oldPos[1],oldPos[2]);
492
493     renderer->DisplayToNormalizedDisplay(newPos[0],newPos[1]);
494     renderer->NormalizedDisplayToViewport(newPos[0],newPos[1]);
495     renderer->ViewportToNormalizedViewport(newPos[0],newPos[1]);
496     renderer->NormalizedViewportToView(newPos[0],newPos[1],newPos[2]);
497     renderer->ViewToWorld(newPos[0],newPos[1],newPos[2]);
498
499     motionVector[0] = newPos[0] - oldPos[0];
500     motionVector[1] = newPos[1] - oldPos[1];
501     motionVector[2] = newPos[2] - oldPos[2];
502
503     camera->GetFocalPoint(viewFocus);
504     camera->GetPosition(viewPoint);
505     camera->SetFocalPoint(motionVector[0] + viewFocus[0],
506                           motionVector[1] + viewFocus[1],
507                           motionVector[2] + viewFocus[2]);
508
509     camera->SetPosition(motionVector[0] + viewPoint[0],
510                         motionVector[1] + viewPoint[1],
511                         motionVector[2] + viewPoint[2]);
512
513     if (camera->GetParallelProjection())
514     {
515         camera->SetParallelScale(camera->GetParallelScale() / factor);
516     }
517     else
518     {
519         camera->Dolly(factor);
520     }
521
522     if (interactor->GetLightFollowCamera())
523     {
524         renderer->UpdateLightsGeometryToFollowCamera();
525     }
526     renderer->ResetCameraClippingRange();
527     //interactor->Render();
528 }
529 //------------------------------------------------------------------------------
530
531
532 //------------------------------------------------------------------------------
533 void vvSlicerManagerCommand::FlyToPosition(vtkRenderWindowInteractor *interactor,vvSlicer* slicer)
534 {
535     double flyFrom[3], flyTo[3];
536     double d[3], focalPt[3], position[3], positionFrom[3];
537     int i, j;
538     int VisibleInWindow = this->FindSlicerNumber(interactor->GetRenderWindow());
539     vtkRenderer* renderer=NULL;
540     if (VisibleInWindow>-1)
541         renderer=this->SM->GetSlicer(VisibleInWindow)->GetRenderer();
542     else
543         return;
544
545     interactor->GetPicker()->Pick(interactor->GetEventPosition()[0],
546                                   interactor->GetEventPosition()[1], 0.0,
547                                   renderer);
548
549     vtkAssemblyPath *path=NULL;
550     vtkAbstractPropPicker *picker;
551     if ( (picker=vtkAbstractPropPicker::SafeDownCast(interactor->GetPicker())))
552     {
553         path = picker->GetPath();
554     }
555     if ( path != NULL )
556     {
557         flyTo[0] = picker->GetPickPosition()[0];
558         flyTo[1] = picker->GetPickPosition()[1];
559         flyTo[2] = picker->GetPickPosition()[2];
560         renderer->GetActiveCamera()->GetFocalPoint(flyFrom);
561         renderer->GetActiveCamera()->GetPosition(positionFrom);
562
563         switch (slicer->GetSliceOrientation())
564         {
565         case vtkImageViewer2::SLICE_ORIENTATION_XY:
566             flyTo[2] = flyFrom[2];
567             break;
568
569         case vtkImageViewer2::SLICE_ORIENTATION_XZ:
570             flyTo[1] = flyFrom[1];
571             break;
572
573         case vtkImageViewer2::SLICE_ORIENTATION_YZ:
574             flyTo[0] = flyFrom[0];
575             break;
576         }
577
578
579         for (i=0; i<3; i++)
580         {
581             d[i] = flyTo[i] - flyFrom[i];
582         }
583         double distance = vtkMath::Normalize(d);
584         double delta = distance/15;
585
586         for (i=1; i<=15; i++)
587         {
588             for (j=0; j<3; j++)
589             {
590                 focalPt[j] = flyFrom[j] + d[j]*i*delta;
591                 position[j] = positionFrom[j] + d[j]*i*delta;
592             }
593             renderer->GetActiveCamera()->SetFocalPoint(focalPt);
594             renderer->GetActiveCamera()->SetPosition(position);
595             renderer->GetActiveCamera()->Dolly(0.3/15 + 1.0);
596             renderer->ResetCameraClippingRange();
597             interactor->Render();
598         }
599     }
600 }
601 //------------------------------------------------------------------------------