From 679170af7c4dab85a71725d805ee8a33495de058 Mon Sep 17 00:00:00 2001 From: Krad Date: Fri, 6 Jan 2023 16:55:12 +0800 Subject: [PATCH] MPRReslice UI and windowlevel fix. --- .../ResliceImageInteractorStyle.cpp | 104 ++++++++++++++++-- .../Interaction/ResliceImageInteractorStyle.h | 7 ++ .../Rendering/Viewer/ResliceImageViewer.cpp | 36 ++++++ src/src/Rendering/Viewer/ResliceImageViewer.h | 20 ++++ src/src/UI/Manager/ResliceImageManager.cpp | 26 +++++ src/src/UI/Manager/ResliceImageManager.h | 2 + src/src/UI/Window/MPRResliceWindow.cpp | 11 ++ src/src/UI/Window/MPRResliceWindow.h | 2 + src/src/UI/Window/QDicomViewer.cpp | 3 + 9 files changed, 204 insertions(+), 7 deletions(-) diff --git a/src/src/Interaction/ResliceImageInteractorStyle.cpp b/src/src/Interaction/ResliceImageInteractorStyle.cpp index 071136f..9b6f668 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.cpp +++ b/src/src/Interaction/ResliceImageInteractorStyle.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "Rendering/Core/RenderingDefines.h" #include "Rendering/Legend/ResliceCursorLegendActor.h" @@ -88,27 +89,29 @@ void ResliceImageInteractorStyle::OnLeftButtonDown() { cursor->SetDragStartPosition(pos); cursor->StartDrag(); } - else if (this->InteractionMode == VTKIS_WINDOW_LEVEL) + else if (this->InteractionMode == VTKIS_IMAGE_WINDOWLEVEL) { this->WindowLevelStartPosition[0] = pos[0]; this->WindowLevelStartPosition[1] = pos[1]; this->StartWindowLevel(); } - else if (this->InteractionMode == VTKIS_IMAGE3D) + else if (this->InteractionMode == VTKIS_IMAGE_ROTATE3D) { this->StartRotate(); } - else if (this->InteractionMode == VTKIS_IMAGE2D) + else if (this->InteractionMode == VTKIS_IMAGE_ROTATE2D) { this->StartSpin(); } - else if (this->InteractionMode == VTKIS_IMAGE_SLICING) + else if (this->InteractionMode == VTKIS_IMAGE_SLICE) { this->StartSlice(); } - else - { - this->Superclass::OnLeftButtonDown(); + else if (this->InteractionMode == VTKIS_IMAGE_ZOOM){ + this->StartDolly(); + } + else if (this->InteractionMode == VTKIS_IMAGE_PAN){ + this->StartPan(); } } @@ -142,3 +145,90 @@ void ResliceImageInteractorStyle::NoneStatePick() { } return; } + +void ResliceImageInteractorStyle::StartWindowLevel() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_WINDOW_LEVEL); + + if (this->HandleObservers && this->HasObserver(vtkCommand::StartWindowLevelEvent)) + { + this->InvokeEvent(vtkCommand::StartWindowLevelEvent, this); + } + else + { + if (this->CurrentImageProperty) + { + vtkImageProperty* property = this->CurrentImageProperty; + this->WindowLevelInitial[0] = property->GetColorWindow(); + this->WindowLevelInitial[1] = property->GetColorLevel(); + } + } +} + +void ResliceImageInteractorStyle::WindowLevel() { + vtkRenderWindowInteractor *rwi = this->Interactor; + + this->WindowLevelCurrentPosition[0] = rwi->GetEventPosition()[0]; + this->WindowLevelCurrentPosition[1] = rwi->GetEventPosition()[1]; + + if (this->CurrentImageProperty) { + int *size = this->CurrentRenderer->GetSize(); + + double window = this->WindowLevelInitial[0]; + double level = this->WindowLevelInitial[1]; + + // Compute normalized delta + + double dx = (this->WindowLevelCurrentPosition[0] - + this->WindowLevelStartPosition[0]) * 4.0 / size[0]; + double dy = (this->WindowLevelStartPosition[1] - + this->WindowLevelCurrentPosition[1]) * 4.0 / size[1]; + + // Scale by current values + + if (fabs(window) > 0.01) { + dx = dx * window; + } else { + dx = dx * (window < 0 ? -0.01 : 0.01); + } + if (fabs(level) > 0.01) { + dy = dy * level; + } else { + dy = dy * (level < 0 ? -0.01 : 0.01); + } + + // Abs so that direction does not flip + + if (window < 0.0) { + dx = -1 * dx; + } + if (level < 0.0) { + dy = -1 * dy; + } + + // Compute new window level + + double newWindow = dx + window; + double newLevel = level - dy; + + if (newWindow < 0.01) { + newWindow = 0.01; + } + + this->CurrentImageProperty->SetColorWindow(newWindow); + this->CurrentImageProperty->SetColorLevel(newLevel); + if (this->HandleObservers && + this->HasObserver(vtkCommand::WindowLevelEvent)) { + this->InvokeEvent(vtkCommand::WindowLevelEvent, this); + } + this->Interactor->Render(); + } +} + +void ResliceImageInteractorStyle::SetMode(int mode) { + this->InteractionMode = mode; +} diff --git a/src/src/Interaction/ResliceImageInteractorStyle.h b/src/src/Interaction/ResliceImageInteractorStyle.h index 9e9abf9..09eb2e6 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.h +++ b/src/src/Interaction/ResliceImageInteractorStyle.h @@ -24,12 +24,19 @@ public: void OnMouseMove() override; + void StartWindowLevel() override; + + void WindowLevel() override; + + void SetMode(int mode); + virtual void StartCursorInteractive(){ this->State = VTKIS_POSITION_PROP; } virtual void StopCursorInteractive(){ this->State = VTKIS_NONE; } + vtkSetMacro(CurrentImageProperty, vtkImageProperty*); protected: ResliceImageInteractorStyle(); diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.cpp b/src/src/Rendering/Viewer/ResliceImageViewer.cpp index ce89918..8a26d30 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.cpp +++ b/src/src/Rendering/Viewer/ResliceImageViewer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -130,6 +131,7 @@ void ResliceImageViewer::InstallPipeline() { if (this->Renderer && this->Actor) { this->Renderer->AddViewProp(Actor); + this->InteractorStyle->SetCurrentImageProperty(Actor->GetProperty()); this->Renderer->SetBackground(0., 0., 0.); } } @@ -150,6 +152,7 @@ void ResliceImageViewer::UnInstallPipeline() { Renderer->RemoveAllObservers(); } if (this->Interactor) { + this->InteractorStyle->SetCurrentImageProperty(nullptr); this->Interactor->SetInteractorStyle(nullptr); this->Interactor->SetRenderWindow(nullptr); } @@ -229,6 +232,8 @@ void ResliceImageViewer::Render() { this->InteractorStyle->AddObserver(ResliceCursorLegendActor::IMAGE_INTERACT_OFF,this,&ResliceImageViewer::ResetHandle); this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::EndDrag); this->InteractorStyle->AddObserver(SliceEvent,this, &ResliceImageViewer::SliceCallback); + this->InteractorStyle->AddObserver(vtkCommand::WindowLevelEvent,this, &ResliceImageViewer::WindowLevelCallback); + this->InteractorStyle->AddObserver(vtkCommand::EndWindowLevelEvent,this, &ResliceImageViewer::EndWindowLevelCallback); this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize); cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); @@ -439,3 +444,34 @@ void ResliceImageViewer::SliceCallback() { this->InvokeEvent(SliceEvent); } } + +void ResliceImageViewer::EndWindowLevelCallback() { + this->InvokeEvent(vtkCommand::EndWindowLevelEvent); +} + +void ResliceImageViewer::SetStyleMode(int mode) { + this->InteractorStyle->SetMode(mode); +} + +void ResliceImageViewer::GetWindowLevel(double* windowLevel) { + if (windowLevel){ + windowLevel[0] = Actor->GetProperty()->GetColorWindow(); + windowLevel[1] = Actor->GetProperty()->GetColorLevel(); + } +} + +void ResliceImageViewer::SetWindowLevel(double* windowLevel) { + if (windowLevel){ + Actor->GetProperty()->SetColorWindow(windowLevel[0]); + Actor->GetProperty()->SetColorLevel(windowLevel[1]); + WindowLevelCallback(); + Render(); + } +} + +void ResliceImageViewer::WindowLevelCallback() { + char buff[1024] = {0}; + sprintf(buff,"WL:%d WW: %d",(int)Actor->GetProperty()->GetColorLevel(), + (int)Actor->GetProperty()->GetColorWindow()); + annotation->SetText(5, buff); +} diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.h b/src/src/Rendering/Viewer/ResliceImageViewer.h index 958b32b..00a44c7 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.h +++ b/src/src/Rendering/Viewer/ResliceImageViewer.h @@ -43,23 +43,43 @@ public: void SetInputData(vtkImageData *in); + void SetStyleMode(int mode); + void SetDefaultSliceOrientation(int orientation); + void SetCoordsTransformMatrix(vtkMatrix4x4* matrix4X4); double* GetCursorSlicePoint(); + double* GetCursorSliceDirection1(); + double* GetCursorSliceDirection2(); void AdjustOrthogonalScale(); + void ChangeSlicePoint(double * point); + void ChangeSliceNormal(double * normal); + void EndDrag(); + void UpdateSliceCursor(); + void AdjustCameraFollowCursor(); void SetChecked(bool checked); + void InvokeClick(); + void SliceCallback(); + + void WindowLevelCallback(); + + void EndWindowLevelCallback(); + + void GetWindowLevel(double* windowLeveL); + + void SetWindowLevel(double* windowLeveL); protected: ResliceImageViewer(); diff --git a/src/src/UI/Manager/ResliceImageManager.cpp b/src/src/UI/Manager/ResliceImageManager.cpp index b6ec30b..f2109ae 100644 --- a/src/src/UI/Manager/ResliceImageManager.cpp +++ b/src/src/UI/Manager/ResliceImageManager.cpp @@ -44,6 +44,9 @@ void ResliceImageManager::InitEvents() { viewerA->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback); viewerS->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback); viewerC->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback); + viewerA->AddObserver(vtkCommand::EndWindowLevelEvent,this,&ResliceImageManager::WindowLevelCallback); + viewerS->AddObserver(vtkCommand::EndWindowLevelEvent,this,&ResliceImageManager::WindowLevelCallback); + viewerC->AddObserver(vtkCommand::EndWindowLevelEvent,this,&ResliceImageManager::WindowLevelCallback); viewerA->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerC->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); @@ -117,3 +120,26 @@ void ResliceImageManager::ClickCallback(vtkObject *sender, unsigned long eventID } } +void ResliceImageManager::SetMode(int mode) { + viewerA->SetStyleMode(mode); + viewerS->SetStyleMode(mode); + viewerC->SetStyleMode(mode); +} + +void ResliceImageManager::WindowLevelCallback(vtkObject *sender, unsigned long eventID, void *data) { + auto viewer = ResliceImageViewer::SafeDownCast(sender); + double windowLevel[2]={.0,.0}; + viewer->GetWindowLevel(windowLevel); + if (viewer) { + if (viewer!=viewerA){ + viewerA->SetWindowLevel(windowLevel); + } + if (viewer!=viewerC){ + viewerC->SetWindowLevel(windowLevel); + } + if (viewer!=viewerS){ + viewerS->SetWindowLevel(windowLevel); + } + } +} + diff --git a/src/src/UI/Manager/ResliceImageManager.h b/src/src/UI/Manager/ResliceImageManager.h index acb1da0..07fc5ab 100644 --- a/src/src/UI/Manager/ResliceImageManager.h +++ b/src/src/UI/Manager/ResliceImageManager.h @@ -21,6 +21,7 @@ public : void SetViewer(int index, ResliceImageViewer* viewer); void InitEvents(); + void SetMode(int mode); private: std::vector mViewers; ResliceImageViewer * viewerA; @@ -30,6 +31,7 @@ private: void RollCallback(vtkObject* sender, unsigned long eventID, void* data); void MoveCallback(vtkObject* sender, unsigned long eventID, void* data); void ClickCallback(vtkObject* sender, unsigned long eventID, void* data); + void WindowLevelCallback(vtkObject* sender, unsigned long eventID, void* data); // void SliceCallback(vtkObject* sender, unsigned long eventID, void* data); void EndDrag(vtkObject* sender, unsigned long eventID, void* data); }; diff --git a/src/src/UI/Window/MPRResliceWindow.cpp b/src/src/UI/Window/MPRResliceWindow.cpp index 3c4eba4..14c1a03 100644 --- a/src/src/UI/Window/MPRResliceWindow.cpp +++ b/src/src/UI/Window/MPRResliceWindow.cpp @@ -69,6 +69,7 @@ MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog manager->SetViewer(2,mViewerS); manager->InitEvents(); + connect(toolBar, &ResliceMPRToolBar::modeButtonClicked,manager,&ResliceImageManager::SetMode); } MPRResliceWindow::~MPRResliceWindow() { @@ -212,15 +213,25 @@ void MPRResliceWindow::loadData(SeriesImageSet *series) { mViewerC->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerC->SetInputData(series->GetData()); mViewerC->SetDefaultSliceOrientation(2); + mViewerC->SetWindowLevel(mWindowLevel); mViewerC->Render(); mViewerS->SetRenderWindow(mWidgetSagittal->renderWindow()); mViewerS->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerS->SetInputData(series->GetData()); mViewerS->SetDefaultSliceOrientation(1); + mViewerS->SetWindowLevel(mWindowLevel); mViewerS->Render(); mViewerA->SetRenderWindow(mWidgetAxial->renderWindow()); mViewerA->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerA->SetInputData(series->GetData()); mViewerA->SetDefaultSliceOrientation(0); + mViewerA->SetWindowLevel(mWindowLevel); mViewerA->Render(); } + +void MPRResliceWindow::SetDefaultWindowLevel(double* windowLevel) { + if (windowLevel){ + mWindowLevel[0] = windowLevel[0]; + mWindowLevel[1] = windowLevel[1]; + } +} diff --git a/src/src/UI/Window/MPRResliceWindow.h b/src/src/UI/Window/MPRResliceWindow.h index 7f41f78..726a6c2 100644 --- a/src/src/UI/Window/MPRResliceWindow.h +++ b/src/src/UI/Window/MPRResliceWindow.h @@ -32,6 +32,7 @@ public: Rows_1_1_1, }; void loadData(SeriesImageSet* series); + void SetDefaultWindowLevel(double * windowLevel); void setRenderWindowLayout(LayoutType type); private: QVTKOpenGLNativeWidget *mWidgetAxial; @@ -44,6 +45,7 @@ private: ResliceImageManager* manager = nullptr; QSplitter* mMainSplitter= nullptr; QSplitter* mAppendSplitter= nullptr; + double mWindowLevel[2]={.0, .0}; int layoutType = 0; }; diff --git a/src/src/UI/Window/QDicomViewer.cpp b/src/src/UI/Window/QDicomViewer.cpp index 24e7e3c..2ecd609 100644 --- a/src/src/UI/Window/QDicomViewer.cpp +++ b/src/src/UI/Window/QDicomViewer.cpp @@ -178,10 +178,13 @@ void QDicomViewer::initViewOperation() { }); // MPR connect(ui->toolBar, &DefaultToolBar::requestMPR,[=](){ + DicomImageView *curV = ui->viewContainer->getCurrentView(); auto mprWin = new MPRResliceWindow(this); connect(mprWin,&QDialog::finished,[=](){ mprWin->deleteLater(); }); + double windowLevel[2] = {curV->getImageViewer()->GetColorWindow(),curV->getImageViewer()->GetColorLevel()}; + mprWin->SetDefaultWindowLevel(windowLevel); mprWin->show(); mprWin->loadData(ui->viewContainer->getViewManager()->getCurrentView()->getSeriesInstance()); });