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