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