]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Interaction/ImageSliceStyle.cxx
93cb1eb2d3f21fc4d0e2b472ae5d627e478af995
[cpPlugins.git] / lib / cpExtensions / Interaction / ImageSliceStyle.cxx
1 #include <cpExtensions/Utility.h>
2 #include <cpExtensions/Interaction/ImageSliceStyle.h>
3 #include <cpExtensions/Visualization/CursorActors.h>
4 #include <cpExtensions/Visualization/LUTImageActor.h>
5 #include <cpExtensions/Visualization/WindowLevelImageActor.h>
6 #include <vtkAssemblyPath.h>
7 #include <vtkImageData.h>
8 #include <vtkImageSlice.h>
9 #include <vtkProperty.h>
10 #include <vtkPropCollection.h>
11 #include <vtkPropPicker.h>
12 #include <vtkRenderer.h>
13 #include <vtkTextActor.h>
14 #include <vtkTextProperty.h>
15 #include <sstream>
16
17 /* TODO
18    #include <cpExtensions/Visualization/ImageViewerActors.h>
19 */
20
21 // -------------------------------------------------------------------------
22 cpExtensions::Interaction::ImageSliceStyle::
23 Self* cpExtensions::Interaction::ImageSliceStyle::
24 New( )
25 {
26   return( new Self( ) );
27 }
28
29 // -------------------------------------------------------------------------
30 int cpExtensions::Interaction::ImageSliceStyle::
31 GetSliceNumber( ) const
32 {
33   if( this->m_WLActor.GetPointer( ) != NULL )
34     return( this->m_WLActor->GetSliceNumber( ) );
35   else
36     return( -1 );
37 }
38
39 // -------------------------------------------------------------------------
40 int cpExtensions::Interaction::ImageSliceStyle::
41 GetOrientation( ) const
42 {
43   if( this->m_WLActor.GetPointer( ) != NULL )
44     return( this->m_WLActor->GetOrientation( ) );
45   else
46     return( -1 );
47 }
48
49 // -------------------------------------------------------------------------
50 void cpExtensions::Interaction::ImageSliceStyle::
51 OnMouseMove( )
52 {
53   static bool cursor_visible = false;
54
55   int idx[ 2 ];
56   double pnt[ 3 ];
57   if( this->_PickPointOnImageActor( idx, pnt ) )
58   {
59     this->m_Cursor->SetCursor( pnt, false );
60     this->_ShowText( pnt );
61     if( !cursor_visible )
62     {
63       this->m_Cursor->VisibilityOn( );
64       this->m_Text->VisibilityOn( );
65       cursor_visible = true;
66
67     } // fi
68     this->Interactor->Render( );
69   }
70   else
71   {
72     if( cursor_visible )
73     {
74       this->m_Cursor->VisibilityOff( );
75       this->m_Text->VisibilityOff( );
76       cursor_visible = false;
77       this->Interactor->Render( );
78
79     } // fi
80
81   } // fi
82
83   this->Overclass::OnMouseMove( );
84 }
85
86 // -------------------------------------------------------------------------
87 void cpExtensions::Interaction::ImageSliceStyle::
88 OnMouseWheelForward( )
89 {
90   static int s = 0;
91   if( this->m_WLActor.GetPointer( ) == NULL )
92     return;
93   s = this->m_WLActor->GetSliceNumber( );
94   s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
95   this->m_WLActor->SetSliceNumber( s );
96   s = this->m_WLActor->GetSliceNumber( );
97   if( this->m_LUTActor.GetPointer( ) != NULL )
98     this->m_LUTActor->SetSliceNumber( s );
99   this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
100   this->Interactor->Render( );
101   this->OnMouseMove( );
102 }
103
104 // -------------------------------------------------------------------------
105 void cpExtensions::Interaction::ImageSliceStyle::
106 OnMouseWheelBackward( )
107 {
108   static int s = 0;
109   if( this->m_WLActor.GetPointer( ) == NULL )
110     return;
111   s = this->m_WLActor->GetSliceNumber( );
112   s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
113   this->m_WLActor->SetSliceNumber( s );
114   s = this->m_WLActor->GetSliceNumber( );
115   if( this->m_LUTActor.GetPointer( ) != NULL )
116     this->m_LUTActor->SetSliceNumber( s );
117   this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
118   this->Interactor->Render( );
119   this->OnMouseMove( );
120 }
121
122 // -------------------------------------------------------------------------
123 void cpExtensions::Interaction::ImageSliceStyle::
124 OnChar( )
125 {
126   switch( this->Interactor->GetKeyCode( ) )
127   {
128   case 'r': case 'R':
129   {
130     this->FindPokedRenderer(
131       this->Interactor->GetEventPosition( )[ 0 ],
132       this->Interactor->GetEventPosition( )[ 1 ]
133       );
134     this->CurrentRenderer->ResetCamera( );
135     this->Interactor->Render( );
136   }
137   break;
138   default:
139     break;
140
141   } // hctiws
142 }
143
144 /* TODO
145 cpExtensions::Visualization::ImageViewerActors*
146 cpExtensions::Interaction::ImageSliceStyle::
147 GetActors( )
148 {
149   return( this->m_Actors );
150 }
151
152 // -------------------------------------------------------------------------
153 const cpExtensions::Visualization::ImageViewerActors*
154 cpExtensions::Interaction::ImageSliceStyle::
155 GetActors( ) const
156 {
157   return( this->m_Actors );
158 }
159
160 // -------------------------------------------------------------------------
161 void cpExtensions::Interaction::ImageSliceStyle::
162 SetActors( cpExtensions::Visualization::ImageViewerActors* actors )
163 {
164   this->m_Actors = actors;
165   if( actors != NULL )
166   {
167     this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
168     this->m_PropPicker->PickFromListOn( );
169     this->m_PropPicker->GetPickList( )->RemoveAllItems( );
170     this->m_PropPicker->
171       AddPickList( this->m_Actors->GetWindowLevelImageActor( ) );
172   }
173   else
174     this->m_PropPicker = NULL;
175 }
176
177 // -------------------------------------------------------------------------
178 void cpExtensions::Interaction::ImageSliceStyle::
179 OnMouseMove( )
180 {
181   this->Superclass::OnMouseMove( );
182   if( this->m_Actors.GetPointer( ) == NULL )
183     return;
184
185   // Slice synch
186   static int idx[ 2 ];
187   static double pos[ 3 ];
188   if( this->_PickPosition( idx, pos ) )
189   {
190     if(
191       this->Interactor->GetControlKey( ) == 1 &&
192       this->GetButtonID( ) == Self::ButtonID_Left
193       )
194     {
195       this->m_Actors->SetSuperCursor( pos, this->m_Actors->GetOrientation( ) == 2 );
196       this->InvokeEvent( vtkCommand::UserEvent + 1, pos );
197     }
198     else
199       this->m_Actors->SetCursor( pos, this->m_Actors->GetOrientation( ) == 2 );
200   }
201   else
202     this->m_Actors->HideViewerActors( );
203   this->Interactor->Render( );
204 }
205
206 // -------------------------------------------------------------------------
207 void cpExtensions::Interaction::ImageSliceStyle::
208 OnMouseWheelForward( )
209 {
210   static int s = 0;
211   if( this->m_Actors.GetPointer( ) == NULL )
212     return;
213   s = this->m_Actors->GetSliceNumber( );
214   s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
215   this->m_Actors->SetSliceNumber( s );
216   s = this->m_Actors->GetSliceNumber( );
217   this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
218   this->Interactor->Render( );
219   this->OnMouseMove( );
220 }
221
222 // -------------------------------------------------------------------------
223 void cpExtensions::Interaction::ImageSliceStyle::
224 OnMouseWheelBackward( )
225 {
226   static int s = 0;
227   if( this->m_Actors.GetPointer( ) == NULL )
228     return;
229   s = this->m_Actors->GetSliceNumber( );
230   s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
231   this->m_Actors->SetSliceNumber( s );
232   s = this->m_Actors->GetSliceNumber( );
233   this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
234   this->Interactor->Render( );
235   this->OnMouseMove( );
236 }
237
238 // -------------------------------------------------------------------------
239 void cpExtensions::Interaction::ImageSliceStyle::
240 OnChar( )
241 {
242 }
243 */
244
245 // -------------------------------------------------------------------------
246 cpExtensions::Interaction::ImageSliceStyle::
247 ImageSliceStyle( )
248   : Superclass( )
249 {
250   this->SetInteractionModeToImage2D( );
251   this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
252   this->m_PropPicker->PickFromListOn( );
253
254   this->m_Cursor = vtkSmartPointer< TCursor >::New( );
255   this->m_Cursor->VisibilityOff( );
256   this->m_Cursor->GetProperty( 0 )->SetColor( 1, 1, 0 );
257   this->m_Cursor->GetProperty( 1 )->SetColor( 1, 1, 0 );
258
259   // Prepare text
260   this->m_TextBuffer[ 0 ] = '\0';
261   this->m_Text = vtkSmartPointer< vtkTextActor >::New( );
262   this->m_Text->SetTextScaleModeToNone( );
263   auto textprop = this->m_Text->GetTextProperty( );
264   textprop->SetColor( 1, 1, 0 );
265   textprop->SetFontFamilyToCourier( );
266   textprop->SetFontSize( 12 );
267   textprop->BoldOff( );
268   textprop->ItalicOff( );
269   textprop->ShadowOff( );
270   textprop->SetJustificationToLeft( );
271   textprop->SetVerticalJustificationToBottom( );
272   auto coord = this->m_Text->GetPositionCoordinate( );
273   coord->SetCoordinateSystemToNormalizedViewport( );
274   coord->SetValue( 0.01, 0.02 );
275   this->m_Text->VisibilityOff( );
276 }
277
278 // -------------------------------------------------------------------------
279 cpExtensions::Interaction::ImageSliceStyle::
280 ~ImageSliceStyle( )
281 {
282 }
283
284 // -------------------------------------------------------------------------
285 bool cpExtensions::Interaction::ImageSliceStyle::
286 _PickPointOnImageActor( int idx[ 2 ], double pnt[ 3 ] )
287 {
288   // Check if data is valid
289   if(
290     this->Interactor == NULL ||
291     this->CurrentRenderer == NULL ||
292     this->m_PropPicker.GetPointer( ) == NULL
293     )
294     return( false );
295
296   // Find the renderer where the event has been raised
297   idx[ 0 ] = this->Interactor->GetEventPosition( )[ 0 ];
298   idx[ 1 ] = this->Interactor->GetEventPosition( )[ 1 ];
299   this->FindPokedRenderer( double( idx[ 0 ] ), double( idx[ 1 ] ) );
300
301   // Check if the image has changed
302   this->Interactor->GetPicker( )->
303     Pick( idx[ 0 ], idx[ 1 ], 0.0, this->CurrentRenderer );
304   auto picker =
305     vtkAbstractPropPicker::SafeDownCast( this->Interactor->GetPicker( ) );
306   if( picker == NULL )
307     return( false );
308   TWLActor* curr_actor = dynamic_cast< TWLActor* >( picker->GetProp3D( ) );
309   if( curr_actor != this->m_WLActor.GetPointer( ) && curr_actor != NULL )
310   {
311     this->m_WLActor = curr_actor;
312     this->m_PropPicker->GetPickList( )->RemoveAllItems( );
313     this->m_PropPicker->AddPickList( curr_actor );
314
315     auto props = this->CurrentRenderer->GetViewProps( );
316     this->m_LUTActor = NULL;
317     props->InitTraversal( );
318     vtkProp* prop;
319     while( ( ( prop = props->GetNextProp( ) ) != NULL ) && ( this->m_LUTActor.GetPointer( ) == NULL ) )
320       this->m_LUTActor = dynamic_cast< TLUTActor* >( prop );
321
322     this->m_Cursor->SetImageBounds( curr_actor->GetImage( )->GetBounds( ) );
323     this->m_Cursor->SetImageOrientation( curr_actor->GetOrientation( ) );
324     this->m_Cursor->InitTraversal( );
325     while( vtkProp* prop = this->m_Cursor->GetNextProp( ) )
326       this->CurrentRenderer->AddViewProp( prop );
327     this->CurrentRenderer->AddViewProp( this->m_Text );
328
329   } // fi
330   if( this->m_WLActor.GetPointer( ) == NULL )
331   {
332     this->m_PropPicker->GetPickList( )->RemoveAllItems( );
333     return( false );
334
335   } // fi
336
337   // Pick a 3D position
338   int r = this->m_PropPicker->Pick(
339     double( idx[ 0 ] ), double( idx[ 1 ] ), double( 0 ),
340     this->CurrentRenderer
341     );
342   if( r == 0 )
343     return( false );
344   this->m_PropPicker->GetPickPosition( pnt );
345   return( true );
346 }
347
348 // -------------------------------------------------------------------------
349 void cpExtensions::Interaction::ImageSliceStyle::
350 _CorrectPosition( double pos[ 3 ], int ijk[ 3 ] )
351 {
352   if( this->m_WLActor.GetPointer( ) == NULL )
353     return;
354   auto image = this->m_WLActor->GetImage( );
355   if( image == NULL )
356     return;
357
358   // Approximate image index
359   double pcoords[ 3 ];
360   image->ComputeStructuredCoordinates( pos, ijk, pcoords );
361
362   // Manually correct index
363   int ext[ 6 ];
364   image->GetExtent( ext );
365   for( int i = 0; i < 3; ++i )
366   {
367     if( ijk[ i ] < ext[ i << 1 ] )
368       ijk[ i ] = ext[ i << 1 ];
369     if( ext[ ( i << 1 ) + 1 ] < ijk[ i ] )
370       ijk[ i ] = ext[ ( i << 1 ) + 1 ];
371
372   } // rof
373
374   // Get real coordinates
375   int o = this->m_WLActor->GetOrientation( );
376   ijk[ o ] = this->m_WLActor->GetSliceNumber( );
377   image->GetPoint( image->ComputePointId( ijk ), pos );
378 }
379
380 // -------------------------------------------------------------------------
381 void cpExtensions::Interaction::ImageSliceStyle::
382 _ShowText( double pos[ 3 ] )
383 {
384   if( this->m_WLActor.GetPointer( ) == NULL )
385     return;
386   auto image = this->m_WLActor->GetImage( );
387   if( image == NULL )
388     return;
389
390   int ijk[ 3 ];
391   this->_CorrectPosition( pos, ijk );
392   int o = this->m_WLActor->GetOrientation( );
393
394   std::stringstream buffer;
395   buffer << "Axis: " << char( 'X' + char( o ) ) << std::endl;
396   int nScl = image->GetNumberOfScalarComponents( );
397   buffer
398     << "Pixel: [" << ijk[ 0 ]
399     << "," << ijk[ 1 ]
400     << "," << ijk[ 2 ] << "] = < "
401     << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
402   for( int n = 1; n < nScl; ++n )
403     buffer
404       << " : "
405       << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n );
406   buffer << " >" << std::endl;
407   buffer
408     << "Point: ("
409     << pos[ 0 ] << ", " << pos[ 1 ] << ", " << pos[ 2 ]
410     << ")";
411   cpExtensions_SPRINTF( this->m_TextBuffer, 1024, buffer.str( ).c_str( ) );
412   this->m_Text->SetInput( this->m_TextBuffer );
413   this->m_Text->VisibilityOn( );
414   this->m_Text->Modified( );
415 }
416
417 // eof - $RCSfile$