X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=Applications%2FOpenHeartGui.cxx;fp=Applications%2FOpenHeartGui.cxx;h=24c324b886b498d7f1881ca2fcdd2dca2fad20a3;hb=e989157c905531306964b1f4d2d70991029aaca2;hp=0000000000000000000000000000000000000000;hpb=a29e955d81fcaf6b37db4a5cb168549f96f1fff3;p=openheart.git diff --git a/Applications/OpenHeartGui.cxx b/Applications/OpenHeartGui.cxx new file mode 100644 index 0000000..24c324b --- /dev/null +++ b/Applications/OpenHeartGui.cxx @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vtkMyInteractorStyleTrackballCameraOpenHeart.h" +#include "vtkMyInteractorStyleTrackballCameraOpenHeartXY.h" +#include "vtkMyInteractorStyleTrackballCameraOpenHeartXZ.h" +#include "vtkMyInteractorStyleTrackballCameraOpenHeartYZ.h" +#include +#include + + +#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::New(); + this->RotationMatrix->Identity(); + this->TransformViewOrientation = vtkSmartPointer::New(); + this->RotationMatrixInv = vtkSmartPointer::New(); + this->RotationMatrixInv->Identity(); + this->TransformViewOrientationInv = vtkSmartPointer::New(); + this->OrientationWidget = vtkSmartPointer::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::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 renwin = vtkSmartPointer::New(); + renwin->StereoCapableWindowOn(); + + /// Activate 3DConnexion device + this->qVTK->SetUseTDx(true); + this->qVTK->SetRenderWindow(renwin); + + /// Initialize interactor + this->Interactor = vtkSmartPointer::New(); + this->Interactor = static_cast(this->qVTK->GetInteractor()->GetRenderWindow()->GetInteractor()); + + /// Add a renderer + this->Ren = vtkSmartPointer::New(); + this->qVTK->GetRenderWindow()->AddRenderer(this->Ren); + this->Ren->SetBackground(0,0,0); + this->Ren->GetActiveCamera()->SetParallelProjection(1); + + + /// **************************************************************** + /// Create XY window + vtkSmartPointer renwinXY = vtkSmartPointer::New(); + renwinXY->StereoCapableWindowOn(); + + /// Activate 3DConnexion device + this->qVTKXY->SetUseTDx(true); + this->qVTKXY->SetRenderWindow(renwinXY); + + /// Initialize interactor + this->InteractorXY = vtkSmartPointer::New(); + this->InteractorXY = static_cast(this->qVTKXY->GetInteractor()->GetRenderWindow()->GetInteractor()); + + /// Add a renderer + this->RenXY = vtkSmartPointer::New(); + this->qVTKXY->GetRenderWindow()->AddRenderer(this->RenXY); + this->RenXY->SetBackground(0,0,0); + this->RenXY->GetActiveCamera()->SetParallelProjection(1); + + + /// **************************************************************** + /// Create XZ window + vtkSmartPointer renwinXZ = vtkSmartPointer::New(); + renwinXZ->StereoCapableWindowOn(); + + /// Activate 3DConnexion device + this->qVTKXZ->SetUseTDx(true); + this->qVTKXZ->SetRenderWindow(renwinXZ); + + /// Initialize interactor + this->InteractorXZ = vtkSmartPointer::New(); + this->InteractorXZ = static_cast(this->qVTKXZ->GetInteractor()->GetRenderWindow()->GetInteractor()); + + /// Add a renderer + this->RenXZ = vtkSmartPointer::New(); + this->qVTKXZ->GetRenderWindow()->AddRenderer(this->RenXZ); + this->RenXZ->SetBackground(0,0,0); + this->RenXZ->GetActiveCamera()->SetParallelProjection(1); + + + /// **************************************************************** + /// Create YZ window + vtkSmartPointer renwinYZ = vtkSmartPointer::New(); + renwinYZ->StereoCapableWindowOn(); + + /// Activate 3DConnexion device + this->qVTKYZ->SetUseTDx(true); + this->qVTKYZ->SetRenderWindow(renwinYZ); + + /// Initialize interactor + this->InteractorYZ = static_cast(this->qVTKYZ->GetInteractor()->GetRenderWindow()->GetInteractor()); + + /// Add a renderer + this->RenYZ = vtkSmartPointer::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]Dims[0]) && + (pixel[1]>=0) && (pixel[1]Dims[1]) && + (pixel[2]>=0) && (pixel[2]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(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_UNSIGNED_SHORT: { + strValue.sprintf("data value: %u", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_INT: { + strValue.sprintf("data value: %d", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_FLOAT: { + strValue.sprintf("data value: %.1f", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_DOUBLE: { + strValue.sprintf("data value: %.1f", static_cast(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]Dims[0]) && + (pixel[1]>=0) && (pixel[1]Dims[1]) && + (pixel[2]>=0) && (pixel[2]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(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_UNSIGNED_SHORT: { + strValue.sprintf("data value: %u", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_INT: { + strValue.sprintf("data value: %d", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_FLOAT: { + strValue.sprintf("data value: %.1f", static_cast(this->ImageData->GetScalarPointer(pixel))[0]); + break; + } + case VTK_DOUBLE: { + strValue.sprintf("data value: %.1f", static_cast(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::New(); + vtkSmartPointer arrX = vtkSmartPointer::New(); + arrX->SetName("Number of frames"); + this->TableChart->AddColumn(arrX); + vtkSmartPointer arrY = vtkSmartPointer::New(); + arrY->SetName("Volume"); + this->TableChart->AddColumn(arrY); + + int numPoints = this->NumberOfVolumes; + this->TableChart->SetNumberOfRows(numPoints); + for (int i=0; iTableChart->SetValue(i, 0, i); + this->TableChart->SetValue(i, 1, 0); + } + // Add multiple line plots, setting the colors etc + vtkSmartPointer chart = vtkSmartPointer::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::New(); + this->Picker->SetTolerance(0.005); + this->Interactor->SetPicker(this->Picker); + this->PickerXY = vtkSmartPointer::New(); + this->PickerXY->SetTolerance(0.005); + this->InteractorXY->SetPicker(this->PickerXY); + this->PickerXZ = vtkSmartPointer::New(); + this->PickerXZ->SetTolerance(0.005); + this->InteractorXZ->SetPicker(this->PickerXZ); + this->PickerYZ = vtkSmartPointer::New(); + this->PickerYZ->SetTolerance(0.005); + this->InteractorYZ->SetPicker(this->PickerYZ); + +} + + + +void OpenHeartGui::InitWidgets() +{ + /// ImagePlane Widget + this->InitPlaneWidget(); +} + + +void OpenHeartGui::InitOrientationAxes() +{ + vtkSmartPointer axes = vtkSmartPointer::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::New(); + this->Properties->yIPW = vtkSmartPointer::New(); + this->Properties->zIPW = vtkSmartPointer::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::New(); + this->Properties->TextMapperPixel = vtkSmartPointer::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::New(); + this->Properties->TextMapperMM= vtkSmartPointer::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::New(); + this->Properties->TextMapperValue = vtkSmartPointer::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::New(); + this->Properties->TextMapperSlice = vtkSmartPointer::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::New(); + this->Properties->TextMapperNumFrame = vtkSmartPointer::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::New(); + this->Properties->TextMapperResolution = vtkSmartPointer::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 CustomInteractorStyle = + vtkSmartPointer::New(); + CustomInteractorStyle->SetOpenHeartGui( this ); + this->Interactor->SetInteractorStyle(CustomInteractorStyle); + + /// customize XY interactor + vtkSmartPointer CustomInteractorStyleXY = + vtkSmartPointer::New(); + CustomInteractorStyleXY->SetOpenHeartGui( this ); + this->InteractorXY->SetInteractorStyle(CustomInteractorStyleXY); + + /// customize XZ interactor + vtkSmartPointer CustomInteractorStyleXZ = + vtkSmartPointer::New(); + CustomInteractorStyleXZ->SetOpenHeartGui( this ); + this->InteractorXZ->SetInteractorStyle(CustomInteractorStyleXZ); + + /// customize YZ interactor + vtkSmartPointer CustomInteractorStyleYZ = + vtkSmartPointer::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::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 outlineData = vtkSmartPointer::New(); + outlineData->SetInput(this->ImageData); + vtkSmartPointer mapOutline = vtkSmartPointer::New(); + mapOutline->SetInput(outlineData->GetOutput()); + this->Properties->BoundingBoxActor = vtkSmartPointer::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::New(); + } + else { + this->GetMainRenderer()->RemoveActor(this->Properties->BasalPointActor); + } + + vtkSmartPointer sphereSource = vtkSmartPointer::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 mapper = vtkSmartPointer::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::New(); + } + else { + this->GetMainRenderer()->RemoveActor(this->Properties->ApexPointActor); + } + + vtkSmartPointer sphereSource = vtkSmartPointer::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 mapper = vtkSmartPointer::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::New(); + } + else { + this->GetMainRenderer()->RemoveActor(this->Properties->LongAxisActor); + } + + vtkSmartPointer lineSource = vtkSmartPointer::New(); + lineSource->SetPoint1(this->BasalPoint); + lineSource->SetPoint2(this->ApexPoint); + lineSource->Update(); + + vtkSmartPointer mapper = vtkSmartPointer::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; kTableChart->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]; + +}