Measure for volume, attempt 1.

This commit is contained in:
Krad
2022-11-11 13:22:10 +08:00
parent 82db8df071
commit ff624ad77e
12 changed files with 185 additions and 60 deletions

View File

@@ -9,13 +9,13 @@
#include <vtkCallbackCommand.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkVolume.h>
#include <vtkPropCollection.h>
#include <vtkAssemblyPath.h>
#include <vtkVolumeProperty.h>
#include <vtkPropPicker.h>
#include <vtkPiecewiseFunction.h>
#include <vtkFixedPointVolumeRayCastMapper.h>
#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();
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;
}
}
measure->SetPlacing(measure->onMeasureLeftButtonDown(this->Interactor));
if (this->State != VTKIS_MEASURE) this->StartMeasure();
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,19 +113,17 @@ 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){
if (VolumeProperty) {
auto opacity = VolumeProperty->GetScalarOpacity();
if (opacity) {
double range[2] = {0.0, 0.0};
@@ -149,12 +149,41 @@ void VolumeInteractorStyle::EndWindowLevel() {
void VolumeInteractorStyle::OnMouseMove() {
int x = this->Interactor->GetEventPosition()[0];
int y = this->Interactor->GetEventPosition()[1];
switch (this->State) {
case VTKIS_VOLUME_WINDOW:
this->FindPokedRenderer(x,y);
switch (this->State) {
// window
case VTKIS_VOLUME_WINDOW:
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);
}

View File

@@ -13,6 +13,7 @@ class vtkPropPicker;
class vtkProp;
class Measure;
#include <vector>
#include <vtkRenderer.h>
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<Measure*> measureStore;
int DragStartOrigin[2] = {0, 0};
double WindowLevelInitial[2] = {0.0, 0.0};
double WindowLevelStartPosition[2] = {0.0, 0.0};

View File

@@ -10,6 +10,7 @@
#include <vtkActor2D.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkCamera.h>
@@ -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();
}

View File

@@ -94,4 +94,8 @@ bool ArrowAnnotationActor::onMeasureLeftButtonDown(vtkRenderWindowInteractor *in
return true;
}
vtkProp *ArrowAnnotationActor::GetProp() {
return this;
}

View File

@@ -26,6 +26,8 @@ public:
bool onMeasureLeftButtonDown(vtkRenderWindowInteractor *) override;
vtkProp *GetProp() override;
protected:
ArrowAnnotationActor();

View File

@@ -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:

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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");

View File

@@ -20,6 +20,7 @@ signals:
void viewDirectionChanged(int id);
void resetView();
void fitWindow();
void activeArrow();
private:
QAction* addButton(QToolButton* button, const char* objectName);

View File

@@ -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){