]> Creatis software - cpPlugins.git/commitdiff
I'm on the middle of something, NOT YET STABLE - Leo
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 30 Oct 2015 23:09:19 +0000 (18:09 -0500)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Fri, 30 Oct 2015 23:09:19 +0000 (18:09 -0500)
appli/examples/example_View2DImage.cxx
lib/cpExtensions/Visualization/ImageBlender.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageBlender.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageSliceActors.cxx
lib/cpExtensions/Visualization/ImageSliceActors.h

index cc8a3e6e1eb61869ef1ab76e7177a292f3fd92f9..ea0554da0e5c7a78216565bd1a1851a6228f09ef 100644 (file)
 
 #include <cpExtensions/Visualization/ImageSliceActors.h>
 
+
+#include <cpExtensions/Visualization/ImageBlender.h>
+#include <vtkPNGWriter.h>
+
+
 // -------------------------------------------------------------------------
 typedef cpPlugins::Interface::Interface     TInterface;
 typedef cpPlugins::Interface::ProcessObject TProcessObject;
@@ -29,7 +34,7 @@ int main( int argc, char* argv[] )
   {
     std::cerr
       << "Usage: " << argv[ 0 ]
-      << " plugins_file input_image"
+      << " plugins_file input_image [widget]"
       << std::endl;
     return( 1 );
 
@@ -59,8 +64,13 @@ int main( int argc, char* argv[] )
 
   // Configure reader
   TParameters* reader_params = reader->GetParameters( );
-  for( int i = 2; i < argc; ++i )
-    reader_params->AddToStringList( "FileNames", argv[ i ] );
+  if( argc > 4 )
+  {
+    for( int i = 2; i < argc; ++i )
+      reader_params->AddToStringList( "FileNames", argv[ i ] );
+  }
+  else
+    reader_params->AddToStringList( "FileNames", argv[ 2 ] );
 
   // Execute pipeline
   std::string err = reader->Update( );
@@ -93,14 +103,48 @@ int main( int argc, char* argv[] )
   image_actors->AddInputData( image->GetVTK< vtkImageData >( ), 2 );
   image_actors->PushActorsInto( window );
 
+
+
+
+
+  vtkImageData* vimage = image->GetVTK< vtkImageData >( );
+  double range[ 2 ];
+  vimage->GetScalarRange( range );
+
+  vtkSmartPointer< cpExtensions::Visualization::ImageBlender > blender =
+    vtkSmartPointer< cpExtensions::Visualization::ImageBlender >::New( );
+  blender->AddInputData( vimage );
+  blender->SetWindow( range[ 1 ] - range[ 0 ] );
+  blender->SetLevel( ( range[ 1 ] + range[ 0 ] ) / double( 2 ) );
+  blender->Update( );
+
+  std::cout << blender->GetWindow( ) << " " << blender->GetLevel( ) << std::endl;
+
+  vtkSmartPointer< vtkPNGWriter > writer =
+    vtkSmartPointer< vtkPNGWriter >::New( );
+  writer->SetInputConnection( blender->GetOutputPort( ) );
+  writer->SetFileName( "leo_actor.png" );
+  writer->Write( );
+
+  return( 0 );
+
+
   // Activate seed widget
-  TSliceActors::TStyle* style =
-    dynamic_cast< TSliceActors::TStyle* >( image_actors->GetStyle( ) );
-  if( style != NULL )
-    style->SeedWidgetOn( );
+  if( argc == 4 )
+  {
+    TSliceActors::TStyle* style =
+      dynamic_cast< TSliceActors::TStyle* >( image_actors->GetStyle( ) );
+    if( style != NULL )
+    {
+      if( std::string( argv[ 3 ] ) == std::string( "seed" ) )
+        style->SeedWidgetOn( );
+
+    } // fi
+
+  } // fi
 
   // Begin interaction
-  renderer->ResetCamera( );
+  image_actors->ResetCamera( );
   window->Render( );
   interactor->Start( );
 
diff --git a/lib/cpExtensions/Visualization/ImageBlender.cxx b/lib/cpExtensions/Visualization/ImageBlender.cxx
new file mode 100644 (file)
index 0000000..3d90d58
--- /dev/null
@@ -0,0 +1,366 @@
+#include <cpExtensions/Visualization/ImageBlender.h>
+
+#include <vtkDataObject.h>
+#include <vtkImageData.h>
+#include <vtkImageIterator.h>
+#include <vtkImageProgressIterator.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageBlender::
+Self* cpExtensions::Visualization::ImageBlender::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+PrintSelf( std::ostream& os, vtkIndent indent )
+{
+  this->Superclass::PrintSelf( os, indent );
+
+  // Objects
+  os << indent << "Colors: " << std::endl;
+  auto i = this->m_Colors.begin( );
+  for( ; i != this->m_Colors.end( ); ++i )
+    os
+      << indent << indent << i->first << " : ["
+      << i->second.R << ", "
+      << i->second.G << ", "
+      << i->second.B << "]"
+      << std::endl;
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetMaxWindow( ) const
+{
+  return( this->m_MaxWindow );
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetMaxLevel( ) const
+{
+  return( this->m_MaxLevel );
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetMinWindow( ) const
+{
+  return( this->m_MinWindow );
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetMinLevel( ) const
+{
+  return( this->m_MinLevel );
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetWindow( ) const
+{
+  return( this->m_Window );
+}
+
+// -------------------------------------------------------------------------
+const double& cpExtensions::Visualization::ImageBlender::
+GetLevel( ) const
+{
+  return( this->m_Level );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+SetWindow( const double& w )
+{
+  if( this->m_Window != w )
+  {
+    this->m_Window = w;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+SetLevel( const double& l )
+{
+  if( this->m_Level != l )
+  {
+    this->m_Level = l;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+SetWindowLevel( const double& w, const double& l )
+{
+  this->SetWindow( w );
+  this->SetLevel( l );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+GetColor(
+  const unsigned int& i,
+  double& r,
+  double& g,
+  double& b
+  ) const
+{
+  auto c = this->m_Colors.find( i );
+  if( c != this->m_Colors.end( ) )
+  {
+    r = c->second.R;
+    g = c->second.G;
+    b = c->second.B;
+  }
+  else
+    r = g = b = double( 1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+SetColor(
+  const unsigned int& i,
+  const double& r,
+  const double& g,
+  const double& b
+  )
+{
+  this->m_Colors[ i ] = TColor( r, g, b );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageBlender::
+ImageBlender( )
+  : Superclass( ),
+    m_MaxWindow( double( 0 ) ),
+    m_MaxLevel( double( 0 ) ),
+    m_MinWindow( double( 0 ) ),
+    m_MinLevel( double( 0 ) ),
+    m_Window( double( 0 ) ),
+    m_Level( double( 0 ) )
+{
+  this->SetNumberOfInputPorts( 1 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageBlender::
+~ImageBlender( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageBlender::
+RequestInformation(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  int numInputs = this->GetNumberOfInputConnections( 0 );
+  if( numInputs == 0 )
+    return( 0 );
+
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject( 0 ),
+    VTK_UNSIGNED_CHAR, 4
+    );
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+ThreadedRequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector,
+  vtkImageData*** inData,
+  vtkImageData** outData,
+  int outExt[ 6 ], int id
+  )
+{
+  if( inData[ 0 ][ 0 ] == NULL )
+  {
+    vtkErrorMacro( << "Input " << 0 << " must be specified." );
+    return;
+
+  } // fi
+
+  int numInputs = this->GetNumberOfInputConnections( 0 );
+  int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
+  if( numComp > 1 )
+  {
+    vtkErrorMacro(
+      "ThreadedRequestData: Input has " << numComp
+      << " components, but just 1 is supported"
+      );
+    return;
+
+  } // fi
+
+  for( int i = 1; i < numInputs; ++i )
+  {
+    int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
+    if( otherComp != numComp )
+    {
+      if( id == 0 )
+        vtkErrorMacro(
+          "ThreadedRequestData: Input " << i
+          << " has " << otherComp
+          << " components, but input 0 has " << numComp
+          << " components"
+          );
+      return;
+
+    } // fi
+
+  } // rof
+
+  // Initialize window/level
+  vtkImageData* main_image = inData[ 0 ][ 0 ];
+  double range[ 2 ];
+  main_image->GetScalarRange( range );
+  this->m_MaxWindow = range[ 1 ] - range[ 0 ];
+  this->m_MinWindow = this->m_MaxWindow * double( 1e-2 );
+  this->m_MinLevel = range[ 0 ];
+  this->m_MaxLevel = range[ 1 ];
+
+  // Update window/level
+  if( this->m_Window < this->m_MinWindow )
+    this->m_Window = this->m_MinWindow;
+  if( this->m_Window > this->m_MaxWindow )
+    this->m_Window = this->m_MaxWindow;
+  if( this->m_Level < this->m_MinLevel )
+    this->m_Level = this->m_MinLevel;
+  if( this->m_Level > this->m_MaxLevel )
+    this->m_Level = this->m_MaxLevel;
+  
+  // Real update
+  this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageBlender::
+FillInputPortInformation( int i, vtkInformation* info )
+{
+  info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
+  return( this->Superclass::FillInputPortInformation( i, info ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageBlender::
+_GenerateData(
+  vtkImageData** inDatas,
+  int numInputs,
+  vtkImageData* outData,
+  int outExt[6],
+  int id
+  )
+{
+  vtkImageIterator< unsigned char > inItsFast[ 256 ];
+  unsigned char* inSIFast[ 256 ];
+  vtkImageProgressIterator< unsigned char > outIt( outData, outExt, this, id );
+
+  /*
+    double *weights =
+    static_cast<vtkDoubleArray *>(this->GetWeights())->GetPointer(0);
+    double totalWeight = this->CalculateTotalWeight();
+    int normalize = this->GetNormalizeByWeight();
+  */
+
+  vtkImageIterator< unsigned char > *inIts;
+  unsigned char** inSI;
+  if( numInputs < 256 )
+  {
+    inIts = inItsFast;
+    inSI = inSIFast;
+  }
+  else
+  {
+    inIts = new vtkImageIterator< unsigned char >[ numInputs ];
+    inSI = new unsigned char*[ numInputs ];
+
+  } // fi
+
+  // Loop through all input ImageData to initialize iterators
+  for( int i = 0; i < numInputs; ++i )
+    inIts[ i ].Initialize( inDatas[ i ], outExt );
+
+  // Loop through output pixels
+  double m = double( 1 ) / this->m_Window;
+  double c = double( 0.5 ) - ( this->m_Level / this->m_Window );
+  while( !outIt.IsAtEnd( ) )
+  {
+    // Prepare all iterators
+    for( int j = 0; j < numInputs; ++j )
+      inSI[ j ] = inIts[ j ].BeginSpan( );
+    unsigned char* outSI = outIt.BeginSpan( );
+    unsigned char* outSIEnd = outIt.EndSpan( );
+
+    // Pixel operation
+    while( outSI != outSIEnd )
+    {
+      // Window/Level value from main image
+      double wl = ( *inSI[ 0 ] * m ) + c;
+      if( wl < double( 0 ) ) wl = double( 0 );
+      if( wl > double( 1 ) ) wl = double( 1 );
+
+      // Prepare color values
+      double r = wl;
+      double g = wl;
+      double b = wl;
+      double a = double( 1 );
+
+      /*
+        double sum = 0.;
+        for(int k=0; k < numInputs; ++k)
+        {
+        sum += weights[k] * *inSI[k];
+        }
+      */
+
+      r *= double( 255 );
+      g *= double( 255 );
+      b *= double( 255 );
+      a *= double( 255 );
+
+      // Assign RGBA value
+      *outSI = static_cast< unsigned char >( r ); outSI++;
+      *outSI = static_cast< unsigned char >( g ); outSI++;
+      *outSI = static_cast< unsigned char >( b ); outSI++;
+      *outSI = static_cast< unsigned char >( a ); outSI++;
+
+      // Advance inputs
+      for( int l = 0; l < numInputs; ++l )
+        inSI[ l ]++;
+
+    } // elihw
+
+    // Advance all iterators
+    for( int j = 0; j < numInputs; ++j )
+      inIts[ j ].NextSpan( );
+    outIt.NextSpan( );
+
+  } // elihw
+
+  // Free auxiliary buffers
+  if( numInputs >= 256 )
+  {
+    delete [] inIts;
+    delete [] inSI;
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageBlender.h b/lib/cpExtensions/Visualization/ImageBlender.h
new file mode 100644 (file)
index 0000000..b74b51a
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEBLENDER__H__
+#define __CPEXTENSIONS__VISUALIZATION__IMAGEBLENDER__H__
+
+#include <cpExtensions/cpExtensions_Export.h>
+
+#include <map>
+#include <vtkThreadedImageAlgorithm.h>
+
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageBlender
+      : public vtkThreadedImageAlgorithm
+    {
+    public:
+      typedef ImageBlender Self;
+      vtkTypeMacro( ImageBlender, vtkThreadedImageAlgorithm );
+
+    public:
+      static Self* New( );
+      void PrintSelf( std::ostream& os, vtkIndent indent );
+
+      const double& GetMaxWindow( ) const;
+      const double& GetMaxLevel( ) const;
+      const double& GetMinWindow( ) const;
+      const double& GetMinLevel( ) const;
+      const double& GetWindow( ) const;
+      const double& GetLevel( ) const;
+
+      void SetWindow( const double& w );
+      void SetLevel( const double& l );
+      void SetWindowLevel( const double& w, const double& l );
+
+      void GetColor(
+        const unsigned int& i,
+        double& r,
+        double& g,
+        double& b
+        ) const;
+      void SetColor(
+        const unsigned int& i,
+        const double& r,
+        const double& g,
+        const double& b
+        );
+
+    protected:
+      ImageBlender( );
+      virtual ~ImageBlender( );
+
+      int RequestInformation(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        );
+      void ThreadedRequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector,
+        vtkImageData*** inData,
+        vtkImageData** outData,
+        int outExt[ 6 ], int id
+        );
+      int FillInputPortInformation( int i, vtkInformation* info );
+
+      void _GenerateData(
+        vtkImageData** inDatas,
+        int numInputs,
+        vtkImageData* outData,
+        int outExt[6],
+        int id
+        );
+
+    private:
+      // Purposely not implemented.
+      ImageBlender( const Self& other );
+      void operator=( const Self& other );
+
+    protected:
+      struct TColor
+      {
+        double R, G, B;
+        TColor(
+          const double& r = double( 1 ),
+          const double& g = double( 0 ),
+          const double& b = double( 0 )
+          )
+          : R( r ),
+            G( g ),
+            B( b )
+          { }
+      };
+      mutable std::map< unsigned int, TColor > m_Colors;
+
+      double m_MaxWindow;
+      double m_MaxLevel;
+      double m_MinWindow;
+      double m_MinLevel;
+      double m_Window;
+      double m_Level;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif //  __CPEXTENSIONS__VISUALIZATION__IMAGEBLENDER__H__
+
+// eof - $RCSfile$
index 0418c3714363d45124a33b0e6f202ac17636bea4..4d20994be61a7ebb29874cd23229feded8513193 100644 (file)
@@ -129,6 +129,18 @@ Clear( )
   this->m_MaxWindow = double( 0 );
   this->m_MinLevel = double( 0 );
   this->m_MaxLevel = double( 0 );
+  this->m_VisibleExtent[ 0 ] =
+    this->m_VisibleExtent[ 2 ] =
+    this->m_VisibleExtent[ 4 ] = -1;
+  this->m_VisibleExtent[ 1 ] =
+    this->m_VisibleExtent[ 3 ] =
+    this->m_VisibleExtent[ 5 ] = 0;
+  this->m_VisibleBounds[ 0 ] =
+    this->m_VisibleBounds[ 2 ] =
+    this->m_VisibleBounds[ 4 ] = double( 0 );
+  this->m_VisibleBounds[ 1 ] =
+    this->m_VisibleBounds[ 3 ] =
+    this->m_VisibleBounds[ 5 ] = double( 0 );
 
   // Unbind from container
   this->RemoveAllItems( );
@@ -139,13 +151,19 @@ Clear( )
   this->m_ImageActors.clear( );
 
   // Reconfigure unique objects
-  this->m_Cursor        = vtkSmartPointer< vtkPolyData >::New( );
-  this->m_CursorMapper  = vtkSmartPointer< vtkPolyDataMapper >::New( );
-  this->m_CursorActor   = vtkSmartPointer< vtkActor >::New( );
-  this->m_Plane         = vtkSmartPointer< vtkPolyData >::New( );
-  this->m_PlaneMapper   = vtkSmartPointer< vtkPolyDataMapper >::New( );
-  this->m_TextActor     = vtkSmartPointer< vtkTextActor >::New( );
-  this->m_PlaneActor    = vtkSmartPointer< vtkActor >::New( );
+  this->m_Cursor               = vtkSmartPointer< vtkPolyData >::New( );
+  this->m_CursorMapper         = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  this->m_CursorActor          = vtkSmartPointer< vtkActor >::New( );
+  this->m_HorizontalLine       = vtkSmartPointer< vtkPolyData >::New( );
+  this->m_HorizontalLineMapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  this->m_HorizontalLineActor  = vtkSmartPointer< vtkActor >::New( );
+  this->m_VerticalLine         = vtkSmartPointer< vtkPolyData >::New( );
+  this->m_VerticalLineMapper   = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  this->m_VerticalLineActor    = vtkSmartPointer< vtkActor >::New( );
+  this->m_Plane                = vtkSmartPointer< vtkPolyData >::New( );
+  this->m_PlaneMapper          = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  this->m_TextActor            = vtkSmartPointer< vtkTextActor >::New( );
+  this->m_PlaneActor           = vtkSmartPointer< vtkActor >::New( );
   this->m_TextBuffer[ 0 ] = '\0';
 
   // Unique objects configuration
@@ -178,6 +196,34 @@ Clear( )
   this->m_CursorMapper->SetInputData( this->m_Cursor );
   this->m_CursorActor->SetMapper( this->m_CursorMapper );
 
+  vtkSmartPointer< vtkPoints > h_points =
+    vtkSmartPointer< vtkPoints >::New( );
+  vtkSmartPointer< vtkCellArray > h_lines =
+    vtkSmartPointer< vtkCellArray >::New( );
+  h_points->InsertNextPoint( 0, 0, 0 );
+  h_points->InsertNextPoint( 0, 0, 0 );
+  h_lines->InsertNextCell( 2 );
+  h_lines->InsertCellPoint( 0 );
+  h_lines->InsertCellPoint( 1 );
+  this->m_HorizontalLine->SetPoints( h_points );
+  this->m_HorizontalLine->SetLines( h_lines );
+  this->m_HorizontalLineMapper->SetInputData( this->m_HorizontalLine );
+  this->m_HorizontalLineActor->SetMapper( this->m_HorizontalLineMapper );
+
+  vtkSmartPointer< vtkPoints > v_points =
+    vtkSmartPointer< vtkPoints >::New( );
+  vtkSmartPointer< vtkCellArray > v_lines =
+    vtkSmartPointer< vtkCellArray >::New( );
+  v_points->InsertNextPoint( 0, 0, 0 );
+  v_points->InsertNextPoint( 0, 0, 0 );
+  v_lines->InsertNextCell( 2 );
+  v_lines->InsertCellPoint( 0 );
+  v_lines->InsertCellPoint( 1 );
+  this->m_VerticalLine->SetPoints( v_points );
+  this->m_VerticalLine->SetLines( v_lines );
+  this->m_VerticalLineMapper->SetInputData( this->m_VerticalLine );
+  this->m_VerticalLineActor->SetMapper( this->m_VerticalLineMapper );
+
   vtkSmartPointer< vtkPoints > plane_points =
     vtkSmartPointer< vtkPoints >::New( );
   vtkSmartPointer< vtkCellArray > plane_lines =
@@ -215,6 +261,8 @@ Clear( )
 
   // Update actor collection
   this->AddItem( this->m_CursorActor );
+  this->AddItem( this->m_HorizontalLineActor );
+  this->AddItem( this->m_VerticalLineActor );
   this->AddItem( this->m_TextActor );
   this->AddItem( this->m_PlaneActor );
 }
@@ -471,7 +519,12 @@ ResetCursor( )
   {
     double bounds[ 6 ];
     this->m_SliceMappers[ 0 ]->GetInput( )->GetBounds( bounds );
-    double pos[] = { bounds[ 0 ], bounds[ 2 ], bounds[ 4 ] };
+    double pos[] =
+      {
+        this->m_VisibleBounds[ 0 ],
+        this->m_VisibleBounds[ 2 ],
+        this->m_VisibleBounds[ 4 ]
+      };
     this->SetCursor( pos );
   }
   else
@@ -507,9 +560,8 @@ SetCursor( double pos[ 3 ] )
   int ma1 = a1 << 1;
   int ma2 = a2 << 1;
 
-  double bounds[ 6 ];
-  this->m_SliceMappers[ 0 ]->GetInput( )->GetBounds( bounds );
-
+  // Update cross
+  double* bounds = this->m_VisibleBounds;
   double
     p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ],
     p4[ 3 ], p5[ 3 ], p6[ 3 ], p7[ 3 ];
@@ -838,8 +890,10 @@ SetSliceNumber( const int& slice )
   if( nImages == 0 )
     return;
 
-  // Change visualization extent
   int axis = this->GetAxis( );
+  double prev_pos = this->m_VisibleBounds[ axis << 1 ];
+
+  // Change visualization extent
   for( unsigned int i = 0; i < nImages; ++i )
   {
     // Update mappers and display bounds
@@ -849,21 +903,31 @@ SetSliceNumber( const int& slice )
     this->m_SliceMappers[ i ]->Update( );
 
     // Update display extent (this isn't done automatically)
-    vtkImageData* image = this->m_SliceMappers[ i ]->GetInput( );
-    int ext[ 6 ];
-    image->GetExtent( ext );
-    ext[ axis << 1 ] = slice;
-    ext[ ( axis << 1 ) + 1 ] = slice;
-    this->m_ImageActors[ i ]->SetDisplayExtent( ext );
+    if( i == 0 )
+    {
+      this->m_SliceMappers[ i ]->GetInput( )->
+        GetExtent( this->m_VisibleExtent );
+      this->m_VisibleExtent[ axis << 1 ] = slice;
+      this->m_VisibleExtent[ ( axis << 1 ) + 1 ] = slice;
+
+    } // fi
+    this->m_ImageActors[ i ]->SetDisplayExtent( this->m_VisibleExtent );
 
   } // rof
 
-  double bnds[ 6 ];
-  this->m_SliceMappers[ 0 ]->GetBounds( bnds );
+  this->m_SliceMappers[ 0 ]->GetBounds( this->m_VisibleBounds );
   double x0[][ 3 ] =
   {
-    { bnds[ 0 ], bnds[ 2 ], bnds[ 4 ] },
-    { bnds[ 1 ], bnds[ 3 ], bnds[ 5 ] }
+    {
+      this->m_VisibleBounds[ 0 ],
+      this->m_VisibleBounds[ 2 ],
+      this->m_VisibleBounds[ 4 ]
+    },
+    {
+      this->m_VisibleBounds[ 1 ],
+      this->m_VisibleBounds[ 3 ],
+      this->m_VisibleBounds[ 5 ]
+    }
   };
   double p0[ 2 ][ 3 ];
 
@@ -871,12 +935,13 @@ SetSliceNumber( const int& slice )
   plane->GeneralizedProjectPoint( x0[ 0 ], p0[ 0 ] );
   plane->GeneralizedProjectPoint( x0[ 1 ], p0[ 1 ] );
 
-  bnds[ 0 ] = p0[ 0 ][ 0 ];
-  bnds[ 1 ] = p0[ 1 ][ 0 ];
-  bnds[ 2 ] = p0[ 0 ][ 1 ];
-  bnds[ 3 ] = p0[ 1 ][ 1 ];
-  bnds[ 4 ] = p0[ 0 ][ 2 ];
-  bnds[ 5 ] = p0[ 1 ][ 2 ];
+  this->m_VisibleBounds[ 0 ] = p0[ 0 ][ 0 ];
+  this->m_VisibleBounds[ 1 ] = p0[ 1 ][ 0 ];
+  this->m_VisibleBounds[ 2 ] = p0[ 0 ][ 1 ];
+  this->m_VisibleBounds[ 3 ] = p0[ 1 ][ 1 ];
+  this->m_VisibleBounds[ 4 ] = p0[ 0 ][ 2 ];
+  this->m_VisibleBounds[ 5 ] = p0[ 1 ][ 2 ];
+  double* bnds = this->m_VisibleBounds;
 
   // Configure visualization and implicit plane orientation
   this->m_PlaneActor->GetProperty( )->SetRepresentationToWireframe( );
@@ -906,6 +971,40 @@ SetSliceNumber( const int& slice )
 
   // Update text
   this->UpdateText( );
+
+  // Update lines from associated slices
+  /* TODO
+     auto sIt = this->m_AssociatedSlices.begin( );
+     for( ; sIt != this->m_AssociatedSlices.end( ); ++sIt )
+     {
+     Self* slice = *sIt;
+     for( unsigned int id = 0; id < slice->m_AssociatedSlices.size( ); ++id )
+     {
+     std::cout << id << std::endl;
+     if( slice->m_AssociatedSlices[ id ] != this )
+     continue;
+
+     std::cout << "id : " << id << std::endl;
+
+     } // rof
+
+     } // rof
+  */
+
+  // Update camera position
+  if( this->m_Window == NULL )
+    return;
+  vtkRenderer* renderer =
+    this->m_Window->GetRenderers( )->GetFirstRenderer( );
+  if( renderer == NULL )
+    return;
+  vtkCamera* camera = renderer->GetActiveCamera( );
+  if( camera == NULL )
+    return;
+  double cam_pos[ 3 ];
+  camera->GetPosition( cam_pos );
+  cam_pos[ axis ] += this->m_VisibleBounds[ axis << 1 ] - prev_pos;
+  camera->SetPosition( cam_pos );
 }
 
 // -------------------------------------------------------------------------
@@ -1059,8 +1158,7 @@ ResetCamera( )
   vtkRenderer* renderer =
     this->m_Window->GetRenderers( )->GetFirstRenderer( );
   if( renderer != NULL )
-    renderer->ResetCamera( );
-#error ACA VOY: reconfigurar la camara alrededor únicamente del plano.
+    renderer->ResetCamera( this->m_VisibleBounds );
 }
 
 // -------------------------------------------------------------------------
index c5113ad725145ad6757d5e542ad78fc55d512334..e086901c32044dd6164e05fac6fe91d9911b6a44 100644 (file)
@@ -178,6 +178,9 @@ namespace cpExtensions
       std::vector< vtkSmartPointer< vtkImageActor > >       m_ImageActors;
       bool m_Interpolate;
 
+      int    m_VisibleExtent[ 6 ];
+      double m_VisibleBounds[ 6 ];
+
       // Associated slices
       std::vector< Self* > m_AssociatedSlices;
 
@@ -189,11 +192,21 @@ namespace cpExtensions
       vtkSmartPointer< vtkPolyData >       m_Cursor;
       vtkSmartPointer< vtkPolyDataMapper > m_CursorMapper;
       vtkSmartPointer< vtkActor >          m_CursorActor;
+
+      vtkSmartPointer< vtkPolyData >       m_HorizontalLine;
+      vtkSmartPointer< vtkPolyDataMapper > m_HorizontalLineMapper;
+      vtkSmartPointer< vtkActor >          m_HorizontalLineActor;
+
+      vtkSmartPointer< vtkPolyData >       m_VerticalLine;
+      vtkSmartPointer< vtkPolyDataMapper > m_VerticalLineMapper;
+      vtkSmartPointer< vtkActor >          m_VerticalLineActor;
+
       vtkSmartPointer< vtkPolyData >       m_Plane;
       vtkSmartPointer< vtkPolyDataMapper > m_PlaneMapper;
+      vtkSmartPointer< vtkActor >          m_PlaneActor;
+
       char                                 m_TextBuffer[ 1024 ];
       vtkSmartPointer< vtkTextActor >      m_TextActor;
-      vtkSmartPointer< vtkActor >          m_PlaneActor;
 
       double m_StartWindowLevelPos[ 3 ];
       double m_StartWindowLevel[ 2 ];