MPRReslice UI and windowlevel fix.

This commit is contained in:
Krad
2023-01-06 16:55:12 +08:00
parent f67cdd3a5c
commit 679170af7c
9 changed files with 204 additions and 7 deletions

View File

@@ -12,6 +12,7 @@
#include <vtkCamera.h> #include <vtkCamera.h>
#include <vtkPropCollection.h> #include <vtkPropCollection.h>
#include <vtkPropPicker.h> #include <vtkPropPicker.h>
#include <vtkImageProperty.h>
#include "Rendering/Core/RenderingDefines.h" #include "Rendering/Core/RenderingDefines.h"
#include "Rendering/Legend/ResliceCursorLegendActor.h" #include "Rendering/Legend/ResliceCursorLegendActor.h"
@@ -88,27 +89,29 @@ void ResliceImageInteractorStyle::OnLeftButtonDown() {
cursor->SetDragStartPosition(pos); cursor->SetDragStartPosition(pos);
cursor->StartDrag(); cursor->StartDrag();
} }
else if (this->InteractionMode == VTKIS_WINDOW_LEVEL) else if (this->InteractionMode == VTKIS_IMAGE_WINDOWLEVEL)
{ {
this->WindowLevelStartPosition[0] = pos[0]; this->WindowLevelStartPosition[0] = pos[0];
this->WindowLevelStartPosition[1] = pos[1]; this->WindowLevelStartPosition[1] = pos[1];
this->StartWindowLevel(); this->StartWindowLevel();
} }
else if (this->InteractionMode == VTKIS_IMAGE3D) else if (this->InteractionMode == VTKIS_IMAGE_ROTATE3D)
{ {
this->StartRotate(); this->StartRotate();
} }
else if (this->InteractionMode == VTKIS_IMAGE2D) else if (this->InteractionMode == VTKIS_IMAGE_ROTATE2D)
{ {
this->StartSpin(); this->StartSpin();
} }
else if (this->InteractionMode == VTKIS_IMAGE_SLICING) else if (this->InteractionMode == VTKIS_IMAGE_SLICE)
{ {
this->StartSlice(); this->StartSlice();
} }
else else if (this->InteractionMode == VTKIS_IMAGE_ZOOM){
{ this->StartDolly();
this->Superclass::OnLeftButtonDown(); }
else if (this->InteractionMode == VTKIS_IMAGE_PAN){
this->StartPan();
} }
} }
@@ -142,3 +145,90 @@ void ResliceImageInteractorStyle::NoneStatePick() {
} }
return; 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;
}

View File

@@ -24,12 +24,19 @@ public:
void OnMouseMove() override; void OnMouseMove() override;
void StartWindowLevel() override;
void WindowLevel() override;
void SetMode(int mode);
virtual void StartCursorInteractive(){ virtual void StartCursorInteractive(){
this->State = VTKIS_POSITION_PROP; this->State = VTKIS_POSITION_PROP;
} }
virtual void StopCursorInteractive(){ virtual void StopCursorInteractive(){
this->State = VTKIS_NONE; this->State = VTKIS_NONE;
} }
vtkSetMacro(CurrentImageProperty, vtkImageProperty*);
protected: protected:
ResliceImageInteractorStyle(); ResliceImageInteractorStyle();

View File

@@ -15,6 +15,7 @@
#include <vtkImageSlice.h> #include <vtkImageSlice.h>
#include <vtkMatrix4x4.h> #include <vtkMatrix4x4.h>
#include <vtkProperty2D.h> #include <vtkProperty2D.h>
#include <vtkImageProperty.h>
#include <vtkTextProperty.h> #include <vtkTextProperty.h>
@@ -130,6 +131,7 @@ void ResliceImageViewer::InstallPipeline() {
if (this->Renderer && this->Actor) { if (this->Renderer && this->Actor) {
this->Renderer->AddViewProp(Actor); this->Renderer->AddViewProp(Actor);
this->InteractorStyle->SetCurrentImageProperty(Actor->GetProperty());
this->Renderer->SetBackground(0., 0., 0.); this->Renderer->SetBackground(0., 0., 0.);
} }
} }
@@ -150,6 +152,7 @@ void ResliceImageViewer::UnInstallPipeline() {
Renderer->RemoveAllObservers(); Renderer->RemoveAllObservers();
} }
if (this->Interactor) { if (this->Interactor) {
this->InteractorStyle->SetCurrentImageProperty(nullptr);
this->Interactor->SetInteractorStyle(nullptr); this->Interactor->SetInteractorStyle(nullptr);
this->Interactor->SetRenderWindow(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::IMAGE_INTERACT_OFF,this,&ResliceImageViewer::ResetHandle);
this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::EndDrag); this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::EndDrag);
this->InteractorStyle->AddObserver(SliceEvent,this, &ResliceImageViewer::SliceCallback); 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); this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize);
cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll);
@@ -439,3 +444,34 @@ void ResliceImageViewer::SliceCallback() {
this->InvokeEvent(SliceEvent); 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);
}

View File

@@ -43,23 +43,43 @@ public:
void SetInputData(vtkImageData *in); void SetInputData(vtkImageData *in);
void SetStyleMode(int mode);
void SetDefaultSliceOrientation(int orientation); void SetDefaultSliceOrientation(int orientation);
void SetCoordsTransformMatrix(vtkMatrix4x4* matrix4X4); void SetCoordsTransformMatrix(vtkMatrix4x4* matrix4X4);
double* GetCursorSlicePoint(); double* GetCursorSlicePoint();
double* GetCursorSliceDirection1(); double* GetCursorSliceDirection1();
double* GetCursorSliceDirection2(); double* GetCursorSliceDirection2();
void AdjustOrthogonalScale(); void AdjustOrthogonalScale();
void ChangeSlicePoint(double * point); void ChangeSlicePoint(double * point);
void ChangeSliceNormal(double * normal); void ChangeSliceNormal(double * normal);
void EndDrag(); void EndDrag();
void UpdateSliceCursor(); void UpdateSliceCursor();
void AdjustCameraFollowCursor(); void AdjustCameraFollowCursor();
void SetChecked(bool checked); void SetChecked(bool checked);
void InvokeClick(); void InvokeClick();
void SliceCallback(); void SliceCallback();
void WindowLevelCallback();
void EndWindowLevelCallback();
void GetWindowLevel(double* windowLeveL);
void SetWindowLevel(double* windowLeveL);
protected: protected:
ResliceImageViewer(); ResliceImageViewer();

View File

@@ -44,6 +44,9 @@ void ResliceImageManager::InitEvents() {
viewerA->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback); viewerA->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback);
viewerS->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback); viewerS->AddObserver(vtkCommand::LeftButtonPressEvent,this,&ResliceImageManager::ClickCallback);
viewerC->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); viewerA->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback);
viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback);
viewerC->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);
}
}
}

View File

@@ -21,6 +21,7 @@ public :
void SetViewer(int index, ResliceImageViewer* viewer); void SetViewer(int index, ResliceImageViewer* viewer);
void InitEvents(); void InitEvents();
void SetMode(int mode);
private: private:
std::vector<ResliceImageViewer*> mViewers; std::vector<ResliceImageViewer*> mViewers;
ResliceImageViewer * viewerA; ResliceImageViewer * viewerA;
@@ -30,6 +31,7 @@ private:
void RollCallback(vtkObject* sender, unsigned long eventID, void* data); void RollCallback(vtkObject* sender, unsigned long eventID, void* data);
void MoveCallback(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 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 SliceCallback(vtkObject* sender, unsigned long eventID, void* data);
void EndDrag(vtkObject* sender, unsigned long eventID, void* data); void EndDrag(vtkObject* sender, unsigned long eventID, void* data);
}; };

View File

@@ -69,6 +69,7 @@ MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog
manager->SetViewer(2,mViewerS); manager->SetViewer(2,mViewerS);
manager->InitEvents(); manager->InitEvents();
connect(toolBar, &ResliceMPRToolBar::modeButtonClicked,manager,&ResliceImageManager::SetMode);
} }
MPRResliceWindow::~MPRResliceWindow() { MPRResliceWindow::~MPRResliceWindow() {
@@ -212,15 +213,25 @@ void MPRResliceWindow::loadData(SeriesImageSet *series) {
mViewerC->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerC->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix());
mViewerC->SetInputData(series->GetData()); mViewerC->SetInputData(series->GetData());
mViewerC->SetDefaultSliceOrientation(2); mViewerC->SetDefaultSliceOrientation(2);
mViewerC->SetWindowLevel(mWindowLevel);
mViewerC->Render(); mViewerC->Render();
mViewerS->SetRenderWindow(mWidgetSagittal->renderWindow()); mViewerS->SetRenderWindow(mWidgetSagittal->renderWindow());
mViewerS->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerS->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix());
mViewerS->SetInputData(series->GetData()); mViewerS->SetInputData(series->GetData());
mViewerS->SetDefaultSliceOrientation(1); mViewerS->SetDefaultSliceOrientation(1);
mViewerS->SetWindowLevel(mWindowLevel);
mViewerS->Render(); mViewerS->Render();
mViewerA->SetRenderWindow(mWidgetAxial->renderWindow()); mViewerA->SetRenderWindow(mWidgetAxial->renderWindow());
mViewerA->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix()); mViewerA->SetCoordsTransformMatrix(series->GetProperty()->GetOrientationMatrix());
mViewerA->SetInputData(series->GetData()); mViewerA->SetInputData(series->GetData());
mViewerA->SetDefaultSliceOrientation(0); mViewerA->SetDefaultSliceOrientation(0);
mViewerA->SetWindowLevel(mWindowLevel);
mViewerA->Render(); mViewerA->Render();
} }
void MPRResliceWindow::SetDefaultWindowLevel(double* windowLevel) {
if (windowLevel){
mWindowLevel[0] = windowLevel[0];
mWindowLevel[1] = windowLevel[1];
}
}

View File

@@ -32,6 +32,7 @@ public:
Rows_1_1_1, Rows_1_1_1,
}; };
void loadData(SeriesImageSet* series); void loadData(SeriesImageSet* series);
void SetDefaultWindowLevel(double * windowLevel);
void setRenderWindowLayout(LayoutType type); void setRenderWindowLayout(LayoutType type);
private: private:
QVTKOpenGLNativeWidget *mWidgetAxial; QVTKOpenGLNativeWidget *mWidgetAxial;
@@ -44,6 +45,7 @@ private:
ResliceImageManager* manager = nullptr; ResliceImageManager* manager = nullptr;
QSplitter* mMainSplitter= nullptr; QSplitter* mMainSplitter= nullptr;
QSplitter* mAppendSplitter= nullptr; QSplitter* mAppendSplitter= nullptr;
double mWindowLevel[2]={.0, .0};
int layoutType = 0; int layoutType = 0;
}; };

View File

@@ -178,10 +178,13 @@ void QDicomViewer::initViewOperation() {
}); });
// MPR // MPR
connect(ui->toolBar, &DefaultToolBar::requestMPR,[=](){ connect(ui->toolBar, &DefaultToolBar::requestMPR,[=](){
DicomImageView *curV = ui->viewContainer->getCurrentView();
auto mprWin = new MPRResliceWindow(this); auto mprWin = new MPRResliceWindow(this);
connect(mprWin,&QDialog::finished,[=](){ connect(mprWin,&QDialog::finished,[=](){
mprWin->deleteLater(); mprWin->deleteLater();
}); });
double windowLevel[2] = {curV->getImageViewer()->GetColorWindow(),curV->getImageViewer()->GetColorLevel()};
mprWin->SetDefaultWindowLevel(windowLevel);
mprWin->show(); mprWin->show();
mprWin->loadData(ui->viewContainer->getViewManager()->getCurrentView()->getSeriesInstance()); mprWin->loadData(ui->viewContainer->getViewManager()->getCurrentView()->getSeriesInstance());
}); });