From 5d5171640548664abbec1d6f7c98b0f795aa871b Mon Sep 17 00:00:00 2001 From: Krad Date: Thu, 29 Dec 2022 09:55:22 +0800 Subject: [PATCH] Reslice hair cross rolling done. --- .../ResliceImageInteractorStyle.cpp | 5 +- .../Legend/ResliceCursorLegendActor.cpp | 25 ++++--- .../Legend/ResliceSquareLegendActor.cpp | 75 +++++++++++++++++++ .../Legend/ResliceSquareLegendActor.h | 70 +++++++++++++++++ .../Rendering/Viewer/ResliceImageViewer.cpp | 35 ++++++++- src/src/Rendering/Viewer/ResliceImageViewer.h | 8 +- src/src/UI/Manager/ResliceImageManager.cpp | 50 ++++++++++--- src/src/UI/Manager/ResliceImageManager.h | 1 + src/src/UI/Window/MPRResliceWindow.cpp | 2 +- 9 files changed, 239 insertions(+), 32 deletions(-) create mode 100644 src/src/Rendering/Legend/ResliceSquareLegendActor.cpp create mode 100644 src/src/Rendering/Legend/ResliceSquareLegendActor.h diff --git a/src/src/Interaction/ResliceImageInteractorStyle.cpp b/src/src/Interaction/ResliceImageInteractorStyle.cpp index 4cf7a9e..5156f8c 100644 --- a/src/src/Interaction/ResliceImageInteractorStyle.cpp +++ b/src/src/Interaction/ResliceImageInteractorStyle.cpp @@ -29,7 +29,7 @@ ResliceImageInteractorStyle::~ResliceImageInteractorStyle() { void ResliceImageInteractorStyle::OnMouseMove() { switch (this->State) { - case VTKIS_NONE: + case VTKIS_NONE:{ if (triggerEvent) { this->InvokeEvent(vtkCommand::UserEvent+20,Interactor->GetEventPosition()); @@ -37,6 +37,7 @@ void ResliceImageInteractorStyle::OnMouseMove() { } NoneStatePick(); break; + } case VTKIS_POSITION_PROP: { this->Interactor->Render(); auto cursor = ResliceCursorLegendActor::SafeDownCast(this->CurrentProp); @@ -44,8 +45,6 @@ void ResliceImageInteractorStyle::OnMouseMove() { } default: vtkInteractorStyleImage::OnMouseMove(); - - } } diff --git a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp index 27bcc07..c9c1ff0 100644 --- a/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp +++ b/src/src/Rendering/Legend/ResliceCursorLegendActor.cpp @@ -136,10 +136,10 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { renderer->DisplayToWorld(); renderer->GetWorldPoint(HandlePoint); HandleUpdated = false; + ControlPoint->SetPosition(Handle2DPoint[0] - 0.5, Handle2DPoint[1] - .5); + ControlPointSenseArea->SetPosition(Handle2DPoint[0], Handle2DPoint[1] - .5); + return; } - 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); @@ -180,7 +180,10 @@ void ResliceCursorLegendActor::BuildShape(vtkRenderer *renderer) { for (int i = 0; i < 2; ++i) { // line point loop for (const auto &pt : pts) { - if (pointIdx >= 2)return; + if (pointIdx >= 2){ + LoadTime.Modified(); + return; + } if (IntersectLine2D(p0, v1, pt, screenVectors[i], intersectPoint)) { int pcV = (int) intersectPoint.getValue(i); if (pcV >= -1 && pcV <= size[i] + 1) { @@ -291,7 +294,7 @@ void ResliceCursorLegendActor::ApplyRoll(vtkRenderer * renderer) { ReferenceCursor->SetSliceDirectionVector(newVector); } vtkMath::Cross(newVector, GetProjectDirectionVector(), newVector); - SetSliceDirectionVector(newVector); + this->SetSliceDirectionVector(newVector); } void ResliceCursorLegendActor::ApplyMove(vtkRenderer * renderer) { @@ -315,7 +318,7 @@ void ResliceCursorLegendActor::ApplyMove(vtkRenderer * renderer) { double intersectPoint[4]={.0,.0,.0,1.}; if (vtkPlane::IntersectWithLine(pt1, pt2, ProjectDirectionVector, SlicePoint,x,intersectPoint)) { - SetSlicePoint(intersectPoint); + this->SetSlicePoint(intersectPoint); if (ReferenceCursor){ ReferenceCursor->SetSlicePoint(intersectPoint); } @@ -335,9 +338,9 @@ void ResliceCursorLegendActor::InvokeDragEvent() { } void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) { - double pt1[3] = {.0, .0, .0}; + double pt1[4] = {.0, .0, .0,.0}; linePolyData->GetPoints()->GetPoint(0, pt1); - double pt2[3] = {.0, .0, .0}; + double pt2[4] = {.0, .0, .0, .0}; linePolyData->GetPoints()->GetPoint(1, pt2); double worldPt1[4] = {.0,.0,.0,1.}; double worldPt2[4] = {.0,.0,.0,1.}; @@ -358,7 +361,6 @@ void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) { 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], @@ -366,9 +368,8 @@ void ResliceCursorLegendActor::UpdateCursor3DPoint(vtkRenderer * renderer) { 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]}; + double vector[3] = {worldPt2[0]-worldPt1[0],worldPt2[1]-worldPt1[1],worldPt2[2]-worldPt1[2]}; vtkMath::Cross(vector, GetProjectDirectionVector(), vector); - SetSliceDirectionVector(vector); + this->SetSliceDirectionVector(vector); } diff --git a/src/src/Rendering/Legend/ResliceSquareLegendActor.cpp b/src/src/Rendering/Legend/ResliceSquareLegendActor.cpp new file mode 100644 index 0000000..bd4b329 --- /dev/null +++ b/src/src/Rendering/Legend/ResliceSquareLegendActor.cpp @@ -0,0 +1,75 @@ +// +// Created by Krad on 2022/12/28. +// + +#include "ResliceSquareLegendActor.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +vtkStandardNewMacro(ResliceSquareLegendActor) + +void ResliceSquareLegendActor::BuildShape(vtkRenderer *renderer) { + int* sizes = renderer->GetSize(); + Square->SetDisplayPosition(sizes[0]-20,sizes[1]-20); +} + +void ResliceSquareLegendActor::ReleaseGraphicsResources(vtkWindow * window) { + Square->ReleaseGraphicsResources(window); +} + +int ResliceSquareLegendActor::RenderOverlay(vtkViewport *viewport) { + auto renderer = vtkRenderer::SafeDownCast(viewport); + if (renderer){ + BuildShape(renderer); + return Square->RenderOverlay(viewport); + } + return 0; +} + +ResliceSquareLegendActor::ResliceSquareLegendActor() { + this->PickableOff(); + Square = vtkActor2D::New(); + Square->Register(this); + Square->Delete(); + vtkNew mapper; + vtkNew polydata; + vtkNew pts; + pts->SetNumberOfPoints(4); + pts->SetPoint(0,0,0,0); + pts->SetPoint(1,18,0,0); + pts->SetPoint(2,18,18,0); + pts->SetPoint(3,0,18,0); + polydata->SetPoints(pts); + vtkNew polygon; + polygon->GetPointIds()->SetNumberOfIds(4); + polygon->GetPointIds()->SetId(0,0); + polygon->GetPointIds()->SetId(1,1); + polygon->GetPointIds()->SetId(2,2); + polygon->GetPointIds()->SetId(3,3); + + vtkNew cells; + cells->InsertNextCell(polygon); + + polydata->SetPolys(cells); + mapper->SetInputData(polydata); + Square->SetMapper(mapper); + + Square->GetProperty()->SetLineWidth(0); + Square->GetProperty()->SetPointSize(0); + +} + +ResliceSquareLegendActor::~ResliceSquareLegendActor() { + +} + +vtkProperty2D *ResliceSquareLegendActor::GetProperty() { + return Square->GetProperty(); +} diff --git a/src/src/Rendering/Legend/ResliceSquareLegendActor.h b/src/src/Rendering/Legend/ResliceSquareLegendActor.h new file mode 100644 index 0000000..595a881 --- /dev/null +++ b/src/src/Rendering/Legend/ResliceSquareLegendActor.h @@ -0,0 +1,70 @@ +// +// Created by Krad on 2022/12/28. +// + +#ifndef OMEGAV_RESLICESQUARELEGENDACTOR_H +#define OMEGAV_RESLICESQUARELEGENDACTOR_H + +#include + +class vtkRenderer; +class vtkActor2D; +class vtkProperty2D; + +class ResliceSquareLegendActor : public vtkProp { +public: + //@{ + /** + * Standard methods for instances of this class. + */ + static ResliceSquareLegendActor *New(); + + vtkTypeMacro(ResliceSquareLegendActor, vtkProp); + + virtual void BuildShape(vtkRenderer *renderer); + + //@{ + /** + * Methods to make this class behave as a vtkProp. + */ + double *GetBounds() VTK_SIZEHINT(6) override { return nullptr; } + + void GetActors(vtkPropCollection *) override {} + + void GetVolumes(vtkPropCollection *) override {} + + void ShallowCopy(vtkProp *prop) override {}; + + void ReleaseGraphicsResources(vtkWindow *) override; + + /** + * Method use to make this actor render in 2D scene; + * @param viewport + * @return render is success + */ + int RenderOverlay(vtkViewport *viewport) override; + + int RenderOpaqueGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; } + + int RenderTranslucentPolygonalGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; } + + int RenderVolumetricGeometry(vtkViewport *vtkNotUsed(viewport)) override { return 0; } + + vtkTypeBool HasTranslucentPolygonalGeometry() override { return 0; } + + vtkProperty2D* GetProperty(); +protected: + ResliceSquareLegendActor(); + + ~ResliceSquareLegendActor() override; + +private: + ResliceSquareLegendActor(const ResliceSquareLegendActor &) = delete; + + void operator=(const ResliceSquareLegendActor &) = delete; + + vtkActor2D * Square; +}; + + +#endif //OMEGAV_RESLICESQUARELEGENDACTOR_H diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.cpp b/src/src/Rendering/Viewer/ResliceImageViewer.cpp index 7f96862..c4a9111 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.cpp +++ b/src/src/Rendering/Viewer/ResliceImageViewer.cpp @@ -17,6 +17,7 @@ #include #include "Rendering/Legend/ResliceCursorLegendActor.h" +#include "Rendering/Legend/ResliceSquareLegendActor.h" #include "Interaction/ResliceImageInteractorStyle.h" vtkStandardNewMacro(ResliceImageViewer); @@ -30,6 +31,7 @@ ResliceImageViewer::ResliceImageViewer() , Mapper(vtkImageResliceMapper::New()) , cursor1(ResliceCursorLegendActor::New()) , cursor2(ResliceCursorLegendActor::New()) + , Square(ResliceSquareLegendActor::New()) , Actor(vtkImageSlice::New()) , OrientationMatrix(vtkMatrix4x4::New()) , DefaultOrientation(0) @@ -141,6 +143,7 @@ void ResliceImageViewer::SetInputData(vtkImageData *in) { void ResliceImageViewer::Render() { if (RenderWindow && Interactor){ if (FirstRender){ + //some first render logic FirstRender = false; Renderer->AddActor2D(cursor1); Renderer->AddActor2D(cursor2); @@ -156,6 +159,7 @@ void ResliceImageViewer::Render() { cursor1->GetProperty()->SetColor(0,0,1); sliceDirection2[1] = 1.0; cursor2->GetProperty()->SetColor(0,1,0); + Square->GetProperty()->SetColor(1,0,0); break; } case 1:{ @@ -163,6 +167,8 @@ void ResliceImageViewer::Render() { cursor1->GetProperty()->SetColor(1,0,0); sliceDirection2[2] = 1.0; cursor2->GetProperty()->SetColor(0,0,1); + Square->GetProperty()->SetColor(0,1,0); + break; } case 2:{ @@ -170,6 +176,7 @@ void ResliceImageViewer::Render() { cursor1->GetProperty()->SetColor(1,0,0); sliceDirection2[1] = 1.0; cursor2->GetProperty()->SetColor(0,1,0); + Square->GetProperty()->SetColor(0,0,1); break; } } @@ -178,12 +185,14 @@ 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); + this->InteractorStyle->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageViewer::EndDrag); + + this->RenderWindow->AddObserver(vtkCommand::WindowResizeEvent,this,&ResliceImageViewer::handleResize); 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 + Renderer->AddActor2D(Square); Render(); return; } @@ -260,7 +269,13 @@ void ResliceImageViewer::ChangeSliceNormal(double *normal) { 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]); + double proj [3]={.0 ,.0 ,.0}; + camera->GetDirectionOfProjection(proj); + double a = proj[0] * normal[0] + proj[1]* normal[1] + proj[2] * normal[2]; + double step = 30.0; + if (a>0)step = step*-1.0; +// vtkErrorMacro("proj:"<SetPosition(focalPt[0]+step*normal[0],focalPt[1]+step*normal[1],focalPt[2]+step*normal[2]); camera->OrthogonalizeViewUp(); Renderer->ResetCameraClippingRange(); } @@ -269,7 +284,19 @@ void ResliceImageViewer::ChangeSlicePoint(double *point) { } -void ResliceImageViewer::updateSliceCursor() { +void ResliceImageViewer::UpdateSliceCursor() { cursor1->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); + cursor1->UpdateCursor3DPoint(Renderer); cursor2->SetProjectDirectionVector(Renderer->GetActiveCamera()->GetDirectionOfProjection()); + cursor2->UpdateCursor3DPoint(Renderer); + Renderer->Render(); +} + +void ResliceImageViewer::EndDrag() { + this->InvokeEvent(ResliceCursorLegendActor::END_DRAG); +} + +void ResliceImageViewer::handleResize() { + cursor1->Modified(); + cursor2->Modified(); } diff --git a/src/src/Rendering/Viewer/ResliceImageViewer.h b/src/src/Rendering/Viewer/ResliceImageViewer.h index 41eae68..958991e 100644 --- a/src/src/Rendering/Viewer/ResliceImageViewer.h +++ b/src/src/Rendering/Viewer/ResliceImageViewer.h @@ -25,6 +25,8 @@ class vtkMatrix4x4; class ResliceCursorLegendActor; +class ResliceSquareLegendActor; + class ResliceImageViewer :public vtkObject { public: static ResliceImageViewer *New(); @@ -47,6 +49,9 @@ public: void ChangeSlicePoint(double * point); void ChangeSliceNormal(double * normal); + void EndDrag(); + void UpdateSliceCursor(); + protected: ResliceImageViewer(); @@ -57,13 +62,13 @@ 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(); + void handleResize(); vtkRenderWindow *RenderWindow; vtkRenderer *Renderer; @@ -73,6 +78,7 @@ private: vtkImageResliceMapper* Mapper; ResliceCursorLegendActor* cursor1; ResliceCursorLegendActor* cursor2; + ResliceSquareLegendActor* Square; vtkImageSlice* Actor; vtkMatrix4x4* OrientationMatrix; int DefaultOrientation; diff --git a/src/src/UI/Manager/ResliceImageManager.cpp b/src/src/UI/Manager/ResliceImageManager.cpp index 9709e1b..6a360ee 100644 --- a/src/src/UI/Manager/ResliceImageManager.cpp +++ b/src/src/UI/Manager/ResliceImageManager.cpp @@ -7,6 +7,7 @@ #include #include "Rendering/Viewer/ResliceImageViewer.h" +#include "Rendering/Legend/ResliceCursorLegendActor.h" ResliceImageManager::ResliceImageManager(QObject *parent) : QObject(parent) { @@ -30,26 +31,53 @@ void ResliceImageManager::SetViewer(int index, ResliceImageViewer *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); + viewerA->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback); + viewerS->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback); + viewerC->AddObserver(ResliceCursorLegendActor::ROLL,this,&ResliceImageManager::RollCallback); + viewerA->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag); + viewerS->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag); + viewerC->AddObserver(ResliceCursorLegendActor::END_DRAG,this,&ResliceImageManager::EndDrag); } 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){ + if (viewer==viewerA){ viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); viewerC->Render(); - } - if (viewer!=viewerS){ - viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); viewerS->Render(); } + if (viewer==viewerC){ + viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerA->Render(); + viewerS->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); + viewerS->Render(); + } + if (viewer==viewerS){ + viewerC->ChangeSliceNormal(viewer->GetCursorSliceDirection2()); + viewerC->Render(); + viewerA->ChangeSliceNormal(viewer->GetCursorSliceDirection1()); + viewerA->Render(); + } } } + +void ResliceImageManager::EndDrag(vtkObject *sender, unsigned long eventID, void *data) { + auto viewer = ResliceImageViewer::SafeDownCast(sender); + if (viewer){ + if (viewer!=viewerA){ + viewerA->UpdateSliceCursor(); + viewerA->Render(); + } + if (viewer!=viewerC){ + viewerC->UpdateSliceCursor(); + viewerC->Render(); + } + if (viewer!=viewerS){ + viewerS->UpdateSliceCursor(); + viewerS->Render(); + } + } +} diff --git a/src/src/UI/Manager/ResliceImageManager.h b/src/src/UI/Manager/ResliceImageManager.h index 0a48076..0ef31bd 100644 --- a/src/src/UI/Manager/ResliceImageManager.h +++ b/src/src/UI/Manager/ResliceImageManager.h @@ -28,6 +28,7 @@ private: ResliceImageViewer * viewerC; void RollCallback(vtkObject* sender, unsigned long eventID, void* data); + void EndDrag(vtkObject* sender, unsigned long eventID, void* data); }; diff --git a/src/src/UI/Window/MPRResliceWindow.cpp b/src/src/UI/Window/MPRResliceWindow.cpp index a336371..3c4eba4 100644 --- a/src/src/UI/Window/MPRResliceWindow.cpp +++ b/src/src/UI/Window/MPRResliceWindow.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -69,6 +68,7 @@ MPRResliceWindow::MPRResliceWindow(QWidget *parent, Qt::WindowFlags f) : QDialog manager->SetViewer(1,mViewerC); manager->SetViewer(2,mViewerS); manager->InitEvents(); + } MPRResliceWindow::~MPRResliceWindow() {