+/**
+* 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];
+
+}