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