From 90b43986616f82e76cfb60ef3e7bccb7aeea328b Mon Sep 17 00:00:00 2001 From: Krad Date: Thu, 16 Mar 2023 11:08:20 +0800 Subject: [PATCH] Add 3D Reslice MPR free rotate. --- .../ResliceImageInteractorStyle.cpp | 46 +++++++++++++++++++ .../Interaction/ResliceImageInteractorStyle.h | 5 ++ .../Legend/ResliceCursorLegendActor.cpp | 17 ++++++- .../Legend/ResliceCursorLegendActor.h | 8 ++++ .../Rendering/Viewer/ResliceImageViewer.cpp | 24 ++++++++++ src/src/Rendering/Viewer/ResliceImageViewer.h | 6 +++ src/src/UI/Manager/ResliceImageManager.cpp | 41 +++++++++++++++-- src/src/UI/Manager/ResliceImageManager.h | 1 + 8 files changed, 142 insertions(+), 6 deletions(-) diff --git a/src/src/Interaction/ResliceImageInteractorStyle.cpp b/src/src/Interaction/ResliceImageInteractorStyle.cpp index 9b6f668..ef8c5f8 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.cpp +++ b/src/src/Interaction/ResliceImageInteractorStyle.cpp @@ -232,3 +232,49 @@ void ResliceImageInteractorStyle::WindowLevel() { void ResliceImageInteractorStyle::SetMode(int mode) { this->InteractionMode = mode; } + +void ResliceImageInteractorStyle::Rotate() +{ + if (this->CurrentRenderer == nullptr) + { + return; + } + + vtkRenderWindowInteractor* rwi = this->Interactor; + + int dx = rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0]; + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + + const int* size = this->CurrentRenderer->GetRenderWindow()->GetSize(); + + double delta_elevation = -20.0 / size[1]; + double delta_azimuth = -20.0 / size[0]; + + double rxf = dx * delta_azimuth * this->MotionFactor; + double ryf = dy * delta_elevation * this->MotionFactor; + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->Azimuth(rxf); + camera->Elevation(ryf); + camera->OrthogonalizeViewUp(); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + if (this->HandleObservers && + this->HasObserver(vtkCommand::RotateEvent)) { + this->InvokeEvent(vtkCommand::RotateEvent, this); + } + rwi->Render(); +} + +void ResliceImageInteractorStyle::EndRotate() { + this->InvokeEvent(vtkCommand::EndRotateEvent); + vtkInteractorStyle::EndRotate(); +} diff --git a/src/src/Interaction/ResliceImageInteractorStyle.h b/src/src/Interaction/ResliceImageInteractorStyle.h index 09eb2e6..11a2c11 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.h +++ b/src/src/Interaction/ResliceImageInteractorStyle.h @@ -37,6 +37,11 @@ public: this->State = VTKIS_NONE; } vtkSetMacro(CurrentImageProperty, vtkImageProperty*); + + void Rotate() override; + + void EndRotate() override; + protected: ResliceImageInteractorStyle(); diff --git a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp index d338b1a..1501940 100644 --- a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp +++ b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp @@ -129,7 +129,13 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { if(dragging){ Drag(renderer); } + auto style = vtkInteractorStyle::SafeDownCast(renderer->GetRenderWindow()->GetInteractor()->GetInteractorStyle()); + if (style){ + //avoid 3d rotate update + if (style->GetState() == VTKIS_ROTATE) return; + } if (LoadTime.GetMTime()>MTime.GetMTime() && LoadTime.GetMTime()>renderer->GetActiveCamera()->GetMTime()) return; + if (StopUpdateFlag) return; //handle disk if (HandleUpdated) { renderer->SetDisplayPoint(Handle2DPoint[0], Handle2DPoint[1], 0); @@ -187,8 +193,15 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { if (IntersectLine2D(p0, v1, pt, screenVectors[i], intersectPoint)) { int pcV = (int) intersectPoint.getValue(i); if (pcV >= -1 && pcV <= size[i] + 1) { - linePolyData->GetPoints()->SetPoint(pointIdx++, (int) intersectPoint.X + 0.05, - (int) intersectPoint.Y + 0.05, 0); + //避免double计算精度导致的极小的移动产生的hair cross振动 + double oldPt[3] = {.0, .0, .0}; + linePolyData->GetPoints()->GetPoint(pointIdx, oldPt); + double newPt[3] = {(int) intersectPoint.X + 0.05, + (int) intersectPoint.Y + 0.05, .0}; + if (vtkMath::Distance2BetweenPoints(oldPt,newPt)>0.9){ + linePolyData->GetPoints()->SetPoint(pointIdx, newPt); + } + pointIdx++; } } } diff --git a/src/src/Rendering/Legend/ResliceCursorLegendActor.h b/src/src/Rendering/Legend/ResliceCursorLegendActor.h index 042d900..9636f7f 100644 --- a/src/src/Rendering/Legend/ResliceCursorLegendActor.h +++ b/src/src/Rendering/Legend/ResliceCursorLegendActor.h @@ -105,6 +105,13 @@ public: } } + void StopUpdate(){ + StopUpdateFlag = true; + } + void BeginUpdate(){ + StopUpdateFlag = false; + } + void ActiveControlPointOn(); void ActiveControlPointOff(); @@ -144,6 +151,7 @@ private: bool dragging = false; bool Moving = false; bool Rolling = false; + bool StopUpdateFlag = false; int DragStartPosition[2] = {0,0}; double Handle2DPoint[2] = {.0, .0, }; double SliceDirectionVector[3] = {.0, .0, .0}; diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.cpp b/src/src/Rendering/Viewer/ResliceImageViewer.cpp index b17cc49..0e9e803 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.cpp +++ b/src/src/Rendering/Viewer/ResliceImageViewer.cpp @@ -198,6 +198,8 @@ void ResliceImageViewer::Render() { this->InteractorStyle->AddObserver(SliceEvent,this, &ResliceImageViewer::SliceCallback); this->InteractorStyle->AddObserver(vtkCommand::WindowLevelEvent,this, &ResliceImageViewer::WindowLevelCallback); this->InteractorStyle->AddObserver(vtkCommand::EndWindowLevelEvent,this, &ResliceImageViewer::EndWindowLevelCallback); + this->InteractorStyle->AddObserver(vtkCommand::RotateEvent,this, &ResliceImageViewer::EndRotateCallback); +// this->InteractorStyle->AddObserver(vtkCommand::EndRotateEvent,this, &ResliceImageViewer::EndRotateCallback); this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize); cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); @@ -494,3 +496,25 @@ void ResliceImageViewer::WindowLevelCallback() { (int)Actor->GetProperty()->GetColorWindow()); annotation->SetText(5, buff); } + +void ResliceImageViewer::EndRotateCallback() { + auto camera = Renderer->GetActiveCamera(); + cursor1->SetProjectDirectionVector(camera->GetDirectionOfProjection()); + cursor2->SetProjectDirectionVector(camera->GetDirectionOfProjection()); + cursor1->UpdateCursor3DPoint(this->Renderer); + cursor2->UpdateCursor3DPoint(this->Renderer); + this->InvokeEvent(vtkCommand::RotateEvent); +} + +void ResliceImageViewer::ChangeCursorVector(double * vector1, double * vector2) { + auto camera = Renderer->GetActiveCamera(); + cursor1->SetProjectDirectionVector(camera->GetDirectionOfProjection()); + cursor2->SetProjectDirectionVector(camera->GetDirectionOfProjection()); + cursor1->SetSliceDirectionVector(vector1); + cursor2->SetSliceDirectionVector(vector2); +} + +double* ResliceImageViewer::GetSliceNormal() { + return Renderer->GetActiveCamera()->GetDirectionOfProjection(); +} + diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.h b/src/src/Rendering/Viewer/ResliceImageViewer.h index 557fc4c..233dd0e 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.h +++ b/src/src/Rendering/Viewer/ResliceImageViewer.h @@ -61,6 +61,10 @@ public: void ChangeSliceNormal(double * normal); + void ChangeCursorVector(double * vector1, double * vector2); + + double* GetSliceNormal(); + void EndDrag(); void UpdateSliceCursor(); @@ -77,6 +81,8 @@ public: void EndWindowLevelCallback(); + void EndRotateCallback(); + void GetWindowLevel(double* windowLeveL); void SetWindowLevel(double* windowLeveL); diff --git a/src/src/UI/Manager/ResliceImageManager.cpp b/src/src/UI/Manager/ResliceImageManager.cpp index 8552320..495a810 100644 --- a/src/src/UI/Manager/ResliceImageManager.cpp +++ b/src/src/UI/Manager/ResliceImageManager.cpp @@ -50,6 +50,9 @@ void ResliceImageManager::InitEvents() { viewerA->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerS->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); viewerC->AddObserver(SliceEvent,this,&ResliceImageManager::MoveCallback); + viewerA->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback); + viewerS->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback); + viewerC->AddObserver(vtkCommand::RotateEvent,this,&ResliceImageManager::RotateCallback); } void ResliceImageManager::RollCallback(vtkObject *sender, unsigned long eventID, void *data) { @@ -113,10 +116,10 @@ void ResliceImageManager::EndDrag(vtkObject *sender, unsigned long eventID, void void ResliceImageManager::ClickCallback(vtkObject *sender, unsigned long eventID, void *data) { auto viewer = ResliceImageViewer::SafeDownCast(sender); - if (viewer){ - viewerA->SetChecked(viewer==viewerA); - viewerS->SetChecked(viewer==viewerS); - viewerC->SetChecked(viewer==viewerC); + if (viewer) { + viewerA->SetChecked(viewer == viewerA); + viewerS->SetChecked(viewer == viewerS); + viewerC->SetChecked(viewer == viewerC); } } @@ -143,3 +146,33 @@ void ResliceImageManager::WindowLevelCallback(vtkObject *sender, unsigned long e } } +void ResliceImageManager::RotateCallback(vtkObject *sender, unsigned long eventID, void *data) { + auto viewer = ResliceImageViewer::SafeDownCast(sender); + if (viewer){ + if (viewer==viewerA){ + viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); + viewerC->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal()); + viewerC->Render(); + viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerS->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2()); + viewerS->Render(); + } + if (viewer==viewerC){ + viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); + viewerA->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal()); + viewerA->Render(); + viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerS->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2()); + viewerS->Render(); + } + if (viewer==viewerS){ + viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); + viewerC->ChangeCursorVector(viewer->GetCursorSliceDirection1(),viewer->GetSliceNormal()); + viewerC->Render(); + viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerA->ChangeCursorVector(viewer->GetSliceNormal(),viewer->GetCursorSliceDirection2()); + viewerA->Render(); + } + } +} + diff --git a/src/src/UI/Manager/ResliceImageManager.h b/src/src/UI/Manager/ResliceImageManager.h index 07fc5ab..b991220 100644 --- a/src/src/UI/Manager/ResliceImageManager.h +++ b/src/src/UI/Manager/ResliceImageManager.h @@ -32,6 +32,7 @@ private: 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 RotateCallback(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); };