Dynamic orientation from calculate.

This commit is contained in:
Krad
2022-04-07 14:18:13 +08:00
parent f96afc95a8
commit ac8e3c6cff
4 changed files with 69 additions and 74 deletions

View File

@@ -18,13 +18,14 @@
#include "vtkPiecewiseFunction.h" #include "vtkPiecewiseFunction.h"
#include "vector" #include "vector"
#include "vtkCornerAnnotation.h" #include "vtkCornerAnnotation.h"
#include "measure/Measure.h"
#include "measure/MeasureStore.h" #include "measure/MeasureStore.h"
#include "vtkTextActor.h" #include "vtkTextActor.h"
#include "vtkTextProperty.h" #include "vtkTextProperty.h"
#include "ExtendMedicalImageProperties.h" #include "ExtendMedicalImageProperties.h"
#include "measure/RulerLegendActor.h"
#include "util/ColorMapReader.h" #include "util/ColorMapReader.h"
#include "vtkMath.h"
#include "DicomLoader.h" #include "DicomLoader.h"
@@ -652,6 +653,7 @@ void infinitiViewer::SetSliceOrientation(int orientation)
} }
this->UpdateOrientation(); this->UpdateOrientation();
updateOrienInfo();
// this->UpdateDisplayExtent(); // this->UpdateDisplayExtent();
if (this->Renderer && this->GetInput()) if (this->Renderer && this->GetInput())
@@ -685,13 +687,13 @@ void infinitiViewer::UpdateOrientation()
case infinitiViewer::SLICE_ORIENTATION_XZ: case infinitiViewer::SLICE_ORIENTATION_XZ:
cam->SetFocalPoint(0, 0, 0); cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(0, 1, 0); // 1 if medical ? cam->SetPosition(0, 1, 0); // 1 if medical ?
cam->SetViewUp(0, 0, 1); cam->SetViewUp(0, 0, -1);
break; break;
case infinitiViewer::SLICE_ORIENTATION_YZ: case infinitiViewer::SLICE_ORIENTATION_YZ:
cam->SetFocalPoint(0, 0, 0); cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(1, 0, 0); // -1 if medical ? cam->SetPosition( 1, 0, 0); // -1 if medical ?
cam->SetViewUp(0, 0, 1); cam->SetViewUp(0, 0, -1);
break; break;
} }
} }
@@ -985,7 +987,6 @@ void infinitiViewer::Render()
int currentIndex = ImageMapper->GetSliceNumber(); int currentIndex = ImageMapper->GetSliceNumber();
if (currentIndex != lastIndex) this->SetSlice(lastIndex); if (currentIndex != lastIndex) this->SetSlice(lastIndex);
this->Renderer->GetActiveCamera()->SetParallelScale(xs < 150 ? 75 : (xs - 1) / 2.0); this->Renderer->GetActiveCamera()->SetParallelScale(xs < 150 ? 75 : (xs - 1) / 2.0);
//calibration of image by VFlip //calibration of image by VFlip
//this->Renderer->GetActiveCamera()->Elevation(-180); //this->Renderer->GetActiveCamera()->Elevation(-180);
//this->Renderer->GetActiveCamera()->Roll(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("****");
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n"); m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
std::vector<std::string>* orien_list = orientationHelper::getOrientationStrList(""); double* d = pSeries->GetDirectionCosine();
//currently only adapt to USCT Format double xVector[3] = {d[0], d[1], d[2]};
if (orien_list) double yVector[3] = {d[3], d[4], d[5]};
{ double zVector[3] = {0, 0, 0};
m_cornerInfo.ConstAnno[BOTTOM_MIDDLE].append(orien_list->at(BOTTOM_MIDDLE - 4)); vtkMath::Cross(xVector, yVector, zVector);
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");
m_cornerInfo.ConstAnno[LEFT_MIDDLE].append(orien_list->at(LEFT_MIDDLE - 4)); matrix->Zero();
m_cornerInfo.ConstAnno[LEFT_MIDDLE].append("\n"); matrix->SetElement(0, 0, xVector[0]);
matrix->SetElement(0, 1, xVector[1]);
m_cornerInfo.ConstAnno[TOP_MIDDLE].append(orien_list->at(TOP_MIDDLE - 4)); matrix->SetElement(0, 2, xVector[2]);
m_cornerInfo.ConstAnno[TOP_MIDDLE].append("\n"); 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]; double viewUpVector[4]= {0,0,0,1};
char left_middle[20]; double viewRightVector[4]= {0,0,0,1};
matrix->MultiplyPoint(viewUp, viewUpVector);
int flag = getOrientationIndex(viewUpVector);
switch (type) cornerAnnotation->SetText(TOP_MIDDLE, dds[flag]);
{ cornerAnnotation->SetText(BOTTOM_MIDDLE, dds[getOppositeOrientation(flag)]);
case ROTATE_90_CCW: matrix->MultiplyPoint(viewRight, viewRightVector);
strcpy_s(top_middle, cornerAnnotation->GetText(TOP_MIDDLE)); flag = getOrientationIndex(viewRightVector);
cornerAnnotation->SetText(TOP_MIDDLE, cornerAnnotation->GetText(RIGHT_MIDDLE)); cornerAnnotation->SetText(RIGHT_MIDDLE, dds[flag]);
cornerAnnotation->SetText(RIGHT_MIDDLE, cornerAnnotation->GetText(BOTTOM_MIDDLE)); cornerAnnotation->SetText(LEFT_MIDDLE, dds[getOppositeOrientation(flag)]);
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->Modified(); cornerAnnotation->Modified();
this->Render();
} }

View File

@@ -6,6 +6,7 @@
#include "vector" #include "vector"
#include "QList" #include "QList"
#include "measure\DraggableActor.h" #include "measure\DraggableActor.h"
#include "vtkMatrix4x4.h"
//for convert vtkEvent to Qt signal //for convert vtkEvent to Qt signal
#include "measure\vtkSignalRaiser.h" #include "measure\vtkSignalRaiser.h"
@@ -58,7 +59,7 @@ public:
void updateCornerInfo(int index); void updateCornerInfo(int index);
void updateCornerInfoAll(); void updateCornerInfoAll();
void initCornerInfo(ExtendMedicalImageProperties *pSeriesTags); void initCornerInfo(ExtendMedicalImageProperties *pSeriesTags);
void updateOrienInfo(TransFormType type); void updateOrienInfo();
void setUpImageViewer(); void setUpImageViewer();
//For Export //For Export
@@ -389,6 +390,7 @@ private:
DicomCornerInfo m_cornerInfo; DicomCornerInfo m_cornerInfo;
char SOP_UID[20]; char SOP_UID[20];
vtkNew<vtkMatrix4x4> matrix;
}; };
#endif #endif

View File

@@ -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---------------------------------------------------------------- //Widget event----------------------------------------------------------------
@@ -360,7 +361,7 @@ void DicomImageView::setDicomImageView(SeriesImageSet *series)
initScrollbar(); initScrollbar();
connect(_scrollBar, &QScrollBar::valueChanged, this, &DicomImageView::Slot_scrollValueChanged); 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() bool DicomImageView::HasSeries()
@@ -374,8 +375,9 @@ void DicomImageView::LoadSeries(SeriesImageSet *series)
_ImageViewer->SetInputData(_Series->GetData()); _ImageViewer->SetInputData(_Series->GetData());
_ImageViewer->initCornerInfo(series->GetProperty()); _ImageViewer->initCornerInfo(series->GetProperty());
_ImageViewer->setUpImageViewer(); _ImageViewer->setUpImageViewer();
_ImageViewer->updateOrienInfo();
//以下是一些转接函数 //以下是一些转接函数
//TODO: 考虑使用connect 替代 AddObserver,避免出现多种事件机制架构 //使用connect 替代 AddObserver,避免出现多种事件机制架构
connect(_ImageViewer->GetSignalRaiser(),&vtkSignalRaiser::raiseEvent, this, &DicomImageView::syncEventFunc); connect(_ImageViewer->GetSignalRaiser(),&vtkSignalRaiser::raiseEvent, this, &DicomImageView::syncEventFunc);
//目前 替换了一部分包括SlicedEventEndDollyEventEndWindowLevelEventEndPanEvent主要关联到sync //目前 替换了一部分包括SlicedEventEndDollyEventEndWindowLevelEventEndPanEvent主要关联到sync

View File

@@ -148,7 +148,7 @@ public slots:
void Slot_ViewEmpty(); void Slot_ViewEmpty();
void Slot_scrollValueChanged(int); void Slot_scrollValueChanged(int);
void Slot_WindowLevelEventForFusion(double level, double width); void Slot_WindowLevelEventForFusion(double level, double width);
void Slot_UpdateOrienInfo(TransFormType); void Slot_Transformation();
void viewerClicked(); void viewerClicked();
protected: protected: