Ver código fonte

ENH: Added vtkLightBoxRendererManager

LightboxRendererManager works with a vtkRenderWindow and a vtkImageData.

It allows:
 - to split the viewport given a layout (row/column)
 - highlight programatically a given item of the viewport
 - dynamically change the layout
 - set either a LeftRightTopBottom or LeftRightBottomTop layout type

Each items of the grid will display a different slice of the image, the
layout type define how the slices should be displayed.
Jean-Christophe Fillion-Robin 14 anos atrás
pai
commit
865c8c71cd

+ 4 - 0
Libs/Visualization/VTK/Core/CMakeLists.txt

@@ -40,6 +40,8 @@ SET(KIT_SRCS
   ctkVTKObjectEventsObserver.h
   ctkVTKPiecewiseFunction.cpp
   ctkVTKPiecewiseFunction.h
+  vtkLightBoxRendererManager.cpp
+  vtkLightBoxRendererManager.h
   )
 
 # Headers that should run through moc
@@ -65,6 +67,8 @@ SET(KIT_resources
 SET(VTK_LIBRARIES
   vtkCommon
   vtkFiltering
+  vtkRendering
+  vtkHybrid
   )
 
 # Target libraries - See CMake/ctkMacroGetTargetLibraries.cmake

+ 45 - 17
Libs/Visualization/VTK/Core/Testing/Cpp/CMakeLists.txt

@@ -1,21 +1,22 @@
 SET(KIT ${PROJECT_NAME})
 
 #
-# Pre-requisites
+# Tests
 #
-
-INCLUDE_DIRECTORIES(
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- )
-  
-# Create ctkVTKObjectTestHelper source list
-
-SET(KIT_HELPER_SRCS
-  ctkVTKObjectTestHelper.cpp
+SET(TEST_SOURCES
+  ctkVTKCommandOptionsTest1.cpp
+  ctkVTKConnectionTest1.cpp
+  ctkVTKObjectTest1.cpp
   )
 
-QT4_WRAP_CPP(KIT_HELPER_SRCS ctkVTKObjectTestHelper.h)
+#
+# Tests expecting CTKData to be set
+#
+IF(EXISTS "${CTKData_DIR}")
+  LIST(APPEND TEST_SOURCES
+    vtkLightBoxRendererManagerTest1.cpp
+    )
+ENDIF()
 
 #
 # Testing data
@@ -25,22 +26,38 @@ SET(TESTING_DATA ${CMAKE_CURRENT_SOURCE_DIR}/Data)
 
 # Resource file used for testing is generated running:
 #    bin/ctkVisualizationVTKCoreCppTests ctkVTKCommandOptionsTest1 --generate-test-data
-
 SET(CTKVTKCOMMANDOPTIONSTEST_SETTINGS ${TESTING_DATA}/Settings/ctkVTKCommandOptionsTest1.ini)
 
+#
+# Pre-requisites
+#
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ )
+
 CONFIGURE_FILE(
   ${CMAKE_CURRENT_SOURCE_DIR}/ctkVisualizationVTKCoreCppTestsConfigure.h.in
   ${CMAKE_CURRENT_BINARY_DIR}/ctkVisualizationVTKCoreCppTestsConfigure.h
   )
 
 #
+# Test helpers
+#
+
+SET(KIT_HELPER_SRCS
+  ctkVTKObjectTestHelper.cpp
+  )
+
+QT4_WRAP_CPP(KIT_HELPER_SRCS ctkVTKObjectTestHelper.h)
+
+#
 # Tests
 #
 
 CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cpp
-  ctkVTKCommandOptionsTest1.cpp
-  ctkVTKConnectionTest1.cpp
-  ctkVTKObjectTest1.cpp
+  ${TEST_SOURCES}
   #EXTRA_INCLUDE TestingMacros.h
   )
 
@@ -58,7 +75,11 @@ IF(WIN32)
 ENDIF(WIN32)
 
 MACRO( SIMPLE_TEST  TESTNAME )
-  ADD_TEST( ${TESTNAME} ${KIT_TESTS} ${TESTNAME} )
+  ADD_TEST( ${TESTNAME} ${KIT_TESTS} ${TESTNAME}
+            -D ${CTKData_DIR}/Data
+            -V ${CTKData_DIR}/Baseline/Libs/Visualization/VTK/Core/${TESTNAME}.png
+            -T ${CTK_BINARY_DIR}/Testing/Temporary
+            )
   SET_PROPERTY(TEST ${TESTNAME} PROPERTY LABELS ${PROJECT_NAME})
 ENDMACRO( SIMPLE_TEST  )
 
@@ -69,6 +90,13 @@ ENDMACRO( SIMPLE_TEST  )
 SIMPLE_TEST( ctkVTKObjectTest1 )
 SIMPLE_TEST( ctkVTKConnectionTest1 )
 
+#
+# Add Tests expecting CTKData to be set
+#
+IF(EXISTS "${CTKData_DIR}")
+  SIMPLE_TEST( vtkLightBoxRendererManagerTest1 )
+ENDIF()
+
 ADD_TEST( ctkVTKCommandOptionsTest1 ${KIT_TESTS}
           ctkVTKCommandOptionsTest1 --help )
           

+ 197 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/vtkLightBoxRendererManagerTest1.cpp

@@ -0,0 +1,197 @@
+
+// CTKVTK includes
+#include "vtkLightBoxRendererManager.h"
+
+// CTKCore includes
+#include "ctkCommandLineParser.h"
+
+// VTK includes
+#include <vtkSmartPointer.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkRenderWindow.h>
+#include <vtkInteractorStyleImage.h>
+#include <vtkImageReader2Factory.h>
+#include <vtkImageReader2.h>
+#include <vtkImageData.h>
+#include <vtkRegressionTestImage.h>
+#include <vtkTestUtilities.h>
+
+// STD includes
+#include <cstdlib>
+
+// Convenient macro
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+  
+//----------------------------------------------------------------------------
+int vtkLightBoxRendererManagerTest1(int argc, char* argv[])
+{
+  const char * imageFilename = vtkTestUtilities::ExpandDataFileName(argc, argv, "HeadMRVolume.mhd");
+
+  //----------------------------------------------------------------------------
+  // Read Image
+  //----------------------------------------------------------------------------
+  // Instanciate the reader factory
+  VTK_CREATE(vtkImageReader2Factory, imageFactory);
+
+  // Instanciate an image reader
+  vtkSmartPointer<vtkImageReader2> imageReader;
+  imageReader.TakeReference(imageFactory->CreateImageReader2(imageFilename));
+  if (!imageReader)
+    {
+    std::cerr << "Failed to instanciate image reader using: " << imageFilename << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  // Read image
+  imageReader->SetFileName(imageFilename);
+  imageReader->Update();
+  vtkSmartPointer<vtkImageData> image = imageReader->GetOutput();
+
+  //----------------------------------------------------------------------------
+  // Renderer, RenderWindow and Interactor
+  //----------------------------------------------------------------------------
+  VTK_CREATE(vtkRenderer, rr);
+  VTK_CREATE(vtkRenderWindow, rw);
+  VTK_CREATE(vtkRenderWindowInteractor, ri);
+  rw->SetSize(600, 600);
+  rw->SetMultiSamples(0); // Ensure to have the same test image everywhere
+  rw->AddRenderer(rr);
+  rw->SetInteractor(ri);
+  
+  // Set Interactor Style
+  VTK_CREATE(vtkInteractorStyleImage, iStyle);
+  ri->SetInteractorStyle(iStyle);
+
+  VTK_CREATE(vtkLightBoxRendererManager, lightBoxRendererManager);
+
+  //----------------------------------------------------------------------------
+  // Check if non initialized case is handled properly / Check default value
+  //----------------------------------------------------------------------------
+  if (lightBoxRendererManager->IsInitialized() != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with IsInitialized()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->IsInitialized() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetRenderWindow() != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetRenderWindow()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetRenderWindow() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetActiveCamera() != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetActiveCamera()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetActiveCamera() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetRenderWindowItemCount() != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetRenderWindowItemCount()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetRenderWindowItemCount() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetRenderer(4) != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetRenderer()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetRenderer(4) << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetRenderer(1,1) != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetRenderer()" << std::endl;
+    std::cerr << "  expected: 0" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetRenderer(1,1) << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetCornerAnnotationText().compare("") != 0)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetCornerAnnotationText()" << std::endl;
+    std::cerr << "  expected: Empty" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->GetCornerAnnotationText() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (lightBoxRendererManager->GetRenderWindowLayoutType() !=
+      vtkLightBoxRendererManager::LeftRightTopBottom)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with GetRenderWindowLayoutType()" << std::endl;
+    std::cerr << "  expected: " <<
+        static_cast<int>(vtkLightBoxRendererManager::LeftRightTopBottom) << std::endl;
+    std::cerr << "  current:" <<
+        static_cast<int>(lightBoxRendererManager->GetRenderWindowLayoutType()) << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  unsigned long mtime = lightBoxRendererManager->GetMTime();
+
+  lightBoxRendererManager->ResetCamera();
+  if (mtime != lightBoxRendererManager->GetMTime())
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with ResetCamera()" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  lightBoxRendererManager->SetActiveCamera(0);
+  if (mtime != lightBoxRendererManager->GetMTime())
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with SetActiveCamera()" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  lightBoxRendererManager->SetImageData(image);
+  if (mtime != lightBoxRendererManager->GetMTime())
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with SetImageData()" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  //----------------------------------------------------------------------------
+  // Initialize
+  //----------------------------------------------------------------------------
+
+  lightBoxRendererManager->Initialize(rw);
+
+  if (lightBoxRendererManager->IsInitialized() != 1)
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with IsInitialized()" << std::endl;
+    std::cerr << "  expected: 1" << std::endl;
+    std::cerr << "  current:" << lightBoxRendererManager->IsInitialized() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if (mtime == lightBoxRendererManager->GetMTime())
+    {
+    std::cerr << "line " << __LINE__ << " - Problem with IsInitialized()" << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  lightBoxRendererManager->SetImageData(image);
+  lightBoxRendererManager->SetRenderWindowLayout(4, 5);
+  lightBoxRendererManager->SetHighlighted(2,2,true);
+  lightBoxRendererManager->SetColorWindowAndLevel(100, 100);
+  double color[3] = {0.5, 0.5, 0.5};
+  lightBoxRendererManager->SetBackgroundColor(color);
+
+  int retval = vtkRegressionTestImage(rw);
+  if (retval == vtkRegressionTester::DO_INTERACTOR)
+    {
+    rw->GetInteractor()->Initialize();
+    rw->GetInteractor()->Start();
+    }
+  
+  return !retval;
+}

+ 688 - 0
Libs/Visualization/VTK/Core/vtkLightBoxRendererManager.cpp

@@ -0,0 +1,688 @@
+
+#include "vtkLightBoxRendererManager.h"
+
+// VTK includes
+#include <vtkObjectFactory.h>
+#include <vtkSmartPointer.h>
+#include <vtkWeakPointer.h>
+#include <vtkRenderWindow.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkTextProperty.h>
+#include <vtkProperty2D.h>
+#include <vtkCamera.h>
+#include <vtkImageData.h>
+#include <vtkImageMapper.h>
+#include <vtkCellArray.h>
+#include <vtkPoints.h>
+#include <vtkPolyData.h>
+#include <vtkPolyDataMapper2D.h>
+#include <vtkCornerAnnotation.h>
+
+// STD includes
+#include <vector>
+#include <cassert>
+
+// Convenient macro
+#define VTK_CREATE(type, name) \
+  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+
+//----------------------------------------------------------------------------
+vtkCxxRevisionMacro(vtkLightBoxRendererManager, "$Revision:$");
+vtkStandardNewMacro(vtkLightBoxRendererManager);
+
+namespace
+{
+//-----------------------------------------------------------------------------
+// RenderWindowItem
+//-----------------------------------------------------------------------------
+/// A RenderWindow can be split in 1x1, 2x3, ... grid view, each element of that grid
+/// will be identified as RenderWindowItem
+class RenderWindowItem
+{
+public:
+  RenderWindowItem(const double rendererBackgroundColor[3], double colorWindow, double colorLevel);
+  void SetViewport(double xMin, double yMin, double viewportWidth, double viewportHeight);
+
+  /// Create the actor supporing the image mapper
+  void SetupImageMapperActor(double colorWindow, double colorLevel);
+
+  /// Create a box around the renderer.
+  void SetupHighlightBoxActor(bool visible = false);
+
+  vtkSmartPointer<vtkRenderer>                Renderer;
+  vtkSmartPointer<vtkImageMapper>             ImageMapper;
+  vtkSmartPointer<vtkActor2D>                 HighlightBoxActor;
+};
+}
+
+// --------------------------------------------------------------------------
+// RenderWindowItem methods
+
+//-----------------------------------------------------------------------------
+RenderWindowItem::RenderWindowItem(const double rendererBackgroundColor[3],
+                                   double colorWindow, double colorLevel)
+{
+  // Instanciate a renderer
+  this->Renderer = vtkSmartPointer<vtkRenderer>::New();
+  this->Renderer->SetBackground(rendererBackgroundColor[0],
+                                rendererBackgroundColor[1],
+                                rendererBackgroundColor[2]);
+
+  this->SetupImageMapperActor(colorWindow, colorLevel);
+  this->SetupHighlightBoxActor();
+}
+
+//-----------------------------------------------------------------------------
+void RenderWindowItem::SetViewport(double xMin, double yMin,
+                                   double viewportWidth, double viewportHeight)
+{
+  assert(this->Renderer);
+  this->Renderer->SetViewport( xMin, yMin, (xMin + viewportWidth), (yMin + viewportHeight));
+}
+
+//---------------------------------------------------------------------------
+void RenderWindowItem::SetupImageMapperActor(double colorWindow, double colorLevel)
+{
+  assert(this->Renderer);
+  assert(!this->ImageMapper);
+
+  // Instanciate an image mapper
+  this->ImageMapper = vtkSmartPointer<vtkImageMapper>::New();
+  this->ImageMapper->SetColorWindow(colorWindow);
+  this->ImageMapper->SetColorLevel(colorLevel);
+
+  // .. and its corresponding 2D actor
+  VTK_CREATE(vtkActor2D, actor2D);
+  actor2D->SetMapper(this->ImageMapper);
+  actor2D->GetProperty()->SetDisplayLocationToBackground();
+
+  // .. and add it to the renderer
+  this->Renderer->AddActor2D(actor2D);
+}
+
+//---------------------------------------------------------------------------
+void RenderWindowItem::SetupHighlightBoxActor(bool visible)
+{
+  assert(this->Renderer);
+  assert(!this->HighlightBoxActor);
+  
+  // Create a highlight actor (2D box around viewport)
+  VTK_CREATE(vtkPolyData, poly);
+  VTK_CREATE(vtkPoints, points);
+  double eps = 0.0;
+  points->InsertNextPoint(eps, eps, 0);
+  points->InsertNextPoint(1, eps, 0);
+  points->InsertNextPoint(1, 1, 0);
+  points->InsertNextPoint(eps, 1, 0);
+
+  VTK_CREATE(vtkCellArray, cells);
+  cells->InsertNextCell(5);
+  cells->InsertCellPoint(0);
+  cells->InsertCellPoint(1);
+  cells->InsertCellPoint(2);
+  cells->InsertCellPoint(3);
+  cells->InsertCellPoint(0);
+  poly->SetPoints(points);
+  poly->SetLines(cells);
+
+  VTK_CREATE(vtkCoordinate, coordinate);
+  coordinate->SetCoordinateSystemToNormalizedViewport();
+  coordinate->SetViewport(this->Renderer);
+
+  VTK_CREATE(vtkPolyDataMapper2D, polyDataMapper);
+  polyDataMapper->SetInput(poly);
+  polyDataMapper->SetTransformCoordinate(coordinate);
+
+  this->HighlightBoxActor = vtkSmartPointer<vtkActor2D>::New();
+  this->HighlightBoxActor->SetMapper(polyDataMapper);
+  this->HighlightBoxActor->GetProperty()->SetColor(1, 1, 0);
+  this->HighlightBoxActor->GetProperty()->SetDisplayLocationToForeground();
+  this->HighlightBoxActor->GetProperty()->SetLineWidth(3); // wide enough so not clipped
+  this->HighlightBoxActor->SetVisibility(visible);
+
+  this->Renderer->AddActor2D(this->HighlightBoxActor);
+}
+
+//-----------------------------------------------------------------------------
+// vtkInternal
+//-----------------------------------------------------------------------------
+class vtkLightBoxRendererManager::vtkInternal
+{
+public:
+  vtkInternal(vtkLightBoxRendererManager* external);
+  ~vtkInternal();
+
+  /// Convenient setup methods
+  void SetupCornerAnnotation();
+  void setupRendering();
+
+  /// Update render window ImageMapper Z slice according to \a layoutType
+  void updateRenderWindowItemsZIndex(int layoutType);
+
+  vtkSmartPointer<vtkRenderWindow>              RenderWindow;
+  int                                           RenderWindowRowCount;
+  int                                           RenderWindowColumnCount;
+  int                                           RenderWindowLayoutType;
+  vtkWeakPointer<vtkRenderWindowInteractor>     CurrentInteractor;
+  vtkSmartPointer<vtkCornerAnnotation>          CornerAnnotation;
+
+  vtkWeakPointer<vtkImageData>                  ImageData;
+  double                                        ColorWindow;
+  double                                        ColorLevel;
+  double                                        RendererBackgroundColor[3];
+
+  /// Collection of RenderWindowItem
+  std::vector<RenderWindowItem* >                  RenderWindowItemList;
+  
+  /// .. and its associated convenient typedef
+  typedef std::vector<RenderWindowItem*>::iterator RenderWindowItemListIt;
+  
+  /// Reference to the public interface
+  vtkLightBoxRendererManager*                         External;
+};
+
+// --------------------------------------------------------------------------
+// vtkInternal methods
+
+// --------------------------------------------------------------------------
+vtkLightBoxRendererManager::vtkInternal::vtkInternal(vtkLightBoxRendererManager* external):
+  External(external)
+{
+  this->CornerAnnotation = vtkSmartPointer<vtkCornerAnnotation>::New();
+  this->RenderWindowRowCount = 0;
+  this->RenderWindowColumnCount = 0;
+  this->RenderWindowLayoutType = vtkLightBoxRendererManager::LeftRightTopBottom;
+  this->ColorWindow = 255;
+  this->ColorLevel = 127.5;
+  // Default background color: black
+  this->RendererBackgroundColor[0] = 0.0;
+  this->RendererBackgroundColor[1] = 0.0;
+  this->RendererBackgroundColor[2] = 0.0;
+}
+
+// --------------------------------------------------------------------------
+vtkLightBoxRendererManager::vtkInternal::~vtkInternal()
+{
+  for(RenderWindowItemListIt it = this->RenderWindowItemList.begin();
+      it != this->RenderWindowItemList.end();
+      ++it)
+    {
+    delete *it;
+    }
+  this->RenderWindowItemList.clear();
+}
+
+// --------------------------------------------------------------------------
+void vtkLightBoxRendererManager::vtkInternal::SetupCornerAnnotation()
+{
+  for(RenderWindowItemListIt it = this->RenderWindowItemList.begin();
+      it != this->RenderWindowItemList.end();
+      ++it)
+    {
+    if (!(*it)->Renderer->HasViewProp(this->CornerAnnotation))
+      {
+      (*it)->Renderer->AddViewProp(this->CornerAnnotation);
+      this->CornerAnnotation->SetMaximumLineHeight(0.07);
+      vtkTextProperty *tprop = this->CornerAnnotation->GetTextProperty();
+      tprop->ShadowOn();
+      }
+    this->CornerAnnotation->ClearAllTexts();
+    }
+}
+
+//---------------------------------------------------------------------------
+void vtkLightBoxRendererManager::vtkInternal::setupRendering()
+{
+  assert(this->RenderWindow);
+  
+  this->RenderWindow->GetRenderers()->RemoveAllItems();
+
+  // Compute the width and height of each RenderWindowItem
+  double viewportWidth  = 1.0 / static_cast<double>(this->RenderWindowColumnCount);
+  double viewportHeight = 1.0 / static_cast<double>(this->RenderWindowRowCount);
+
+  // Postion of the Top-Left corner of the RenderWindowItem
+  float xMin, yMin;
+
+  // Loop through RenderWindowItem
+  for ( int rowId = 0; rowId < this->RenderWindowRowCount; ++rowId )
+    {
+    yMin = (this->RenderWindowRowCount - 1 - rowId) * viewportHeight;
+    xMin = 0.0;
+
+    for ( int columnId = 0; columnId < this->RenderWindowColumnCount; ++columnId )
+      {
+      // Get reference to the renderWindowItem
+      RenderWindowItem * item  =
+          this->RenderWindowItemList.at(
+              this->External->ComputeRenderWindowItemId(rowId, columnId));
+
+      // Set viewport
+      item->SetViewport(xMin, yMin, viewportWidth, viewportHeight);
+
+      // Add to RenderWindow
+      this->RenderWindow->AddRenderer(item->Renderer);
+
+      xMin += viewportWidth;
+      }
+    }
+}
+
+// --------------------------------------------------------------------------
+void vtkLightBoxRendererManager::vtkInternal::updateRenderWindowItemsZIndex(int layoutType)
+{
+  for (int rowId = 0; rowId < this->RenderWindowRowCount; ++rowId)
+    {
+    for (int columnId = 0; columnId < this->RenderWindowColumnCount; ++columnId)
+      {
+      int itemId = this->External->ComputeRenderWindowItemId(rowId, columnId);
+      assert(itemId <= static_cast<int>(this->RenderWindowItemList.size()));
+
+      RenderWindowItem * item = this->RenderWindowItemList.at(itemId);
+      assert(item->ImageMapper->GetInput());
+
+      // Default to ctkVTKSliceView::LeftRightTopBottom
+      int zSliceIndex = rowId * this->RenderWindowColumnCount + columnId;
+
+      if (layoutType == vtkLightBoxRendererManager::LeftRightBottomTop)
+        {
+        zSliceIndex = (this->RenderWindowRowCount - rowId - 1) *
+                      this->RenderWindowColumnCount + columnId;
+        }
+
+      item->ImageMapper->SetZSlice(zSliceIndex);
+      }
+    }
+}
+
+//---------------------------------------------------------------------------
+// vtkLightBoxRendererManager methods
+
+// --------------------------------------------------------------------------
+vtkLightBoxRendererManager::vtkLightBoxRendererManager() : Superclass()
+{
+  this->Internal = new vtkInternal(this);
+}
+
+// --------------------------------------------------------------------------
+vtkLightBoxRendererManager::~vtkLightBoxRendererManager()
+{
+  delete this->Internal;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+}
+
+//----------------------------------------------------------------------------
+vtkRenderWindow* vtkLightBoxRendererManager::GetRenderWindow()
+{
+  return this->Internal->RenderWindow;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::Initialize(vtkRenderWindow* renderWindow)
+{
+  if (this->Internal->RenderWindow)
+    {
+    vtkWarningMacro( << "vtkLightBoxRendererManager has already been initialized");
+    return;
+    }
+  if (!renderWindow)
+    {
+    vtkErrorMacro("Failed to initialize vtkLightBoxRendererManager with a NULL renderWindow");
+    return;
+    }
+  this->Internal->RenderWindow = renderWindow;
+
+  // Set default Layout
+  this->SetRenderWindowLayout(1, 1); // Modified() is invoked by SetRenderWindowLayout
+}
+
+//----------------------------------------------------------------------------
+bool vtkLightBoxRendererManager::IsInitialized()
+{
+  return this->Internal->RenderWindow;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetImageData(vtkImageData* newImageData)
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetImageData failed - vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  vtkInternal::RenderWindowItemListIt it;
+  for(it = this->Internal->RenderWindowItemList.begin();
+      it != this->Internal->RenderWindowItemList.end();
+      ++it)
+    {
+    (*it)->ImageMapper->SetInput(newImageData);
+    }
+
+  if (newImageData)
+    {
+    this->Internal->updateRenderWindowItemsZIndex(this->Internal->RenderWindowLayoutType);
+    }
+
+  this->Internal->ImageData = newImageData;
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+vtkCamera* vtkLightBoxRendererManager::GetActiveCamera()
+{
+  if (this->Internal->RenderWindowItemList.size() == 0)
+    {
+    return 0;
+    }
+
+  // Obtain reference of the first renderer
+  vtkRenderer * firstRenderer = this->Internal->RenderWindowItemList.at(0)->Renderer;
+  if (firstRenderer->IsActiveCameraCreated())
+    {
+    return firstRenderer->GetActiveCamera();
+    }
+  else
+    {
+    return 0;
+    }
+  return 0;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetActiveCamera(vtkCamera* newActiveCamera)
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetActiveCamera failed - vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  if (newActiveCamera == this->GetActiveCamera())
+    {
+    return;
+    }
+
+  newActiveCamera->ParallelProjectionOn();
+
+  vtkInternal::RenderWindowItemListIt it;
+  for(it = this->Internal->RenderWindowItemList.begin();
+      it != this->Internal->RenderWindowItemList.end();
+      ++it)
+    {
+    (*it)->Renderer->SetActiveCamera(newActiveCamera);
+    }
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::ResetCamera()
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "ResetCamera failed - vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  vtkInternal::RenderWindowItemListIt it;
+  for(it = this->Internal->RenderWindowItemList.begin();
+      it != this->Internal->RenderWindowItemList.end();
+      ++it)
+    {
+    (*it)->Renderer->ResetCamera();
+    }
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+int vtkLightBoxRendererManager::GetRenderWindowItemCount()
+{
+  return this->Internal->RenderWindowItemList.size();
+}
+
+//----------------------------------------------------------------------------
+vtkRenderer* vtkLightBoxRendererManager::GetRenderer(int id)
+{
+  if (id < 0 || id >= static_cast<int>(this->Internal->RenderWindowItemList.size()))
+    {
+    return 0;
+    }
+  return this->Internal->RenderWindowItemList.at(id)->Renderer;
+}
+
+//----------------------------------------------------------------------------
+vtkRenderer* vtkLightBoxRendererManager::GetRenderer(int rowId, int columnId)
+{
+  return this->GetRenderer(this->ComputeRenderWindowItemId(rowId, columnId));
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetRenderWindowLayoutType(int layoutType)
+{
+  if (this->Internal->RenderWindowLayoutType == layoutType)
+    {
+    return;
+    }
+
+  if (this->Internal->ImageData)
+    {
+    this->Internal->updateRenderWindowItemsZIndex(layoutType);
+    }
+
+  this->Internal->RenderWindowLayoutType = layoutType;
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+int vtkLightBoxRendererManager::GetRenderWindowLayoutType() const
+{
+  return this->Internal->RenderWindowLayoutType;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetRenderWindowLayout(int rowCount, int columnCount)
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetRenderWindowLayout failed - "
+                  "vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+
+  // Sanity checks
+  assert(rowCount >= 0 && columnCount >= 0);
+  if(!(rowCount >= 0 && columnCount >= 0))
+    {
+    return;
+    }
+
+  if (this->Internal->RenderWindowRowCount == rowCount && 
+      this->Internal->RenderWindowColumnCount == columnCount)
+    {
+    return;
+    }
+
+  int extraItem = (rowCount * columnCount) - this->Internal->RenderWindowItemList.size();
+  if (extraItem > 0)
+    {
+    //std::cout << "Creating " << extraItem << " RenderWindowItem";
+
+    // Create extra RenderWindowItem(s)
+    while(extraItem > 0)
+      {
+      RenderWindowItem * item =
+          new RenderWindowItem(this->Internal->RendererBackgroundColor, 
+                               this->Internal->ColorWindow, this->Internal->ColorLevel);
+      item->ImageMapper->SetInput(this->Internal->ImageData);
+      this->Internal->RenderWindowItemList.push_back(item);
+      --extraItem;
+      }
+    }
+  else
+    {
+    //std::cout << "Removing " << extraItem << " RenderWindowItem";
+
+    // Remove extra RenderWindowItem(s)
+    extraItem = extraItem >= 0 ? extraItem : -extraItem; // Compute Abs
+    while(extraItem > 0)
+      {
+      delete this->Internal->RenderWindowItemList.back();
+      this->Internal->RenderWindowItemList.pop_back();
+      --extraItem;
+      }
+    }
+
+  this->Internal->RenderWindowRowCount = rowCount;
+  this->Internal->RenderWindowColumnCount = columnCount;
+
+  this->Internal->setupRendering();
+  this->Internal->SetupCornerAnnotation();
+
+  if (this->Internal->ImageData)
+    {
+    this->Internal->updateRenderWindowItemsZIndex(this->Internal->RenderWindowLayoutType);
+    }
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetHighlightedById(int id, bool highlighted)
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetHighlightedById failed - vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  if (id < 0 || id >= static_cast<int>(this->Internal->RenderWindowItemList.size()))
+    {
+    return;
+    }
+  this->Internal->RenderWindowItemList.at(id)->HighlightBoxActor->SetVisibility(highlighted);
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetHighlighted(int rowId, int columnId, bool highlighted)
+{
+  this->SetHighlightedById(this->ComputeRenderWindowItemId(rowId, columnId), highlighted);
+}
+
+//----------------------------------------------------------------------------
+int vtkLightBoxRendererManager::ComputeRenderWindowItemId(int rowId, int columnId)
+{
+  return this->Internal->RenderWindowColumnCount * rowId + columnId;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetCornerAnnotationText(const std::string& text)
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetCornerAnnotationText failed - "
+                  "vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  if (text.compare(this->Internal->CornerAnnotation->GetText(2)) == 0)
+    {
+    return;
+    }
+
+  this->Internal->CornerAnnotation->ClearAllTexts();
+  this->Internal->CornerAnnotation->SetText(2, text.c_str());
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+const std::string vtkLightBoxRendererManager::GetCornerAnnotationText() const
+{
+  const char * text = this->Internal->CornerAnnotation->GetText(2);
+  return text ? text : "";
+}
+
+// --------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetBackgroundColor(const double newBackgroundColor[3])
+{
+  if (!this->IsInitialized())
+    {
+    vtkErrorMacro(<< "SetBackgroundColor failed - vtkLightBoxRendererManager is NOT initialized");
+    return;
+    }
+  vtkInternal::RenderWindowItemListIt it;
+  for(it = this->Internal->RenderWindowItemList.begin();
+      it != this->Internal->RenderWindowItemList.end();
+      ++it)
+    {
+    (*it)->Renderer->SetBackground(newBackgroundColor[0],
+                                   newBackgroundColor[1],
+                                   newBackgroundColor[2]);
+    }
+
+  this->Internal->RendererBackgroundColor[0] = newBackgroundColor[0];
+  this->Internal->RendererBackgroundColor[1] = newBackgroundColor[1];
+  this->Internal->RendererBackgroundColor[2] = newBackgroundColor[2];
+
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+double* vtkLightBoxRendererManager::GetBackgroundColor()const
+{
+  return this->Internal->RendererBackgroundColor;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetColorLevel(double colorLevel)
+{
+  this->SetColorWindowAndLevel(this->Internal->ColorWindow, colorLevel);
+}
+
+//----------------------------------------------------------------------------
+double vtkLightBoxRendererManager::GetColorLevel()const
+{
+  return this->Internal->ColorLevel;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetColorWindow(double colorWindow)
+{
+  this->SetColorWindowAndLevel(colorWindow, this->Internal->ColorLevel);
+}
+
+//----------------------------------------------------------------------------
+double vtkLightBoxRendererManager::GetColorWindow()const
+{
+  return this->Internal->ColorWindow;
+}
+
+//----------------------------------------------------------------------------
+void vtkLightBoxRendererManager::SetColorWindowAndLevel(double colorWindow, double colorLevel)
+{
+  if (this->Internal->ColorWindow == colorWindow &&
+      this->Internal->ColorLevel == colorLevel)
+    {
+    return;
+    }
+
+  vtkInternal::RenderWindowItemListIt it;
+  for(it = this->Internal->RenderWindowItemList.begin();
+      it != this->Internal->RenderWindowItemList.end();
+      ++it)
+    {
+    (*it)->ImageMapper->SetColorWindow(colorWindow);
+    (*it)->ImageMapper->SetColorLevel(colorLevel);
+    }
+
+  this->Internal->ColorWindow = colorWindow;
+  this->Internal->ColorLevel = colorLevel;
+
+  this->Modified();
+}
+

+ 122 - 0
Libs/Visualization/VTK/Core/vtkLightBoxRendererManager.h

@@ -0,0 +1,122 @@
+#ifndef __vtkLightBoxRendererManager_h
+#define __vtkLightBoxRendererManager_h
+
+#include <vtkObject.h>
+
+#include "CTKVisualizationVTKCoreExport.h"
+
+class vtkRenderWindow;
+class vtkRenderer;
+class vtkImageData;
+class vtkCamera;
+
+class CTK_VISUALIZATION_VTK_CORE_EXPORT vtkLightBoxRendererManager : public vtkObject
+{
+  vtkTypeRevisionMacro(vtkLightBoxRendererManager,vtkObject);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  static vtkLightBoxRendererManager *New();
+
+  void Initialize(vtkRenderWindow* renderWindow);
+
+  bool IsInitialized();
+
+  /// Get associated RenderWindow
+  vtkRenderWindow* GetRenderWindow();
+
+  /// Set image data
+  void SetImageData(vtkImageData* newImageData);
+
+  /// Get active camera
+  /// Note that the same camera is used with all the renderWindowItem
+  vtkCamera* GetActiveCamera();
+
+  /// Set actice camera
+  void SetActiveCamera(vtkCamera* newActiveCamera);
+
+  /// Reset cameras associated with all renderWindowItem
+  void ResetCamera();
+  
+  /// Return number of underlying render window Item
+  /// \note In the current implementation
+  int GetRenderWindowItemCount();
+  
+  /// Get a reference to the associated vtkRenderer(s) identified by its \a id
+  vtkRenderer* GetRenderer(int id);
+  
+  /// Get a reference to the associated vtkRenderer(s) given its position in the grid
+  /// \sa GetRenderer(int)
+  vtkRenderer* GetRenderer(int rowId, int columnId);
+  
+  /// The layout type determines how the image slices should be displayed
+  /// within the different render view items.
+  /// \sa SetRenderWindowLayout() GetRenderWindowLayoutType()
+  enum RenderWindowLayoutType{LeftRightTopBottom = 0, LeftRightBottomTop};
+  
+  /// Get current layout type
+  int GetRenderWindowLayoutType() const;
+  
+  /// Set current \a layoutType
+  void SetRenderWindowLayoutType(int layoutType);
+
+  /// Split the current vtkRenderWindow in \a rowCount per \a columnCount grid
+  void SetRenderWindowLayout(int rowCount, int columnCount);
+
+  /// Highlight / Unhighlight a render view item given its \a id
+  void SetHighlightedById(int id, bool highlighted);
+
+  ///  Highlight / Unhighlight a render view item given its position in the grid
+  /// \sa setHighlighted(int, bool)
+  void SetHighlighted(int rowId, int columnId, bool highlighted);
+  
+  /// Convenient function allowing to compute the renderWindowItemId
+  /// given \a rowId and \a columnId.
+  /// The following formula is used: ColumnCount * rowId + columnId
+  /// \note The \a rowCount and \a columnCount correspond to the one set
+  /// using setRenderWindowLayout.
+  inline int ComputeRenderWindowItemId(int rowId, int columnId);
+  
+  /// Set corner annotation \a text
+  void SetCornerAnnotationText(const std::string& text);
+
+  /// Get current corner annotation
+  const std::string GetCornerAnnotationText()const;
+
+  /// Set background color
+  void SetBackgroundColor(const double newBackgroundColor[3]);
+
+  /// Get background color
+  double* GetBackgroundColor()const;
+
+  /// Set color level
+  void SetColorLevel(double colorLevel);
+
+  /// Get color level
+  double GetColorLevel()const;
+
+  /// Set color window
+  void SetColorWindow(double colorWindow);
+
+  /// Get color window
+  double GetColorWindow()const;
+
+  /// Set color Window and color level
+  void SetColorWindowAndLevel(double colorWindow, double colorLevel);
+  
+protected:
+
+  vtkLightBoxRendererManager();
+  ~vtkLightBoxRendererManager();
+  
+private:
+  vtkLightBoxRendererManager(const vtkLightBoxRendererManager&); // Not implemented.
+  void operator=(const vtkLightBoxRendererManager&);             // Not implemented.
+  
+//BTX
+  class vtkInternal;
+  vtkInternal* Internal;
+//ETX
+
+};
+
+#endif
+