From 2120dd2432571ac799a1f9e2b35fb55665980c14 Mon Sep 17 00:00:00 2001 From: Krad Date: Tue, 27 Dec 2022 14:31:56 +0800 Subject: [PATCH] Reslice hair cross temp1. --- .../ResliceImageInteractorStyle.cpp | 69 +++++- .../Interaction/ResliceImageInteractorStyle.h | 13 ++ src/src/Rendering/Core/ControlPointRActor.cpp | 29 ++- src/src/Rendering/Core/ControlPointRActor.h | 13 ++ .../Legend/ResliceCursorLegendActor.cpp | 203 +++++++++++++++--- .../Legend/ResliceCursorLegendActor.h | 61 +++++- .../Rendering/Viewer/ResliceImageViewer.cpp | 56 ++++- src/src/Rendering/Viewer/ResliceImageViewer.h | 10 + src/src/UI/Manager/ResliceImageManager.cpp | 55 +++++ src/src/UI/Manager/ResliceImageManager.h | 34 +++ src/src/UI/Window/MPRResliceWindow.cpp | 7 + src/src/UI/Window/MPRResliceWindow.h | 2 + 12 files changed, 489 insertions(+), 63 deletions(-) create mode 100644 src/src/UI/Manager/ResliceImageManager.cpp create mode 100644 src/src/UI/Manager/ResliceImageManager.h diff --git a/src/src/Interaction/ResliceImageInteractorStyle.cpp b/src/src/Interaction/ResliceImageInteractorStyle.cpp index 676ae09..4cf7a9e 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.cpp +++ b/src/src/Interaction/ResliceImageInteractorStyle.cpp @@ -11,11 +11,16 @@ #include #include #include +#include + +#include "Rendering/Legend/ResliceCursorLegendActor.h" vtkStandardNewMacro(ResliceImageInteractorStyle) ResliceImageInteractorStyle::ResliceImageInteractorStyle():vtkInteractorStyleImage() { - + picker = vtkPropPicker::New(); + picker->Register(this); + picker->Delete(); } ResliceImageInteractorStyle::~ResliceImageInteractorStyle() { @@ -23,23 +28,65 @@ ResliceImageInteractorStyle::~ResliceImageInteractorStyle() { } void ResliceImageInteractorStyle::OnMouseMove() { + switch (this->State) { + case VTKIS_NONE: + if (triggerEvent) + { + this->InvokeEvent(vtkCommand::UserEvent+20,Interactor->GetEventPosition()); + this->Interactor->Render(); + } + NoneStatePick(); + break; + case VTKIS_POSITION_PROP: { + this->Interactor->Render(); + auto cursor = ResliceCursorLegendActor::SafeDownCast(this->CurrentProp); + cursor->InvokeDragEvent(); + } + default: + vtkInteractorStyleImage::OnMouseMove(); - if (triggerEvent) - { - this->InvokeEvent(vtkCommand::UserEvent+20,Interactor->GetEventPosition()); - this->Interactor->Render(); - } - else{ - vtkInteractorStyleImage::OnMouseMove(); - } + + } } void ResliceImageInteractorStyle::OnLeftButtonDown() { triggerEvent = false; - vtkInteractorStyleImage::OnLeftButtonDown(); + if (this->CurrentProp){ + StartCursorInteractive(); + auto cursor = ResliceCursorLegendActor::SafeDownCast(this->CurrentProp); + cursor->SetDragStartPosition(Interactor->GetEventPosition()); + cursor->StartDrag(); + } + else{ + vtkInteractorStyleImage::OnLeftButtonDown(); + } } void ResliceImageInteractorStyle::OnLeftButtonUp() { - vtkInteractorStyleImage::OnLeftButtonUp(); + if (this->CurrentProp){ + StopCursorInteractive(); + ResliceCursorLegendActor::SafeDownCast(this->CurrentProp)->StopDrag(); + this->InvokeEvent(ResliceCursorLegendActor::END_DRAG); + } + else { + vtkInteractorStyleImage::OnLeftButtonUp(); + } triggerEvent = true; } + +void ResliceImageInteractorStyle::NoneStatePick() { + int *pos = this->Interactor->GetEventPosition(); + this->FindPokedRenderer(pos[0], pos[1]); + int ret = picker->PickProp(pos[0],pos[1],this->CurrentRenderer); + if (ret){ + auto prop = picker->GetViewProp(); + auto cursor = ResliceCursorLegendActor::SafeDownCast(prop); + if (cursor){ + this->CurrentProp = cursor; + } + } + else { + this->CurrentProp = nullptr; + } + return; +} diff --git a/src/src/Interaction/ResliceImageInteractorStyle.h b/src/src/Interaction/ResliceImageInteractorStyle.h index 143120a..9e9abf9 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.h +++ b/src/src/Interaction/ResliceImageInteractorStyle.h @@ -10,6 +10,8 @@ #include #include +class vtkPropPicker; + class ResliceImageInteractorStyle:public vtkInteractorStyleImage { public: static ResliceImageInteractorStyle *New(); @@ -21,18 +23,29 @@ public: void OnLeftButtonUp() override; void OnMouseMove() override; + + virtual void StartCursorInteractive(){ + this->State = VTKIS_POSITION_PROP; + } + virtual void StopCursorInteractive(){ + this->State = VTKIS_NONE; + } protected: ResliceImageInteractorStyle(); ~ResliceImageInteractorStyle() override; + void NoneStatePick(); + private: ResliceImageInteractorStyle(const ResliceImageInteractorStyle &) = delete; void operator=(const ResliceImageInteractorStyle &) = delete; bool triggerEvent = true; + + vtkPropPicker * picker; }; diff --git a/src/src/Rendering/Core/ControlPointRActor.cpp b/src/src/Rendering/Core/ControlPointRActor.cpp index 16ee3cb..6246096 100644 --- a/src/src/Rendering/Core/ControlPointRActor.cpp +++ b/src/src/Rendering/Core/ControlPointRActor.cpp @@ -36,14 +36,25 @@ void ControlPointRActor::BuildShape() { } void ControlPointRActor::Highlight(int highlightOn) { - if (highlightOn > 0) { - actor2D->GetProperty()->SetColor(1.0, 1.0, 0); - actor2D->GetProperty()->SetOpacity(1.0); - shadow2D->GetProperty()->SetOpacity(1.0); - } else { - actor2D->GetProperty()->SetOpacity(0.0); - shadow2D->GetProperty()->SetOpacity(0.0); - actor2D->GetProperty()->SetColor(1.0, 0.0, 0); + if (AutoHover){ + if (highlightOn > 0) { + actor2D->GetProperty()->SetColor(1.0, 1.0, 0); + } else { + actor2D->GetProperty()->SetColor(1.0, 0.0, 0); + } } - if (this->Renderer)this->Renderer->GetRenderWindow()->Render(); + else{ + if (highlightOn > 0) { + actor2D->GetProperty()->SetColor(1.0, 1.0, 0); + actor2D->GetProperty()->SetOpacity(1.0); + shadow2D->GetProperty()->SetOpacity(1.0); + } else { + actor2D->GetProperty()->SetOpacity(0.0); + shadow2D->GetProperty()->SetOpacity(0.0); + actor2D->GetProperty()->SetColor(1.0, 0.0, 0); + } + if (this->Renderer)this->Renderer->GetRenderWindow()->Render(); + } + } + diff --git a/src/src/Rendering/Core/ControlPointRActor.h b/src/src/Rendering/Core/ControlPointRActor.h index 157afa0..3b6931e 100644 --- a/src/src/Rendering/Core/ControlPointRActor.h +++ b/src/src/Rendering/Core/ControlPointRActor.h @@ -18,19 +18,32 @@ public: vtkTypeMacro(ControlPointRActor, ControlPointActor); //@} + vtkSetMacro(AutoHover, bool); + vtkBooleanMacro(AutoHover, bool); + vtkGetMacro(AutoHover, bool); + void BuildShape() override; void Highlight(int highlightOn) override; void MouseEntered() override { this->InvokeEvent(vtkCommand::EnterEvent, nullptr); + if (AutoHover){ + Highlight(1); + } } void MouseLeave() override { this->InvokeEvent(vtkCommand::LeaveEvent, nullptr); + if (AutoHover){ + Highlight(0); + } } + vtkIdType Index; +private: + bool AutoHover = false; }; diff --git a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp index 0d81cf4..27bcc07 100644 --- a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp +++ b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp @@ -17,8 +17,9 @@ #include #include #include +#include + -#include "Rendering/Core/ControlPointRActor.h" namespace { class Vector2 { @@ -79,9 +80,8 @@ vtkStandardNewMacro(ResliceCursorLegendActor) ResliceCursorLegendActor::ResliceCursorLegendActor() : vtkProp() , LineActor(vtkActor2D::New()) -, ControlPoint(ControlPointRActor::New()) -, LineShadow(vtkActor2D::New()) -, senseArea(vtkActor2D::New()) +, ControlPoint(vtkActor2D::New()) +, ControlPointSenseArea(vtkActor2D::New()) , linePolyData(vtkPolyData::New()){ vtkNew pts; pts->SetNumberOfPoints(2); @@ -94,12 +94,24 @@ ResliceCursorLegendActor::ResliceCursorLegendActor() vtkNew mapper1 ; vtkNew mapper2 ; mapper->SetInputData(linePolyData); - mapper1->SetInputData(linePolyData); - mapper2->SetInputData(linePolyData); + vtkNew disk; + disk->SetInnerRadius(0); + disk->SetOuterRadius(5); + disk->SetCircumferentialResolution(36); + disk->SetRadialResolution(36); + vtkNew diskSense; + diskSense->SetInnerRadius(0); + diskSense->SetOuterRadius(10); + diskSense->SetCircumferentialResolution(36); + diskSense->SetRadialResolution(36); + mapper1->SetInputConnection(disk->GetOutputPort()); + mapper2->SetInputConnection(diskSense->GetOutputPort()); LineActor->SetMapper(mapper); - LineShadow->SetMapper(mapper1); - senseArea->SetMapper(mapper2); - ControlPoint->SetWorldPosition(0,0,0); + LineActor->GetProperty()->SetLineWidth(2); + ControlPoint->SetMapper(mapper1); + ControlPoint->SetProperty(LineActor->GetProperty()); + ControlPointSenseArea->SetMapper(mapper2); + ControlPointSenseArea->GetProperty()->SetOpacity(0); } ResliceCursorLegendActor::~ResliceCursorLegendActor() { @@ -114,21 +126,26 @@ void AlignDoubleVector3(double* in, double *out){ } void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { + if(dragging){ + Drag(renderer); + } + if (LoadTime.GetMTime()>MTime.GetMTime()) return; //handle disk - if (HandleUpdated){ - renderer->SetDisplayPoint(Handle2DPoint[0],Handle2DPoint[1], 0); + if (HandleUpdated) { + renderer->SetDisplayPoint(Handle2DPoint[0], Handle2DPoint[1], 0); renderer->DisplayToWorld(); renderer->GetWorldPoint(HandlePoint); HandleUpdated = false; } - ControlPoint->SetWorldPosition(HandlePoint); + ControlPoint->SetPosition(Handle2DPoint[0] - 0.5, Handle2DPoint[1] - .5); + ControlPointSenseArea->SetPosition(Handle2DPoint[0], Handle2DPoint[1] - .5); //cross hair double vector[3] = {.0, .0, .0}; vtkMath::Cross(GetSliceDirectionVector(), GetProjectDirectionVector(), vector); vtkMath::Normalize(vector); - double point1[4] = {SlicePoint[0] , - SlicePoint[1] , + double point1[4] = {SlicePoint[0], + SlicePoint[1], SlicePoint[2], 1.0}; @@ -136,47 +153,49 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { SlicePoint[1] + vector[1], SlicePoint[2] + vector[2], 1.0}; - double out1[4] = {.0, .0, .0,.0}; double out2[4] = {.0, .0, .0, .0}; linePolyData->GetPoints()->SetNumberOfPoints(2); renderer->SetWorldPoint(point1); renderer->WorldToDisplay(); - renderer->GetDisplayPoint(out1); + renderer->GetDisplayPoint(SliceDisplayPoint); renderer->SetWorldPoint(point2); renderer->WorldToDisplay(); renderer->GetDisplayPoint(out2); - double vector2D[2] = {out2[0] - out1[0], out2[1] - out1[1]}; + double vector2D[2] = {out2[0] - SliceDisplayPoint[0], out2[1] - SliceDisplayPoint[1]}; vtkMath::Normalize2D(vector2D); Vector2 v1 = {vector2D[0], vector2D[1]}; - Vector2 screenVectors[2] ={{0, 1}, {1, 0}}; - Vector2 p0 = {out1[0],out1[1]}; + Vector2 screenVectors[2] = {{0, 1}, + {1, 0}}; + Vector2 p0 = {SliceDisplayPoint[0], SliceDisplayPoint[1]}; int *size = renderer->GetSize(); - Vector2 pts[2] = {{-0.5,-0.5} ,{size[0] + 0.5,size[1] + 0.5}}; + Vector2 pts[2] = {{-0.5, -0.5}, + {size[0] + 0.5, size[1] + 0.5}}; Vector2 intersectPoint(.0, .0); // calc the point, which line cross the screen border int pointIdx = 0; // line vector loop for (int i = 0; i < 2; ++i) { // line point loop - for (const auto & pt : pts) { + for (const auto &pt : pts) { if (pointIdx >= 2)return; 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.5, (int)intersectPoint.Y + 0.5, 0); + linePolyData->GetPoints()->SetPoint(pointIdx++, (int) intersectPoint.X + 0.05, + (int) intersectPoint.Y + 0.05, 0); } } } } + LoadTime.Modified(); } void ResliceCursorLegendActor::ReleaseGraphicsResources(vtkWindow * window) { - senseArea->ReleaseGraphicsResources(window); + ControlPointSenseArea->ReleaseGraphicsResources(window); LineActor->ReleaseGraphicsResources(window); - LineShadow->ReleaseGraphicsResources(window); ControlPoint->ReleaseGraphicsResources(window); vtkProp::ReleaseGraphicsResources(window); } @@ -184,15 +203,12 @@ void ResliceCursorLegendActor::ReleaseGraphicsResources(vtkWindow * window) { int ResliceCursorLegendActor::RenderOverlay(vtkViewport *viewport) { auto renderer = vtkRenderer::SafeDownCast(viewport); if (!renderer) return 0; - if (firstRender){ - ControlPoint->SetRenderer(renderer); - firstRender = false; - } BuildShape(renderer); - if (senseArea->GetVisibility())senseArea->RenderOverlay(viewport); - if (LineShadow->GetVisibility())LineShadow->RenderOverlay(viewport); if (LineActor->GetVisibility())LineActor->RenderOverlay(viewport); - if (ControlPoint->GetVisibility())ControlPoint->RenderOverlay(viewport); + if (ControlPointActive){ + if (ControlPointSenseArea->GetVisibility())ControlPointSenseArea->RenderOverlay(viewport); + if (ControlPoint->GetVisibility())ControlPoint->RenderOverlay(viewport); + } return 1; } @@ -201,6 +217,7 @@ vtkProperty2D *ResliceCursorLegendActor::GetProperty() { } void ResliceCursorLegendActor::UpdateMousePosition(int* pos) { + ControlPointActive = true; double point0[3] = {.0,.0,.0}; double point1[3] = {.0,.0,.0}; linePolyData->GetPoints()->GetPoint(0,point0); @@ -231,3 +248,127 @@ void ResliceCursorLegendActor::UpdateMousePosition(int* pos) { void ResliceCursorLegendActor::Pick() { vtkProp::Pick(); } + +void ResliceCursorLegendActor::GetActors(vtkPropCollection * collection) { + collection->AddItem(ControlPointSenseArea); +} + +void ResliceCursorLegendActor::Drag(vtkRenderer* renderer) { + int *pos = renderer->GetRenderWindow()->GetInteractor()->GetEventPosition(); + int distance2 =pow((DragStartPosition[0] - (int)(SliceDisplayPoint[0])),2) + pow((DragStartPosition[1] - (int)(SliceDisplayPoint[1])),2); + if (distance2<=225 || Moving){ + ApplyMove(renderer); + Moving = true; + } + else{ + ApplyRoll(renderer); + Rolling = true; + } + +} + +void ResliceCursorLegendActor::ApplyRoll(vtkRenderer * renderer) { + int *pos = renderer->GetRenderWindow()->GetInteractor()->GetEventPosition(); + double slicePt[4] = {SlicePoint[0] , + SlicePoint[1] , + SlicePoint[2], + 1.0};; + SliceDisplayPoint[2] = 0.0; + SliceDisplayPoint[3] = 1.0; + renderer->SetDisplayPoint(SliceDisplayPoint); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(slicePt); + double position [4] ={ pos[0]+0.05, pos[1]+0.05,0,1}; + double vector2D[2] = {position[0] - SliceDisplayPoint[0], position[1] - SliceDisplayPoint[1]}; + vtkMath::Normalize2D(vector2D); + renderer->SetDisplayPoint(position); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(position); + double newVector[3]={position[0] - slicePt[0], position[1] - slicePt[1], position[2] - slicePt[2]}; + vtkMath::Normalize(newVector); + + if (ReferenceCursor){ + ReferenceCursor->SetSliceDirectionVector(newVector); + } + vtkMath::Cross(newVector, GetProjectDirectionVector(), newVector); + SetSliceDirectionVector(newVector); +} + +void ResliceCursorLegendActor::ApplyMove(vtkRenderer * renderer) { + int *pos = renderer->GetRenderWindow()->GetInteractor()->GetEventPosition(); + if (!Moving){ + LastSliceDisplayPoint[0]=SliceDisplayPoint[0]; + LastSliceDisplayPoint[1]=SliceDisplayPoint[1]; + } + double pt1[4] = {LastSliceDisplayPoint[0]+(pos[0]-DragStartPosition[0]) + 0.5 , + LastSliceDisplayPoint[1]+(pos[1]-DragStartPosition[1]) + 0.5 , + 0, + 1.0}; + renderer->SetDisplayPoint(pt1); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(pt1); + double pt2[4] = {pt1[0] + 10000.0 * ProjectDirectionVector[0], + pt1[1] + 10000.0 * ProjectDirectionVector[1], + pt1[2] + 10000.0 * ProjectDirectionVector[2], + 1.0}; + double x ; + double intersectPoint[4]={.0,.0,.0,1.}; + if (vtkPlane::IntersectWithLine(pt1, pt2, ProjectDirectionVector, SlicePoint,x,intersectPoint)) + { + SetSlicePoint(intersectPoint); + if (ReferenceCursor){ + ReferenceCursor->SetSlicePoint(intersectPoint); + } + this->InvokeEvent(MOVE); + } +} + +void ResliceCursorLegendActor::InvokeDragEvent() { + if (Rolling){ + this->InvokeEvent(ROLL); + return; + } + if (Moving){ + this->InvokeEvent(MOVE); + return; + } +} + +void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) { + double pt1[3] = {.0, .0, .0}; + linePolyData->GetPoints()->GetPoint(0, pt1); + double pt2[3] = {.0, .0, .0}; + linePolyData->GetPoints()->GetPoint(1, pt2); + double worldPt1[4] = {.0,.0,.0,1.}; + double worldPt2[4] = {.0,.0,.0,1.}; + renderer->SetDisplayPoint(pt1); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(worldPt1); + renderer->SetDisplayPoint(pt2); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(worldPt2); + + vtkNew plane; + plane->SetOrigin(GetSlicePoint()); + plane->SetNormal(GetProjectDirectionVector()); + double t; + double wpt_end[4] = {worldPt1[0] + 10000.0 * ProjectDirectionVector[0], + worldPt1[1] + 10000.0 * ProjectDirectionVector[1], + worldPt1[2] + 10000.0 * ProjectDirectionVector[2], + 1.0}; + double newPt1[4] = {.0,.0,.0,1.}; + int ret = plane->IntersectWithLine(worldPt1,wpt_end,t,newPt1); + if (ret == 0 ) vtkErrorMacro("no intersect!"); + + double wpt_end2[4] = {worldPt2[0] + 10000.0 * ProjectDirectionVector[0], + worldPt2[1] + 10000.0 * ProjectDirectionVector[1], + worldPt2[2] + 10000.0 * ProjectDirectionVector[2], + 1.0}; + double newPt2[4] = {.0,.0,.0,1.}; + ret = plane->IntersectWithLine(worldPt2,wpt_end2,t,newPt2); + if (ret == 0 ) vtkErrorMacro("no intersect!"); + + double vector[3] = {newPt2[0]-newPt1[0],newPt2[1]-newPt1[1],newPt2[2]-newPt1[2]}; + vtkMath::Cross(vector, GetProjectDirectionVector(), vector); + SetSliceDirectionVector(vector); +} diff --git a/src/src/Rendering/Legend/ResliceCursorLegendActor.h b/src/src/Rendering/Legend/ResliceCursorLegendActor.h index 1f44ca0..5ae6826 100644 --- a/src/src/Rendering/Legend/ResliceCursorLegendActor.h +++ b/src/src/Rendering/Legend/ResliceCursorLegendActor.h @@ -6,6 +6,8 @@ #define RENDERLAB_RESLICECURSORLEGENDACTOR_H #include +#include +#include class vtkRenderer; class vtkPolyData; @@ -26,6 +28,12 @@ public: virtual void BuildShape(vtkRenderer *renderer); + enum EventType{ + ROLL = vtkCommand::UserEvent+1000, + MOVE, + END_DRAG + }; + vtkSetVector3Macro(SlicePoint,double); vtkGetVector3Macro(SlicePoint,double); @@ -35,6 +43,9 @@ public: vtkSetVector3Macro(ProjectDirectionVector,double); vtkGetVector3Macro(ProjectDirectionVector,double); + vtkGetVector2Macro(DragStartPosition, int); + vtkSetVector2Macro(DragStartPosition, int); + vtkProperty2D* GetProperty(); //@{ @@ -43,7 +54,7 @@ public: */ double *GetBounds() VTK_SIZEHINT(6) override { return nullptr; } - void GetActors(vtkPropCollection *) override {} + void GetActors(vtkPropCollection *) override; void GetVolumes(vtkPropCollection *) override {} @@ -68,8 +79,35 @@ public: void UpdateMousePosition(int* pos); + void UpdateCursor3DPoint(vtkRenderer * renderer); + void Pick() override; + void StartDrag(){ + dragging = true; + ControlPointActive = false; + if (ReferenceCursor){ + ReferenceCursor->ControlPointActive = false; + } + } + + void StopDrag(){ + dragging = false; + ControlPointActive = true; + Moving = false; + Rolling = false; + if (ReferenceCursor){ + ReferenceCursor->ControlPointActive = true; + ReferenceCursor->Moving = false; + } + } + + void Drag(vtkRenderer* renderer); + + void InvokeDragEvent(); + + vtkSetMacro(ReferenceCursor,ResliceCursorLegendActor*); + protected: ResliceCursorLegendActor(); @@ -79,19 +117,32 @@ private: void operator=(const ResliceCursorLegendActor &) = delete; + void ApplyRoll(vtkRenderer * renderer); + + void ApplyMove(vtkRenderer* renderer); + + vtkActor2D *LineActor; - ControlPointRActor *ControlPoint; - vtkActor2D *LineShadow; - vtkActor2D *senseArea; + vtkActor2D *ControlPoint; + vtkActor2D *ControlPointSenseArea; vtkPolyData* linePolyData; double LineHalfLength = 500.0; double SlicePoint[3] = {.0, .0, .0}; double HandlePoint[4] = {.0, .0, .0, .0}; bool HandleUpdated = false; - bool firstRender = true; + bool SliceUpdated = false; + ResliceCursorLegendActor* ReferenceCursor = nullptr; + bool ControlPointActive = false; + bool dragging = false; + bool Moving = false; + bool Rolling = false; + int DragStartPosition[2] = {0,0}; double Handle2DPoint[2] = {.0, .0, }; double SliceDirectionVector[3] = {.0, .0, .0}; double ProjectDirectionVector[3] = {.0, .0, .0}; + double SliceDisplayPoint[4] = {.0, .0, .0, .0}; + double LastSliceDisplayPoint[2] = {.0, .0}; + vtkTimeStamp LoadTime; }; diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.cpp b/src/src/Rendering/Viewer/ResliceImageViewer.cpp index 89a6799..7f96862 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.cpp +++ b/src/src/Rendering/Viewer/ResliceImageViewer.cpp @@ -41,7 +41,8 @@ ResliceImageViewer::ResliceImageViewer() Mapper->SetResampleToScreenPixels(0); Mapper->SetSeparateWindowLevelOperation(0); Actor->SetMapper(Mapper); - + cursor1->SetReferenceCursor(cursor2); + cursor2->SetReferenceCursor(cursor1); OrientationMatrix->Identity(); } @@ -145,11 +146,8 @@ void ResliceImageViewer::Render() { Renderer->AddActor2D(cursor2); cursor1->SetSlicePoint(Renderer->GetActiveCamera()->GetFocalPoint()); cursor2->SetSlicePoint(Renderer->GetActiveCamera()->GetFocalPoint()); - double project[3] = {0,0.0,1.0}; - project[DefaultOrientation] = 1.; - OrientationMatrix->MultiplyPoint(project,project); - cursor1->SetProjectDirectionVector(project); - cursor2->SetProjectDirectionVector(project); + cursor1->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); + cursor2->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); double sliceDirection1[4]{.0, .0, .0, 1.}; double sliceDirection2[4]{.0, .0, .0, 1.}; switch (DefaultOrientation) { @@ -170,7 +168,7 @@ void ResliceImageViewer::Render() { case 2:{ sliceDirection1[0] = 1.0; cursor1->GetProperty()->SetColor(1,0,0); - sliceDirection2[01] = 1.0; + sliceDirection2[1] = 1.0; cursor2->GetProperty()->SetColor(0,1,0); break; } @@ -180,6 +178,11 @@ void ResliceImageViewer::Render() { cursor1->SetSliceDirectionVector(sliceDirection1); cursor2->SetSliceDirectionVector(sliceDirection2); this->InteractorStyle->AddObserver(vtkCommand::UserEvent+20,this,&ResliceImageViewer::updateHandle); + this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::updateSliceCursor); + cursor1->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); + cursor1->AddObserver(ResliceCursorLegendActor::MOVE,this, &ResliceImageViewer::handleMove); + cursor2->AddObserver(ResliceCursorLegendActor::ROLL,this, &ResliceImageViewer::handleRoll); + cursor2->AddObserver(ResliceCursorLegendActor::MOVE,this, &ResliceImageViewer::handleMove); //some first render logic Render(); return; @@ -231,3 +234,42 @@ void ResliceImageViewer::updateHandle(vtkObject* sender, unsigned long eventID, cursor1->UpdateMousePosition(pos); cursor2->UpdateMousePosition(pos); } + +double *ResliceImageViewer::GetCursorSlicePoint() { + return cursor1->GetSlicePoint(); +} + +double *ResliceImageViewer::GetCursorSliceDirection1() { + return cursor1->GetSliceDirectionVector(); +} + +double *ResliceImageViewer::GetCursorSliceDirection2() { + return cursor2->GetSliceDirectionVector(); +} + +void ResliceImageViewer::handleRoll() { + this->InvokeEvent(ResliceCursorLegendActor::ROLL); +} + +void ResliceImageViewer::handleMove() { + this->InvokeEvent(ResliceCursorLegendActor::MOVE); +} + +void ResliceImageViewer::ChangeSliceNormal(double *normal) { + auto camera = Renderer->GetActiveCamera(); + double focalPt[3] = {.0, .0, .0}; + camera->GetFocalPoint(focalPt); + vtkMath::Normalize(normal); + camera->SetPosition(focalPt[0]+30.0*normal[0],focalPt[1]+30.0*normal[1],focalPt[2]+30.0*normal[2]); + camera->OrthogonalizeViewUp(); + Renderer->ResetCameraClippingRange(); +} + +void ResliceImageViewer::ChangeSlicePoint(double *point) { + +} + +void ResliceImageViewer::updateSliceCursor() { + cursor1->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); + cursor2->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); +} diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.h b/src/src/Rendering/Viewer/ResliceImageViewer.h index 0b7c7f2..41eae68 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.h +++ b/src/src/Rendering/Viewer/ResliceImageViewer.h @@ -41,6 +41,12 @@ public: void SetDefaultSliceOrientation(int orientation); void SetCoordsTransformMatrix(vtkMatrix4x4* matrix4X4); + double* GetCursorSlicePoint(); + double* GetCursorSliceDirection1(); + double* GetCursorSliceDirection2(); + + void ChangeSlicePoint(double * point); + void ChangeSliceNormal(double * normal); protected: ResliceImageViewer(); @@ -51,10 +57,14 @@ protected: virtual void UnInstallPipeline(); void updateHandle(vtkObject* sender, unsigned long eventID, void* callData); + void updateSliceCursor(); private: ResliceImageViewer(const ResliceImageViewer &) = delete; void operator=(const ResliceImageViewer &) = delete; + void handleRoll(); + void handleMove(); + vtkRenderWindow *RenderWindow; vtkRenderer *Renderer; vtkRenderer *MeasureRenderer; diff --git a/src/src/UI/Manager/ResliceImageManager.cpp b/src/src/UI/Manager/ResliceImageManager.cpp new file mode 100644 index 0000000..9709e1b --- /dev/null +++ b/src/src/UI/Manager/ResliceImageManager.cpp @@ -0,0 +1,55 @@ +// +// Created by Krad on 2022/12/26. +// + +#include "ResliceImageManager.h" + +#include + +#include "Rendering/Viewer/ResliceImageViewer.h" + +ResliceImageManager::ResliceImageManager(QObject *parent) : QObject(parent) { + +} + +void ResliceImageManager::SetViewer(int index, ResliceImageViewer *viewer) { + if (!viewer) return; + switch (index){ + case 0:{ + viewerA = viewer; + break; + } + case 1:{ + viewerC = viewer; + break; + } + case 2:{ + viewerS = viewer; + } + } +} + +void ResliceImageManager::InitEvents() { + viewerA->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback); + viewerS->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback); + viewerC->AddObserver(vtkCommand::UserEvent+1000,this,&ResliceImageManager::RollCallback); +} + +void ResliceImageManager::RollCallback(vtkObject *sender, unsigned long eventID, void *data) { + auto viewer = ResliceImageViewer::SafeDownCast(sender); + if (viewer){ + if (viewer!=viewerA){ + viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerA->Render(); + } + if (viewer!=viewerC){ + viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerC->Render(); + } + if (viewer!=viewerS){ + viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerS->Render(); + } + } + +} diff --git a/src/src/UI/Manager/ResliceImageManager.h b/src/src/UI/Manager/ResliceImageManager.h new file mode 100644 index 0000000..0a48076 --- /dev/null +++ b/src/src/UI/Manager/ResliceImageManager.h @@ -0,0 +1,34 @@ +// +// Created by Krad on 2022/12/26. +// + +#ifndef OMEGAV_RESLICEIMAGEMANAGER_H +#define OMEGAV_RESLICEIMAGEMANAGER_H + +#include +#include + +class ResliceImageViewer; +class vtkObject; + +class ResliceImageManager:public QObject { +public : + ResliceImageManager(QObject *parent=nullptr); + + ~ResliceImageManager() override { + mViewers.clear(); + }; + void SetViewer(int index, ResliceImageViewer* viewer); + + void InitEvents(); +private: + std::vector mViewers; + ResliceImageViewer * viewerA; + ResliceImageViewer * viewerS; + ResliceImageViewer * viewerC; + + void RollCallback(vtkObject* sender, unsigned long eventID, void* data); +}; + + +#endif //OMEGAV_RESLICEIMAGEMANAGER_H diff --git a/src/src/UI/Window/MPRResliceWindow.cpp b/src/src/UI/Window/MPRResliceWindow.cpp index e0a02b7..a336371 100644 --- a/src/src/UI/Window/MPRResliceWindow.cpp +++ b/src/src/UI/Window/MPRResliceWindow.cpp @@ -15,6 +15,7 @@ #include "Common/SeriesImageSet.h" #include "UI/Widget/ToolBar/ResliceMPRToolBar.h" #include "Rendering/Viewer/ResliceImageViewer.h" +#include "UI/Manager/ResliceImageManager.h" MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { setObjectName("MPRWin"); @@ -62,6 +63,12 @@ MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog window3->SetPolygonSmoothing(1); mViewerS = ResliceImageViewer::New(); mWidgetSagittal->setRenderWindow(window3); + + manager = new ResliceImageManager(this); + manager->SetViewer(0,mViewerA); + manager->SetViewer(1,mViewerC); + manager->SetViewer(2,mViewerS); + manager->InitEvents(); } MPRResliceWindow::~MPRResliceWindow() { diff --git a/src/src/UI/Window/MPRResliceWindow.h b/src/src/UI/Window/MPRResliceWindow.h index b85d75c..7f41f78 100644 --- a/src/src/UI/Window/MPRResliceWindow.h +++ b/src/src/UI/Window/MPRResliceWindow.h @@ -15,6 +15,7 @@ class QSplitter; class SeriesImageSet; +class ResliceImageManager; class MPRResliceWindow :public QDialog { Q_OBJECT @@ -40,6 +41,7 @@ private: ResliceImageViewer *mViewerA = nullptr; ResliceImageViewer *mViewerS = nullptr; ResliceImageViewer *mViewerC = nullptr; + ResliceImageManager* manager = nullptr; QSplitter* mMainSplitter= nullptr; QSplitter* mAppendSplitter= nullptr; int layoutType = 0;