]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Extensions/Visualization/ImageInteractorStyle.cxx
...
[cpPlugins.git] / lib / cpPlugins / Extensions / Visualization / ImageInteractorStyle.cxx
1 #include <cpPlugins/Extensions/Visualization/ImageInteractorStyle.h>
2
3 #include <cmath>
4 #include <ctime>
5
6 #include <vtkAnnotatedCubeActor.h>
7 #include <vtkAxesActor.h>
8 #include <vtkCallbackCommand.h>
9 #include <vtkCamera.h>
10 #include <vtkCellArray.h>
11 #include <vtkCommand.h>
12 #include <vtkMatrix4x4.h>
13 #include <vtkPropAssembly.h>
14 #include <vtkProperty.h>
15 #include <vtkRendererCollection.h>
16 #include <vtkRenderWindow.h>
17 #include <vtkRenderWindowInteractor.h>
18
19 #include <cpPlugins/Extensions/Visualization/ImageSliceActors.h>
20 #include <cpPlugins/Extensions/Visualization/MPRActors.h>
21
22 // -------------------------------------------------------------------------
23 const int cpPlugins::Extensions::Visualization::
24 ImageInteractorStyle::CursorEvent = vtkCommand::UserEvent + 1;
25 const int cpPlugins::Extensions::Visualization::
26 ImageInteractorStyle::RadiusEvent = vtkCommand::UserEvent + 2;
27 const int cpPlugins::Extensions::Visualization::
28 ImageInteractorStyle::DoubleClickEvent = vtkCommand::UserEvent + 3;
29
30 // -------------------------------------------------------------------------
31 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
32 Self* cpPlugins::Extensions::Visualization::ImageInteractorStyle::
33 New( )
34 {
35   return( new Self( ) );
36 }
37
38 // -------------------------------------------------------------------------
39 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
40 Configure( ImageSliceActors* slice_actors, MPRActors* mpr_actors )
41 {
42   this->m_SliceActors = slice_actors;
43   this->m_MPRActors = mpr_actors;
44   this->SetModeToNavigation( );
45   this->PropPicker->AddPickList( slice_actors->GetImageActor( ) );
46   this->Modified( );
47 }
48
49 // -------------------------------------------------------------------------
50 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
51 AssociateInteractor( vtkRenderWindowInteractor* interactor )
52 {
53   if( interactor != NULL )
54   {
55     this->AssociatedInteractors.push_back( interactor );
56     this->Modified( );
57
58   } // fi
59 }
60
61 // -------------------------------------------------------------------------
62 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
63 SetModeToNavigation( )
64 {
65   this->Mode = Self::NavigationMode;
66 }
67
68 // -------------------------------------------------------------------------
69 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
70 SetModeToDeformation( )
71 {
72   this->Mode = Self::DeformationMode;
73 }
74
75 // -------------------------------------------------------------------------
76 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
77 SetInteractor( vtkRenderWindowInteractor* interactor, const int& axis )
78 {
79   this->Superclass::SetInteractor( interactor );
80   this->OrientationWidget->SetInteractor( interactor );
81   interactor->SetInteractorStyle( this );
82   if( interactor == NULL )
83     return;
84
85   // Get camera, avoiding segfaults
86   vtkRenderer* ren =
87     interactor->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( );
88   if( ren == NULL )
89     return;
90   vtkCamera* cam = ren->GetActiveCamera( );
91   if( cam == NULL )
92     return;
93
94   // Parallel projections are better when displaying 2D images
95   cam->ParallelProjectionOn( );
96   cam->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
97   if( axis == 0 )
98   {
99     cam->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
100     cam->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
101   }
102   else if( axis == 1 )
103   {
104     cam->SetPosition( double( 0 ), double( 1 ), double(  0 ) );
105     cam->SetViewUp  ( double( 0 ), double( 0 ), double( -1 ) );
106   }
107   else // if( axis == 2 )
108   {
109     cam->SetPosition( double( 0 ), double( 0 ), double( 1 ) );
110     cam->SetViewUp  ( double( 0 ), double( 1 ), double( 0 ) );
111
112   } // fi
113   ren->ResetCamera( );
114
115   // Enable 2D orientation widget
116   this->OrientationWidget->SetEnabled( 1 );
117   this->OrientationWidget->InteractiveOff( );
118 }
119
120 // -------------------------------------------------------------------------
121 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
122 OnMouseMove( )
123 {
124   if( this->m_MPRActors == NULL )
125     return;
126   
127   if( this->CursorMoving )
128   {
129     bool picked = this->_PickPosition( this->Cursor );
130     if( picked )
131     {
132       for( int i = 0; i < 3; ++i )
133         if( this->m_SliceActors->GetAxis( ) != i )
134           this->m_MPRActors->SetSlice( i, this->Cursor[ i ] );
135       this->InvokeEvent( Self::CursorEvent, this->Cursor );
136       this->Interactor->Render( );
137       this->_RenderAssociateInteractors( );
138
139     } // fi
140   }
141   else if( this->RadiusMoving )
142   {
143     bool picked = this->_PickPosition( this->Radius );
144     if( picked )
145     {
146       this->InvokeEvent( Self::RadiusEvent, this->Radius );
147       this->_UpdateRadius( );
148
149     } // fi
150   }
151   else
152   {
153     switch( this->State )
154     {
155     case VTKIS_WINDOW_LEVEL:
156       this->WindowLevel( );
157       break;
158     case VTKIS_DOLLY:
159       this->Dolly( );
160       break;
161     case VTKIS_PAN:
162       this->Pan( );
163       break;
164     } // hctiws
165
166   } // fi
167 }
168
169 // -------------------------------------------------------------------------
170 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
171 OnLeftButtonDown( )
172 {
173   static double pnt[ 3 ];
174   static int pos[ 2 ];
175   this->Interactor->GetEventPosition( pos );
176   this->FindPokedRenderer( pos[ 0 ], pos[ 1 ] );
177   if( this->CurrentRenderer == NULL )
178     return;
179   this->GrabFocus( this->EventCallbackCommand );
180
181   // TODO: check this code
182   // Manage double-click
183   static const long epsilon_time = 800;
184   static long last_click_time = -( epsilon_time << 1 );
185   long click_time = static_cast< long >( std::clock( ) );
186   if( ( click_time - last_click_time ) < epsilon_time )
187   {
188     last_click_time = -( epsilon_time << 1 );
189     if( this->_PickPosition( pnt ) )
190       this->InvokeEvent( Self::DoubleClickEvent, pnt );
191   }
192   else
193   {
194     last_click_time = click_time;
195     if( this->Interactor->GetControlKey( ) )
196       this->StartCursorMoving( );
197
198   } // fi
199 }
200
201 // -------------------------------------------------------------------------
202 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
203 OnLeftButtonUp( )
204 {
205   if( this->CursorMoving )
206   {
207     this->EndCursorMoving( );
208     if( this->Interactor )
209       this->ReleaseFocus( );
210
211   } // fi
212 }
213
214 // -------------------------------------------------------------------------
215 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
216 OnMiddleButtonDown( )
217 {
218   int x = this->Interactor->GetEventPosition( )[ 0 ];
219   int y = this->Interactor->GetEventPosition( )[ 1 ];
220
221   this->FindPokedRenderer( x, y );
222   if( this->CurrentRenderer == NULL )
223     return;
224   this->GrabFocus( this->EventCallbackCommand );
225
226   if( this->Interactor->GetAltKey( ) )
227   {
228   }
229   else if( this->Interactor->GetControlKey( ) )
230   {
231     this->StartRadiusMoving( );
232   }
233   else if( this->Interactor->GetShiftKey( ) )
234   {
235   }
236   else
237     this->StartPan( );
238 }
239
240 // -------------------------------------------------------------------------
241 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
242 OnMiddleButtonUp( )
243 {
244   if( this->RadiusMoving )
245   {
246     this->EndRadiusMoving( );
247     if( this->Interactor )
248       this->ReleaseFocus( );
249   }
250   else
251   {
252     switch( this->State )
253     {
254     case VTKIS_PAN:
255       this->EndPan( );
256       break;
257     } // hctiws
258
259   } // fi
260 }
261
262 // -------------------------------------------------------------------------
263 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
264 OnRightButtonDown( )
265 {
266   int x = this->Interactor->GetEventPosition( )[ 0 ];
267   int y = this->Interactor->GetEventPosition( )[ 1 ];
268
269   this->FindPokedRenderer( x, y );
270   if( this->CurrentRenderer == NULL )
271     return;
272   this->GrabFocus( this->EventCallbackCommand );
273
274   if( this->Interactor->GetControlKey( ) )
275   {
276     this->WindowLevelStartPosition[ 0 ] = x;
277     this->WindowLevelStartPosition[ 1 ] = y;
278     this->StartWindowLevel( );
279   }
280   else
281   {
282     this->StartDolly( );
283
284   } // fi
285 }
286
287 // -------------------------------------------------------------------------
288 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
289 OnRightButtonUp( )
290 {
291   switch( this->State )
292   {
293   case VTKIS_WINDOW_LEVEL:
294   {
295     this->EndWindowLevel( );
296     if( this->Interactor )
297       this->ReleaseFocus( );
298   }
299   break;
300   case VTKIS_DOLLY:
301     this->EndDolly( );
302     break;
303   } // hctiws
304 }
305
306 // -------------------------------------------------------------------------
307 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
308 OnMouseWheelForward( )
309 {
310   if( this->m_SliceActors == NULL || this->Interactor == NULL )
311     return;
312   int off = 1;
313   if( this->Interactor->GetShiftKey( ) == 1 )
314     off *= 10;
315   int s = this->m_SliceActors->GetSliceNumber( ) + off;
316   int maxs = this->m_SliceActors->GetSliceNumberMaxValue( );
317   this->m_SliceActors->SetSliceNumber( ( s < maxs )? s: maxs );
318   this->Interactor->Render( );
319   this->_RenderAssociateInteractors( );
320 }
321
322 // -------------------------------------------------------------------------
323 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
324 OnMouseWheelBackward( )
325 {
326   if( this->m_SliceActors == NULL || this->Interactor == NULL )
327     return;
328   int off = 1;
329   if( this->Interactor->GetShiftKey( ) == 1 )
330     off *= 10;
331   int s = this->m_SliceActors->GetSliceNumber( ) - off;
332   int mins = this->m_SliceActors->GetSliceNumberMinValue( );
333   this->m_SliceActors->SetSliceNumber( ( mins < s )? s: mins );
334   this->Interactor->Render( );
335   this->_RenderAssociateInteractors( );
336 }
337
338 // -------------------------------------------------------------------------
339 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
340 OnChar( )
341 {
342   switch( this->Interactor->GetKeyCode( ) )
343   {
344   case 'r': case 'R':
345   {
346     vtkRenderer* ren =
347       this->Interactor->GetRenderWindow( )->
348       GetRenderers( )->GetFirstRenderer( );
349     if( ren != NULL )
350       ren->ResetCamera( );
351     this->Interactor->Render( );
352   }
353   break;
354   case 'w': case 'W': case 'l': case 'L':
355   {
356     if( this->m_MPRActors != NULL )
357     {
358       this->m_MPRActors->ResetWindowLevel( );
359       this->Interactor->Render( );
360       this->_RenderAssociateInteractors( );
361
362     } // fi
363   }
364   break;
365   } // hctiws
366 }
367
368 // -------------------------------------------------------------------------
369 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
370 WindowLevel( )
371 {
372   if( this->Mode == Self::NavigationMode )
373   {
374     if( this->Interactor == NULL )
375       return;
376     vtkRenderer* ren =
377       this->Interactor->GetRenderWindow( )->
378       GetRenderers( )->GetFirstRenderer( );
379     if( ren == NULL )
380       return;
381
382     // Compute scales
383     this->WindowLevelCurrentPosition[ 0 ] =
384       this->Interactor->GetEventPosition( )[ 0 ];
385     this->WindowLevelCurrentPosition[ 1 ] =
386       this->Interactor->GetEventPosition( )[ 1 ];
387     int* size = ren->GetSize( );
388     double sw = double(
389       this->WindowLevelCurrentPosition[ 0 ] -
390       this->WindowLevelStartPosition[ 0 ]
391       ) / double( size[ 0 ] );
392     double sl = (
393       this->WindowLevelStartPosition[ 1 ] -
394       this->WindowLevelCurrentPosition[ 1 ]
395       ) / double( size[ 1 ] );
396
397     double w = this->WindowLevelInitial[ 0 ] * ( double( 1 ) + sw );
398     double l = this->WindowLevelInitial[ 1 ] * ( double( 1 ) + sl );
399     double minw = this->m_MPRActors->GetMinWindow( );
400     double maxw = this->m_MPRActors->GetMaxWindow( );
401     double minl = this->m_MPRActors->GetMinLevel( );
402     double maxl = this->m_MPRActors->GetMaxLevel( );
403
404     if( w < minw ) w = minw;
405     if( maxw < w ) w = maxw;
406     if( l < minl ) l = minl;
407     if( maxl < l ) l = maxl;
408
409     this->m_MPRActors->SetWindowLevel( w, l );
410     this->Interactor->Render( );
411     this->_RenderAssociateInteractors( );
412   }
413   else if( this->Mode == Self::DeformationMode )
414   {
415     // TODO
416
417   } // fi
418 }
419
420 // -------------------------------------------------------------------------
421 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
422 StartWindowLevel( )
423 {
424   if( this->State != VTKIS_NONE )
425     return;
426   if( this->Mode == Self::NavigationMode )
427   {
428     this->StartState( VTKIS_WINDOW_LEVEL );
429
430     this->WindowLevelInitial[ 0 ] = this->m_MPRActors->GetWindow( );
431     this->WindowLevelInitial[ 1 ] = this->m_MPRActors->GetLevel( );
432   }
433   else if( this->Mode == Self::DeformationMode )
434   {
435     // TODO
436
437   } // fi
438 }
439
440 // -------------------------------------------------------------------------
441 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
442 EndWindowLevel( )
443 {
444   if( this->Mode == Self::NavigationMode )
445   {
446     if( this->State != VTKIS_WINDOW_LEVEL )
447       return;
448     this->StopState( );
449   }
450   else
451   {
452     // TODO
453
454   } // fi
455 }
456
457 // -------------------------------------------------------------------------
458 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
459 StartCursorMoving( )
460 {
461   if( this->CursorMoving )
462     return;
463   this->_PickPosition( this->Cursor );
464   this->CursorMoving = true;
465 }
466
467 // -------------------------------------------------------------------------
468 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
469 EndCursorMoving( )
470 {
471   if( !( this->CursorMoving ) )
472     return;
473   this->CursorMoving = false;
474 }
475
476 // -------------------------------------------------------------------------
477 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
478 StartRadiusMoving( )
479 {
480   if( this->RadiusMoving )
481     return;
482   this->_PickPosition( this->Radius );
483   this->RadiusMoving = true;
484   this->_UpdateRadius( );
485 }
486
487 // -------------------------------------------------------------------------
488 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
489 EndRadiusMoving( )
490 {
491   if( !( this->RadiusMoving ) )
492     return;
493   this->RadiusMoving = false;
494   this->_UpdateRadius( );
495   this->InvokeEvent( Self::RadiusEvent, NULL );
496 }
497
498 // -------------------------------------------------------------------------
499 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
500 ImageInteractorStyle( )
501   : Superclass( ),
502     Mode( Self::NavigationMode ),
503     m_SliceActors( NULL ),
504     m_MPRActors( NULL ),
505     CursorMoving( false ),
506     RadiusMoving( false )
507 {
508   // Orientation marks
509   vtkSmartPointer< vtkAnnotatedCubeActor > cube =
510     vtkSmartPointer< vtkAnnotatedCubeActor >::New( );
511   cube->GetCubeProperty( )->SetColor( 0.9, 0.7, 0.2 );
512   cube->GetTextEdgesProperty( )->SetLineWidth( 1 );
513   cube->GetTextEdgesProperty( )->SetDiffuse( 0 );
514   cube->GetTextEdgesProperty( )->SetAmbient( 1 );
515   cube->GetTextEdgesProperty( )->SetColor( 0.18, 0.28, 0.23 );
516   cube->GetXPlusFaceProperty( )->SetColor( 1, 0, 0 );
517   cube->GetXPlusFaceProperty( )->SetInterpolationToFlat( );
518   cube->GetXMinusFaceProperty( )->SetColor( 1, 0, 0 );
519   cube->GetXMinusFaceProperty( )->SetInterpolationToFlat( );
520   cube->GetYPlusFaceProperty( )->SetColor( 0, 1, 0 );
521   cube->GetYPlusFaceProperty( )->SetInterpolationToFlat( );
522   cube->GetYMinusFaceProperty( )->SetColor( 0, 1, 0 );
523   cube->GetYMinusFaceProperty( )->SetInterpolationToFlat( );
524   cube->GetZPlusFaceProperty( )->SetColor( 0, 0, 1 );
525   cube->GetZPlusFaceProperty( )->SetInterpolationToFlat( );
526   cube->GetZMinusFaceProperty( )->SetColor( 0, 0, 1 );
527   cube->GetZMinusFaceProperty( )->SetInterpolationToFlat( );
528
529   vtkSmartPointer< vtkAxesActor > axes =
530     vtkSmartPointer< vtkAxesActor >::New( );
531   axes->AxisLabelsOff( );
532   axes->SetShaftTypeToCylinder( );
533   axes->SetTotalLength( 2, 2, 2 );
534
535   vtkSmartPointer< vtkPropAssembly > actors =
536     vtkSmartPointer< vtkPropAssembly >::New( );
537   actors->AddPart( cube );
538   actors->AddPart( axes );
539
540   this->OrientationWidget =
541     vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
542   this->OrientationWidget->SetOutlineColor( 0.93, 0.57, 0.13 );
543   this->OrientationWidget->SetOrientationMarker( actors );
544   this->OrientationWidget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
545
546   // Circle
547   unsigned long circle_samples = 1000;
548   this->Circle = vtkSmartPointer< vtkPolyData >::New( );
549
550   vtkSmartPointer< vtkPoints > circle_points =
551     vtkSmartPointer< vtkPoints >::New( );
552   vtkSmartPointer< vtkCellArray > circle_lines =
553     vtkSmartPointer< vtkCellArray >::New( );
554   for( unsigned long s = 0; s < circle_samples; ++s )
555   {
556     double t = double( 6.2832 ) * double( s ) / double( circle_samples );
557     circle_points->InsertNextPoint(
558       std::cos( t ), std::sin( t ), double( 0 )
559       );
560
561     circle_lines->InsertNextCell( 2 );
562     circle_lines->InsertCellPoint( s );
563     circle_lines->InsertCellPoint( ( s + 1 ) % circle_samples );
564
565   } // rof
566   this->Circle->SetPoints( circle_points );
567   this->Circle->SetLines( circle_lines );
568
569   this->CircleMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
570   this->CircleMapper->SetInputData( this->Circle );
571   this->CircleActor = vtkSmartPointer< vtkActor >::New( );
572   this->CircleActor->SetMapper( this->CircleMapper );
573   this->CircleActor->GetProperty( )->SetColor( 1, 0, 1 );
574   this->CircleActor->GetProperty( )->SetLineWidth( 2 );
575
576   this->PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
577   this->PropPicker->PickFromListOn( );
578 }
579
580 // -------------------------------------------------------------------------
581 cpPlugins::Extensions::Visualization::ImageInteractorStyle::
582 ~ImageInteractorStyle( )
583 {
584 }
585
586 // -------------------------------------------------------------------------
587 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
588 _RenderAssociateInteractors( )
589 {
590   std::vector< vtkRenderWindowInteractor* >::iterator rIt =
591     this->AssociatedInteractors.begin( );
592   for( ; rIt != this->AssociatedInteractors.end( ); ++rIt )
593     ( *rIt )->Render( );
594 }
595
596 // -------------------------------------------------------------------------
597 bool cpPlugins::Extensions::Visualization::ImageInteractorStyle::
598 _PickPosition( double pos[ 3 ] )
599 {
600   if( this->m_SliceActors == NULL )
601     return( false );
602
603   double x = double( this->Interactor->GetEventPosition( )[ 0 ] );
604   double y = double( this->Interactor->GetEventPosition( )[ 1 ] );
605   this->FindPokedRenderer( x, y );
606   int success =
607     this->PropPicker->Pick( x, y, double( 0 ), this->CurrentRenderer );
608   if( success == 0 )
609     return( false );
610   this->PropPicker->GetPickPosition( pos );
611
612   int axis = this->m_SliceActors->GetAxis( );
613   double* bounds = this->m_SliceActors->GetDisplayBounds( );
614   pos[ axis ] = bounds[ axis << 1 ];
615
616   return( true );
617 }
618
619 // -------------------------------------------------------------------------
620 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
621 _UpdateCursor( )
622 {
623   std::cout << "upcur" << std::endl;
624 }
625
626 // -------------------------------------------------------------------------
627 void cpPlugins::Extensions::Visualization::ImageInteractorStyle::
628 _UpdateRadius( )
629 {
630   vtkRenderer* ren =
631     this->Interactor->GetRenderWindow( )->
632     GetRenderers( )->GetFirstRenderer( );
633   if( ren == NULL )
634     return;
635   vtkCamera* cam = ren->GetActiveCamera( );
636   if( cam == NULL )
637     return;
638
639   if( this->RadiusMoving )
640   {
641     double x = this->Cursor[ 0 ] - this->Radius[ 0 ];
642     double y = this->Cursor[ 1 ] - this->Radius[ 1 ];
643     double z = this->Cursor[ 2 ] - this->Radius[ 2 ];
644     double r = std::sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
645
646     vtkMatrix4x4* cam_matrix = cam->GetModelViewTransformMatrix( );
647     vtkSmartPointer< vtkMatrix4x4 > circle_matrix =
648       this->CircleActor->GetUserMatrix( );
649     if( circle_matrix.GetPointer( ) == NULL )
650     {
651       circle_matrix = vtkSmartPointer< vtkMatrix4x4 >::New( );
652       this->CircleActor->SetUserMatrix( circle_matrix );
653
654     } // fi
655     for( int i = 0; i < 4; ++i )
656     {
657       for( int j = 0; j < 4; ++j )
658       {
659         double v = cam_matrix->GetElement( i, j );
660         if( i < 3 && j == 3 )
661           v = this->Cursor[ i ];
662         if( i < 3 && j < 3 )
663           v *= r;
664         circle_matrix->SetElement( i, j, v );
665
666       } // rof
667
668     } // rof
669     this->CircleActor->Modified( );
670     ren->AddActor( this->CircleActor );
671   }
672   else
673     ren->RemoveActor( this->CircleActor );
674
675   this->Interactor->Render( );
676 }
677
678 // eof - $RCSfile$