From ff624ad77e1d13e1e80f3079f2ea210349a951e8 Mon Sep 17 00:00:00 2001 From: Krad Date: Fri, 11 Nov 2022 13:22:10 +0800 Subject: [PATCH] Measure for volume, attempt 1. --- src/src/Interaction/VolumeInteractorStyle.cpp | 162 +++++++++++++----- src/src/Interaction/VolumeInteractorStyle.h | 22 ++- src/src/Rendering/Core/DraggableActor.cpp | 5 +- .../Measure/ArrowAnnotationActor.cpp | 4 + .../Rendering/Measure/ArrowAnnotationActor.h | 2 + src/src/Rendering/Measure/Measure.h | 3 + src/src/Rendering/Viewer/DICOMImageViewer.cxx | 1 - .../Viewer/VolumeRenderingViewer.cpp | 28 ++- .../Rendering/Viewer/VolumeRenderingViewer.h | 9 +- .../Widget/ToolBar/VolumeRenderingToolBar.cpp | 3 + .../Widget/ToolBar/VolumeRenderingToolBar.h | 1 + src/src/UI/Window/VolumeRenderingWindow.cpp | 5 + 12 files changed, 185 insertions(+), 60 deletions(-) diff --git a/src/src/Interaction/VolumeInteractorStyle.cpp b/src/src/Interaction/VolumeInteractorStyle.cpp index b37131d..d4c5875 100644 --- a/src/src/Interaction/VolumeInteractorStyle.cpp +++ b/src/src/Interaction/VolumeInteractorStyle.cpp @@ -9,13 +9,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "Rendering/Core/DraggableActor.h" @@ -25,7 +25,7 @@ VolumeInteractorStyle::VolumeInteractorStyle():vtkInteractorStyleTrackballCamera ,InteractionMode(VTKIS_VOLUME_ROTATE3D) ,picker(vtkPropPicker::New()) { - + picker->SetPickFromList(1); } VolumeInteractorStyle::~VolumeInteractorStyle() { @@ -42,39 +42,20 @@ void VolumeInteractorStyle::OnLeftButtonDown() { } this->GrabFocus(this->EventCallbackCommand); - if (selectedProp) { - selectedProp->InvokeEvent(DraggableActor::DraggableActorEvents::UnSelectedEvent); - selectedProp = nullptr; + // un select last selected prop + if (CurrentProp) { + CurrentProp->InvokeEvent(DraggableActor::DraggableActorEvents::UnSelectedEvent); + CurrentProp = nullptr; } - if (dragProp) { - selectedProp = dragProp; - selectedProp->InvokeEvent(DraggableActor::DraggableActorEvents::SelectedEvent); - if (this->Interactor->GetRepeatCount()) { - dragProp->InvokeEvent(DraggableStyleEvents::PopPropEvent, nullptr); - } - DragStartOrigin[0] = x; - DragStartOrigin[1] = y; - this->StartDrag(); + if (measure) { + measure->SetPlacing(measure->onMeasureLeftButtonDown(this->Interactor)); + if (this->State != VTKIS_MEASURE) this->StartMeasure(); return; } - if (Interactor->GetRepeatCount()) { - if (measure) { - measure->SetPlacing(measure->onMeasureDoubleClick(this->Interactor)); - if (!measure->isMeasurePlacing()) { - this->EndMeasure(); - auto temp = measure; - measure = measure->GetNextMeasure(); - if (!temp->Valid()) { - temp->ForceDelete(); - temp = nullptr; - } - } - return; - } - } switch(this->InteractionMode) { case VTKIS_VOLUME_ROTATE3D: { this->StartRotate(); + ClearMeasure(); break; } case VTKIS_VOLUME_PAN: { @@ -100,6 +81,27 @@ void VolumeInteractorStyle::OnLeftButtonDown() { void VolumeInteractorStyle::OnLeftButtonUp() { switch (this->State) { + case VTKIS_DRAG: + DraggableActor::SafeDownCast(this->CurrentProp)->ApplyTransform(); + this->EndDrag(); + break; + case VTKIS_MEASURE: + measure->SetPlacing(measure->onMeasureLeftButtonUp(this->Interactor)); + if (!measure->isMeasurePlacing()) { + this->EndMeasure(); + auto temp = measure; + + measure = measure->GetNextMeasure(); + if (!temp->Valid()) { + temp->ForceDelete(); + temp = nullptr; + } + else{ + picker->AddPickList(temp->GetProp()); + measureStore.push_back(temp); + } + } + break; case VTKIS_VOLUME_WINDOW: this->EndWindowLevel(); if (this->Interactor) { @@ -111,27 +113,25 @@ void VolumeInteractorStyle::OnLeftButtonUp() { } void VolumeInteractorStyle::StartWindowLevel() { - if (this->State != VTKIS_NONE) - { + if (this->State != VTKIS_NONE) { return; } this->StartState(VTKIS_VOLUME_WINDOW); if (this->HandleObservers && - this->HasObserver(vtkCommand::StartWindowLevelEvent)) - { + this->HasObserver(vtkCommand::StartWindowLevelEvent)) { this->InvokeEvent(vtkCommand::StartWindowLevelEvent, this); } - GetCurrentVolumeProperty(); - if(VolumeProperty){ - auto opacity = VolumeProperty->GetScalarOpacity(); - if (opacity) { - double range[2] = {0.0, 0.0}; - opacity->GetRange(range); - this->WindowLevelInitial[0] = range[1] - range[0]; - this->WindowLevelInitial[1] = (range[1] + range[0]) / 2; - } + GetCurrentVolumeProperty(); + if (VolumeProperty) { + auto opacity = VolumeProperty->GetScalarOpacity(); + if (opacity) { + double range[2] = {0.0, 0.0}; + opacity->GetRange(range); + this->WindowLevelInitial[0] = range[1] - range[0]; + this->WindowLevelInitial[1] = (range[1] + range[0]) / 2; } + } } void VolumeInteractorStyle::EndWindowLevel() { @@ -149,12 +149,41 @@ void VolumeInteractorStyle::EndWindowLevel() { void VolumeInteractorStyle::OnMouseMove() { int x = this->Interactor->GetEventPosition()[0]; int y = this->Interactor->GetEventPosition()[1]; + this->FindPokedRenderer(x,y); switch (this->State) { + // window case VTKIS_VOLUME_WINDOW: - this->FindPokedRenderer(x,y); this->WindowLevel(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); break; + case VTKIS_MEASURE: + MeasurePlace(); +// this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); + break; + // no state pick + default:{ + if (measureStore.size()){ + int ret = picker->PickProp(x,y,this->CurrentRenderer); + if (ret){ + auto prop = picker->GetViewProp(); + if (prop->IsA("DraggableActor")) { + //active highlight + auto old = DraggableActor::SafeDownCast(this->CurrentProp); + if (old) old->MouseLeave(); + this->CurrentProp = prop; + auto newOne = DraggableActor::SafeDownCast(prop); + if (newOne){ + newOne->MouseEntered(); + } + } + } + else if (this->CurrentProp) { + DraggableActor::SafeDownCast(this->CurrentProp)->MouseLeave(); + this->CurrentProp = nullptr; + } + return; + } + } } vtkInteractorStyleTrackballCamera::OnMouseMove(); @@ -240,7 +269,7 @@ void VolumeInteractorStyle::GetCurrentVolumeProperty() { vtkPropCollection *props = this->CurrentRenderer->GetViewProps(); vtkProp *prop = nullptr; vtkAssemblyPath *path; - vtkVolume *volumeProp = nullptr; + volumeProp = nullptr; vtkCollectionSimpleIterator pit; for (int k = 0; k < 2; k++) @@ -287,3 +316,48 @@ void VolumeInteractorStyle::Drag() { this->Interactor->Render(); } +void VolumeInteractorStyle::ActiveMeasure(Measure *m) { + if (this->measure && nullptr == m) { + this->measure->onTerminate(this->Interactor); + this->measure->ForceDelete(); + } + this->measure = m; +} + +void VolumeInteractorStyle::MeasurePlace() { + if (measure)measure->onMeasureMouseMove(this->Interactor); +} + +void VolumeInteractorStyle::ClearMeasure() { + + std::for_each(measureStore.begin(), measureStore.end(),[=](Measure* m){ + picker->DeletePickList(m->GetProp()); + m->ForceDelete(); + }); + + measureStore.clear(); +} + +void VolumeInteractorStyle::StartMeasure() { + this->StartState(VTKIS_MEASURE); + if (!volumeProp){ + GetCurrentVolumeProperty(); + } + auto mapper = vtkFixedPointVolumeRayCastMapper::SafeDownCast(this->volumeProp->GetMapper()); + if (mapper){ + mapper->SetAutoAdjustSampleDistances(0); + } +} + +void VolumeInteractorStyle::EndMeasure() { + if (this->State != VTKIS_MEASURE) { + return; + } + this->StopState(); + auto mapper = vtkFixedPointVolumeRayCastMapper::SafeDownCast(this->volumeProp->GetMapper()); + if (mapper){ + mapper->SetAutoAdjustSampleDistances(1); + } + this->InvokeEvent(EndMeasureEvent, this->measure); +} + diff --git a/src/src/Interaction/VolumeInteractorStyle.h b/src/src/Interaction/VolumeInteractorStyle.h index a92cf59..76b7732 100644 --- a/src/src/Interaction/VolumeInteractorStyle.h +++ b/src/src/Interaction/VolumeInteractorStyle.h @@ -13,6 +13,7 @@ class vtkPropPicker; class vtkProp; class Measure; +#include #include class VolumeInteractorStyle:public vtkInteractorStyleTrackballCamera { @@ -39,7 +40,11 @@ public: void WindowLevel(); + void ActiveMeasure(Measure *m); + + void ClearMeasure(); protected: + VolumeInteractorStyle(); ~VolumeInteractorStyle() override; @@ -56,18 +61,11 @@ protected: } void Drag(); + void StartMeasure(); - void StartMeasure() { - this->StartState(VTKIS_MEASURE); - } + void EndMeasure(); - void EndMeasure() { - if (this->State != VTKIS_MEASURE) { - return; - } - this->StopState(); - this->InvokeEvent(EndMeasureEvent, this->measure); - } + void MeasurePlace(); private: VolumeInteractorStyle(const VolumeInteractorStyle &) = delete; @@ -80,9 +78,9 @@ private: vtkVolumeProperty* VolumeProperty = nullptr; vtkPropPicker* picker; vtkProp *dragProp = nullptr; - vtkProp *selectedProp = nullptr; Measure *measure = nullptr; - vtkRenderer* MainRenderer; + vtkVolume *volumeProp = nullptr; + std::vector measureStore; int DragStartOrigin[2] = {0, 0}; double WindowLevelInitial[2] = {0.0, 0.0}; double WindowLevelStartPosition[2] = {0.0, 0.0}; diff --git a/src/src/Rendering/Core/DraggableActor.cpp b/src/src/Rendering/Core/DraggableActor.cpp index 4595d45..15ad0fa 100644 --- a/src/src/Rendering/Core/DraggableActor.cpp +++ b/src/src/Rendering/Core/DraggableActor.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -163,7 +164,9 @@ void DraggableActor::Pick() { } void DraggableActor::Highlight(int highlightOn) { - this->Highlighted = highlightOn > 0; + bool temp = highlightOn > 0; + if (temp == this->Highlighted) return; + this->Highlighted = temp; RenderWithState(); if (this->Renderer)this->Renderer->GetRenderWindow()->Render(); } diff --git a/src/src/Rendering/Measure/ArrowAnnotationActor.cpp b/src/src/Rendering/Measure/ArrowAnnotationActor.cpp index 8a6edc2..847a26f 100644 --- a/src/src/Rendering/Measure/ArrowAnnotationActor.cpp +++ b/src/src/Rendering/Measure/ArrowAnnotationActor.cpp @@ -94,4 +94,8 @@ bool ArrowAnnotationActor::onMeasureLeftButtonDown(vtkRenderWindowInteractor *in return true; } +vtkProp *ArrowAnnotationActor::GetProp() { + return this; +} + diff --git a/src/src/Rendering/Measure/ArrowAnnotationActor.h b/src/src/Rendering/Measure/ArrowAnnotationActor.h index 28fd07b..a0d65a5 100644 --- a/src/src/Rendering/Measure/ArrowAnnotationActor.h +++ b/src/src/Rendering/Measure/ArrowAnnotationActor.h @@ -26,6 +26,8 @@ public: bool onMeasureLeftButtonDown(vtkRenderWindowInteractor *) override; + vtkProp *GetProp() override; + protected: ArrowAnnotationActor(); diff --git a/src/src/Rendering/Measure/Measure.h b/src/src/Rendering/Measure/Measure.h index 6ca09e7..4985e7f 100644 --- a/src/src/Rendering/Measure/Measure.h +++ b/src/src/Rendering/Measure/Measure.h @@ -13,6 +13,7 @@ Measure* GetNextMeasure() override\ #include "Events/EventsCenter.h" class vtkRenderWindowInteractor; +class vtkProp; class Measure { public: @@ -65,6 +66,8 @@ public: virtual bool Valid() { return true; } + virtual vtkProp* GetProp(){return nullptr;} + protected: static bool Hidden; private: diff --git a/src/src/Rendering/Viewer/DICOMImageViewer.cxx b/src/src/Rendering/Viewer/DICOMImageViewer.cxx index 90cf2d6..473472b 100644 --- a/src/src/Rendering/Viewer/DICOMImageViewer.cxx +++ b/src/src/Rendering/Viewer/DICOMImageViewer.cxx @@ -319,7 +319,6 @@ void DICOMImageViewer::InstallPipeline() { if (this->Renderer && this->ImageActor) { this->Renderer->AddViewProp(this->ImageStack); -// this->Renderer->AddViewProp(this->ImageActor); this->Renderer->GetActiveCamera()->SetParallelProjection(1); this->Renderer->SetBackground(0.0, 0.0, 0.0); } diff --git a/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp b/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp index d699933..d93f65e 100644 --- a/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp +++ b/src/src/Rendering/Viewer/VolumeRenderingViewer.cpp @@ -26,6 +26,7 @@ #include "Interaction/VolumeInteractorStyle.h" #include "Rendering/Widget/ClickableOrientationMarkerWidget.h" #include "IO/DICOM/ExtendMedicalImageProperties.h" +#include "Rendering/Measure/ArrowAnnotationActor.h" namespace { enum ViewDirection{ @@ -199,7 +200,7 @@ void VolumeRenderingViewer::InstallPipeline() { if (this->Renderer && this->VolumeActor) { this->Renderer->AddVolume(this->VolumeActor); this->Renderer->AddViewProp(annotation); - Renderer->AddObserver(vtkCommand::EndEvent,this, &VolumeRenderingViewer::renderAnnotation); +// Renderer->AddObserver(vtkCommand::EndEvent,this, &VolumeRenderingViewer::renderAnnotation); this->Renderer->SetBackground(0.0, 0.0, 0.0); } } @@ -605,3 +606,28 @@ void VolumeRenderingViewer::pressedOrientationMarker(vtkObject* sender, unsigned } } } + +void VolumeRenderingViewer::ActiveArrow() { + auto style = VolumeInteractorStyle::SafeDownCast(this->InteractorStyle); + if (style){ + style->ActiveMeasure(ArrowAnnotationActor::New()); + } +} + +void VolumeRenderingViewer::UnActiveMeasure() { + auto style = VolumeInteractorStyle::SafeDownCast(this->InteractorStyle); + if (style){ + style->ActiveMeasure(nullptr); + } +} + +void VolumeRenderingViewer::PokeMeasureRender() { + if(!MeasureRenderer) { + MeasureRenderer = vtkRenderer::New(); + if (this->RenderWindow && this->MeasureRenderer) { + this->RenderWindow->AddRenderer(this->MeasureRenderer); + } + } + this->MeasureRenderer->SetLayer(1); + this->Renderer->SetLayer(0); +} diff --git a/src/src/Rendering/Viewer/VolumeRenderingViewer.h b/src/src/Rendering/Viewer/VolumeRenderingViewer.h index d706867..996b29e 100644 --- a/src/src/Rendering/Viewer/VolumeRenderingViewer.h +++ b/src/src/Rendering/Viewer/VolumeRenderingViewer.h @@ -91,6 +91,10 @@ public: void ResetZoomFitWindow(); + void ActiveArrow(); + + void UnActiveMeasure(); + protected: VolumeRenderingViewer(); @@ -103,14 +107,17 @@ protected: void renderAnnotation(); private: VolumeRenderingViewer(const VolumeRenderingViewer &) = delete; - void operator=(const VolumeRenderingViewer &) = delete; void DecreaseMaximumImageSampleDistance(); void ResetMaximumImageSampleDistance(); + void PokeMeasureRender(); + void PokeMainRender(); + vtkRenderWindow *RenderWindow; vtkRenderer *Renderer; + vtkRenderer *MeasureRenderer; vtkVolume * VolumeActor; vtkVolumeMapper *VolumeMapper; vtkInteractorStyle *InteractorStyle; diff --git a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp index ef6b8d5..82f1096 100644 --- a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp +++ b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.cpp @@ -78,6 +78,9 @@ VolumeRenderingToolBar::VolumeRenderingToolBar(QWidget *parent) : QToolBar(paren addSeparator(); auto btnMeasure = new QToolButton(this); addButton(btnMeasure, "measure"); + connect(btnMeasure,&QToolButton::clicked,[=](){ + emit activeArrow(); + }); addSeparator(); auto btnPreset = new QToolButton(this); addButton(btnPreset, "preset"); diff --git a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h index 4282ba3..2cbdfd0 100644 --- a/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h +++ b/src/src/UI/Widget/ToolBar/VolumeRenderingToolBar.h @@ -20,6 +20,7 @@ signals: void viewDirectionChanged(int id); void resetView(); void fitWindow(); + void activeArrow(); private: QAction* addButton(QToolButton* button, const char* objectName); diff --git a/src/src/UI/Window/VolumeRenderingWindow.cpp b/src/src/UI/Window/VolumeRenderingWindow.cpp index 1bb6356..e2e647d 100644 --- a/src/src/UI/Window/VolumeRenderingWindow.cpp +++ b/src/src/UI/Window/VolumeRenderingWindow.cpp @@ -40,12 +40,17 @@ VolumeRenderingWindow::VolumeRenderingWindow(QWidget *parent , Qt::WindowFlags f mViewer->ResetView(); mViewer->Render(); }); + connect(toolBar, &VolumeRenderingToolBar::activeArrow,[=](){ + mViewer->ActiveArrow(); + mViewer->Render(); + }); connect(toolBar, &VolumeRenderingToolBar::fitWindow,[=](){ mViewer->ResetZoomFitWindow(); mViewer->Render(); }); connect(toolBar, &VolumeRenderingToolBar::modeButtonClicked,[=](int mode){ mViewer->SetInteractorStyleMode(mode); + mViewer->UnActiveMeasure(); }); connect(toolBar, &VolumeRenderingToolBar::viewDirectionChanged, [=](int direction){