From 0ef2d6ae784a865d069ca5dc77b540f859011848 Mon Sep 17 00:00:00 2001 From: tbaudier Date: Mon, 20 Feb 2017 16:52:52 +0100 Subject: [PATCH] Add interactions with window/level bars in the histogram tool --- vv/CMakeLists.txt | 1 + vv/vvToolHistogram.cxx | 151 ++++++++++++++++++++++++---------- vv/vvToolHistogram.h | 19 ++++- vv/vvToolHistogramCommand.cxx | 73 ++++++++++++++++ vv/vvToolHistogramCommand.h | 56 +++++++++++++ 5 files changed, 256 insertions(+), 44 deletions(-) create mode 100644 vv/vvToolHistogramCommand.cxx create mode 100644 vv/vvToolHistogramCommand.h diff --git a/vv/CMakeLists.txt b/vv/CMakeLists.txt index 43b71a1..436dfc6 100644 --- a/vv/CMakeLists.txt +++ b/vv/CMakeLists.txt @@ -91,6 +91,7 @@ set(vv_SRCS vvGlyph2D.cxx vvSlicerManager.cxx vvSlicerManagerCommand.cxx + vvToolHistogramCommand.cxx vvUtils.cxx # vvMaximumIntensityProjection.cxx vvMesh.cxx diff --git a/vv/vvToolHistogram.cxx b/vv/vvToolHistogram.cxx index b647fdd..24b0864 100644 --- a/vv/vvToolHistogram.cxx +++ b/vv/vvToolHistogram.cxx @@ -27,6 +27,7 @@ #include "vvSlicerManager.h" #include "vvSlicer.h" #include "vvToolInputSelectorWidget.h" +#include "vvToolHistogramCommand.h" // vtk #include @@ -79,6 +80,8 @@ vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f) // GUI Initialization Ui_vvToolHistogram::setupUi(mToolWidget); + mModificationsDone = false; + // Connect signals & slots connect(mSaveHistogramButton, SIGNAL(clicked()), this, SLOT(SaveAs())); @@ -90,6 +93,7 @@ vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f) chart->SetAutoSize(false); chart->SetRenderEmpty(true); mView->GetScene()->AddItem(chart); + mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0); this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems(); this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer()); HistogramWidget->show(); @@ -128,34 +132,16 @@ void vvToolHistogram::computeHistogram() mFilter->Update(); //Creation of the XY chart - vtkSmartPointer table = vtkSmartPointer::New(); vtkSmartPointer arrX = vtkSmartPointer::New(); vtkSmartPointer arrY = vtkSmartPointer::New(); arrX = mFilter->GetArrayX(); arrY = mFilter->GetArrayY(); arrX->SetName("Intensity"); arrY->SetName("#Voxels"); - - table->AddColumn(arrX); - table->AddColumn(arrY); - - mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0); - - vtkSmartPointer chart = vtkSmartPointer::New(); - chart->SetAutoSize(true); - mView->GetScene()->ClearItems(); - mView->GetScene()->AddItem(chart); - vtkPlot *line = chart->AddPlot(vtkChart::LINE); -#if VTK_MAJOR_VERSION <= 5 - line->SetInput(table, 0, 1); -#else - line->SetInputData(table, 0, 1); -#endif - line->SetColor(0, 255, 0, 255); - line->SetWidth(1.0); + mTable->AddColumn(arrX); + mTable->AddColumn(arrY); //Upper and Lower lines for window/level - vtkSmartPointer tableWindowLevel = vtkSmartPointer::New(); vtkSmartPointer arrXUpperWindowLevel = vtkSmartPointer::New(); vtkSmartPointer arrXLowerWindowLevel = vtkSmartPointer::New(); vtkSmartPointer arrYWindowLevel = vtkSmartPointer::New(); @@ -168,17 +154,44 @@ void vvToolHistogram::computeHistogram() arrXUpperWindowLevel->SetName("IntensityUp"); arrXLowerWindowLevel->SetName("IntensityLow"); arrYWindowLevel->SetName("#Voxels"); - tableWindowLevel->AddColumn(arrXUpperWindowLevel); - tableWindowLevel->AddColumn(arrXLowerWindowLevel); - tableWindowLevel->AddColumn(arrYWindowLevel); + mTableWindowLevel->AddColumn(arrXUpperWindowLevel); + mTableWindowLevel->AddColumn(arrXLowerWindowLevel); + mTableWindowLevel->AddColumn(arrYWindowLevel); + + displayHistogram(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolHistogram::displayHistogram() +{ + if (!mCurrentSlicerManager) close(); + HistogramWidget->hide(); + + + vtkSmartPointer chart = vtkSmartPointer::New(); + chart->SetAutoSize(true); + mView->GetScene()->ClearItems(); + mView->GetScene()->AddItem(chart); + vtkPlot *line = chart->AddPlot(vtkChart::LINE); +#if VTK_MAJOR_VERSION <= 5 + line->SetInput(mTable, 0, 1); +#else + line->SetInputData(mTable, 0, 1); +#endif + line->SetColor(0, 255, 0, 255); + line->SetWidth(1.0); + + vtkPlot *upperWindowLine = chart->AddPlot(vtkChart::LINE); vtkPlot *lowerWindowLine = chart->AddPlot(vtkChart::LINE); #if VTK_MAJOR_VERSION <= 5 - upperWindowLine->SetInput(tableWindowLevel, 0, 2); - lowerWindowLine->SetInput(tableWindowLevel, 1, 2); + upperWindowLine->SetInput(mTableWindowLevel, 0, 2); + lowerWindowLine->SetInput(mTableWindowLevel, 1, 2); #else - upperWindowLine->SetInputData(tableWindowLevel, 0, 2); - lowerWindowLine->SetInputData(tableWindowLevel, 1, 2); + upperWindowLine->SetInputData(mTableWindowLevel, 0, 2); + lowerWindowLine->SetInputData(mTableWindowLevel, 1, 2); #endif upperWindowLine->SetColor(255, 0, 0, 255); lowerWindowLine->SetColor(255, 0, 0, 255); @@ -192,25 +205,25 @@ void vvToolHistogram::computeHistogram() this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer()); HistogramWidget->show(); - //mView->GetInteractor()->Start(); - QApplication::restoreOverrideCursor(); } //------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void vvToolHistogram::changeWindowLevel() { - vtkChartXY* chart = vtkChartXY::New(); - chart = static_cast(mView->GetScene()->GetItem(0)); vtkFloatArray* upperArray = vtkFloatArray::New(); - upperArray = static_cast(chart->GetPlot(1)->GetInput()->GetColumn(0)); + upperArray = static_cast(mTableWindowLevel->GetColumn(0)); upperArray->SetTuple1(0, mMaxWindowLevel); upperArray->SetTuple1(1, mMaxWindowLevel); vtkFloatArray* lowerArray = vtkFloatArray::New(); - lowerArray = static_cast(chart->GetPlot(2)->GetInput()->GetColumn(1)); + lowerArray = static_cast(mTableWindowLevel->GetColumn(1)); lowerArray->SetTuple1(0, mMinWindowLevel); lowerArray->SetTuple1(1, mMinWindowLevel); + displayHistogram(); + mCurrentSlicerManager->UpdateWindowLevel(); + mCurrentSlicerManager->Render(); } //------------------------------------------------------------------------------ @@ -227,12 +240,6 @@ void vvToolHistogram::windowLevelChanged() //------------------------------------------------------------------------------ void vvToolHistogram::RemoveVTKObjects() { - if (mCurrentSlicerManager) - { - connect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float))); - - mCurrentSlicerManager->Render(); - } } //------------------------------------------------------------------------------ @@ -240,8 +247,13 @@ void vvToolHistogram::RemoveVTKObjects() //------------------------------------------------------------------------------ bool vvToolHistogram::close() { - //RemoveVTKObjects(); - + if (!mModificationsDone) + { + mCurrentSlicerManager->SetColorLevel(originalLevel); + mCurrentSlicerManager->SetColorWindow(originalWindow); + mCurrentSlicerManager->UpdateWindowLevel(); + mCurrentSlicerManager->Render(); + } return vvToolWidgetBase::close(); } //------------------------------------------------------------------------------ @@ -274,12 +286,34 @@ void vvToolHistogram::InputIsSelected(vvSlicerManager * m) mSaveHistogramButton->setEnabled(true); mTextFileName = "Histogram.txt"; + mTableWindowLevel = vtkSmartPointer::New(); + mTable = vtkSmartPointer::New(); + + originalWindow = mCurrentSlicerManager->GetColorWindow(); + originalLevel = mCurrentSlicerManager->GetColorLevel(); + //Compute Min & Max for Window/Level computeMinMax(); computeHistogram(); - disconnect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float))); + // Connect signals & slots + vvToolHistogramCommand *smc = vvToolHistogramCommand::New(); + smc->mHist = this; + HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonPressEvent, smc); + HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseMoveEvent, smc); + HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelForwardEvent, smc); + HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelBackwardEvent, smc); + smc->Delete(); + +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +QVTKWidget* vvToolHistogram::GetHistogramWidget() +{ + return(HistogramWidget); } //------------------------------------------------------------------------------ @@ -302,6 +336,36 @@ void vvToolHistogram::computeWindowLevel() //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void vvToolHistogram::expandWindow() +{ + mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()+10.0); + computeMinMax(); + changeWindowLevel(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolHistogram::reduceWindow() +{ + mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()-10.0); + computeMinMax(); + changeWindowLevel(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolHistogram::translateWindow(double x) +{ + mCurrentSlicerManager->SetColorLevel(mCurrentSlicerManager->GetColorLevel()+10.0*x); + computeMinMax(); + changeWindowLevel(); +} +//------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------ void vvToolHistogram::GetArgsInfoFromGUI() { @@ -333,7 +397,8 @@ void vvToolHistogram::GetArgsInfoFromGUI() //------------------------------------------------------------------------------ void vvToolHistogram::apply() -{ +{ + mModificationsDone = true; close(); } //------------------------------------------------------------------------------ diff --git a/vv/vvToolHistogram.h b/vv/vvToolHistogram.h index d81aee7..ce58d07 100644 --- a/vv/vvToolHistogram.h +++ b/vv/vvToolHistogram.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include //------------------------------------------------------------------------------ class vvToolHistogram: @@ -53,12 +55,20 @@ class vvToolHistogram: void computeMinMax(); void SetPoints(); + void displayHistogram(); + + QVTKWidget* GetHistogramWidget(); + //----------------------------------------------------- public slots: virtual void apply(); virtual bool close(); virtual void reject(); - virtual void windowLevelChanged(); + + void windowLevelChanged(); + void reduceWindow(); + void expandWindow(); + void translateWindow(double x); void SaveAs(); @@ -70,8 +80,15 @@ class vvToolHistogram: double mMinWindowLevel; double mMaxWindowLevel; + double originalWindow; + double originalLevel; + bool mModificationsDone; vtkSmartPointer mView; + + vtkSmartPointer mTableWindowLevel; + vtkSmartPointer mTable; + //vtkSmartPointer mView; clitk::HistogramImageGenericFilter::Pointer mFilter; std::string mTextFileName; diff --git a/vv/vvToolHistogramCommand.cxx b/vv/vvToolHistogramCommand.cxx new file mode 100644 index 0000000..585f16c --- /dev/null +++ b/vv/vvToolHistogramCommand.cxx @@ -0,0 +1,73 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ +#include "vvToolHistogramCommand.h" +#include "vvSlicerManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vvSlicer.h" +#include "vvInteractorStyleNavigator.h" +#include "vtkTransform.h" + +#include +//------------------------------------------------------------------------------ +vvToolHistogramCommand::vvToolHistogramCommand() +{ + mFollowMouse = false; +} +//------------------------------------------------------------------------------ + + + + +//------------------------------------------------------------------------------ +void vvToolHistogramCommand::Execute(vtkObject *caller, + unsigned long event, + void *vtkNotUsed(callData)) +{ + if (event == vtkCommand::MouseWheelForwardEvent) { + mHist->expandWindow(); + } + if (event == vtkCommand::MouseWheelBackwardEvent) { + mHist->reduceWindow(); + } + if (event == vtkCommand::LeftButtonPressEvent) { + mFollowMouse = !mFollowMouse; + } + if (event == vtkCommand::MouseMoveEvent) { + if (mFollowMouse) { + vtkSmartPointer interactor = mHist->GetHistogramWidget()->GetRenderWindow()->GetInteractor(); + if (interactor->GetEventPosition()[0] != interactor->GetLastEventPosition()[0]) + mHist->translateWindow(interactor->GetEventPosition()[0] - interactor->GetLastEventPosition()[0]); + } + } +} +//------------------------------------------------------------------------------ diff --git a/vv/vvToolHistogramCommand.h b/vv/vvToolHistogramCommand.h new file mode 100644 index 0000000..0a73dbe --- /dev/null +++ b/vv/vvToolHistogramCommand.h @@ -0,0 +1,56 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ +#ifndef __vvToolHistogramCommand_h +#define __vvToolHistogramCommand_h +#include "vtkCommand.h" +#include "vvSlicerManager.h" +#include "vvToolHistogram.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkImageData.h" +#include "vtkImageActor.h" +#include "vvInteractorStyleNavigator.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkInteractorStyleImage.h" +#include "vtkPropPicker.h" + +#include +#include +#include + +class vvToolHistogramCommand : public vtkCommand +{ +public: + static vvToolHistogramCommand *New() { + return new vvToolHistogramCommand; + } + + void Execute(vtkObject *caller, + unsigned long event, + void *vtkNotUsed(callData)); + + vvToolHistogram* mHist; + +protected : + vvToolHistogramCommand(); + ~vvToolHistogramCommand() {} + + bool mFollowMouse; +}; + +#endif -- 2.47.1