From ac8e3c6cff4e8e0ab4e09eccbf17bf28d0766d66 Mon Sep 17 00:00:00 2001 From: Krad Date: Thu, 7 Apr 2022 14:18:13 +0800 Subject: [PATCH] Dynamic orientation from calculate. --- src/src/base/infinitiViewer.cxx | 127 +++++++++++++++----------------- src/src/base/infinitiViewer.h | 4 +- src/src/view/dicomimageview.cpp | 10 ++- src/src/view/dicomimageview.h | 2 +- 4 files changed, 69 insertions(+), 74 deletions(-) diff --git a/src/src/base/infinitiViewer.cxx b/src/src/base/infinitiViewer.cxx index 1fb2fd0..51012f4 100644 --- a/src/src/base/infinitiViewer.cxx +++ b/src/src/base/infinitiViewer.cxx @@ -18,13 +18,14 @@ #include "vtkPiecewiseFunction.h" #include "vector" #include "vtkCornerAnnotation.h" -#include "measure/Measure.h" #include "measure/MeasureStore.h" #include "vtkTextActor.h" #include "vtkTextProperty.h" #include "ExtendMedicalImageProperties.h" -#include "measure/RulerLegendActor.h" #include "util/ColorMapReader.h" +#include "vtkMath.h" + + #include "DicomLoader.h" @@ -652,6 +653,7 @@ void infinitiViewer::SetSliceOrientation(int orientation) } this->UpdateOrientation(); + updateOrienInfo(); // this->UpdateDisplayExtent(); if (this->Renderer && this->GetInput()) @@ -685,13 +687,13 @@ void infinitiViewer::UpdateOrientation() case infinitiViewer::SLICE_ORIENTATION_XZ: cam->SetFocalPoint(0, 0, 0); cam->SetPosition(0, 1, 0); // 1 if medical ? - cam->SetViewUp(0, 0, 1); + cam->SetViewUp(0, 0, -1); break; case infinitiViewer::SLICE_ORIENTATION_YZ: cam->SetFocalPoint(0, 0, 0); - cam->SetPosition(1, 0, 0); // -1 if medical ? - cam->SetViewUp(0, 0, 1); + cam->SetPosition( 1, 0, 0); // -1 if medical ? + cam->SetViewUp(0, 0, -1); break; } } @@ -985,7 +987,6 @@ void infinitiViewer::Render() int currentIndex = ImageMapper->GetSliceNumber(); if (currentIndex != lastIndex) this->SetSlice(lastIndex); this->Renderer->GetActiveCamera()->SetParallelScale(xs < 150 ? 75 : (xs - 1) / 2.0); - //calibration of image by VFlip //this->Renderer->GetActiveCamera()->Elevation(-180); //this->Renderer->GetActiveCamera()->Roll(180); @@ -1257,77 +1258,67 @@ void infinitiViewer::initCornerInfo(ExtendMedicalImageProperties* pSeries) m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("****"); m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n"); - std::vector* orien_list = orientationHelper::getOrientationStrList(""); - //currently only adapt to USCT Format - if (orien_list) - { - m_cornerInfo.ConstAnno[BOTTOM_MIDDLE].append(orien_list->at(BOTTOM_MIDDLE - 4)); - m_cornerInfo.ConstAnno[BOTTOM_MIDDLE].append("\n"); - - m_cornerInfo.ConstAnno[RIGHT_MIDDLE].append(orien_list->at(RIGHT_MIDDLE - 4)); - m_cornerInfo.ConstAnno[RIGHT_MIDDLE].append("\n"); + double* d = pSeries->GetDirectionCosine(); + double xVector[3] = {d[0], d[1], d[2]}; + double yVector[3] = {d[3], d[4], d[5]}; + double zVector[3] = {0, 0, 0}; + vtkMath::Cross(xVector, yVector, zVector); - m_cornerInfo.ConstAnno[LEFT_MIDDLE].append(orien_list->at(LEFT_MIDDLE - 4)); - m_cornerInfo.ConstAnno[LEFT_MIDDLE].append("\n"); - - m_cornerInfo.ConstAnno[TOP_MIDDLE].append(orien_list->at(TOP_MIDDLE - 4)); - m_cornerInfo.ConstAnno[TOP_MIDDLE].append("\n"); - } + matrix->Zero(); + matrix->SetElement(0, 0, xVector[0]); + matrix->SetElement(0, 1, xVector[1]); + matrix->SetElement(0, 2, xVector[2]); + matrix->SetElement(1, 0, yVector[0]); + matrix->SetElement(1, 1, yVector[1]); + matrix->SetElement(1, 2, yVector[2]); + matrix->SetElement(2, 0, zVector[0]); + matrix->SetElement(2, 1, zVector[1]); + matrix->SetElement(2, 2, zVector[2]); + matrix->SetElement(3, 3, 1); + matrix->Invert(); } -void infinitiViewer::updateOrienInfo(TransFormType type) +int getOrientationIndex(double* v){ + int max_index = 0; + if (fabs(v[0])>fabs(v[1])){ + if (fabs(v[0])<=fabs(v[2])) max_index = 2; + } + else{ + if(fabs(v[1])>=fabs(v[2])) max_index=1; + else max_index = 2; + } + return v[max_index]>0?max_index*2:2*max_index+1; +} + +int getOppositeOrientation(int f){ + int inner_idx = f % 2; + return f + 1 - inner_idx * 2; +} + +void infinitiViewer::updateOrienInfo() { + static const char* dds[6] ={"R","L","P","A","F","H"}; + double proj[4] ={0,0,0,1}; + Renderer->GetActiveCamera()->GetDirectionOfProjection(proj); + double viewUp[4]= {0,0,0,1}; + this->Renderer->GetActiveCamera()->GetViewUp(viewUp); + double viewRight[4] = {0, 0, 0, 1}; + vtkMath::Cross(viewUp,proj, viewRight); - char top_middle[20]; - char left_middle[20]; + double viewUpVector[4]= {0,0,0,1}; + double viewRightVector[4]= {0,0,0,1}; + matrix->MultiplyPoint(viewUp, viewUpVector); + int flag = getOrientationIndex(viewUpVector); - switch (type) - { - case ROTATE_90_CCW: - strcpy_s(top_middle, cornerAnnotation->GetText(TOP_MIDDLE)); - cornerAnnotation->SetText(TOP_MIDDLE, cornerAnnotation->GetText(RIGHT_MIDDLE)); - cornerAnnotation->SetText(RIGHT_MIDDLE, cornerAnnotation->GetText(BOTTOM_MIDDLE)); - cornerAnnotation->SetText(BOTTOM_MIDDLE, cornerAnnotation->GetText(LEFT_MIDDLE)); - cornerAnnotation->SetText(LEFT_MIDDLE, top_middle); - break; - case ROTATE_90_CW: - strcpy_s(top_middle, cornerAnnotation->GetText(TOP_MIDDLE)); - cornerAnnotation->SetText(TOP_MIDDLE, cornerAnnotation->GetText(LEFT_MIDDLE)); - cornerAnnotation->SetText(LEFT_MIDDLE, cornerAnnotation->GetText(BOTTOM_MIDDLE)); - cornerAnnotation->SetText(BOTTOM_MIDDLE, cornerAnnotation->GetText(RIGHT_MIDDLE)); - cornerAnnotation->SetText(RIGHT_MIDDLE, top_middle); - break; - case ROTATE_180: - strcpy_s(top_middle, cornerAnnotation->GetText(TOP_MIDDLE)); - strcpy_s(left_middle, cornerAnnotation->GetText(LEFT_MIDDLE)); - cornerAnnotation->SetText(TOP_MIDDLE, cornerAnnotation->GetText(BOTTOM_MIDDLE)); - cornerAnnotation->SetText(LEFT_MIDDLE, cornerAnnotation->GetText(RIGHT_MIDDLE)); - cornerAnnotation->SetText(BOTTOM_MIDDLE, top_middle); - cornerAnnotation->SetText(RIGHT_MIDDLE, left_middle); - break; - case H_FLIP: - strcpy_s(left_middle, cornerAnnotation->GetText(LEFT_MIDDLE)); - cornerAnnotation->SetText(LEFT_MIDDLE, cornerAnnotation->GetText(RIGHT_MIDDLE)); - cornerAnnotation->SetText(RIGHT_MIDDLE, left_middle); - break; - case V_FLIP: - strcpy_s(top_middle, cornerAnnotation->GetText(TOP_MIDDLE)); - cornerAnnotation->SetText(TOP_MIDDLE, cornerAnnotation->GetText(BOTTOM_MIDDLE)); - cornerAnnotation->SetText(BOTTOM_MIDDLE, top_middle); - break; - case CLEAR: - cornerAnnotation->SetText(TOP_MIDDLE, m_cornerInfo.ConstAnno[TOP_MIDDLE].c_str()); - cornerAnnotation->SetText(BOTTOM_MIDDLE, m_cornerInfo.ConstAnno[BOTTOM_MIDDLE].c_str()); - cornerAnnotation->SetText(LEFT_MIDDLE, m_cornerInfo.ConstAnno[LEFT_MIDDLE].c_str()); - cornerAnnotation->SetText(RIGHT_MIDDLE, m_cornerInfo.ConstAnno[RIGHT_MIDDLE].c_str()); - break; - default: - break; - } + cornerAnnotation->SetText(TOP_MIDDLE, dds[flag]); + cornerAnnotation->SetText(BOTTOM_MIDDLE, dds[getOppositeOrientation(flag)]); + matrix->MultiplyPoint(viewRight, viewRightVector); + flag = getOrientationIndex(viewRightVector); + cornerAnnotation->SetText(RIGHT_MIDDLE, dds[flag]); + cornerAnnotation->SetText(LEFT_MIDDLE, dds[getOppositeOrientation(flag)]); cornerAnnotation->Modified(); - this->Render(); } diff --git a/src/src/base/infinitiViewer.h b/src/src/base/infinitiViewer.h index 599b5e4..c0a1120 100644 --- a/src/src/base/infinitiViewer.h +++ b/src/src/base/infinitiViewer.h @@ -6,6 +6,7 @@ #include "vector" #include "QList" #include "measure\DraggableActor.h" +#include "vtkMatrix4x4.h" //for convert vtkEvent to Qt signal #include "measure\vtkSignalRaiser.h" @@ -58,7 +59,7 @@ public: void updateCornerInfo(int index); void updateCornerInfoAll(); void initCornerInfo(ExtendMedicalImageProperties *pSeriesTags); - void updateOrienInfo(TransFormType type); + void updateOrienInfo(); void setUpImageViewer(); //For Export @@ -389,6 +390,7 @@ private: DicomCornerInfo m_cornerInfo; char SOP_UID[20]; + vtkNew matrix; }; #endif diff --git a/src/src/view/dicomimageview.cpp b/src/src/view/dicomimageview.cpp index e601775..5a3f3e1 100644 --- a/src/src/view/dicomimageview.cpp +++ b/src/src/view/dicomimageview.cpp @@ -153,9 +153,10 @@ void DicomImageView::Slot_WindowLevelEventForFusion(double level, double width) } } -void DicomImageView::Slot_UpdateOrienInfo(TransFormType operation) +void DicomImageView::Slot_Transformation() { - _ImageViewer->updateOrienInfo(operation); + _ImageViewer->updateOrienInfo(); + _ImageViewer->Render(); } //Widget event---------------------------------------------------------------- @@ -360,7 +361,7 @@ void DicomImageView::setDicomImageView(SeriesImageSet *series) initScrollbar(); connect(_scrollBar, &QScrollBar::valueChanged, this, &DicomImageView::Slot_scrollValueChanged); - connect(this, &DicomImageView::Signal_Transformation, this, &DicomImageView::Slot_UpdateOrienInfo); + connect(this, &DicomImageView::Signal_Transformation, this, &DicomImageView::Slot_Transformation); } bool DicomImageView::HasSeries() @@ -374,8 +375,9 @@ void DicomImageView::LoadSeries(SeriesImageSet *series) _ImageViewer->SetInputData(_Series->GetData()); _ImageViewer->initCornerInfo(series->GetProperty()); _ImageViewer->setUpImageViewer(); + _ImageViewer->updateOrienInfo(); //以下是一些转接函数 - //TODO: 考虑使用connect 替代 AddObserver,避免出现多种事件机制架构 + //使用connect 替代 AddObserver,避免出现多种事件机制架构 connect(_ImageViewer->GetSignalRaiser(),&vtkSignalRaiser::raiseEvent, this, &DicomImageView::syncEventFunc); //目前 替换了一部分包括SlicedEvent,EndDollyEvent,EndWindowLevelEvent,EndPanEvent,主要关联到sync diff --git a/src/src/view/dicomimageview.h b/src/src/view/dicomimageview.h index b18141e..9f7fc11 100644 --- a/src/src/view/dicomimageview.h +++ b/src/src/view/dicomimageview.h @@ -148,7 +148,7 @@ public slots: void Slot_ViewEmpty(); void Slot_scrollValueChanged(int); void Slot_WindowLevelEventForFusion(double level, double width); - void Slot_UpdateOrienInfo(TransFormType); + void Slot_Transformation(); void viewerClicked(); protected: