]> Creatis software - openheart.git/blobdiff - Applications/OpenHeartGui.cxx
commit all the files for the first time
[openheart.git] / Applications / OpenHeartGui.cxx
diff --git a/Applications/OpenHeartGui.cxx b/Applications/OpenHeartGui.cxx
new file mode 100644 (file)
index 0000000..24c324b
--- /dev/null
@@ -0,0 +1,2491 @@
+/**
+* Progam made by Olivier Bernard, associate professor
+* at Institut National des Sciences Appliquees (INSA) Lyon,
+* CREATIS Laboratory,
+* 69621 Villeurbanne, France,
+* 07th of May 2014
+*/
+
+#include "OpenHeartGui.h"
+
+#include <vtkObjectFactory.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderer.h>
+#include <vtkImageData.h>
+#include <vtkTextProperty.h>
+#include <vtkProperty.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderer.h>
+#include <vtkInteractorStyleTrackballCamera.h>
+#include <vtkCamera.h>
+#include <vtkImageGaussianSmooth.h>
+#include <vtkMarchingCubes.h>
+#include <vtkDataSetMapper.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkCutter.h>
+#include <vtkSphereSource.h>
+#include <vtkInteractorStyleSwitch.h>
+#include <vtkTextMapper.h>
+#include <vtkMath.h>
+#include <vtkMetaImageWriter.h>
+#include <vtkDepthSortPolyData.h>
+#include <vtkTimerLog.h>
+#include <vtkTransform.h>
+#include <vtkTransformPolyDataFilter.h>
+#include <vtkContextView.h>
+#include <vtkTable.h>
+#include <vtkFloatArray.h>
+#include <vtkChartXY.h>
+#include <vtkPlot.h>
+#include <vtkContextScene.h>
+#include <vtkAxis.h>
+#include <vtkCamera.h>
+#include <vtkAxesActor.h>
+#include <vtkOrientationMarkerWidget.h>
+#include <vtkCaptionActor2D.h>
+#include <vtkMetaImageReader.h>
+#include <vtkImageCast.h>
+#include <vtkUnstructuredGridReader.h>
+#include <vtkUnstructuredGrid.h>
+#include <vtkGenericDataObjectReader.h>
+#include <vtkCellArray.h>
+#include <vtkXMLPolyDataReader.h>
+#include <vtkPolyDataReader.h>
+#include <vtkUnstructuredGridGeometryFilter.h>
+#include <vtkDepthSortPolyData.h>
+#include <vtkLineSource.h>
+#include <vtkSmartPointer.h>
+#include <vtkIntersectionPolyDataFilter.h>
+#include <vtkTriangleFilter.h>
+#include <vtkImageData.h>
+#include <vtkImageReslice.h>
+#include <vtkImageMapper.h>
+#include <vtkSphereSource.h>
+#include <vtkLine.h>
+#include <vtkOutlineFilter.h>
+#include "vtkMyInteractorStyleTrackballCameraOpenHeart.h"
+#include "vtkMyInteractorStyleTrackballCameraOpenHeartXY.h"
+#include "vtkMyInteractorStyleTrackballCameraOpenHeartXZ.h"
+#include "vtkMyInteractorStyleTrackballCameraOpenHeartYZ.h"
+#include <QResizeEvent>
+#include <QPalette>
+
+
+#define CONFIG_FILE "../../Config/ConfigOpenHeart.txt"
+
+
+// ****************************************************************
+// ****************************************************************
+// ****************************************************************
+class vtkMyChartXY : public vtkChartXY
+{
+
+    bool MouseButtonPressEvent(const vtkContextMouseEvent &mouse) { return true; }
+    bool MouseWheelEvent(const vtkContextMouseEvent &mouse, int delta) { return true; }
+    bool MouseMoveEvent(const vtkContextMouseEvent &mouse) { return true; }
+    bool MouseButtonReleaseEvent(const vtkContextMouseEvent &mouse) { return true; }
+
+};
+
+
+// ****************************************************************
+// ****************************************************************
+// ****************************************************************
+OpenHeartGui::OpenHeartGui()
+{
+
+    /// Initialize window
+    this->setupUi(this);
+    this->InstantiateQtVtkRenderers();
+
+    /// Set colors of the interface
+    this->SetInterfaceColors();
+
+    /// Allocate attributes
+    for ( int k=0; k<3; k++ )
+        this->Dims[k] = 0;
+    this->PreviousFrame = 0;
+    this->CurrentFrame = 0;
+    this->NumberOfVolumes = 0;
+    this->ImageData = 0;
+    this->TableChart = 0;
+    this->Properties = new RendererProperties;
+    this->ViewButton = 0;
+    this->MeshRepresentation = 0;
+    this->MeshColor = 0;
+    this->ZoomLabel = 1.6;
+    this->ZoomMain = 1.5;
+    this->RotationMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
+    this->RotationMatrix->Identity();
+    this->TransformViewOrientation = vtkSmartPointer<vtkTransform>::New();
+    this->RotationMatrixInv = vtkSmartPointer<vtkMatrix4x4>::New();
+    this->RotationMatrixInv->Identity();
+    this->TransformViewOrientationInv = vtkSmartPointer<vtkTransform>::New();
+    this->OrientationWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
+
+    /// Flag management
+    this->FlagInterpolation = 0;
+    this->FlagDisplayMesh = 0;
+    this->FlagDisplayMeshContours = 0;
+    this->FlagDisplayMeshContourX = 0;
+    this->FlagDisplayMeshContourY = 0;
+    this->FlagDisplayMeshContourZ = 0;
+    this->FlagLoopEndToBegin = 0;
+    this->FlagLoopBeginToEnd = 0;
+    this->FlagPlay = 0;
+    this->FlagDisplayText = 1;
+    this->FlagHidePlan = 0;
+    this->FlagLongAxis = 0;
+    this->FlagDisplayApexPoint = 0;
+    this->FlagDisplayBasalPoint = 0;
+    this->FlagDisplayMeshContours = 1;
+    this->FlagDisplayLongAxis = 0;
+    this->FlagReslice = 0;
+
+    /// Widget management
+    this->InitPickers();
+    this->InitProperties();
+    this->InitWidgets();
+    this->SetCustomInteractorStyle();
+
+    /// Read 3D volume and create corresponding OpenHeart
+    std::ifstream file(CONFIG_FILE, std::ifstream::in);
+    std::string inputFilename;
+    file >> inputFilename;
+    file >> this->NumberOfVolumes;
+
+    /// Load sequence of volumes
+    this->CreateFromSequenceDataPointer(inputFilename);
+
+    /// Manage main window display
+    /// Force to view XZ orientation at initialization
+    this->ForceXZView();
+
+    /// Initialize text displayed in the main window
+    this->InitTexts();
+
+    /// Initialize the orientation axes after rendering the volume
+    this->InitOrientationAxes();
+
+    /// Manage XY window display
+    this->qVTKXY->GetRenderWindow()->Render();
+
+    /// Manage XZ window display
+    this->qVTKXZ->GetRenderWindow()->Render();
+
+    /// Manage YZ window display
+    this->qVTKYZ->GetRenderWindow()->Render();
+
+    /// Manage scrollbar
+    this->scrollBar->setMaximum(this->NumberOfVolumes-1);
+    this->SliderMeshAlpha->setMaximum(100);
+    this->SliderMeshAlpha->setSingleStep(1);
+    this->SliderMeshAlpha->setValue(20);
+
+    /// Initialized the chart part of the interface
+    this->ViewChart = vtkSmartPointer<vtkContextView>::New();
+    this->ViewChart->SetInteractor(this->qVTKChart->GetInteractor());
+    this->qVTKChart->SetRenderWindow(this->ViewChart->GetRenderWindow());
+    this->qVTKChart->GetRenderWindow()->SetSize(478,478);
+    this->ViewChart->GetRenderer()->SetBackground(255./255.,255./255.,255./255.);
+    this->InitChar();
+
+    /// Instantiate timer for the player
+    Timer = new QTimer(this);
+
+    /// Instantiate Qt events
+    connect(this->scrollBar, SIGNAL(valueChanged(int)), this, SLOT(slotRefreshViewer(int)));
+    connect(this->SliderMeshAlpha, SIGNAL(valueChanged(int)), this, SLOT(slotMeshAlpha(int)));
+    connect(this->pushButtonPlay, SIGNAL(clicked()), this, SLOT(slotPlay()));
+    connect(this->pushButtonXY, SIGNAL(clicked()), this, SLOT(slotXYView()));
+    connect(this->pushButtonXZ, SIGNAL(clicked()), this, SLOT(slotXZView()));
+    connect(this->pushButtonYZ, SIGNAL(clicked()), this, SLOT(slotYZView()));
+    connect(this->pushButton3D, SIGNAL(clicked()), this, SLOT(slot3DView()));
+    connect(this->pushButtonMesh, SIGNAL(clicked()), this, SLOT(slotMeshView()));
+    connect(this->pushButtonMeshRepresentation, SIGNAL(clicked()), this, SLOT(slotMeshRepresentation()));
+    connect(this->pushButtonMeshColor, SIGNAL(clicked()), this, SLOT(slotMeshColor()));
+    connect(this->pushButtonCutter, SIGNAL(clicked()), this, SLOT(slotMeshCutter()));
+    connect(this->Timer, SIGNAL(timeout()), this, SLOT(slotTimerEvent()));
+    connect(this->tabWidgetOption, SIGNAL(currentChanged(int)), this, SLOT(slotTabChange(int)));
+    connect(this->pushButtonBasalPoint, SIGNAL(clicked()), this, SLOT(slotBasalPoint()));
+    connect(this->pushButtonApexPoint, SIGNAL(clicked()), this, SLOT(slotApexPoint()));
+    connect(this->pushButtonReslice, SIGNAL(clicked()), this, SLOT(slotReslice()));
+
+    /// Update coords as we move through the window
+    Connections = vtkEventQtSlotConnect::New();
+    Connections->Connect(this->qVTK->GetRenderWindow()->GetInteractor(),
+                        vtkCommand::MouseMoveEvent,
+                        this,
+                        SLOT(slotUpdateCoords(vtkObject*)));
+
+}
+
+
+OpenHeartGui::~OpenHeartGui()
+{
+
+  Connections->Delete();
+
+}
+
+
+void OpenHeartGui::InstantiateQtVtkRenderers()
+{
+
+    /// ****************************************************************
+    /// Create the main window
+    vtkSmartPointer<vtkRenderWindow> renwin = vtkSmartPointer<vtkRenderWindow>::New();
+    renwin->StereoCapableWindowOn();
+
+    /// Activate 3DConnexion device
+    this->qVTK->SetUseTDx(true);
+    this->qVTK->SetRenderWindow(renwin);
+
+    /// Initialize interactor
+    this->Interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
+    this->Interactor = static_cast<vtkRenderWindowInteractor *>(this->qVTK->GetInteractor()->GetRenderWindow()->GetInteractor());
+
+    /// Add a renderer
+    this->Ren = vtkSmartPointer<vtkRenderer>::New();
+    this->qVTK->GetRenderWindow()->AddRenderer(this->Ren);
+    this->Ren->SetBackground(0,0,0);
+    this->Ren->GetActiveCamera()->SetParallelProjection(1);
+
+
+    /// ****************************************************************
+    /// Create XY window
+    vtkSmartPointer<vtkRenderWindow> renwinXY = vtkSmartPointer<vtkRenderWindow>::New();
+    renwinXY->StereoCapableWindowOn();
+
+    /// Activate 3DConnexion device
+    this->qVTKXY->SetUseTDx(true);
+    this->qVTKXY->SetRenderWindow(renwinXY);
+
+    /// Initialize interactor
+    this->InteractorXY = vtkSmartPointer<vtkRenderWindowInteractor>::New();
+    this->InteractorXY = static_cast<vtkRenderWindowInteractor *>(this->qVTKXY->GetInteractor()->GetRenderWindow()->GetInteractor());
+
+    /// Add a renderer
+    this->RenXY = vtkSmartPointer<vtkRenderer>::New();
+    this->qVTKXY->GetRenderWindow()->AddRenderer(this->RenXY);
+    this->RenXY->SetBackground(0,0,0);
+    this->RenXY->GetActiveCamera()->SetParallelProjection(1);
+
+
+    /// ****************************************************************
+    /// Create XZ window
+    vtkSmartPointer<vtkRenderWindow> renwinXZ = vtkSmartPointer<vtkRenderWindow>::New();
+    renwinXZ->StereoCapableWindowOn();
+
+    /// Activate 3DConnexion device
+    this->qVTKXZ->SetUseTDx(true);
+    this->qVTKXZ->SetRenderWindow(renwinXZ);
+
+    /// Initialize interactor
+    this->InteractorXZ = vtkSmartPointer<vtkRenderWindowInteractor>::New();
+    this->InteractorXZ = static_cast<vtkRenderWindowInteractor *>(this->qVTKXZ->GetInteractor()->GetRenderWindow()->GetInteractor());
+
+    /// Add a renderer
+    this->RenXZ = vtkSmartPointer<vtkRenderer>::New();
+    this->qVTKXZ->GetRenderWindow()->AddRenderer(this->RenXZ);
+    this->RenXZ->SetBackground(0,0,0);
+    this->RenXZ->GetActiveCamera()->SetParallelProjection(1);
+
+
+    /// ****************************************************************
+    /// Create YZ window
+    vtkSmartPointer<vtkRenderWindow> renwinYZ = vtkSmartPointer<vtkRenderWindow>::New();
+    renwinYZ->StereoCapableWindowOn();
+
+    /// Activate 3DConnexion device
+    this->qVTKYZ->SetUseTDx(true);
+    this->qVTKYZ->SetRenderWindow(renwinYZ);
+
+    /// Initialize interactor
+    this->InteractorYZ = static_cast<vtkRenderWindowInteractor *>(this->qVTKYZ->GetInteractor()->GetRenderWindow()->GetInteractor());
+
+    /// Add a renderer
+    this->RenYZ = vtkSmartPointer<vtkRenderer>::New();
+    this->qVTKYZ->GetRenderWindow()->AddRenderer(this->RenYZ);
+    this->RenYZ->SetBackground(0,0,0);
+    this->RenYZ->GetActiveCamera()->SetParallelProjection(1);
+
+}
+
+
+void OpenHeartGui::slotMeshView()
+{
+    this->HidePlanModeManagement();
+}
+
+
+void OpenHeartGui::slotYZView()
+{
+
+    this->ViewButton = 1;
+    this->Properties->xIPW->SetTextureVisibility(1);
+    this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->yIPW->SetTextureVisibility(0);
+    this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->zIPW->SetTextureVisibility(0);
+    this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
+
+    if ( this->FlagHidePlan == 0 )
+    {
+
+        /// Update corresponding viewer
+        int view = 2;
+        this->UpdateViewer(view,this->ZoomMain,this->Ren);
+
+        /// Also update Slice text
+        int slice = (int)( (this->Properties->position[0] - this->ImageData->GetOrigin()[0]) / this->ImageData->GetSpacing()[0] + 0.5f );
+        QString strSlice;
+        strSlice.sprintf("Slice: %d",slice);
+        this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
+
+    }
+    else {
+        this->FlagHidePlan = 0;
+    }
+
+    if ( this->FlagDisplayMeshContours == 1 )
+    {
+        this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+        this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+        this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slotXZView()
+{
+
+    this->ViewButton = 2;
+    this->Properties->xIPW->SetTextureVisibility(0);
+    this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->yIPW->SetTextureVisibility(1);
+    this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->zIPW->SetTextureVisibility(0);
+    this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
+
+    if ( this->FlagHidePlan == 0 )
+    {
+
+        /// Update corresponding viewer
+        int view = 1;
+        this->UpdateViewer(view,this->ZoomMain,this->Ren);
+
+        /// Also update Slice text
+        int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
+        QString strSlice;
+        strSlice.sprintf("Slice: %d",slice);
+        this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
+
+    }
+    else {
+        this->FlagHidePlan = 0;
+    }
+
+    if ( this->FlagDisplayMeshContours == 1 )
+    {
+        this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+        this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+        this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slotXYView()
+{
+
+    this->ViewButton = 3;
+    this->Properties->xIPW->SetTextureVisibility(0);
+    this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->yIPW->SetTextureVisibility(0);
+    this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->zIPW->SetTextureVisibility(1);
+    this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
+
+    if ( this->FlagHidePlan == 0 )
+    {
+
+        /// Update corresponding viewer
+        int view = 0;
+        this->UpdateViewer(view,this->ZoomMain,this->Ren);
+
+        /// Also update Slice text
+        int slice = (int)( (this->Properties->position[2] - this->ImageData->GetOrigin()[2]) / this->ImageData->GetSpacing()[2] + 0.5f );
+        QString strSlice;
+        strSlice.sprintf("Slice: %d",slice);
+        this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
+
+    }
+    else {
+        this->FlagHidePlan = 0;
+    }
+
+    if ( this->FlagDisplayMeshContours == 1 )
+    {
+        this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+        this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+        this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slot3DView()
+{
+
+    this->ViewButton = 0;
+    this->Properties->xIPW->SetTextureVisibility(1);
+    this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->xIPW->GetPlaneProperty()->SetColor(1,0,0);
+    this->Properties->yIPW->SetTextureVisibility(1);
+    this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->yIPW->GetPlaneProperty()->SetColor(1,1,0);
+    this->Properties->zIPW->SetTextureVisibility(1);
+    this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->zIPW->GetTextProperty()->SetColor(1,0,0);
+    this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,1);
+
+    if ( this->FlagHidePlan == 0 )
+    {
+
+        this->Ren->ResetCamera();
+        this->Ren->GetActiveCamera()->Zoom(1.);
+
+        if ( this->Properties->MeshActor != 0 )
+        {
+            if ( this->FlagDisplayMesh == 0 ) {
+                this->FlagDisplayMesh = 1;
+                this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            }
+        }
+
+    }
+    else {
+        this->FlagHidePlan = 0;
+    }
+    this->GetRenderWindow()->Render();
+
+}
+
+
+void OpenHeartGui::slotMeshRepresentation()
+{
+
+    if ( this->Properties->MeshActor )
+    {
+
+        if ( this->FlagDisplayMeshContours == 1 )
+        {
+            this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+            this->FlagDisplayMeshContours = 0;
+            this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 1;
+        }
+        switch (this->MeshRepresentation) {
+        case 0:
+            this->MeshRepresentation = 1;
+            this->pushButtonMeshRepresentation->setText("Surface");
+            this->Properties->MeshActor->GetProperty()->SetRepresentationToPoints();
+            break;
+        case 1:
+            this->MeshRepresentation = 2;
+            this->pushButtonMeshRepresentation->setText("No mesh");
+            this->Properties->MeshActor->GetProperty()->SetRepresentationToSurface();
+            break;
+        case 2:
+            this->MeshRepresentation = 3;
+            this->pushButtonMeshRepresentation->setText("Wire");
+            this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 0;
+            break;
+        case 3:
+            this->MeshRepresentation = 0;
+            this->pushButtonMeshRepresentation->setText("Points");
+            this->Properties->MeshActor->GetProperty()->SetRepresentationToWireframe();
+            this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 1;
+            break;
+        default:
+            break;
+        }
+        this->GetRenderWindow()->Render();
+
+    }
+
+}
+
+
+
+void OpenHeartGui::slotMeshColor()
+{
+
+    if ( this->Properties->MeshActor ) {
+        if ( this->MeshColor == 0 ) {
+            this->MeshColor = 1;
+            this->pushButtonMeshColor->setText("Color R");
+            this->Properties->MeshActor->GetProperty()->SetColor(1,1,0);
+            //this->Properties->xCutActor->GetProperty()->SetColor(1,1,0);
+            //this->Properties->yCutActor->GetProperty()->SetColor(1,1,0);
+            //this->Properties->zCutActor->GetProperty()->SetColor(1,1,0);
+        }
+        else if ( this->MeshColor == 1 ) {
+            this->MeshColor = 2;
+            this->pushButtonMeshColor->setText("Color G");
+            this->Properties->MeshActor->GetProperty()->SetColor(1,0,0);
+            //this->Properties->xCutActor->GetProperty()->SetColor(1,0,0);
+            //this->Properties->yCutActor->GetProperty()->SetColor(1,0,0);
+            //this->Properties->zCutActor->GetProperty()->SetColor(1,0,0);
+        }
+        else if ( this->MeshColor == 2 ) {
+            this->MeshColor = 3;
+            this->pushButtonMeshColor->setText("Color B");
+            this->Properties->MeshActor->GetProperty()->SetColor(0,1,0);
+            //this->Properties->xCutActor->GetProperty()->SetColor(0,1,0);
+            //this->Properties->yCutActor->GetProperty()->SetColor(0,1,0);
+            //this->Properties->zCutActor->GetProperty()->SetColor(0,1,0);
+        }
+        else if ( this->MeshColor == 3 ) {
+            this->MeshColor = 4;
+            this->pushButtonMeshColor->setText("Color W");
+            this->Properties->MeshActor->GetProperty()->SetColor(0,0,1);
+            //this->Properties->xCutActor->GetProperty()->SetColor(0,0,1);
+            //this->Properties->yCutActor->GetProperty()->SetColor(0,0,1);
+            //this->Properties->zCutActor->GetProperty()->SetColor(0,0,1);
+        }
+        else if ( this->MeshColor == 4 ) {
+            this->MeshColor = 0;
+            this->pushButtonMeshColor->setText("Color Y");
+            this->Properties->MeshActor->GetProperty()->SetColor(1,1,1);
+            //this->Properties->xCutActor->GetProperty()->SetColor(1,1,1);
+            //this->Properties->yCutActor->GetProperty()->SetColor(1,1,1);
+            //this->Properties->zCutActor->GetProperty()->SetColor(1,1,1);
+        }
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slotMeshCutter()
+{
+
+    if ( this->Properties->MeshActor )
+    {
+        if ( this->FlagDisplayMeshContours == 1 )
+        {
+            this->FlagDisplayMeshContours = 0;
+            this->pushButtonCutter->setText("Cut on");
+            this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+            if ( this->FlagDisplayMesh == 0 ) {
+                this->FlagDisplayMesh = 1;
+                this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            }
+        }
+        else
+        {
+            if ( this->FlagDisplayMesh == 1 ) {
+                this->FlagDisplayMesh = 0;
+                this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
+            }
+            this->FlagDisplayMeshContours = 1;
+            this->pushButtonCutter->setText("Cut off");
+            switch (this->ViewButton) {
+            case 0:
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+                break;
+            case 1:
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+                break;
+            case 2:
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+                break;
+            case 3:
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+                break;
+            default:
+                break;
+            }
+            /*
+            if (this->ViewButton == 0) {
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+            }
+            else if (this->ViewButton == 1) {
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+            }
+            else if (this->ViewButton == 2) {
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+            }
+            else if (this->ViewButton == 3) {
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+            }
+            */
+        }
+        this->GetRenderWindow()->Render();
+    }
+
+
+}
+
+
+void OpenHeartGui::ForceXZView()
+{
+
+    this->ViewButton = 2;
+    this->Properties->xIPW->SetTextureVisibility(0);
+    this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
+    this->Properties->yIPW->SetTextureVisibility(1);
+    this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
+    this->Properties->zIPW->SetTextureVisibility(0);
+    this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
+
+    this->Ren->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
+                                                 this->ImageData->GetDimensions()[0]/2,
+                                                 this->ImageData->GetDimensions()[2]/2 );
+    this->Ren->GetActiveCamera()->SetPosition(   this->ImageData->GetDimensions()[0]/2,
+                                                 this->ImageData->GetDimensions()[1]*10,
+                                                 this->ImageData->GetDimensions()[0]/2 );
+    this->Ren->GetActiveCamera()->SetViewUp(0,0,-1);
+    this->Ren->ResetCamera();
+    this->Ren->GetActiveCamera()->Zoom(this->ZoomMain);
+    this->GetRenderWindow()->Render();
+
+}
+
+void OpenHeartGui::slotUpdateCoords(vtkObject* obj)
+{
+
+    if (this->FlagPlay == 0)
+    {
+
+        if ( (this->FlagDisplayText) && (this->Properties->TextMapperPixel) )
+        {
+
+            /// Get interactor
+            vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
+
+            // Get intensity value at the corresponding position
+            int X = iren->GetEventPosition()[0];
+            int Y = iren->GetEventPosition()[1];
+            this->Picker->Pick(X,Y,0.0,this->GetMeshRenderer());
+            double pos[3];
+            this->Picker->GetPickPosition( pos );
+            int pixel[3];
+            for ( int i=0; i<3; i++) {
+                pixel[i] = (int)( (pos[i] - this->ImageData->GetOrigin()[i]) / this->ImageData->GetSpacing()[i] + 0.5f );
+            }
+
+            if ( (pixel[0]>=0) && (pixel[0]<this->Dims[0]) &&
+                 (pixel[1]>=0) && (pixel[1]<this->Dims[1]) &&
+                 (pixel[2]>=0) && (pixel[2]<this->Dims[2]) )
+            {
+
+                /// Display Pixel coordinates
+                QString strPixel;
+                strPixel.sprintf("pixel: (%d %d %d)", pixel[0], pixel[1], pixel[2]);
+                this->Properties->TextMapperPixel->SetInput(strPixel.toStdString().c_str());
+
+                /// Display Pixel coordinates
+                QString strMM;
+                strMM.sprintf("mm:  (%.0f %.0f %.0f)", pos[0]*1000, pos[1]*1000, pos[2]*1000);
+                this->Properties->TextMapperMM->SetInput(strMM.toStdString().c_str());
+
+                QString strValue;
+                switch (this->ImageData->GetScalarType())
+                {
+                    case VTK_UNSIGNED_CHAR: {
+                        strValue.sprintf("data value: %u", static_cast<unsigned char*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_UNSIGNED_SHORT: {
+                        strValue.sprintf("data value: %u", static_cast<unsigned short*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_INT: {
+                        strValue.sprintf("data value: %d", static_cast<int*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_FLOAT: {
+                        strValue.sprintf("data value: %.1f", static_cast<float*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_DOUBLE: {
+                        strValue.sprintf("data value: %.1f", static_cast<double*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+
+                }
+                this->Properties->TextMapperValue->SetInput(strValue.toStdString().c_str());
+
+            }
+
+            else {
+                this->Properties->TextMapperPixel->SetInput("");
+                this->Properties->TextMapperMM->SetInput("");
+                this->Properties->TextMapperValue->SetInput("");
+            }
+
+        }
+
+        else
+        {
+            if ( this->Properties->TextMapperPixel )
+            {
+                this->Properties->TextMapperPixel->SetInput("");
+                this->Properties->TextMapperMM->SetInput("");
+                this->Properties->TextMapperValue->SetInput("");
+            }
+        }
+
+        this->GetRenderWindow()->Render();
+
+    }
+
+}
+
+
+void OpenHeartGui::UpdateCoords(double *pos)
+{
+
+    if (this->FlagPlay == 0)
+    {
+
+        if ( (this->FlagDisplayText) && (this->Properties->TextMapperPixel) )
+        {
+
+            int pixel[3];
+            for ( int i=0; i<3; i++) {
+                pixel[i] = (int)( (pos[i] - this->ImageData->GetOrigin()[i]) / this->ImageData->GetSpacing()[i] + 0.5f );
+            }
+
+            if ( (pixel[0]>=0) && (pixel[0]<this->Dims[0]) &&
+                 (pixel[1]>=0) && (pixel[1]<this->Dims[1]) &&
+                 (pixel[2]>=0) && (pixel[2]<this->Dims[2]) )
+            {
+
+                /// Display Pixel coordinates
+                QString strPixel;
+                strPixel.sprintf("pixel: (%d %d %d)", pixel[0], pixel[1], pixel[2]);
+                this->Properties->TextMapperPixel->SetInput(strPixel.toStdString().c_str());
+
+                /// Display Pixel coordinates
+                QString strMM;
+                strMM.sprintf("mm:  (%.0f %.0f %.0f)", pos[0]*1000, pos[1]*1000, pos[2]*1000);
+                this->Properties->TextMapperMM->SetInput(strMM.toStdString().c_str());
+
+                QString strValue;
+                switch (this->ImageData->GetScalarType())
+                {
+                    case VTK_UNSIGNED_CHAR: {
+                        strValue.sprintf("data value: %u", static_cast<unsigned char*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_UNSIGNED_SHORT: {
+                        strValue.sprintf("data value: %u", static_cast<unsigned short*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_INT: {
+                        strValue.sprintf("data value: %d", static_cast<int*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_FLOAT: {
+                        strValue.sprintf("data value: %.1f", static_cast<float*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                    case VTK_DOUBLE: {
+                        strValue.sprintf("data value: %.1f", static_cast<double*>(this->ImageData->GetScalarPointer(pixel))[0]);
+                        break;
+                    }
+                }
+                this->Properties->TextMapperValue->SetInput(strValue.toStdString().c_str());
+
+            }
+
+            else {
+                this->Properties->TextMapperPixel->SetInput("");
+                this->Properties->TextMapperMM->SetInput("");
+                this->Properties->TextMapperValue->SetInput("");
+            }
+
+        }
+        else
+        {
+            if ( this->Properties->TextMapperPixel )
+            {
+                this->Properties->TextMapperPixel->SetInput("");
+                this->Properties->TextMapperMM->SetInput("");
+                this->Properties->TextMapperValue->SetInput("");
+            }
+        }
+
+        this->GetRenderWindow()->Render();
+
+    }
+
+}
+
+
+void OpenHeartGui::InitChar()
+{
+
+    this->TableChart = vtkSmartPointer<vtkTable>::New();
+    vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
+    arrX->SetName("Number of frames");
+    this->TableChart->AddColumn(arrX);
+    vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
+    arrY->SetName("Volume");
+    this->TableChart->AddColumn(arrY);
+
+    int numPoints = this->NumberOfVolumes;
+    this->TableChart->SetNumberOfRows(numPoints);
+    for (int i=0; i<numPoints; ++i)
+    {
+        this->TableChart->SetValue(i, 0, i);
+        this->TableChart->SetValue(i, 1, 0);
+    }
+    // Add multiple line plots, setting the colors etc
+    vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
+    ViewChart->GetScene()->AddItem(chart);
+    chart->AddPlot(vtkChart::LINE);
+    vtkPlot *line = chart->AddPlot(vtkChart::LINE);
+    line->SetInput(this->TableChart, 0, 1);
+    line->SetColor(0, 0, 255, 255);
+    line->SetWidth(3.0);
+    chart->GetAxis(vtkAxis::LEFT)->SetTitle("Volume (mL)");
+    chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Frames");
+    chart->GetAxis(vtkAxis::LEFT)->SetNotation(2);
+    chart->GetAxis(vtkAxis::LEFT)->SetPrecision(1);
+
+}
+
+
+void OpenHeartGui::InitPickers()
+{
+    this->Picker = vtkSmartPointer<vtkCellPicker>::New();
+    this->Picker->SetTolerance(0.005);
+    this->Interactor->SetPicker(this->Picker);
+    this->PickerXY = vtkSmartPointer<vtkCellPicker>::New();
+    this->PickerXY->SetTolerance(0.005);
+    this->InteractorXY->SetPicker(this->PickerXY);
+    this->PickerXZ = vtkSmartPointer<vtkCellPicker>::New();
+    this->PickerXZ->SetTolerance(0.005);
+    this->InteractorXZ->SetPicker(this->PickerXZ);
+    this->PickerYZ = vtkSmartPointer<vtkCellPicker>::New();
+    this->PickerYZ->SetTolerance(0.005);
+    this->InteractorYZ->SetPicker(this->PickerYZ);
+
+}
+
+
+
+void OpenHeartGui::InitWidgets()
+{
+    /// ImagePlane Widget
+    this->InitPlaneWidget();
+}
+
+
+void OpenHeartGui::InitOrientationAxes()
+{
+    vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
+    axes->GetYAxisTipProperty()->SetColor(1,1,0);
+    axes->GetYAxisShaftProperty()->SetColor(1,1,0);
+    this->OrientationWidget->SetOrientationMarker( axes );
+    this->OrientationWidget->SetInteractor( this->qVTK->GetRenderWindow()->GetInteractor() );
+    this->OrientationWidget->SetViewport( 0.8, 0.0, 1.0, 0.2 );
+    this->OrientationWidget->SetEnabled( 1 );
+    this->OrientationWidget->InteractiveOff();
+}
+
+
+void OpenHeartGui::InitProperties()
+{
+    this->Properties->lut = 0;
+    this->Properties->xIPW = 0;
+    this->Properties->yIPW = 0;
+    this->Properties->zIPW = 0;
+    this->Properties->xyIPW = 0;
+    this->Properties->xzIPW = 0;
+    this->Properties->yzIPW = 0;
+    this->Properties->TextActorPixel = 0;
+    this->Properties->TextMapperPixel = 0;
+    this->Properties->TextActorMM = 0;
+    this->Properties->TextMapperMM = 0;
+    this->Properties->TextActorValue = 0;
+    this->Properties->TextMapperValue = 0;
+    this->Properties->TextActorSlice = 0;
+    this->Properties->TextMapperSlice = 0;
+    this->Properties->TextActorNumFrame = 0;
+    this->Properties->TextMapperNumFrame = 0;
+    this->Properties->TextActorResolution = 0;
+    this->Properties->TextMapperResolution = 0;
+    this->Properties->MeshActor = 0;
+    this->Properties->xCutActor = 0;
+    this->Properties->yCutActor = 0;
+    this->Properties->zCutActor = 0;
+    this->Properties->BasalPointActor = 0;
+    this->Properties->ApexPointActor = 0;
+    this->Properties->LongAxisActor = 0;
+    this->Properties->BoundingBoxActor = 0;
+    this->Properties->position = new double[3];
+}
+
+
+void OpenHeartGui::InitPlaneWidget()
+{
+
+    /// Manage main window
+    this->Properties->xIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
+    this->Properties->yIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
+    this->Properties->zIPW = vtkSmartPointer<vtkImagePlaneWidget>::New();
+
+    this->Properties->xIPW->SetInteractor(vtkRenderWindowInteractor::New());
+    this->Properties->yIPW->SetInteractor(this->Properties->xIPW->GetInteractor());
+    this->Properties->zIPW->SetInteractor(this->Properties->xIPW->GetInteractor());
+
+    this->Properties->xIPW->DisplayTextOn();
+    this->Properties->xIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->xIPW->SetPicker(this->Picker);
+    this->Properties->xIPW->RestrictPlaneToVolumeOn();
+    this->Properties->xIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->xIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->xIPW->TextureInterpolateOff();
+
+    this->Properties->yIPW->DisplayTextOn();
+    this->Properties->yIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->yIPW->SetPicker(this->Picker);
+    this->Properties->yIPW->RestrictPlaneToVolumeOn();
+    this->Properties->yIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->yIPW->SetTexturePlaneProperty(this->Properties->xIPW->GetTexturePlaneProperty());
+    this->Properties->yIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->yIPW->TextureInterpolateOff();
+
+    this->Properties->zIPW->DisplayTextOn();
+    this->Properties->zIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->zIPW->SetPicker(this->Picker);
+    this->Properties->zIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->zIPW->SetTexturePlaneProperty(this->Properties->xIPW->GetTexturePlaneProperty());
+    this->Properties->zIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->zIPW->TextureInterpolateOff();
+
+
+    /// Manage XY window
+    this->Properties->xyIPW = vtkImagePlaneWidget::New();
+    this->Properties->xyIPW->SetInteractor(vtkRenderWindowInteractor::New());
+    this->Properties->xyIPW->DisplayTextOn();
+    this->Properties->xyIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->xyIPW->SetPicker(this->PickerXY);
+    this->Properties->xyIPW->RestrictPlaneToVolumeOn();
+    this->Properties->xyIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->xyIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->xyIPW->TextureInterpolateOff();
+
+    /// Manage XZ window
+    this->Properties->xzIPW = vtkImagePlaneWidget::New();
+    this->Properties->xzIPW->SetInteractor(vtkRenderWindowInteractor::New());
+    this->Properties->xzIPW->DisplayTextOn();
+    this->Properties->xzIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->xzIPW->RestrictPlaneToVolumeOn();
+    this->Properties->xzIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->xzIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->xzIPW->TextureInterpolateOff();
+
+    /// Manage YZ window
+    this->Properties->yzIPW = vtkImagePlaneWidget::New();
+    this->Properties->yzIPW->SetInteractor(vtkRenderWindowInteractor::New());
+    this->Properties->yzIPW->DisplayTextOn();
+    this->Properties->yzIPW->GetTextProperty()->SetColor(0,0,0);
+    this->Properties->yzIPW->RestrictPlaneToVolumeOn();
+    this->Properties->yzIPW->GetPlaneProperty()->SetColor(0,0,0);
+    this->Properties->yzIPW->SetResliceInterpolateToNearestNeighbour();
+    this->Properties->yzIPW->TextureInterpolateOff();
+
+}
+
+void OpenHeartGui::InitTexts()
+{
+
+    /// Display pixel coordinates
+    this->Properties->TextActorPixel = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperPixel = vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperPixel->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperPixel->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        this->Properties->TextMapperPixel->SetInput("");
+    }
+    this->Properties->TextMapperPixel->GetTextProperty()->SetJustificationToRight();
+    this->Properties->TextMapperPixel->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorPixel->SetPosition(490,520);
+    this->Properties->TextActorPixel->SetMapper(this->Properties->TextMapperPixel);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorPixel);
+
+    /// Display mm coordinates
+    this->Properties->TextActorMM = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperMM= vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperMM->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperMM->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        this->Properties->TextMapperMM->SetInput("");
+    }
+    this->Properties->TextMapperMM->GetTextProperty()->SetJustificationToRight();
+    this->Properties->TextMapperMM->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorMM->SetPosition(490,495);
+    this->Properties->TextActorMM->SetMapper(this->Properties->TextMapperMM);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorMM);
+
+    /// Display data value
+    this->Properties->TextActorValue = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperValue = vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperValue->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperValue->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        this->Properties->TextMapperValue->SetInput("");
+    }
+    this->Properties->TextMapperValue->GetTextProperty()->SetJustificationToRight();
+    this->Properties->TextMapperValue->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorValue->SetPosition(490,470);
+    this->Properties->TextActorValue->SetMapper(this->Properties->TextMapperValue);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorValue);
+
+    /// Display Slice
+    this->Properties->TextActorSlice = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperSlice = vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperSlice->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperSlice->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
+        //cout << this->Properties->position[1] << endl;
+        QString strSlice;
+        strSlice.sprintf("Slice: %d",slice);
+        this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
+    }
+    this->Properties->TextMapperSlice->GetTextProperty()->SetJustificationToLeft();
+    this->Properties->TextMapperSlice->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorSlice->SetPosition(10,520);
+    this->Properties->TextActorSlice->SetMapper(this->Properties->TextMapperSlice);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorSlice);
+
+    /// Display frame number
+    this->Properties->TextActorNumFrame = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperNumFrame = vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperNumFrame->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperNumFrame->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        QString str;
+        str.sprintf("Frame: %d",this->CurrentFrame);
+        this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
+    }
+    this->Properties->TextMapperNumFrame->GetTextProperty()->SetJustificationToLeft();
+    this->Properties->TextMapperNumFrame->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorNumFrame->SetPosition(10, 45);
+    this->Properties->TextActorNumFrame->SetMapper(this->Properties->TextMapperNumFrame);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorNumFrame);
+
+    /// Display resolution value
+    this->Properties->TextActorResolution = vtkSmartPointer<vtkActor2D>::New();
+    this->Properties->TextMapperResolution = vtkSmartPointer<vtkTextMapper>::New();
+    this->Properties->TextMapperResolution->GetTextProperty()->SetColor(0, 1, 0);
+    this->Properties->TextMapperResolution->GetTextProperty()->SetFontSize(15);
+    if ( this->FlagDisplayText ) {
+        QString str;
+        str.sprintf("Resolution: %.2f x %.2f x %.2f mm",this->ImageData->GetSpacing()[0]*1000,this->ImageData->GetSpacing()[1]*1000,this->ImageData->GetSpacing()[2]*1000);
+        this->Properties->TextMapperResolution->SetInput(str.toStdString().c_str());
+    }
+    this->Properties->TextMapperResolution->GetTextProperty()->SetJustificationToLeft();
+    this->Properties->TextMapperResolution->GetTextProperty()->ShadowOff();
+    this->Properties->TextActorResolution->SetPosition(10, 20);
+    this->Properties->TextActorResolution->SetMapper(this->Properties->TextMapperResolution);
+    this->GetMeshRenderer()->AddActor(this->Properties->TextActorResolution);
+
+}
+
+
+void OpenHeartGui::SetCustomInteractorStyle()
+{
+
+    /// customize main interactor
+    vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeart> CustomInteractorStyle =
+            vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeart>::New();
+    CustomInteractorStyle->SetOpenHeartGui( this );
+    this->Interactor->SetInteractorStyle(CustomInteractorStyle);
+
+    /// customize XY interactor
+    vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXY> CustomInteractorStyleXY =
+            vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXY>::New();
+    CustomInteractorStyleXY->SetOpenHeartGui( this );
+    this->InteractorXY->SetInteractorStyle(CustomInteractorStyleXY);
+
+    /// customize XZ interactor
+    vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXZ> CustomInteractorStyleXZ =
+            vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartXZ>::New();
+    CustomInteractorStyleXZ->SetOpenHeartGui( this );
+    this->InteractorXZ->SetInteractorStyle(CustomInteractorStyleXZ);
+
+    /// customize YZ interactor
+    vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartYZ> CustomInteractorStyleYZ =
+            vtkSmartPointer<vtkMyInteractorStyleTrackballCameraOpenHeartYZ>::New();
+    CustomInteractorStyleYZ->SetOpenHeartGui( this );
+    this->InteractorYZ->SetInteractorStyle(CustomInteractorStyleYZ);
+
+}
+
+
+void OpenHeartGui::CreateFromSequenceDataPointer(std::string inputFilename)
+{
+
+    /// Read 3D volume
+    QString str;
+    for (int i=1; i<=this->NumberOfVolumes; i++)
+    {
+        if (i<10)
+            str.sprintf("%s0%d.mhd",inputFilename.c_str(),i);
+        else
+            str.sprintf("%s%d.mhd",inputFilename.c_str(),i);
+        vtkMetaImageReader *reader = vtkMetaImageReader::New();
+        reader->SetFileName(str.toStdString().c_str());
+        reader->Update();
+        this->StackVolume.push_back(reader->GetOutput());
+    }
+
+    /// Initialize attibute related to stack of volumes
+    this->itStackVolume = this->StackVolume.begin();
+    this->CurrentFrame = 0;
+    this->ImageData = (*this->itStackVolume);
+    double center[3];
+    for ( unsigned int k=0; k<3; k++ ) {
+        this->Dims[k] = this->ImageData->GetDimensions()[k];
+        center[k] = ((this->ImageData->GetDimensions()[k])*(this->ImageData->GetSpacing()[k]))/2;
+    }
+
+    /// Allocate lookuptable
+    double range[2];
+    this->ImageData->GetScalarRange(range);
+    int NumberOfColors = vtkMath::Round(range[1]-range[0]);
+    NumberOfColors++;
+    this->Properties->lut = vtkSmartPointer<vtkLookupTable>::New();
+    this->Properties->lut->SetNumberOfColors(NumberOfColors);
+    this->Properties->lut->SetValueRange(range[0]/NumberOfColors,range[1]/NumberOfColors);
+    this->Properties->lut->SetRampToLinear();
+    this->Properties->lut->SetSaturationRange(0.,0.);
+    this->Properties->lut->SetHueRange(0.,0.);
+
+    /// Manage main window
+    this->Properties->xIPW->SetCurrentRenderer(this->GetMainRenderer());
+    this->Properties->yIPW->SetCurrentRenderer(this->GetMainRenderer());
+    this->Properties->zIPW->SetCurrentRenderer(this->GetMainRenderer());
+
+    /// The 3 image plane widgets are used.
+    this->Properties->xIPW->SetInput(this->ImageData);
+    this->Properties->yIPW->SetInput(this->ImageData);
+    this->Properties->zIPW->SetInput(this->ImageData);
+
+    this->Properties->xIPW->SetPlaneOrientationToXAxes();
+    this->Properties->yIPW->SetPlaneOrientationToYAxes();
+    this->Properties->zIPW->SetPlaneOrientationToZAxes();
+
+    this->Properties->xIPW->SetSlicePosition(center[0]);
+    this->Properties->yIPW->SetSlicePosition(center[1]);
+    this->Properties->zIPW->SetSlicePosition(center[2]);
+
+    this->Properties->xIPW->SetLookupTable(this->Properties->lut);
+    this->Properties->yIPW->SetLookupTable(this->Properties->lut);
+    this->Properties->zIPW->SetLookupTable(this->Properties->lut);
+
+    this->Properties->position[0] = center[0];
+    this->Properties->position[1] = center[1];
+    this->Properties->position[2] = center[2];
+
+    this->Properties->xIPW->On();
+    this->Properties->yIPW->On();
+    this->Properties->zIPW->On();
+
+    /// Manage XY window
+    this->Properties->xyIPW->SetCurrentRenderer(this->GetXYRenderer());
+    this->Properties->xyIPW->SetInput(this->ImageData);
+    this->Properties->xyIPW->SetPlaneOrientationToZAxes();
+    this->Properties->xyIPW->SetSlicePosition(center[2]);
+    this->Properties->xyIPW->SetLookupTable(this->Properties->lut);
+    this->Properties->xyIPW->On();
+    this->RenXY->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
+                                                   this->ImageData->GetDimensions()[1]/2,
+                                                   this->ImageData->GetDimensions()[2]/2 );
+    this->RenXY->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]/2,
+                                                 this->ImageData->GetDimensions()[1]/2,
+                                                 this->ImageData->GetDimensions()[2]*10 );
+    this->RenXY->GetActiveCamera()->SetViewUp(0,0,-1);
+    this->RenXY->ResetCamera();
+    this->RenXY->GetActiveCamera()->Zoom(this->ZoomLabel);
+    this->GetRenderWindowXY()->Render();
+
+    /// Manage XZ window
+    this->Properties->xzIPW->SetCurrentRenderer(this->GetXZRenderer());
+    this->Properties->xzIPW->SetInput(this->ImageData);
+    this->Properties->xzIPW->SetPlaneOrientationToYAxes();
+    this->Properties->xzIPW->SetSlicePosition(center[1]);
+    this->Properties->xzIPW->SetLookupTable(this->Properties->lut);
+    this->Properties->xzIPW->On();
+    this->RenXZ->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
+                                                   this->ImageData->GetDimensions()[1]/2,
+                                                   this->ImageData->GetDimensions()[2]/2 );
+    this->RenXZ->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]/2,
+                                                 this->ImageData->GetDimensions()[1]*10,
+                                                 this->ImageData->GetDimensions()[2]/2 );
+    this->RenXZ->GetActiveCamera()->SetViewUp(0,0,-1);
+
+    this->RenXZ->ResetCamera();
+    this->RenXZ->GetActiveCamera()->Zoom(this->ZoomLabel);
+
+
+    /// Manage YZ window
+    this->Properties->yzIPW->SetCurrentRenderer(this->GetYZRenderer());
+    this->Properties->yzIPW->SetInput(this->ImageData);
+    this->Properties->yzIPW->SetPlaneOrientationToXAxes();
+    this->Properties->yzIPW->SetSlicePosition(center[0]);
+    this->Properties->yzIPW->SetLookupTable(this->Properties->lut);
+    this->Properties->yzIPW->On();
+    this->RenYZ->GetActiveCamera()->SetFocalPoint( this->ImageData->GetDimensions()[0]/2,
+                                                   this->ImageData->GetDimensions()[1]/2,
+                                                   this->ImageData->GetDimensions()[2]/2 );
+    this->RenYZ->GetActiveCamera()->SetPosition( this->ImageData->GetDimensions()[0]*10,
+                                                 this->ImageData->GetDimensions()[1]/2,
+                                                 this->ImageData->GetDimensions()[2]/2 );
+    this->RenYZ->GetActiveCamera()->SetViewUp(0,0,-1);
+    this->RenYZ->ResetCamera();
+    this->RenYZ->GetActiveCamera()->Zoom(this->ZoomLabel);
+
+    /// Manage Bounding box around the volume for the 3D display
+    vtkSmartPointer<vtkOutlineFilter> outlineData = vtkSmartPointer<vtkOutlineFilter>::New();
+    outlineData->SetInput(this->ImageData);
+    vtkSmartPointer<vtkPolyDataMapper> mapOutline = vtkSmartPointer<vtkPolyDataMapper>::New();
+    mapOutline->SetInput(outlineData->GetOutput());
+    this->Properties->BoundingBoxActor = vtkSmartPointer<vtkActor>::New();
+    this->Properties->BoundingBoxActor->SetMapper(mapOutline);
+
+    /// Refresh YZ viewer
+    this->GetRenderWindowYZ()->Render();
+
+}
+
+
+void OpenHeartGui::InterpolationManagement()
+{
+
+    if ( this->FlagReslice == 0 )
+    {
+        if ( this->FlagInterpolation == 0 )
+        {
+            this->FlagInterpolation = 1;
+            this->Properties->xIPW->TextureInterpolateOn();
+            this->Properties->yIPW->TextureInterpolateOn();
+            this->Properties->zIPW->TextureInterpolateOn();
+        }
+        else
+        {
+            this->FlagInterpolation = 0;
+            this->Properties->xIPW->TextureInterpolateOff();
+            this->Properties->yIPW->TextureInterpolateOff();
+            this->Properties->zIPW->TextureInterpolateOff();
+        }
+
+        /// Force to display the change on the XYZ planes
+        this->Properties->xIPW->SetInput(this->ImageData);
+        this->Properties->yIPW->SetInput(this->ImageData);
+        this->Properties->zIPW->SetInput(this->ImageData);
+        this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
+        this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
+        this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
+
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::UpdateForwardViewers()
+{
+
+    if ( this->ImageData )
+    {
+
+        ++(this->itStackVolume);
+        ++(this->CurrentFrame);
+        if (this->Properties->MeshActor) {
+            ++(this->itStackMesh);
+            ++(this->Properties->itStackMapperList);
+            ++(this->Properties->itStackMapXCutter);
+            ++(this->Properties->itStackMapYCutter);
+            ++(this->Properties->itStackMapZCutter);
+        }
+
+        if ( this->itStackVolume == this->StackVolume.end() ) {
+            this->itStackVolume = this->StackVolume.begin();
+            this->CurrentFrame = 0;
+            if (this->Properties->MeshActor) {
+                this->itStackMesh = this->StackMesh.begin();
+                this->Properties->itStackMapperList = this->Properties->StackMapperList.begin();
+                this->Properties->itStackMapXCutter = this->Properties->StackMapXCutter.begin();
+                this->Properties->itStackMapYCutter = this->Properties->StackMapYCutter.begin();
+                this->Properties->itStackMapZCutter = this->Properties->StackMapZCutter.begin();
+            }
+        }
+
+        /// Update image data pointer
+        this->ImageData = (*this->itStackVolume);
+
+        if ( this->FlagReslice == 0 )
+        {
+
+            /// Update the 3 planes and the corresponding 2D plane windows
+            this->Properties->xIPW->SetInput(this->ImageData);
+            this->Properties->yIPW->SetInput(this->ImageData);
+            this->Properties->zIPW->SetInput(this->ImageData);
+            this->Properties->xyIPW->SetInput(this->ImageData);
+            this->Properties->xzIPW->SetInput(this->ImageData);
+            this->Properties->yzIPW->SetInput(this->ImageData);
+            this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
+            this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
+            this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
+            this->Properties->xyIPW->SetSlicePosition(this->Properties->position[2]);
+            this->Properties->xzIPW->SetSlicePosition(this->Properties->position[1]);
+            this->Properties->yzIPW->SetSlicePosition(this->Properties->position[0]);
+
+        }
+        else
+        {
+
+            /// Update X plan
+            double pto[3];
+            double pt1[3];
+            double pt2[3];
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->xIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->xIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->xIPW->GetPoint2()[i];
+            }
+            double position = this->Properties->xIPW->GetSlicePosition();
+            this->Properties->xIPW->SetInput(this->ImageData);
+            this->Properties->yzIPW->SetInput(this->ImageData);
+            this->Properties->xIPW->SetOrigin(pto);
+            this->Properties->xIPW->SetPoint1(pt1);
+            this->Properties->xIPW->SetPoint2(pt2);
+            this->Properties->xIPW->UpdatePlacement();
+            this->Properties->yzIPW->SetOrigin(pto);
+            this->Properties->yzIPW->SetPoint1(pt1);
+            this->Properties->yzIPW->SetPoint2(pt2);
+            this->Properties->yzIPW->UpdatePlacement();
+            this->Properties->xIPW->SetSlicePosition(position);
+            this->Properties->yzIPW->SetSlicePosition(position);
+
+            /// Update Y plan
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->yIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->yIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->yIPW->GetPoint2()[i];
+            }
+            position = this->Properties->yIPW->GetSlicePosition();
+            this->Properties->yIPW->SetInput(this->ImageData);
+            this->Properties->xzIPW->SetInput(this->ImageData);
+            this->Properties->yIPW->SetOrigin(pto);
+            this->Properties->yIPW->SetPoint1(pt1);
+            this->Properties->yIPW->SetPoint2(pt2);
+            this->Properties->yIPW->UpdatePlacement();
+            this->Properties->xzIPW->SetOrigin(pto);
+            this->Properties->xzIPW->SetPoint1(pt1);
+            this->Properties->xzIPW->SetPoint2(pt2);
+            this->Properties->xzIPW->UpdatePlacement();
+            this->Properties->yIPW->SetSlicePosition(position);
+            this->Properties->xzIPW->SetSlicePosition(position);
+
+            /// Update Z plan
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->zIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->zIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->zIPW->GetPoint2()[i];
+            }
+            position = this->Properties->zIPW->GetSlicePosition();
+            this->Properties->zIPW->SetInput(this->ImageData);
+            this->Properties->xyIPW->SetInput(this->ImageData);
+            this->Properties->zIPW->SetOrigin(pto);
+            this->Properties->zIPW->SetPoint1(pt1);
+            this->Properties->zIPW->SetPoint2(pt2);
+            this->Properties->zIPW->UpdatePlacement();
+            this->Properties->xyIPW->SetOrigin(pto);
+            this->Properties->xyIPW->SetPoint1(pt1);
+            this->Properties->xyIPW->SetPoint2(pt2);
+            this->Properties->xyIPW->UpdatePlacement();
+            this->Properties->zIPW->SetSlicePosition(position);
+            this->Properties->xyIPW->SetSlicePosition(position);
+
+        }
+
+        /// Update the segmented mesh if needed
+        if (this->Properties->MeshActor)
+        {
+            this->Properties->MeshActor->SetMapper(*this->Properties->itStackMapperList);
+            vtkPolyDataMapper* cutMapperX = vtkPolyDataMapper::New();
+            cutMapperX->SetInputConnection((*this->Properties->itStackMapXCutter)->GetOutputPort());
+            this->Properties->xCutActor->SetMapper(cutMapperX);
+            vtkPolyDataMapper* cutMapperY = vtkPolyDataMapper::New();
+            cutMapperY->SetInputConnection((*this->Properties->itStackMapYCutter)->GetOutputPort());
+            this->Properties->yCutActor->SetMapper(cutMapperY);
+            vtkPolyDataMapper* cutMapperZ = vtkPolyDataMapper::New();
+            cutMapperZ->SetInputConnection((*this->Properties->itStackMapZCutter)->GetOutputPort());
+            this->Properties->zCutActor->SetMapper(cutMapperZ);
+        }
+
+        /// Update viewers
+        this->GetRenderWindow()->Render();
+        this->GetXYRenderer()->ResetCameraClippingRange();
+        this->GetRenderWindowXY()->Render();
+        this->GetXZRenderer()->ResetCameraClippingRange();
+        this->GetRenderWindowXZ()->Render();
+        this->GetYZRenderer()->ResetCameraClippingRange();
+        this->GetRenderWindowYZ()->Render();
+
+    }
+
+}
+
+
+void OpenHeartGui::UpdateBackwardViewers()
+{
+
+    if ( this->ImageData )
+    {
+
+        if ( this->itStackVolume == this->StackVolume.begin() )
+        {
+            this->itStackVolume = this->StackVolume.end();
+            this->CurrentFrame = this->NumberOfVolumes;
+            if (this->Properties->MeshActor) {
+                this->itStackMesh = this->StackMesh.end();
+                this->Properties->itStackMapperList = this->Properties->StackMapperList.end();
+                this->Properties->itStackMapXCutter = this->Properties->StackMapXCutter.end();
+                this->Properties->itStackMapYCutter = this->Properties->StackMapYCutter.end();
+                this->Properties->itStackMapZCutter = this->Properties->StackMapZCutter.end();
+            }
+        }
+
+        --(this->itStackVolume);
+        --(this->CurrentFrame);
+        if (this->Properties->MeshActor) {
+            --(this->itStackMesh);
+            --(this->Properties->itStackMapperList);
+            --(this->Properties->itStackMapXCutter);
+            --(this->Properties->itStackMapYCutter);
+            --(this->Properties->itStackMapZCutter);
+        }
+
+        /// Update image data pointer
+        this->ImageData = (*this->itStackVolume);
+
+        if ( this->FlagReslice == 0 )
+        {
+
+            /// Update the 3 planes
+            this->Properties->xIPW->SetInput(this->ImageData);
+            this->Properties->yIPW->SetInput(this->ImageData);
+            this->Properties->zIPW->SetInput(this->ImageData);
+            this->Properties->xyIPW->SetInput(this->ImageData);
+            this->Properties->xzIPW->SetInput(this->ImageData);
+            this->Properties->yzIPW->SetInput(this->ImageData);
+            this->Properties->xIPW->SetSlicePosition(this->Properties->position[0]);
+            this->Properties->yIPW->SetSlicePosition(this->Properties->position[1]);
+            this->Properties->zIPW->SetSlicePosition(this->Properties->position[2]);
+            this->Properties->xyIPW->SetSlicePosition(this->Properties->position[2]);
+            this->Properties->xzIPW->SetSlicePosition(this->Properties->position[1]);
+            this->Properties->yzIPW->SetSlicePosition(this->Properties->position[0]);
+
+        }
+        else
+        {
+
+            /// Update X plan
+            double pto[3];
+            double pt1[3];
+            double pt2[3];
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->xIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->xIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->xIPW->GetPoint2()[i];
+            }
+            double position = this->Properties->xIPW->GetSlicePosition();
+            this->Properties->xIPW->SetInput(this->ImageData);
+            this->Properties->yzIPW->SetInput(this->ImageData);
+            this->Properties->xIPW->SetOrigin(pto);
+            this->Properties->xIPW->SetPoint1(pt1);
+            this->Properties->xIPW->SetPoint2(pt2);
+            this->Properties->xIPW->UpdatePlacement();
+            this->Properties->yzIPW->SetOrigin(pto);
+            this->Properties->yzIPW->SetPoint1(pt1);
+            this->Properties->yzIPW->SetPoint2(pt2);
+            this->Properties->yzIPW->UpdatePlacement();
+            this->Properties->xIPW->SetSlicePosition(position);
+            this->Properties->yzIPW->SetSlicePosition(position);
+
+            /// Update Y plan
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->yIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->yIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->yIPW->GetPoint2()[i];
+            }
+            position = this->Properties->yIPW->GetSlicePosition();
+            this->Properties->yIPW->SetInput(this->ImageData);
+            this->Properties->xzIPW->SetInput(this->ImageData);
+            this->Properties->yIPW->SetOrigin(pto);
+            this->Properties->yIPW->SetPoint1(pt1);
+            this->Properties->yIPW->SetPoint2(pt2);
+            this->Properties->yIPW->UpdatePlacement();
+            this->Properties->xzIPW->SetOrigin(pto);
+            this->Properties->xzIPW->SetPoint1(pt1);
+            this->Properties->xzIPW->SetPoint2(pt2);
+            this->Properties->xzIPW->UpdatePlacement();
+            this->Properties->yIPW->SetSlicePosition(position);
+            this->Properties->xzIPW->SetSlicePosition(position);
+
+            /// Update Z plan
+            for (int i=0;i<3; i++) {
+                pto[i] = this->Properties->zIPW->GetOrigin()[i];
+                pt1[i] = this->Properties->zIPW->GetPoint1()[i];
+                pt2[i] = this->Properties->zIPW->GetPoint2()[i];
+            }
+            position = this->Properties->zIPW->GetSlicePosition();
+            this->Properties->zIPW->SetInput(this->ImageData);
+            this->Properties->xyIPW->SetInput(this->ImageData);
+            this->Properties->zIPW->SetOrigin(pto);
+            this->Properties->zIPW->SetPoint1(pt1);
+            this->Properties->zIPW->SetPoint2(pt2);
+            this->Properties->zIPW->UpdatePlacement();
+            this->Properties->xyIPW->SetOrigin(pto);
+            this->Properties->xyIPW->SetPoint1(pt1);
+            this->Properties->xyIPW->SetPoint2(pt2);
+            this->Properties->xyIPW->UpdatePlacement();
+            this->Properties->zIPW->SetSlicePosition(position);
+            this->Properties->xyIPW->SetSlicePosition(position);
+
+        }
+
+        /// Update the segmented mesh if needed
+        if (this->Properties->MeshActor)
+        {
+            this->Properties->MeshActor->SetMapper(*this->Properties->itStackMapperList);
+            vtkPolyDataMapper* cutMapperX = vtkPolyDataMapper::New();
+            cutMapperX->SetInputConnection((*this->Properties->itStackMapXCutter)->GetOutputPort());
+            this->Properties->xCutActor->SetMapper(cutMapperX);
+            vtkPolyDataMapper* cutMapperY = vtkPolyDataMapper::New();
+            cutMapperY->SetInputConnection((*this->Properties->itStackMapYCutter)->GetOutputPort());
+            this->Properties->yCutActor->SetMapper(cutMapperY);
+            vtkPolyDataMapper* cutMapperZ = vtkPolyDataMapper::New();
+            cutMapperZ->SetInputConnection((*this->Properties->itStackMapZCutter)->GetOutputPort());
+            this->Properties->zCutActor->SetMapper(cutMapperZ);
+        }
+
+        this->GetRenderWindow()->Render();
+        this->GetRenderWindowXY()->Render();
+        this->GetRenderWindowXZ()->Render();
+        this->GetRenderWindowYZ()->Render();
+
+    }
+
+}
+
+
+void OpenHeartGui::slotMeshAlpha(int val)
+{
+
+    if ( this->Properties->MeshActor )
+    {
+        this->Properties->MeshActor->GetProperty()->SetOpacity(val/100.);
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slotRefreshViewer(int val)
+{
+
+    /// Loop cases
+    while ( val != this->CurrentFrame )
+    {
+        if ( (this->FlagLoopEndToBegin == 0) && (this->FlagLoopBeginToEnd == 0) )
+        {
+            /// Normal transition
+            if ( ( val-this->CurrentFrame ) > 0 )
+                UpdateForwardViewers();
+            else
+                UpdateBackwardViewers();
+        }
+        else
+        {
+            /// Loop end to begin
+            if ( this->FlagLoopEndToBegin == 1 ) {
+                this->FlagLoopEndToBegin = 0;
+                UpdateForwardViewers();
+            }
+            /// Loop begin to end
+            if ( this->FlagLoopBeginToEnd == 1 ) {
+                this->FlagLoopBeginToEnd = 0;
+                UpdateBackwardViewers();
+            }
+        }
+    }
+
+    /// Update Frame text
+    if ( (this->FlagDisplayText) && (this->Properties->TextMapperNumFrame) )
+    {
+        QString str;
+        str.sprintf("Frame: %d",this->CurrentFrame);
+        this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::slotTabChange(int val)
+{
+
+    if (val==3)
+    {
+
+        if ( this->Properties->ApexPointActor != 0 ) {
+            this->GetMainRenderer()->AddActor(this->Properties->ApexPointActor);
+            this->FlagDisplayApexPoint = 1;
+        }
+        if ( this->Properties->BasalPointActor != 0 ) {
+            this->GetMainRenderer()->AddActor(this->Properties->BasalPointActor);
+            this->FlagDisplayBasalPoint = 1;
+        }
+        if ( this->Properties->LongAxisActor != 0 ) {
+            this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
+            this->FlagDisplayLongAxis = 1;
+        }
+
+        this->slot3DView();
+    }
+    else
+    {
+
+        if ( this->FlagDisplayApexPoint == 1 ) {
+            this->GetMainRenderer()->RemoveActor(this->Properties->ApexPointActor);
+            this->FlagDisplayApexPoint = 0;
+            this->GetRenderWindow()->Render();
+        }
+        if ( this->FlagDisplayBasalPoint == 1 ) {
+            this->GetMainRenderer()->RemoveActor(this->Properties->BasalPointActor);
+            this->FlagDisplayBasalPoint = 0;
+            this->GetRenderWindow()->Render();
+        }
+        if ( this->FlagDisplayLongAxis == 1 ) {
+            this->GetMainRenderer()->RemoveActor(this->Properties->LongAxisActor);
+            this->FlagDisplayLongAxis = 0;
+            this->GetRenderWindow()->Render();
+        }
+
+    }
+
+}
+
+
+
+void OpenHeartGui::slotPlay()
+{
+    if ( this->FlagPlay == 0 ) {
+        this->FlagPlay = 1;
+        this->pushButtonPlay->setText("Pause");
+        this->scrollBar->setEnabled(false);
+        this->Timer->start(40);
+    }
+    else {
+        this->FlagPlay = 0;
+        this->Timer->stop();
+        this->pushButtonPlay->setText("Play");
+        this->scrollBar->setEnabled(true);
+    }
+}
+
+
+void OpenHeartGui::slotTimerEvent()
+{
+
+    int val = this->CurrentFrame;
+    if ( val < (this->NumberOfVolumes-1) )
+        this->scrollBar->setSliderPosition(val+1);
+    else {
+        this->FlagLoopEndToBegin = 1;
+        this->scrollBar->setSliderPosition(0);
+    }
+
+}
+
+
+void OpenHeartGui::slotBasalPoint()
+{
+
+    if ( this->Properties->BasalPointActor == 0 ) {
+        this->Properties->BasalPointActor = vtkSmartPointer<vtkActor>::New();
+    }
+    else {
+        this->GetMainRenderer()->RemoveActor(this->Properties->BasalPointActor);
+    }
+
+    vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
+    sphereSource->SetCenter(this->Properties->position[0],
+                            this->Properties->position[1],
+                            this->Properties->position[2]);
+    sphereSource->SetRadius(5.0*this->ImageData->GetSpacing()[0]);
+    sphereSource->Update();
+
+    for (int i=0; i<3; i++)
+        this->BasalPoint[i] = this->Properties->position[i];
+
+    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    mapper->SetInput(sphereSource->GetOutput());
+
+    this->Properties->BasalPointActor->SetMapper(mapper);
+    this->Properties->BasalPointActor->GetProperty()->SetColor(0,1,0);
+
+    this->GetMainRenderer()->AddActor(this->Properties->BasalPointActor);
+    this->FlagDisplayBasalPoint = 1;
+
+    if ( this->Properties->ApexPointActor != 0 )
+    {
+        this->CreateLongAxisActor();
+        this->FlagLongAxis = 1;
+        this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
+        this->FlagDisplayLongAxis = 1;
+        this->pushButtonReslice->setEnabled(true);
+    }
+
+    this->GetRenderWindow()->Render();
+
+}
+
+
+void OpenHeartGui::slotApexPoint()
+{
+
+    if ( this->Properties->ApexPointActor == 0 ) {
+        this->Properties->ApexPointActor = vtkSmartPointer<vtkActor>::New();
+    }
+    else {
+        this->GetMainRenderer()->RemoveActor(this->Properties->ApexPointActor);
+    }
+
+    vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
+    sphereSource->SetCenter(this->Properties->position[0],
+                            this->Properties->position[1],
+                            this->Properties->position[2]);
+    sphereSource->SetRadius(5.0*this->ImageData->GetSpacing()[0]);
+    sphereSource->Update();
+
+    for (int i=0; i<3; i++)
+        this->ApexPoint[i] = this->Properties->position[i];
+
+    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    mapper->SetInput(sphereSource->GetOutput());
+
+    this->Properties->ApexPointActor->SetMapper(mapper);
+    this->Properties->ApexPointActor->GetProperty()->SetColor(0,1,0);
+
+    this->GetMainRenderer()->AddActor(this->Properties->ApexPointActor);
+    this->FlagDisplayApexPoint = 1;
+
+    if ( this->Properties->BasalPointActor != 0 )
+    {
+        this->CreateLongAxisActor();
+        this->FlagLongAxis = 1;
+        this->GetMainRenderer()->AddActor(this->Properties->LongAxisActor);
+        this->FlagDisplayLongAxis = 1;
+        this->pushButtonReslice->setEnabled(true);
+    }
+
+    this->GetRenderWindow()->Render();
+
+}
+
+
+void OpenHeartGui::CreateLongAxisActor()
+{
+
+    if ( this->Properties->LongAxisActor == 0 ) {
+        this->Properties->LongAxisActor = vtkSmartPointer<vtkActor>::New();
+    }
+    else {
+        this->GetMainRenderer()->RemoveActor(this->Properties->LongAxisActor);
+    }
+
+    vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
+    lineSource->SetPoint1(this->BasalPoint);
+    lineSource->SetPoint2(this->ApexPoint);
+    lineSource->Update();
+
+    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+    mapper->SetInputConnection(lineSource->GetOutputPort());
+
+    this->Properties->LongAxisActor->SetMapper(mapper);
+    this->Properties->LongAxisActor->GetProperty()->SetLineWidth(2);
+    this->Properties->LongAxisActor->GetProperty()->SetColor(0,1,0);
+
+}
+
+
+void OpenHeartGui::DisplayMainAxisManagement()
+{
+
+}
+
+
+void OpenHeartGui::DisplayMeshManagement()
+{
+
+    if ( this->Properties->MeshActor != 0 )
+    {
+
+        if ( this->FlagDisplayMesh == 0 )
+        {
+            this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 1;
+        }
+        else
+        {
+            this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 0;
+        }
+        this->GetRenderWindow()->Render();
+
+    }
+
+}
+
+void OpenHeartGui::DisplayModeManagement()
+{
+
+    if ( this->FlagDisplayText == 0 )
+    {
+
+        this->FlagDisplayText = 1;
+        if ( this->Properties->TextMapperPixel ) {
+            this->Properties->TextMapperPixel->SetInput("Display on");
+        }
+        if ( this->Properties->TextMapperNumFrame ) {
+            QString str;
+            str.sprintf("f = %d",this->CurrentFrame);
+            this->Properties->TextMapperNumFrame->SetInput(str.toStdString().c_str());
+        }
+        if ( this->Properties->TextMapperResolution ) {
+            QString str;
+            str.sprintf("Resolution: %.2f x %.2f x %.2f mm",this->ImageData->GetSpacing()[0]*1000,this->ImageData->GetSpacing()[1]*1000,this->ImageData->GetSpacing()[2]*1000);
+            this->Properties->TextMapperResolution->SetInput(str.toStdString().c_str());
+        }
+        if ( this->Properties->TextMapperSlice ) {
+            int slice = (int)( (this->Properties->position[1] - this->ImageData->GetOrigin()[1]) / this->ImageData->GetSpacing()[1] + 0.5f );
+            QString strSlice;
+            strSlice.sprintf("Slice: %d",slice);
+            this->Properties->TextMapperSlice->SetInput(strSlice.toStdString().c_str());
+        }
+
+        this->GetRenderWindow()->Render();
+
+    }
+    else
+    {
+
+        this->FlagDisplayText = 0;
+        if ( this->Properties->TextMapperPixel ) {
+            this->Properties->TextMapperPixel->SetInput("Display off");
+        }
+        if ( this->Properties->TextMapperNumFrame ) {
+            this->Properties->TextMapperNumFrame->SetInput("");
+        }
+        if ( this->Properties->TextMapperResolution ) {
+            this->Properties->TextMapperResolution->SetInput("");
+        }
+        if ( this->Properties->TextMapperSlice ) {
+            this->Properties->TextMapperSlice->SetInput("");
+        }
+        if ( this->Properties->TextMapperMM ) {
+            this->Properties->TextMapperMM->SetInput("");
+        }
+        if ( this->Properties->TextMapperValue ) {
+            this->Properties->TextMapperValue->SetInput("");
+        }
+        this->GetRenderWindow()->Render();
+
+    }
+
+}
+
+
+vtkActor2D* OpenHeartGui::AddFixedText(const char *text, float x, float y, float R,float G, float B, int Size)
+{
+
+    vtkTextMapper *Mapper = vtkTextMapper::New();
+    vtkActor2D *Actor = vtkActor2D::New();
+    Mapper->SetInput(text);
+    Mapper->GetTextProperty()->SetColor(R, G, B);
+    Mapper->GetTextProperty()->SetFontSize(Size);
+    Mapper->GetTextProperty()->SetJustificationToLeft();
+    Mapper->GetTextProperty()->ShadowOff();
+    Actor->SetPosition(x, y);
+    Actor->SetMapper(Mapper);
+    return Actor;
+
+}
+
+
+void OpenHeartGui::resizeEvent(QResizeEvent* event)
+{
+    int sizeX = this->qVTK->GetRenderWindow()->GetSize()[0];
+    int sizeY = this->qVTK->GetRenderWindow()->GetSize()[1];
+    if ( (sizeX!=382) || (sizeY!=462) ) {
+        this->Properties->TextActorSlice->SetPosition(10,this->GetRenderWindow()->GetSize()[1]-20);
+        this->Properties->TextActorPixel->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-20);
+        this->Properties->TextActorMM->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-45);
+        this->Properties->TextActorValue->SetPosition(this->GetRenderWindow()->GetSize()[0]-10,this->GetRenderWindow()->GetSize()[1]-70);
+        this->GetRenderWindow()->Render();
+        QMainWindow::resizeEvent(event);
+    }
+}
+
+
+void OpenHeartGui::HidePlanModeManagement()
+{
+
+    if ( this->FlagHidePlan == 0 )
+    {
+        this->FlagHidePlan = 1;
+        this->Properties->xIPW->SetTextureVisibility(0);
+        this->Properties->xIPW->GetPlaneProperty()->SetOpacity(0);
+        this->Properties->yIPW->SetTextureVisibility(0);
+        this->Properties->yIPW->GetPlaneProperty()->SetOpacity(0);
+        this->Properties->zIPW->SetTextureVisibility(0);
+        this->Properties->zIPW->GetPlaneProperty()->SetOpacity(0);
+
+        if ( (this->FlagDisplayMesh==0) && (this->FlagDisplayMeshContours==0) ) {
+            this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+            this->FlagDisplayMesh = 1;
+        }
+        /*
+        if ( this->FlagDisplayMeshContours == 1 ) {
+            this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+            this->FlagDisplayMeshContours = 0;
+        }
+        */
+        this->GetRenderWindow()->Render();
+
+    }
+    else
+    {
+        if ( this->FlagDisplayMesh == 1 )
+            this->GetMeshRenderer()->RemoveActor(this->Properties->MeshActor);
+        if ( this->FlagDisplayMeshContours == 1 ) {
+            this->GetMeshRenderer()->RemoveActor(this->Properties->xCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->yCutActor);
+            this->GetMeshRenderer()->RemoveActor(this->Properties->zCutActor);
+        }
+        this->FlagHidePlan = 0;
+
+        switch (this->ViewButton) {
+        case 0:  /// 3D view
+            this->Properties->xIPW->SetTextureVisibility(1);
+            this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
+            this->Properties->yIPW->SetTextureVisibility(1);
+            this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
+            this->Properties->zIPW->SetTextureVisibility(1);
+            this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
+            if ( this->FlagDisplayMeshContours == 1 ) {
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+            }
+            break;
+        case 1:  /// XY view
+            this->Properties->xIPW->SetTextureVisibility(1);
+            this->Properties->xIPW->GetPlaneProperty()->SetOpacity(1);
+            if ( this->FlagDisplayMeshContours == 1 ) {
+                this->GetMeshRenderer()->AddActor(this->Properties->xCutActor);
+            }
+            break;
+        case 2:  /// XZ view
+            this->Properties->yIPW->SetTextureVisibility(1);
+            this->Properties->yIPW->GetPlaneProperty()->SetOpacity(1);
+            if ( this->FlagDisplayMeshContours == 1 ) {
+                this->GetMeshRenderer()->AddActor(this->Properties->yCutActor);
+            }
+            break;
+        case 3:  /// YZ view
+            this->Properties->zIPW->SetTextureVisibility(1);
+            this->Properties->zIPW->GetPlaneProperty()->SetOpacity(1);
+            if ( this->FlagDisplayMeshContours == 1 ) {
+                this->GetMeshRenderer()->AddActor(this->Properties->zCutActor);
+            }
+            break;
+        default:
+            break;
+        }
+
+        if ( this->FlagDisplayMesh == 1 )
+            this->GetMeshRenderer()->AddActor(this->Properties->MeshActor);
+        this->GetRenderWindow()->Render();
+    }
+
+}
+
+
+void OpenHeartGui::UpdateClinicalIndices()
+{
+
+    float EDV = 0;
+    float ESV = 1000000;
+    int NbElements = this->TableChart->GetNumberOfRows();
+    for ( int k=0; k<NbElements; k++)
+    {
+        float val = this->TableChart->GetValue(k,1).ToFloat();
+        if ( val > EDV )
+            EDV = val;
+        if ( val < ESV )
+            ESV = val;
+    }
+    /// End Diastolic and End systolic volume
+    QString strESV;
+    strESV.sprintf("%2.1f ml",ESV);
+    QString strEDV;
+    strEDV.sprintf("%2.1f ml",EDV);
+    this->labelESVValue->setText(strESV);
+    this->labelEDVValue->setText(strEDV);
+    /// Ejection fraction indice
+    float EF = 100 * (EDV-ESV) / (EDV+1e-6);
+    QString strEF;
+    strEF.sprintf("%2.1f %%",EF);
+    this->labelEFValue->setText(strEF);
+    /// Stroke volume indice
+    float SV = EDV-ESV;
+    QString strSV;
+    strSV.sprintf("%2.1f ml",SV);
+    this->labelSVValue->setText(strSV);
+
+}
+
+
+/// Custimize interface colors
+void OpenHeartGui::SetInterfaceColors()
+{
+    this->tabMesh->setStyleSheet("background-color: rgb(0,0,0);");
+    this->widgetXY->setStyleSheet("border-style: solid; border-width: 2px;  border-color: blue;");
+    this->widgetXZ->setStyleSheet("border-style: solid; border-width: 2px;  border-color: yellow;");
+    this->widgetYZ->setStyleSheet("border-style: solid; border-width: 2px;  border-color: red;");
+}
+
+
+void OpenHeartGui::slotReslice()
+{
+
+    if ( this->pushButtonReslice->isEnabled() )
+    {
+        if ( this->FlagReslice == 0 )
+        {
+            /// Reslice planes according to the main axis
+            this->SetLongAxisView();
+            /// Display off the Slice text actor
+            this->GetMainRenderer()->RemoveActor(this->Properties->TextActorSlice);
+            /// Replace Reslice text by Reset one into the push button
+            this->pushButtonReslice->setText("Reset");
+            /// Set corresponding flag to 1
+            this->FlagReslice = 1;
+        }
+        else
+        {
+            /// Reset the reslicing operation
+            this->ResetReslicing();
+            /// Display on the Slice text actor
+            this->GetMainRenderer()->AddActor(this->Properties->TextActorSlice);
+            /// Replace Reslice text by Reset one into the push button
+            this->pushButtonReslice->setText("Reslice");
+            /// Set corresponding flag to 0
+            this->FlagReslice = 0;
+        }
+
+    }
+
+}
+
+
+void OpenHeartGui::SetLongAxisView()
+{
+
+    /// Compute the rotation matrix between the Z-axis and the long axis of the heart
+    this->ComputeRotationMatrix();
+
+    /// Set the corresponding vtkTransform object
+    this->TransformViewOrientation->SetMatrix(this->RotationMatrix);
+    this->TransformViewOrientationInv->SetMatrix(this->RotationMatrixInv);
+
+    /// Set the plans at the center of the volume
+    double center[3];
+    for ( int i=0; i<3; i++ )
+        center[i] = 0.5*(this->ImageData->GetDimensions()[i])*(this->ImageData->GetSpacing()[i]);
+    this->Properties->xIPW->SetSlicePosition(center[0]);
+    this->Properties->yIPW->SetSlicePosition(center[1]);
+    this->Properties->zIPW->SetSlicePosition(center[2]);
+    this->Properties->yzIPW->SetSlicePosition(center[0]);
+    this->Properties->xzIPW->SetSlicePosition(center[1]);
+    this->Properties->xyIPW->SetSlicePosition(center[2]);
+
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /// Process XZ-plans
+
+    /// Apply the rotation to the points defining the cartesian plan of interest
+    //double *cy = this->Properties->yIPW->GetCenter();
+    double *pt1 = this->Properties->yIPW->GetPoint1();
+    double *pt2 = this->Properties->yIPW->GetPoint2();
+    double *pto = this->Properties->yIPW->GetOrigin();
+    double newpt1[3];
+    double newpt2[3];
+    double newpto[3];
+
+    /// Do this to ensure that the center of the rotation corresponds to the center of the volume
+    for (int i=0; i<3; i++) {
+        pt1[i] -= center[i];
+        pt2[i] -= center[i];
+        pto[i] -= center[i];
+    }
+
+    /// Apply transformation
+    this->TransformViewOrientation->TransformPoint(pt1,newpt1);
+    this->TransformViewOrientation->TransformPoint(pt2,newpt2);
+    this->TransformViewOrientation->TransformPoint(pto,newpto);
+    for (int i=0; i<3; i++) {
+        newpt1[i] += center[i];
+        newpt2[i] += center[i];
+        newpto[i] += center[i];
+    }
+    ///
+    this->Properties->yIPW->SetOrigin(newpto);
+    this->Properties->yIPW->SetPoint1(newpt1);
+    this->Properties->yIPW->SetPoint2(newpt2);
+    this->Properties->yIPW->UpdatePlacement();
+    ///
+    this->Properties->xzIPW->SetOrigin(newpto);
+    this->Properties->xzIPW->SetPoint1(newpt1);
+    this->Properties->xzIPW->SetPoint2(newpt2);
+    this->Properties->xzIPW->UpdatePlacement();
+
+
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /// Process YZ-plans
+
+    pt1 = this->Properties->xIPW->GetPoint1();
+    pt2 = this->Properties->xIPW->GetPoint2();
+    pto = this->Properties->xIPW->GetOrigin();
+
+    /// Do this to ensure that the center of the rotation corresponds to the center of the volume
+    for (int i=0; i<3; i++) {
+        pt1[i] -= center[i];
+        pt2[i] -= center[i];
+        pto[i] -= center[i];
+    }
+
+    /// Apply transformation
+    this->TransformViewOrientation->TransformPoint(pt1,newpt1);
+    this->TransformViewOrientation->TransformPoint(pt2,newpt2);
+    this->TransformViewOrientation->TransformPoint(pto,newpto);
+    for (int i=0; i<3; i++) {
+        newpt1[i] += center[i];
+        newpt2[i] += center[i];
+        newpto[i] += center[i];
+    }
+    ///
+    this->Properties->xIPW->SetOrigin(newpto);
+    this->Properties->xIPW->SetPoint1(newpt1);
+    this->Properties->xIPW->SetPoint2(newpt2);
+    this->Properties->xIPW->UpdatePlacement();
+    ///
+    this->Properties->yzIPW->SetOrigin(newpto);
+    this->Properties->yzIPW->SetPoint1(newpt1);
+    this->Properties->yzIPW->SetPoint2(newpt2);
+    this->Properties->yzIPW->UpdatePlacement();
+
+
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /// Process XY-plans
+
+    pt1 = this->Properties->zIPW->GetPoint1();
+    pt2 = this->Properties->zIPW->GetPoint2();
+    pto = this->Properties->zIPW->GetOrigin();
+
+    /// Do this to ensure that the center of the rotation corresponds to the center of the volume
+    for (int i=0; i<3; i++) {
+        pt1[i] -= center[i];
+        pt2[i] -= center[i];
+        pto[i] -= center[i];
+    }
+
+    /// Apply transformation
+    this->TransformViewOrientation->TransformPoint(pt1,newpt1);
+    this->TransformViewOrientation->TransformPoint(pt2,newpt2);
+    this->TransformViewOrientation->TransformPoint(pto,newpto);
+    for (int i=0; i<3; i++) {
+        newpt1[i] += center[i];
+        newpt2[i] += center[i];
+        newpto[i] += center[i];
+    }
+    ///
+    this->Properties->zIPW->SetOrigin(newpto);
+    this->Properties->zIPW->SetPoint1(newpt1);
+    this->Properties->zIPW->SetPoint2(newpt2);
+    this->Properties->zIPW->UpdatePlacement();
+    ///
+    this->Properties->xyIPW->SetOrigin(newpto);
+    this->Properties->xyIPW->SetPoint1(newpt1);
+    this->Properties->xyIPW->SetPoint2(newpt2);
+    this->Properties->xyIPW->UpdatePlacement();
+
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /// Final translation to match the Long axis
+
+    /// XZ plan translation
+    double *ncy = this->Properties->yIPW->GetCenter();
+    double t;
+    double closest[3];
+    vtkLine::DistanceToLine(ncy, this->BasalPoint, this->ApexPoint, t, closest);
+    double offset = this->Properties->yIPW->GetSlicePosition() + (closest[1] - ncy[1]);
+    this->Properties->yIPW->SetSlicePosition(offset);
+    this->Properties->xzIPW->SetSlicePosition(offset);
+
+    /// YZ plan translation
+    double *ncx = this->Properties->xIPW->GetCenter();
+    vtkLine::DistanceToLine(ncx, this->BasalPoint, this->ApexPoint, t, closest);
+    offset = this->Properties->xIPW->GetSlicePosition() + (closest[0] - ncx[0]);
+    this->Properties->xIPW->SetSlicePosition(offset);
+    this->Properties->yzIPW->SetSlicePosition(offset);
+
+    /// XY plan translation
+    double *ncz = this->Properties->zIPW->GetCenter();
+    double mid[3];
+    for (int i=0; i<3; i++)
+        mid[i] = this->BasalPoint[i] + 0.5 * (this->ApexPoint[i]-this->BasalPoint[i]);
+    offset = this->Properties->zIPW->GetSlicePosition() + (mid[2] - ncz[2]);
+    this->Properties->zIPW->SetSlicePosition(offset);
+    this->Properties->xyIPW->SetSlicePosition(offset);
+
+    /// Update Properties->position to fit to the new position
+    this->Properties->position[0] = this->Properties->xIPW->GetSlicePosition();
+    this->Properties->position[1] = this->Properties->yIPW->GetSlicePosition();
+    this->Properties->position[2] = this->Properties->zIPW->GetSlicePosition();
+
+
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /////////////////////////////////////////////////
+    /// Update renderer
+    this->UpdateViewer(0,this->ZoomLabel,this->RenXY);
+    this->UpdateViewer(1,this->ZoomLabel,this->RenXZ);
+    this->UpdateViewer(2,this->ZoomLabel,this->RenYZ);
+    this->GetRenderWindow()->Render();
+
+}
+
+
+/// Compute the rotation matrix between the Z-axis and the long axis of the heart
+void OpenHeartGui::ComputeRotationMatrix()
+{
+
+    double ZAxis[] = {0,0,1};
+    double MainAxis[3];
+    for (int i=0; i<3; i++)
+        MainAxis[i] = this->BasalPoint[i] - this->ApexPoint[i];
+    vtkMath::Normalize(MainAxis);
+
+    /// Compute rotation matrix between two vectors: MainAxis and ZAxis
+    double normal1[3];
+    double normal2[3];
+    for (int i=0; i<3; i++) {
+        normal1[i] = ZAxis[i];
+        normal2[i] = MainAxis[i];
+    }
+
+    double vec[3];
+    vtkMath::Cross(normal1, normal2, vec);
+    double costheta = vtkMath::Dot(normal1, normal2);
+    double sintheta = vtkMath::Norm(vec);
+    double theta = atan2(sintheta, costheta);
+    if (sintheta != 0)
+    {
+        vec[0] /= sintheta;
+        vec[1] /= sintheta;
+        vec[2] /= sintheta;
+    }
+
+    /// convert to quaternion
+    costheta = cos(0.5*theta);
+    sintheta = sin(0.5*theta);
+    double quat[4];
+    quat[0] = costheta;
+    quat[1] = vec[0]*sintheta;
+    quat[2] = vec[1]*sintheta;
+    quat[3] = vec[2]*sintheta;
+
+    /// convert to matrix
+    double mat[3][3];
+    vtkMath::QuaternionToMatrix3x3(quat,mat);
+
+    /// Create corresponding 4x4 matrix
+    this->RotationMatrix->Identity();
+    this->RotationMatrixInv->Identity();
+    for (unsigned int i = 0; i < 3; i++) {
+        for (unsigned int j = 0; j < 3; j++) {
+            this->RotationMatrix->SetElement(i, j, mat[i][j]);
+            this->RotationMatrixInv->SetElement(i, j, mat[i][j]);
+        }
+    }
+    this->RotationMatrixInv->Invert();
+
+}
+
+
+/// Reset the reslicing operation
+void OpenHeartGui::ResetReslicing()
+{
+
+    /// Set the rotation matrix to identity
+    this->RotationMatrix->Identity();
+    this->RotationMatrixInv->Identity();
+
+    /// Set the corresponding vtkTransform object
+    this->TransformViewOrientation->SetMatrix(this->RotationMatrix);
+    this->TransformViewOrientationInv->SetMatrix(this->RotationMatrixInv);
+
+    /// Switch off the oblique orientation of each plan
+    this->Properties->xIPW->SetPlaneOrientationToXAxes();
+    this->Properties->yzIPW->SetPlaneOrientationToXAxes();
+    this->Properties->yIPW->SetPlaneOrientationToYAxes();
+    this->Properties->xzIPW->SetPlaneOrientationToYAxes();
+    this->Properties->zIPW->SetPlaneOrientationToZAxes();
+    this->Properties->xyIPW->SetPlaneOrientationToZAxes();
+
+    /// Set the plans at the center of the volume
+    double center[3];
+    for ( unsigned int k=0; k<3; k++ )
+        center[k] = ((this->ImageData->GetDimensions()[k])*(this->ImageData->GetSpacing()[k]))/2;
+
+    this->Properties->xIPW->SetSlicePosition(center[0]);
+    this->Properties->yzIPW->SetSlicePosition(center[0]);
+    this->Properties->yIPW->SetSlicePosition(center[1]);
+    this->Properties->xzIPW->SetSlicePosition(center[1]);
+    this->Properties->zIPW->SetSlicePosition(center[2]);
+    this->Properties->xyIPW->SetSlicePosition(center[2]);
+
+    /// Update Properties->position to fit to the new position
+    this->Properties->position[0] = center[0];
+    this->Properties->position[1] = center[1];
+    this->Properties->position[2] = center[2];
+
+    /// Update renderer
+    this->UpdateViewer(0,this->ZoomLabel,this->RenXY);
+    this->UpdateViewer(1,this->ZoomLabel,this->RenXZ);
+    this->UpdateViewer(2,this->ZoomLabel,this->RenYZ);
+    this->GetRenderWindow()->Render();
+
+}
+
+
+void OpenHeartGui::UpdateViewer(int view, double zoom, vtkRenderer *ren)
+{
+
+    /// Set Focal Point
+    double center[3];
+    for (int i=0; i<3; i++)
+        center[i] = 0.5 * this->ImageData->GetDimensions()[i] * this->ImageData->GetSpacing()[i];
+    ren->GetActiveCamera()->SetFocalPoint(center);
+
+    /// Set Position
+    double position[3];
+    double newPosition[3];
+    switch (view)
+    {
+    case 0: /// XY view
+        position[0] = 0.5 * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
+        position[1] = 0.5 * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
+        position[2] = 10  * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
+        break;
+    case 1: /// XZ view
+        position[0] = 0.5 * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
+        position[1] = 10  * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
+        position[2] = 0.5 * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
+        break;
+    case 2: /// YZ view
+        position[0] = 10  * this->ImageData->GetDimensions()[0] * this->ImageData->GetSpacing()[0];
+        position[1] = 0.5 * this->ImageData->GetDimensions()[1] * this->ImageData->GetSpacing()[1];
+        position[2] = 0.5 * this->ImageData->GetDimensions()[2] * this->ImageData->GetSpacing()[2];
+    }
+    for (int i=0; i<3; i++)
+        position[i]  = position[i] - center[i];
+    this->TransformViewOrientation->TransformPoint(position,newPosition);
+    for (int i=0; i<3; i++)
+        newPosition[i]  = newPosition[i] + center[i];
+    ren->GetActiveCamera()->SetPosition(newPosition);
+
+    /// Set ViewUp
+    double pt[] = {0,0,-1};
+    double viewup[3];
+    this->TransformViewOrientation->TransformPoint(pt,viewup);
+    ren->GetActiveCamera()->SetViewUp(viewup);
+    ren->ResetCamera();
+    ren->GetActiveCamera()->Zoom(zoom);
+    ren->GetRenderWindow()->Render();
+
+}
+
+
+void OpenHeartGui::ComputePointBeforeRotation(double *position)
+{
+
+    double center[3];
+    double newPosition[3];
+    for (int i=0; i<3; i++)
+        center[i] = 0.5 * this->ImageData->GetDimensions()[i] * this->ImageData->GetSpacing()[i];
+
+    for (int i=0; i<3; i++)
+        position[i]  = position[i] - center[i];
+    this->TransformViewOrientationInv->TransformPoint(position,newPosition);
+    for (int i=0; i<3; i++)
+        position[i]  = newPosition[i] + center[i];
+
+}