1 #include <cpExtensions/Visualization/ImageSliceActors.h>
6 #include <vtkAlgorithmOutput.h>
8 #include <vtkCellArray.h>
9 #include <vtkImageData.h>
10 #include <vtkInformation.h>
12 #include <vtkPoints.h>
13 #include <vtkProperty.h>
14 #include <vtkRenderer.h>
15 #include <vtkRendererCollection.h>
16 #include <vtkRenderWindow.h>
17 #include <vtkRenderWindowInteractor.h>
18 #include <vtkStreamingDemandDrivenPipeline.h>
19 #include <vtkTextProperty.h>
20 #include <vtkWindowLevelLookupTable.h>
22 // -------------------------------------------------------------------------
23 cpExtensions::Visualization::ImageSliceActors*
24 cpExtensions::Visualization::ImageSliceActors::
27 return( new Self( ) );
30 // -------------------------------------------------------------------------
31 void cpExtensions::Visualization::ImageSliceActors::
32 AddInputConnection( vtkAlgorithmOutput* aout, int axis )
34 vtkImageData* data = dynamic_cast< vtkImageData* >(
35 aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
40 vtkImageMapToColors* new_map =
41 dynamic_cast< vtkImageMapToColors* >( aout->GetProducer( ) );
45 this->_ConfigureNewLUT( data );
46 new_map = *( this->ImageMaps.rbegin( ) );
49 new_map->SetInputConnection( aout );
55 this->ImageMaps.push_back( new_map );
57 // Create mapper and actors
58 vtkSmartPointer< vtkImageSliceMapper > mapper =
59 vtkSmartPointer< vtkImageSliceMapper >::New( );
61 mapper->SetInputConnection( new_map->GetOutputPort( ) );
63 mapper->SetInputConnection( aout );
64 this->SliceMappers.push_back( mapper );
65 this->_ConfigureNewInput( axis );
68 // -------------------------------------------------------------------------
69 void cpExtensions::Visualization::ImageSliceActors::
70 AddInputData( vtkImageData* data, int axis )
73 this->_ConfigureNewLUT( data );
74 vtkImageMapToColors* new_map = *( this->ImageMaps.rbegin( ) );
77 new_map->SetInputData( data );
82 // Create mapper and actors
83 vtkSmartPointer< vtkImageSliceMapper > mapper =
84 vtkSmartPointer< vtkImageSliceMapper >::New( );
86 mapper->SetInputConnection( new_map->GetOutputPort( ) );
88 mapper->SetInputData( data );
89 this->SliceMappers.push_back( mapper );
90 this->_ConfigureNewInput( axis );
93 // -------------------------------------------------------------------------
94 void cpExtensions::Visualization::ImageSliceActors::
97 // Unbind from container
98 this->RemoveAllItems( );
101 this->ImageMaps.clear( );
102 this->SliceMappers.clear( );
103 this->ImageActors.clear( );
104 this->AssociatedSlices.clear( );
105 this->AssociatedActors.clear( );
107 // Reconfigure unique objects
108 this->Cursor = vtkSmartPointer< vtkPolyData >::New( );
109 this->CursorMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
110 this->CursorActor = vtkSmartPointer< vtkActor >::New( );
111 this->PlaneFunction = vtkSmartPointer< vtkPlane >::New( );
112 this->Plane = vtkSmartPointer< vtkPolyData >::New( );
113 this->PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
114 this->TextActor = vtkSmartPointer< vtkTextActor >::New( );
115 this->PlaneActor = vtkSmartPointer< vtkActor >::New( );
116 this->TextBuffer[ 0 ] = '\0';
118 // Unique objects configuration
119 vtkSmartPointer< vtkPoints > cursor_points =
120 vtkSmartPointer< vtkPoints >::New( );
121 vtkSmartPointer< vtkCellArray > cursor_lines =
122 vtkSmartPointer< vtkCellArray >::New( );
123 cursor_points->InsertNextPoint( 0, 0, 0 );
124 cursor_points->InsertNextPoint( 0, 0, 0 );
125 cursor_points->InsertNextPoint( 0, 0, 0 );
126 cursor_points->InsertNextPoint( 0, 0, 0 );
127 cursor_points->InsertNextPoint( 0, 0, 0 );
128 cursor_points->InsertNextPoint( 0, 0, 0 );
129 cursor_points->InsertNextPoint( 0, 0, 0 );
130 cursor_points->InsertNextPoint( 0, 0, 0 );
131 cursor_lines->InsertNextCell( 2 );
132 cursor_lines->InsertCellPoint( 0 );
133 cursor_lines->InsertCellPoint( 1 );
134 cursor_lines->InsertNextCell( 2 );
135 cursor_lines->InsertCellPoint( 2 );
136 cursor_lines->InsertCellPoint( 3 );
137 cursor_lines->InsertNextCell( 2 );
138 cursor_lines->InsertCellPoint( 4 );
139 cursor_lines->InsertCellPoint( 5 );
140 cursor_lines->InsertNextCell( 2 );
141 cursor_lines->InsertCellPoint( 6 );
142 cursor_lines->InsertCellPoint( 7 );
143 this->Cursor->SetPoints( cursor_points );
144 this->Cursor->SetLines( cursor_lines );
145 this->CursorMapper->SetInputData( this->Cursor );
146 this->CursorActor->SetMapper( this->CursorMapper );
148 vtkSmartPointer< vtkPoints > plane_points =
149 vtkSmartPointer< vtkPoints >::New( );
150 vtkSmartPointer< vtkCellArray > plane_lines =
151 vtkSmartPointer< vtkCellArray >::New( );
153 plane_points->InsertNextPoint( 0, 0, 0 );
154 plane_points->InsertNextPoint( 0, 1, 0 );
155 plane_points->InsertNextPoint( 1, 1, 0 );
156 plane_points->InsertNextPoint( 1, 0, 0 );
157 plane_lines->InsertNextCell( 5 );
158 plane_lines->InsertCellPoint( 0 );
159 plane_lines->InsertCellPoint( 1 );
160 plane_lines->InsertCellPoint( 2 );
161 plane_lines->InsertCellPoint( 3 );
162 plane_lines->InsertCellPoint( 0 );
163 this->Plane->SetPoints( plane_points );
164 this->Plane->SetLines( plane_lines );
166 this->PlaneMapper->SetInputData( this->Plane );
167 this->PlaneActor->SetMapper( this->PlaneMapper );
169 this->TextActor->SetTextScaleModeToNone( );
170 vtkTextProperty* textprop = this->TextActor->GetTextProperty( );
171 textprop->SetColor( 1, 1, 1 );
172 textprop->SetFontFamilyToCourier( );
173 textprop->SetFontSize( 18 );
174 textprop->BoldOff( );
175 textprop->ItalicOff( );
176 textprop->ShadowOff( );
177 textprop->SetJustificationToLeft( );
178 textprop->SetVerticalJustificationToBottom( );
179 vtkCoordinate* coord = this->TextActor->GetPositionCoordinate( );
180 coord->SetCoordinateSystemToNormalizedViewport( );
181 coord->SetValue( 0.01, 0.01 );
184 // -------------------------------------------------------------------------
185 void cpExtensions::Visualization::ImageSliceActors::
186 AssociateSlice( Self* other )
188 this->AssociatedSlices.push_back( other );
192 // -------------------------------------------------------------------------
193 void cpExtensions::Visualization::ImageSliceActors::
194 SetSlicesCommand( TCursorCommand cmd, void* data )
196 this->SlicesCommand = cmd;
197 this->SlicesData = data;
201 // -------------------------------------------------------------------------
202 vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
205 return( this->Style.GetPointer( ) );
208 // -------------------------------------------------------------------------
209 const vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors::
212 return( this->Style.GetPointer( ) );
215 // -------------------------------------------------------------------------
216 void cpExtensions::Visualization::ImageSliceActors::
217 PushActorsInto( vtkRenderWindow* window, bool force_style )
221 vtkRenderWindowInteractor* rwi = window->GetInteractor( );
222 vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
223 if( rwi == NULL || renderer == NULL )
228 if( rwi->GetInteractorStyle( ) != this->Style.GetPointer( ) )
229 rwi->SetInteractorStyle( this->Style );
232 unsigned int N = this->GetNumberOfImageActors( );
233 for( unsigned int n = 0; n < N; ++n )
234 renderer->AddActor( this->GetImageActor( n ) );
235 renderer->AddActor( this->CursorActor );
236 renderer->AddActor( this->PlaneActor );
237 renderer->AddActor( this->TextActor );
238 renderer->Modified( );
241 vtkCamera* camera = renderer->GetActiveCamera( );
245 // Parallel projections are better when displaying 2D images
248 int axis = this->GetAxis( );
249 camera->ParallelProjectionOn( );
250 camera->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) );
253 camera->SetPosition( double( 1 ), double( 0 ), double( 0 ) );
254 camera->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) );
258 camera->SetPosition( double( 0 ), double( 1 ), double( 0 ) );
259 camera->SetViewUp ( double( 0 ), double( 0 ), double( -1 ) );
261 else // if( axis == 2 )
263 camera->SetPosition( double( 0 ), double( 0 ), double( 1 ) );
264 camera->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) );
269 renderer->ResetCamera( );
273 // -------------------------------------------------------------------------
274 void cpExtensions::Visualization::ImageSliceActors::
275 PopActorsFrom( vtkRenderWindow* window )
277 vtkRenderWindowInteractor* rwi = window->GetInteractor( );
278 vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( );
280 if( renderer != NULL )
283 unsigned int N = this->GetNumberOfImageActors( );
284 for( unsigned int n = 0; n < N; ++n )
285 renderer->RemoveActor( this->GetImageActor( n ) );
286 renderer->RemoveActor( this->CursorActor );
287 renderer->RemoveActor( this->PlaneActor );
288 renderer->RemoveActor( this->TextActor );
289 renderer->Modified( );
294 // -------------------------------------------------------------------------
295 unsigned int cpExtensions::Visualization::ImageSliceActors::
296 GetNumberOfImageActors( ) const
298 return( this->ImageActors.size( ) );
301 // -------------------------------------------------------------------------
302 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
303 GetImageActor( unsigned int id )
305 if( id < this->ImageActors.size( ) )
306 return( this->ImageActors[ id ] );
311 // -------------------------------------------------------------------------
312 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
313 GetImageActor( unsigned int id ) const
315 if( id < this->ImageActors.size( ) )
316 return( this->ImageActors[ id ] );
321 // -------------------------------------------------------------------------
322 vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
325 return( this->TextActor );
328 // -------------------------------------------------------------------------
329 const vtkTextActor* cpExtensions::Visualization::ImageSliceActors::
330 GetTextActor( ) const
332 return( this->TextActor );
335 // -------------------------------------------------------------------------
336 vtkActor* cpExtensions::Visualization::ImageSliceActors::
339 return( this->PlaneActor );
342 // -------------------------------------------------------------------------
343 const vtkActor* cpExtensions::Visualization::ImageSliceActors::
344 GetPlaneActor( ) const
346 return( this->PlaneActor );
349 // -------------------------------------------------------------------------
350 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
353 return( this->PlaneFunction );
356 // -------------------------------------------------------------------------
357 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
358 GetPlaneFunction( ) const
360 return( this->PlaneFunction );
363 // -------------------------------------------------------------------------
364 void cpExtensions::Visualization::ImageSliceActors::
365 AddActor( vtkAlgorithm* algorithm, vtkActor* actor )
367 this->AssociatedActors.push_back( TAssociatedActor( algorithm, actor ) );
368 this->AddItem( actor );
371 // -------------------------------------------------------------------------
372 void cpExtensions::Visualization::ImageSliceActors::
373 AddActor( vtkActor* actor )
375 this->AddActor( NULL, actor );
378 // -------------------------------------------------------------------------
379 void cpExtensions::Visualization::ImageSliceActors::
380 SetInterpolate( bool v )
382 if( this->Interpolate != v )
384 for( unsigned int i = 0; i < this->ImageActors.size( ); ++i )
385 this->ImageActors[ i ]->SetInterpolate( v );
386 this->Interpolate = v;
392 // -------------------------------------------------------------------------
393 void cpExtensions::Visualization::ImageSliceActors::
396 this->SetInterpolate( true );
399 // -------------------------------------------------------------------------
400 void cpExtensions::Visualization::ImageSliceActors::
403 this->SetInterpolate( false );
406 // -------------------------------------------------------------------------
407 double* cpExtensions::Visualization::ImageSliceActors::
408 GetDisplayBounds( ) const
410 if( this->ImageActors.size( ) > 0 )
411 return( this->ImageActors[ 0 ]->GetDisplayBounds( ) );
416 // -------------------------------------------------------------------------
417 void cpExtensions::Visualization::ImageSliceActors::
418 GetDisplayBounds( double bounds[ 6 ] ) const
420 if( this->ImageActors.size( ) == 0 )
422 bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
423 bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
426 this->ImageActors[ 0 ]->GetDisplayBounds( bounds );
429 // -------------------------------------------------------------------------
430 void cpExtensions::Visualization::ImageSliceActors::
433 vtkPoints* points = this->Cursor->GetPoints( );
434 points->SetPoint( 0, 0, 0, 0 );
435 points->SetPoint( 1, 0, 0, 0 );
436 points->SetPoint( 2, 0, 0, 0 );
437 points->SetPoint( 3, 0, 0, 0 );
438 points->SetPoint( 4, 0, 0, 0 );
439 points->SetPoint( 5, 0, 0, 0 );
440 points->SetPoint( 6, 0, 0, 0 );
441 points->SetPoint( 7, 0, 0, 0 );
442 this->Cursor->Modified( );
443 this->CursorMapper->Modified( );
444 this->CursorActor->Modified( );
447 // -------------------------------------------------------------------------
448 void cpExtensions::Visualization::ImageSliceActors::
449 SetCursor( double pos[ 3 ] )
451 if( this->SliceMappers.size( ) == 0 )
455 int a0 = this->GetAxis( );
456 int a1 = ( a0 + 1 ) % 3;
457 int a2 = ( a0 + 2 ) % 3;
463 this->SliceMappers[ 0 ]->GetInput( )->GetBounds( bounds );
466 p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ],
467 p4[ 3 ], p5[ 3 ], p6[ 3 ], p7[ 3 ];
469 p0[ a2 ] = p1[ a2 ] = p4[ a2 ] = p5[ a2 ] = pos[ a2 ];
470 p2[ a1 ] = p3[ a1 ] = p6[ a1 ] = p7[ a1 ] = pos[ a1 ];
471 p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ];
472 p4[ a0 ] = p5[ a0 ] = p6[ a0 ] = p7[ a0 ] = bounds[ ma0 + 1 ];
473 p0[ a1 ] = p4[ a1 ] = bounds[ ma1 ];
474 p1[ a1 ] = p5[ a1 ] = bounds[ ma1 + 1 ];
475 p2[ a2 ] = p6[ a2 ] = bounds[ ma2 ];
476 p3[ a2 ] = p7[ a2 ] = bounds[ ma2 + 1 ];
478 vtkPoints* points = this->Cursor->GetPoints( );
479 points->SetPoint( 0, p0 );
480 points->SetPoint( 1, p1 );
481 points->SetPoint( 2, p2 );
482 points->SetPoint( 3, p3 );
483 points->SetPoint( 4, p4 );
484 points->SetPoint( 5, p5 );
485 points->SetPoint( 6, p6 );
486 points->SetPoint( 7, p7 );
487 this->Cursor->Modified( );
488 this->CursorMapper->Modified( );
489 this->CursorActor->Modified( );
492 // -------------------------------------------------------------------------
493 vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
494 GetImageMap( unsigned int id )
496 if( id < this->ImageMaps.size( ) )
497 return( this->ImageMaps[ id ].GetPointer( ) );
502 // -------------------------------------------------------------------------
503 const vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
504 GetImageMap( unsigned int id ) const
506 if( id < this->ImageMaps.size( ) )
507 return( this->ImageMaps[ id ].GetPointer( ) );
512 // -------------------------------------------------------------------------
513 double cpExtensions::Visualization::ImageSliceActors::
516 if( this->ImageMaps.size( ) > 0 )
518 if( this->ImageMaps[ 0 ].GetPointer( ) != NULL )
520 vtkWindowLevelLookupTable* lut =
521 dynamic_cast< vtkWindowLevelLookupTable* >(
522 this->ImageMaps[ 0 ]->GetLookupTable( )
525 return( lut->GetWindow( ) );
527 return( double( 0 ) );
530 return( double( 0 ) );
533 return( double( 0 ) );
536 // -------------------------------------------------------------------------
537 double cpExtensions::Visualization::ImageSliceActors::
540 if( this->ImageMaps.size( ) > 0 )
542 if( this->ImageMaps[ 0 ].GetPointer( ) != NULL )
544 vtkWindowLevelLookupTable* lut =
545 dynamic_cast< vtkWindowLevelLookupTable* >(
546 this->ImageMaps[ 0 ]->GetLookupTable( )
549 return( lut->GetLevel( ) );
551 return( double( 0 ) );
554 return( double( 0 ) );
557 return( double( 0 ) );
560 // -------------------------------------------------------------------------
561 void cpExtensions::Visualization::ImageSliceActors::
562 SetWindow( double w )
564 if( this->ImageMaps.size( ) > 0 )
566 if( this->ImageMaps[ 0 ].GetPointer( ) != NULL )
568 vtkWindowLevelLookupTable* lut =
569 dynamic_cast< vtkWindowLevelLookupTable* >(
570 this->ImageMaps[ 0 ]->GetLookupTable( )
574 /* TODO: Min and Max values are assigned 0!!!
575 if( w < this->MinWindow )
577 if( w > this->MaxWindow )
582 this->ImageMaps[ 0 ]->Modified( );
592 // -------------------------------------------------------------------------
593 void cpExtensions::Visualization::ImageSliceActors::
596 if( this->ImageMaps.size( ) > 0 )
598 if( this->ImageMaps[ 0 ].GetPointer( ) != NULL )
600 vtkWindowLevelLookupTable* lut =
601 dynamic_cast< vtkWindowLevelLookupTable* >(
602 this->ImageMaps[ 0 ]->GetLookupTable( )
606 /* TODO: Min and Max values are assigned 0!!!
607 if( l < this->MinLevel )
609 if( l > this->MaxLevel )
614 this->ImageMaps[ 0 ]->Modified( );
624 // -------------------------------------------------------------------------
625 void cpExtensions::Visualization::ImageSliceActors::
626 SetWindowLevel( double w, double l )
628 if( this->ImageMaps.size( ) > 0 )
630 if( this->ImageMaps[ 0 ].GetPointer( ) != NULL )
632 vtkWindowLevelLookupTable* lut =
633 dynamic_cast< vtkWindowLevelLookupTable* >(
634 this->ImageMaps[ 0 ]->GetLookupTable( )
638 /* TODO: Min and Max values are assigned 0!!!
639 std::cout << this->MinWindow << " " << this->MaxWindow << std::endl;
640 std::cout << this->MinLevel << " " << this->MaxLevel << std::endl;
641 std::cout << w << " " << l << " <-> " << std::ends;
642 if( w < this->MinWindow )
644 if( w > this->MaxWindow )
646 if( l < this->MinLevel )
648 if( l > this->MaxLevel )
650 std::cout << w << " " << l << std::endl;
655 this->ImageMaps[ 0 ]->Modified( );
665 // -------------------------------------------------------------------------
666 void cpExtensions::Visualization::ImageSliceActors::
669 this->SetWindowLevel(
671 ( this->MaxLevel + this->MinLevel ) / double( 2 )
675 // -------------------------------------------------------------------------
676 void cpExtensions::Visualization::ImageSliceActors::
677 SetLookupTable( unsigned int id, vtkLookupTable* lut )
679 if( id < this->ImageMaps.size( ) && id > 0 )
681 if( this->ImageMaps[ id ].GetPointer( ) != NULL )
683 this->ImageMaps[ id ]->SetLookupTable( lut );
684 this->ImageMaps[ id ]->Modified( );
692 // -------------------------------------------------------------------------
693 void cpExtensions::Visualization::ImageSliceActors::
694 SetLookupTableAsColor( unsigned int id, double r, double g, double b )
696 static const double _0 = double( 0 );
697 static const double _2 = double( 2 );
698 static const double _4 = double( 4 );
699 static const double _6 = double( 6 );
700 static const double _OPACITY = double( 0.6 );
702 // Check ID consistency
703 if( id == 0 || id >= this->ImageMaps.size( ) )
706 // Get image scalar range
707 vtkAlgorithmOutput* aout = this->ImageMaps[ id ]->GetOutputPort( );
708 vtkImageData* image = dynamic_cast< vtkImageData* >(
709 aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
712 image->GetScalarRange( range );
714 // Get HSV from display color
715 double cmax = ( r > g )? r: g; cmax = ( b > cmax )? b: cmax;
716 double cmin = ( r < g )? r: g; cmin = ( b < cmin )? b: cmin;
717 double d = cmax - cmin;
719 double saturation = ( std::fabs( cmax ) > _0 )? d / cmax: _0;
725 hue = std::fmod( ( g - b ) / d, _6 );
727 hue = ( ( b - r ) / d ) + _2;
729 hue = ( ( r - g ) / d ) + _4;
734 // Define new lookup table
735 vtkSmartPointer< vtkLookupTable > lut =
736 vtkSmartPointer< vtkLookupTable >::New( );
737 lut->SetScaleToLinear( );
738 lut->SetNanColor( _0, _0, _0, _0 );
739 lut->SetTableRange( range[ 0 ], range[ 1 ] );
740 lut->SetAlphaRange( _0, _OPACITY );
741 lut->SetHueRange( _0, hue );
742 lut->SetSaturationRange( _0, saturation );
743 lut->SetValueRange( _0, value );
745 this->SetLookupTable( id, lut );
748 // -------------------------------------------------------------------------
749 int cpExtensions::Visualization::ImageSliceActors::
752 if( this->SliceMappers.size( ) > 0 )
753 return( this->SliceMappers[ 0 ]->GetOrientation( ) );
758 // -------------------------------------------------------------------------
759 int cpExtensions::Visualization::ImageSliceActors::
760 GetSliceNumber( ) const
762 if( this->SliceMappers.size( ) > 0 )
763 return( this->SliceMappers[ 0 ]->GetSliceNumber( ) );
768 // -------------------------------------------------------------------------
769 int cpExtensions::Visualization::ImageSliceActors::
770 GetSliceNumberMinValue( ) const
772 if( this->SliceMappers.size( ) > 0 )
773 return( this->SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
778 // -------------------------------------------------------------------------
779 int cpExtensions::Visualization::ImageSliceActors::
780 GetSliceNumberMaxValue( ) const
782 if( this->SliceMappers.size( ) > 0 )
783 return( this->SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
788 // -------------------------------------------------------------------------
789 void cpExtensions::Visualization::ImageSliceActors::
790 SetSliceNumber( const int& slice )
792 unsigned int nImages = this->SliceMappers.size( );
796 // Change visualization extent
797 for( unsigned int i = 0; i < nImages; ++i )
799 this->SliceMappers[ i ]->SetSliceNumber( slice );
800 this->SliceMappers[ i ]->Modified( );
801 this->ImageActors[ i ]->Modified( );
802 this->SliceMappers[ i ]->Update( );
807 vtkAlgorithm* algo = this->SliceMappers[ 0 ]->GetInputAlgorithm( );
808 vtkInformation* info = algo->GetOutputInformation( 0 );
810 double ori[ 3 ], spac[ 3 ], pos[ 3 ];
811 info->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT( ), ext );
812 info->Get( vtkDataObject::ORIGIN( ), ori );
813 info->Get( vtkDataObject::SPACING( ), spac );
814 this->SliceMappers[ 0 ]->GetSlicePlane( )->GetOrigin( pos );
816 // Prevent obscuring voxels by offsetting the plane geometry
819 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 0 ] ) ),
820 ori[ 0 ] + ( spac[ 0 ] * double( ext[ 1 ] ) )
824 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 2 ] ) ),
825 ori[ 1 ] + ( spac[ 1 ] * double( ext[ 3 ] ) )
829 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 4 ] ) ),
830 ori[ 2 ] + ( spac[ 2 ] * double( ext[ 5 ] ) )
833 if( spac[ 0 ] < double( 0 ) )
835 double t = xbnds[ 0 ];
836 xbnds[ 0 ] = xbnds[ 1 ];
840 if( spac[ 1 ] < double( 0 ) )
842 double t = ybnds[ 0 ];
843 ybnds[ 0 ] = ybnds[ 1 ];
847 if( spac[ 2 ] < double( 0 ) )
849 double t = zbnds[ 0 ];
850 zbnds[ 0 ] = zbnds[ 1 ];
855 // Plane function origin
856 this->PlaneFunction->SetOrigin( pos );
858 // Configure visualization and implicit plane orientation
859 int axis = this->SliceMappers[ 0 ]->GetOrientation( );
860 this->PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
861 this->PlaneActor->GetProperty( )->SetLineWidth( 2 );
862 vtkPoints* plane_points = this->Plane->GetPoints( );
863 if( axis == 0 ) // YZ, x-normal
865 this->PlaneFunction->SetNormal( 1, 0, 0 );
866 plane_points->SetPoint( 0, pos[ 0 ], ybnds[ 0 ], zbnds[ 0 ] );
867 plane_points->SetPoint( 1, pos[ 0 ], ybnds[ 1 ], zbnds[ 0 ] );
868 plane_points->SetPoint( 2, pos[ 0 ], ybnds[ 1 ], zbnds[ 1 ] );
869 plane_points->SetPoint( 3, pos[ 0 ], ybnds[ 0 ], zbnds[ 1 ] );
870 this->PlaneActor->GetProperty( )->SetColor( 1, 0, 0 );
872 else if( axis == 1 ) // ZX, y-normal
874 this->PlaneFunction->SetNormal( 0, 1, 0 );
875 plane_points->SetPoint( 0, xbnds[ 0 ], pos[ 1 ], zbnds[ 0 ] );
876 plane_points->SetPoint( 1, xbnds[ 0 ], pos[ 1 ], zbnds[ 1 ] );
877 plane_points->SetPoint( 2, xbnds[ 1 ], pos[ 1 ], zbnds[ 1 ] );
878 plane_points->SetPoint( 3, xbnds[ 1 ], pos[ 1 ], zbnds[ 0 ] );
879 this->PlaneActor->GetProperty( )->SetColor( 0, 1, 0 );
883 this->PlaneFunction->SetNormal( 0, 0, 1 );
884 plane_points->SetPoint( 0, xbnds[ 0 ], ybnds[ 0 ], pos[ 2 ] );
885 plane_points->SetPoint( 1, xbnds[ 1 ], ybnds[ 0 ], pos[ 2 ] );
886 plane_points->SetPoint( 2, xbnds[ 1 ], ybnds[ 1 ], pos[ 2 ] );
887 plane_points->SetPoint( 3, xbnds[ 0 ], ybnds[ 1 ], pos[ 2 ] );
888 this->PlaneActor->GetProperty( )->SetColor( 0, 0, 1 );
891 this->PlaneFunction->Modified( );
892 this->Plane->Modified( );
893 this->PlaneMapper->Modified( );
894 this->PlaneActor->Modified( );
896 // Prepare other actors to update
898 for( unsigned int i = 0; i < this->OtherActors.size( ); ++i )
900 if( this->OtherActors[ i ].first.GetPointer( ) != NULL )
902 this->OtherActors[ i ].first->Modified( );
903 this->OtherActors[ i ].first->Update( );
907 if( this->OtherActors[ i ].second.GetPointer( ) != NULL )
909 this->OtherActors[ i ].second->GetMapper( )->Modified( );
910 this->OtherActors[ i ].second->Modified( );
916 if( this->m_UpdateCommand != NULL )
917 this->m_UpdateCommand( this->m_UpdateData );
924 for( unsigned int i = 0; i < this->AssociatedSlices.size( ); ++i )
925 if( this->AssociatedSlices[ i ]->GetAxis( ) == this->GetAxis( ) )
926 this->AssociatedSlices[ i ]->SetSliceNumber( slice );
929 // -------------------------------------------------------------------------
930 void cpExtensions::Visualization::ImageSliceActors::
931 SetSlice( double* pos )
934 if( this->ImageMaps[ 0 ] != NULL )
936 dynamic_cast< vtkImageData* >( this->ImageMaps[ 0 ]->GetInput( ) );
938 image = this->SliceMappers[ 0 ]->GetInput( );
942 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
943 this->SetSliceNumber( ijk[ this->GetAxis( ) ] );
946 // -------------------------------------------------------------------------
947 void cpExtensions::Visualization::ImageSliceActors::
950 if( this->SliceMappers.size( ) > 0 )
953 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
954 if ( axId == 0 ) axis = 'X';
955 else if( axId == 1 ) axis = 'Y';
956 else if( axId == 2 ) axis = 'Z';
959 this->TextBuffer, "Axis: %c (%d)",
960 axis, this->SliceMappers[ 0 ]->GetSliceNumber( )
964 this->TextBuffer[ 0 ] = '\0';
965 this->TextActor->SetInput( this->TextBuffer );
966 this->TextActor->Modified( );
970 // -------------------------------------------------------------------------
971 void cpExtensions::Visualization::ImageSliceActors::
972 UpdateText( double pos[ 3 ] )
975 if( this->SliceMappers.size( ) > 0 )
978 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
979 if ( axId == 0 ) axis = 'X';
980 else if( axId == 1 ) axis = 'Y';
981 else if( axId == 2 ) axis = 'Z';
982 int slice = this->GetSliceNumber( );
985 if( this->ImageMaps[ 0 ] != NULL )
987 dynamic_cast< vtkImageData* >( this->ImageMaps[ 0 ]->GetInput( ) );
989 image = this->SliceMappers[ 0 ]->GetInput( );
993 image->ComputeStructuredCoordinates( pos, ijk, pcoords );
997 image->GetExtent( ext );
999 ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] &&
1000 ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] &&
1001 ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ]
1004 int nScl = image->GetNumberOfScalarComponents( );
1005 std::stringstream str;
1009 << "," << ijk[ 2 ] << "]=(";
1011 image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
1012 for( int n = 1; n < nScl; ++n )
1015 << image->GetScalarComponentAsFloat(
1016 ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n
1020 this->TextBuffer, "Axis: %c (%d)\nPixel %s",
1021 axis, slice, str.str( ).c_str( )
1027 this->TextBuffer[ 0 ] = '\0';
1028 this->TextActor->SetInput( this->TextBuffer );
1029 this->TextActor->Modified( );
1034 // -------------------------------------------------------------------------
1035 void cpExtensions::Visualization::ImageSliceActors::
1036 UpdateText( const double& w, const double& l )
1038 if( this->SliceMappers.size( ) > 0 )
1041 int axId = this->SliceMappers[ 0 ]->GetOrientation( );
1042 if ( axId == 0 ) axis = 'X';
1043 else if( axId == 1 ) axis = 'Y';
1044 else if( axId == 2 ) axis = 'Z';
1047 this->TextBuffer, "Axis: %c (%d)\nW/L (%.2f/%.2f)",
1048 axis, this->SliceMappers[ 0 ]->GetSliceNumber( ), w, l
1052 this->TextBuffer[ 0 ] = '\0';
1053 this->TextActor->SetInput( this->TextBuffer );
1054 this->TextActor->Modified( );
1058 // -------------------------------------------------------------------------
1059 cpExtensions::Visualization::ImageSliceActors::
1062 Interpolate( false )
1066 this->SlicesCommand = NULL;
1068 // Connect this view with a controller
1069 this->Style = vtkSmartPointer< ImageInteractorStyle >::New( );
1070 this->Style->AssociateView( this );
1071 this->Style->SetMouseMoveCommand( Self::_MouseMoveCommand );
1072 this->Style->SetMouseClickCommand( Self::_MouseClickCommand );
1073 this->Style->SetMouseDoubleClickCommand( Self::_MouseDoubleClickCommand );
1074 this->Style->SetMouseWheelCommand( Self::_MouseWheelCommand );
1075 this->Style->SetKeyCommand( Self::_KeyCommand );
1078 // -------------------------------------------------------------------------
1079 cpExtensions::Visualization::ImageSliceActors::
1080 ~ImageSliceActors( )
1084 // -------------------------------------------------------------------------
1085 void cpExtensions::Visualization::ImageSliceActors::
1086 _ConfigureNewLUT( vtkImageData* data )
1088 // Does the new LUT is a window-level one?
1089 unsigned int nImgs = this->ImageMaps.size( );
1090 unsigned int nCmps = data->GetNumberOfScalarComponents( );
1094 this->ImageMaps.push_back( NULL );
1099 // Create LUT filter
1100 this->ImageMaps.push_back( vtkSmartPointer< vtkImageMapToColors >::New( ) );
1104 data->GetScalarRange( range );
1105 vtkSmartPointer< vtkWindowLevelLookupTable > lut =
1106 vtkSmartPointer< vtkWindowLevelLookupTable >::New( );
1107 lut->SetScaleToLinear( );
1108 lut->SetTableRange( range );
1109 lut->SetWindow( range[ 1 ] - range[ 0 ] );
1110 lut->SetLevel( ( range[ 1 ] + range[ 0 ] ) / double( 2 ) );
1112 this->ImageMaps[ 0 ]->SetLookupTable( lut );
1114 this->MinWindow = double( 0 );
1115 this->MaxWindow = range[ 1 ] - range[ 0 ];
1116 this->MinLevel = range[ 0 ];
1117 this->MaxLevel = range[ 1 ];
1120 this->SetLookupTableAsColor( nImgs, 1, 0, 0 );
1123 // -------------------------------------------------------------------------
1124 void cpExtensions::Visualization::ImageSliceActors::
1125 _ConfigureNewInput( int axis )
1127 unsigned int nImages = this->ImageActors.size( );
1130 vtkImageSliceMapper* mapper = this->SliceMappers[ nImages ];
1132 mapper->SetOrientation( axis );
1134 mapper->SetOrientation( this->SliceMappers[ 0 ]->GetOrientation( ) );
1138 vtkSmartPointer< vtkImageActor > actor =
1139 vtkSmartPointer< vtkImageActor >::New( );
1140 this->ImageActors.push_back( actor );
1141 actor->SetMapper( mapper );
1142 actor->SetInterpolate( this->Interpolate );
1147 this->AddItem( this->CursorActor );
1148 this->AddItem( this->PlaneActor );
1149 this->AddItem( this->TextActor );
1150 this->Style->AssociateImageActor( actor );
1153 this->AddItem( actor );
1156 this->SetSliceNumber( this->GetSliceNumber( ) );
1160 // -------------------------------------------------------------------------
1161 void cpExtensions::Visualization::ImageSliceActors::
1164 const ImageInteractorStyle::ButtonID& btn, double* pos,
1165 bool alt, bool ctr, bool sft
1168 ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1169 if( actors == NULL )
1172 if( btn == ImageInteractorStyle::ButtonID_None )
1174 actors->UpdateText( pos );
1176 else if( btn == ImageInteractorStyle::ButtonID_Left )
1178 if( !alt && ctr && !sft && actors->SlicesCommand != NULL )
1179 actors->SlicesCommand( pos, actors->GetAxis( ), actors->SlicesData );
1181 else if( btn == ImageInteractorStyle::ButtonID_Middle )
1184 else if( btn == ImageInteractorStyle::ButtonID_Right )
1186 if( !alt && !ctr && sft )
1189 actors->SliceMappers[ 0 ]->GetBounds( bounds );
1191 int a0 = actors->GetAxis( );
1192 int a1 = ( a0 + 1 ) % 3;
1193 int a2 = ( a0 + 2 ) % 3;
1194 double dx = pos[ a1 ] - actors->StartWindowLevelPos[ a1 ];
1195 double dy = pos[ a2 ] - actors->StartWindowLevelPos[ a2 ];
1196 dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ];
1197 dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ];
1199 dx *= actors->StartWindowLevel[ 0 ];
1200 dy *= actors->StartWindowLevel[ 1 ];
1201 actors->SetWindowLevel(
1202 actors->StartWindowLevel[ 0 ] + dx,
1203 actors->StartWindowLevel[ 1 ] + dy
1211 // -------------------------------------------------------------------------
1212 void cpExtensions::Visualization::ImageSliceActors::
1215 const ImageInteractorStyle::ButtonID& btn, double* pos,
1216 bool alt, bool ctr, bool sft
1219 ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1220 if( actors == NULL )
1223 actors->StartWindowLevelPos[ 0 ] = pos[ 0 ];
1224 actors->StartWindowLevelPos[ 1 ] = pos[ 1 ];
1225 actors->StartWindowLevelPos[ 2 ] = pos[ 2 ];
1226 actors->StartWindowLevel[ 0 ] = actors->GetWindow( );
1227 actors->StartWindowLevel[ 1 ] = actors->GetLevel( );
1230 // -------------------------------------------------------------------------
1231 void cpExtensions::Visualization::ImageSliceActors::
1232 _MouseDoubleClickCommand(
1234 const ImageInteractorStyle::ButtonID& btn, double* pos,
1235 bool alt, bool ctr, bool sft
1238 ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1239 if( actors == NULL )
1242 if( btn == ImageInteractorStyle::ButtonID_Left )
1244 if( !alt && !ctr && !sft )
1245 actors->SetCursor( pos );
1246 else if( !alt && ctr && !sft && actors->SlicesCommand != NULL )
1248 actors->SlicesCommand( pos, actors->GetAxis( ), actors->SlicesData );
1249 for( unsigned int i = 0; i < actors->CursorCommands.size( ); ++i )
1250 actors->CursorCommands[ i ].first(
1253 actors->CursorCommands[ i ].second
1258 else if( btn == ImageInteractorStyle::ButtonID_Middle )
1261 else if( btn == ImageInteractorStyle::ButtonID_Right )
1266 // -------------------------------------------------------------------------
1267 void cpExtensions::Visualization::ImageSliceActors::
1270 const int& dir, bool alt, bool ctr, bool sft
1273 ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data );
1274 if( actors == NULL )
1277 if( !alt && !ctr && !sft )
1279 actors->SetSliceNumber( actors->GetSliceNumber( ) + dir );
1281 else if( !alt && !ctr && sft )
1283 actors->SetSliceNumber( actors->GetSliceNumber( ) + ( dir * 10 ) );
1288 // -------------------------------------------------------------------------
1289 void cpExtensions::Visualization::ImageSliceActors::