MPR menu button.

This commit is contained in:
Krad
2022-08-24 10:51:00 +08:00
parent 12bc958c4a
commit 203ab67002
11 changed files with 191 additions and 146 deletions

View File

@@ -27,6 +27,31 @@
#include "IO/General/ColorMapReader.h"
#include "Interaction/ActorDraggableInteractorStyle.h"
namespace {
//扭转存在偏转的坐标轴
void adjustVector(double* vector,int & ijkIdx){
int maxIdx = fabs(vector[0]) > fabs(vector[1]) ?
(fabs(vector[0]) > fabs(vector[2]) ? 0 : 2) :
(fabs(vector[1]) > fabs(vector[2]) ? 1 : 2);
double temp = vector[maxIdx];
vector[0] = 0.0;
vector[1] = 0.0;
vector[2] = 0.0;
vector[maxIdx] = 1.0*(temp>0?1.0:-1.0);
ijkIdx = maxIdx;
}
void adjustVector(double* vector){
int a;
adjustVector(vector, a);
}
int projToPlane(int idx){
if(idx == 0) return 1;
if(idx == 1) return 0;
return idx;
}
}
vtkStandardNewMacro(DICOMImageViewer);
@@ -37,7 +62,7 @@ DICOMImageViewer::DICOMImageViewer()
ImageActor(vtkImageSlice::New()), ImageMapper(vtkImageSliceMapper::New()), FusionActor(nullptr),
FusionMapper(nullptr), Interactor(nullptr), InteractorStyle(nullptr), OpacityActor(nullptr),
cornerAnnotation(vtkCornerAnnotation::New()), bar(nullptr),
SliceOrientation(DICOMImageViewer::SLICE_ORIENTATION_XY), FirstRender(1), Slice(0), loadedMeasureSlice(0),
SliceIJK(-1),SlicePlane(-1), FirstRender(1), Slice(0), loadedMeasureSlice(0),
currentPresetIndex(1), Fusion(false), firstFusion(true), FusionOpacity(0.5), list(nullptr),
measureStore(MeasureStore::Instance()),
rulerActive(false){
@@ -125,8 +150,6 @@ DICOMImageViewer::~DICOMImageViewer() {
void DICOMImageViewer::SetupImageViewer() {
this->SetColorLevel(m_cornerInfo.win_level);
this->SetColorWindow(m_cornerInfo.win_width);
//this->GetRenderer()->ResetCamera();
this->SetSliceOrientationToXY();
this->Render(); //first render will call resetcamera
this->SetSlice(0);
UpdateCornerInfoAll();
@@ -208,7 +231,6 @@ void DICOMImageViewer::SetRenderer(vtkRenderer *arg) {
}
this->InstallPipeline();
this->UpdateOrientation();
}
void DICOMImageViewer::SetInputData(vtkImageData *in) {
@@ -315,33 +337,6 @@ void DICOMImageViewer::Render() {
vtkAlgorithm *input = this->GetInputAlgorithm();
if (input) {
input->UpdateInformation();
int *w_ext =
this->GetInputInformation()->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
int xs = 0, ys = 0;
switch (this->SliceOrientation) {
case DICOMImageViewer::SLICE_ORIENTATION_XY:
default:
xs = w_ext[1] - w_ext[0] + 1;
ys = w_ext[3] - w_ext[2] + 1;
break;
case DICOMImageViewer::SLICE_ORIENTATION_XZ:
xs = w_ext[1] - w_ext[0] + 1;
ys = w_ext[5] - w_ext[4] + 1;
break;
case DICOMImageViewer::SLICE_ORIENTATION_YZ:
xs = w_ext[3] - w_ext[2] + 1;
ys = w_ext[5] - w_ext[4] + 1;
break;
}
// if it would be smaller than 150 by 100 then limit to 150 by 100
if (this->RenderWindow->GetSize()[0] == 0) {
this->RenderWindow->SetSize(xs < 150 ? 150 : xs, ys < 100 ? 100 : ys);
}
if (this->Renderer) {
this->Renderer->ResetCamera();
auto camera = this->Renderer->GetActiveCamera();
@@ -354,12 +349,6 @@ void DICOMImageViewer::Render() {
int currentIndex = ImageMapper->GetSliceNumber();
if (currentIndex != lastIndex) this->SetSlice(lastIndex);
ResetZoomScaleToFitWindowSize();
// 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);
//this->Renderer->ResetCameraClippingRange();
}
this->FirstRender = 0;
}
@@ -387,8 +376,8 @@ void DICOMImageViewer::GetSliceRange(int &min, int &max) {
input->UpdateInformation();
int *w_ext =
input->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
min = w_ext[this->SliceOrientation * 2];
max = w_ext[this->SliceOrientation * 2 + 1];
min = w_ext[this->SliceIJK * 2];
max = w_ext[this->SliceIJK * 2 + 1];
}
}
@@ -397,7 +386,7 @@ int *DICOMImageViewer::GetSliceRange() {
if (input) {
input->UpdateInformation();
return input->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()) +
this->SliceOrientation * 2;
this->SliceIJK * 2;
}
return nullptr;
}
@@ -452,8 +441,8 @@ void DICOMImageViewer::SetSlice(int slice) {
double *origin = outInfo->Get(vtkDataObject::ORIGIN());
double *pos = camera->GetPosition();
double newFocalPoint = origin[SliceOrientation] + Slice * spacing[SliceOrientation];
double newDistance = fabs(newFocalPoint - pos[SliceOrientation]);
double newFocalPoint = origin[SliceIJK] + Slice * spacing[SliceIJK];
double newDistance = fabs(newFocalPoint - pos[SliceIJK]);
double offset = fabs(newDistance - camera->GetDistance());
camera->SetDistance(newDistance);
if (Fusion && FusionMapper) {
@@ -488,8 +477,8 @@ void DICOMImageViewer::GetSlicePoint(double *point) {
}
void DICOMImageViewer::applySliceOffset(double offset, double direction){
double projV = Renderer->GetActiveCamera()->GetDirectionOfProjection()[SliceOrientation];
double defaultProjV = defaultProjection[SliceOrientation][SliceOrientation];
double projV = Renderer->GetActiveCamera()->GetDirectionOfProjection()[SliceIJK];
double defaultProjV = defaultProjection[SliceIJK][SliceIJK];
// 根据投影向量判断当前镜头方向, innerDirection>0 与默认同向, innerDirection<0 与默认反向
// 与默认相同时距离额的正增长为slice+
double innerDirection = projV * defaultProjV;
@@ -508,20 +497,20 @@ vtkPoints* DICOMImageViewer::GetSliceBoundPoints() {
vtkCamera *camera = this->Renderer->GetActiveCamera();
double fpt[3] = {.0, .0, .0};
camera->GetFocalPoint(fpt);
bounds[SliceOrientation * 2] = fpt[SliceOrientation];
bounds[SliceOrientation * 2+1] = fpt[SliceOrientation];
bounds[SliceIJK * 2] = fpt[SliceIJK];
bounds[SliceIJK * 2 + 1] = fpt[SliceIJK];
vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
//只取4个点
pts->InsertNextPoint(bounds[0], bounds[2], bounds[4]);
if (SliceOrientation != 1) {
if (SliceIJK != 1) {
pts->InsertNextPoint(bounds[0], bounds[3], bounds[4]);
if (SliceOrientation != 2) {
if (SliceIJK != 2) {
pts->InsertNextPoint(bounds[0], bounds[3], bounds[5]);
pts->InsertNextPoint(bounds[0], bounds[2], bounds[5]);
}
}
if (SliceOrientation != 0) {
if (SliceOrientation != 1) {
if (SliceIJK != 0) {
if (SliceIJK != 1) {
pts->InsertNextPoint(bounds[1], bounds[3], bounds[4]);
pts->InsertNextPoint(bounds[1], bounds[2], bounds[4]);
} else {
@@ -565,7 +554,7 @@ void DICOMImageViewer::SyncSlicePoint(double *point) {
Renderer->GetActiveCamera()->GetFocalPoint(f);
double bounds[6] = {.0, .0, .0, .0, .0, .0};
ImageMapper->GetBounds(bounds);
f[SliceOrientation] = focusPoint[SliceOrientation];
f[SliceIJK] = focusPoint[SliceIJK];
Renderer->GetActiveCamera()->SetFocalPoint(f);
this->Render();
UpdateTopLeftCornerInfo();
@@ -635,10 +624,10 @@ void DICOMImageViewer::shiftCamera(const double *point) {
double fp[3] = {0.0, 0.0, 0.0};
double newP[3] = {point[0], point[1], point[2]};
Renderer->GetActiveCamera()->GetPosition(fp);
newP[SliceOrientation] = fp[2];
newP[SliceIJK] = fp[2];
Renderer->GetActiveCamera()->SetPosition(newP);
Renderer->GetActiveCamera()->GetFocalPoint(fp);
newP[SliceOrientation] = fp[2];
newP[SliceIJK] = fp[2];
Renderer->GetActiveCamera()->SetFocalPoint(newP);
}
@@ -994,7 +983,7 @@ void DICOMImageViewer::LoadMeasures(bool forceReload) {
}
void DICOMImageViewer::ReloadCurrentSliceMeasure() {
list = measureStore->GetMeasures(SOP_UID, this->SliceOrientation, ImageMapper->GetSliceNumber());
list = measureStore->GetMeasures(SOP_UID, this->SliceIJK, ImageMapper->GetSliceNumber());
if (list) {
for (int i = 0; i < list->length(); i++) {
@@ -1018,7 +1007,7 @@ void DICOMImageViewer::ClearCurrentSliceMeasure() const {
void DICOMImageViewer::AddMeasures(vtkObject *, unsigned long eventid, void *calldata) {
auto m = static_cast<Measure *>(calldata);
if (m->Valid()) {
measureStore->Store(SOP_UID, this->SliceOrientation, this->ImageMapper->GetSliceNumber(), m);
measureStore->Store(SOP_UID, this->SliceIJK, this->ImageMapper->GetSliceNumber(), m);
}
LoadMeasures(true);
this->Render();
@@ -1044,7 +1033,7 @@ void DICOMImageViewer::DeleteSelectedMeasure() {
void DICOMImageViewer::DeleteCurrentSliceMeasure() {
this->InteractorStyle->ClearSelectedProp();
ClearCurrentSliceMeasure();
measureStore->RemoveAllInSlice(SOP_UID, this->SliceOrientation, this->ImageMapper->GetSliceNumber());
measureStore->RemoveAllInSlice(SOP_UID, this->SliceIJK, this->ImageMapper->GetSliceNumber());
ReloadCurrentSliceMeasure();
this->Render();
}
@@ -1116,10 +1105,13 @@ void DICOMImageViewer::InitCornerInfo(ExtendMedicalImageProperties *pSeries) {
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
}
void DICOMImageViewer::SetCoordsTransformMatrix(ExtendMedicalImageProperties *pSeries) const {
void DICOMImageViewer::SetCoordsTransformMatrix(ExtendMedicalImageProperties *pSeries) {
OrientationMatrix->DeepCopy(pSeries->GetOrientationMatrix());
WorldToModelMatrix->DeepCopy(pSeries->GetWorldToModelMatrix());
ModelToWorldMatrix->DeepCopy(pSeries->GetModelToWorldMatrix());
SliceIJK = 2;
SlicePlane = -1;
SetReconPlane(GetReconPlane());
}
void DICOMImageViewer::InitTopLeftCornerInfo(const std::string &lbl_ser_num, const std::string &ser_num) {
@@ -1196,18 +1188,18 @@ void DICOMImageViewer::UpdateTopLeftCornerInfo() {
}
// SliceOrientation------------------------------------------------------------
void DICOMImageViewer::SetSliceOrientation(int orientation) {
if (orientation < DICOMImageViewer::SLICE_ORIENTATION_YZ ||
orientation > DICOMImageViewer::SLICE_ORIENTATION_XY) {
vtkErrorMacro("Error - invalid slice orientation " << orientation);
void DICOMImageViewer::SetReconPlane(int plane) {
if (plane < DICOMImageViewer::CORONAL ||
plane > DICOMImageViewer::AXIAL) {
vtkErrorMacro("Error - invalid slice plane " << plane);
return;
}
if (this->SliceOrientation == orientation) {
if (this->SlicePlane == plane) {
return;
}
this->SliceOrientation = orientation;
this->SlicePlane = plane;
// Update the viewer
@@ -1216,7 +1208,7 @@ void DICOMImageViewer::SetSliceOrientation(int orientation) {
this->Slice = static_cast<int>((range[0] + range[1]) * 0.5);
}
this->UpdateOrientation();
this->UpdateReconPlane();
UpdateOrientationInfo();
// this->UpdateDisplayExtent();
@@ -1230,48 +1222,77 @@ void DICOMImageViewer::SetSliceOrientation(int orientation) {
SetSlice(0);
}
//TODO暂时只有正交数据否则强制转型会有一些问题
int DICOMImageViewer::GetWorldSliceOrientation() {
double orientations[4] = {.0, .0, .0, 1.0};
orientations[SliceOrientation] = 1.0;
OrientationMatrix->MultiplyPoint(orientations, orientations);
return (int) abs(round(1.0 * orientations[1]) + round(2.0 * orientations[2]));
int DICOMImageViewer::GetReconPlane() {
if (SlicePlane>=0) return SlicePlane;
double projVector[4] = {.0, .0, .0, 1.0};
projVector[SliceIJK] = 1.0;
OrientationMatrix->MultiplyPoint(projVector, projVector);
int ret = 0;
::adjustVector(projVector, ret);
return ::projToPlane(ret);
}
// Orientation (with corner text)----------------------------------------------
void DICOMImageViewer::UpdateOrientation() {
// Set the camera position
void DICOMImageViewer::UpdateReconPlane() {
// Set the camera position
vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : nullptr;
if (cam) {
switch (SliceOrientation) {
case DICOMImageViewer::SLICE_ORIENTATION_XY: {
OrientationMatrix->Invert();
switch (SlicePlane) {
case CORONAL: {
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(0, 0, -1);
cam->SetViewUp(0, -1, 0);
double position[4]={.0, -1.0, .0, 1.0};
OrientationMatrix->MultiplyPoint(position,position);
::adjustVector(position, SliceIJK);
//原图非切片直接使用原方向
if (SliceIJK == 2)break;
cam->SetPosition(position);
double viewUp[4]={.0, .0, 1.0, 1.0};
OrientationMatrix->MultiplyPoint(viewUp,viewUp);
adjustVector(viewUp);
cam->SetViewUp(viewUp);
break;
}
//Z轴负数间隔则Z轴的slice为反方向堆叠
//初始的朝向和ViewUp都需要调整
case DICOMImageViewer::SLICE_ORIENTATION_XZ: {
double zVec = GetInput()->GetSpacing()[2];
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
case AXIAL: {
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(0, 1 * upVal, 0);
cam->SetViewUp(0, 0, -1.0 * upVal);
double position[4] = {.0, .0, -1.0, 1.0};
OrientationMatrix->MultiplyPoint(position, position);
::adjustVector(position, SliceIJK);
//原图非切片直接使用原方向
if (SliceIJK == 2)break;
cam->SetPosition(position);
double viewUp[4] = {.0, -1.0, 0.0, 1.0};
OrientationMatrix->MultiplyPoint(viewUp, viewUp);
adjustVector(viewUp);
cam->SetViewUp(viewUp);
break;
}
case DICOMImageViewer::SLICE_ORIENTATION_YZ: {
double zVec = GetInput()->GetSpacing()[2];
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
case SAGITTAL: {
cam->SetFocalPoint(0, 0, 0);
cam->SetPosition(-1 * upVal, 0, 0);
cam->SetViewUp(0, 0, -1.0 * upVal);
double position[4] = {1.0, .0, .0, 1.0};
OrientationMatrix->MultiplyPoint(position, position);
::adjustVector(position, SliceIJK);
//原图非切片直接使用原方向
if (SliceIJK == 2)break;
cam->SetPosition(position);
double viewUp[4] = {.0, .0, 1.0, 1.0};
OrientationMatrix->MultiplyPoint(viewUp, viewUp);
adjustVector(viewUp);
cam->SetViewUp(viewUp);
break;
}
}
OrientationMatrix->Invert();
if (SliceIJK == 2){
double position[3]={.0, 0, -1.0};
cam->SetPosition(position);
double viewUp[4] = {.0, -1.0, .0, 1.0};
cam->SetViewUp(viewUp);
}
}
}
int getOrientationIndex(double *v) {
@@ -1364,7 +1385,7 @@ void DICOMImageViewer::PrintSelf(ostream &os, vtkIndent indent) {
os << indent << "ImageMapper:\n" << endl;
this->ImageMapper->PrintSelf(os, indent.GetNextIndent());
os << indent << "Slice: " << this->Slice << endl;
os << indent << "SliceOrientation: " << this->SliceOrientation << endl;
os << indent << "SliceIJK: " << this->SliceIJK << endl;
os << indent << "InteractorStyle: " << endl;
if (this->InteractorStyle) {
os << "\n";

View File

@@ -109,29 +109,17 @@ public:
* Set/get the slice orientation
*/
enum {
SLICE_ORIENTATION_YZ = 0,
SLICE_ORIENTATION_XZ = 1,
SLICE_ORIENTATION_XY = 2
enum SlicePlane{
CORONAL = 0, //冠状面
SAGITTAL = 1, //矢状面
AXIAL = 2, //横断面
};
vtkGetMacro(SliceOrientation, int);
vtkGetMacro(SliceIJK, int);
virtual void SetSliceOrientation(int orientation);
virtual void SetReconPlane(int plane);
virtual void SetSliceOrientationToXY() {
this->SetSliceOrientation(DICOMImageViewer::SLICE_ORIENTATION_XY);
}
virtual void SetSliceOrientationToYZ() {
this->SetSliceOrientation(DICOMImageViewer::SLICE_ORIENTATION_YZ);
}
virtual void SetSliceOrientationToXZ() {
this->SetSliceOrientation(DICOMImageViewer::SLICE_ORIENTATION_XZ);
}
int GetWorldSliceOrientation();
int GetReconPlane();
//@{
/**
* Set/Get the current slice to display (depending on the orientation
@@ -391,9 +379,9 @@ public:
void applySliceOffset(double offset, double direction);
virtual void UpdateOrientation();
virtual void UpdateReconPlane();
void SetCoordsTransformMatrix(ExtendMedicalImageProperties *pSeries) const;
void SetCoordsTransformMatrix(ExtendMedicalImageProperties *pSeries);
protected:
DICOMImageViewer();
@@ -465,7 +453,8 @@ private:
vtkNew<vtkMatrix4x4> ModelToWorldMatrix;
DicomCornerInfo m_cornerInfo;
int SliceOrientation;
int SliceIJK;
int SlicePlane;
int FirstRender;
int Slice;
int loadedMeasureSlice;

View File

@@ -139,7 +139,7 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
if (!v->hasSeries()) return;
//check series
auto series = sourceView->getSeriesInstance();
if (v->getSeriesInstance() == series && v->getSliceOrientation() == sourceView->getSliceOrientation()) {
if (v->getSeriesInstance() == series && v->getReconPlane() == sourceView->getReconPlane()) {
cb(v, callData);
}
else{
@@ -159,14 +159,14 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
//same series
if (series == currentSeries
//equal slice orientation
&& v->getSliceOrientation() == sourceView->getSliceOrientation()) {
&& v->getReconPlane() == sourceView->getReconPlane()) {
cb(v, callData);
return;
}
//equal study
else if (strcmp(currentSeries->getStudyUID(), series->getStudyUID()) == 0
//equal world slice orientation
&& v->CompareWorldSliceOrientation(sourceView)
&& v->CompareReconPlane(sourceView)
//Intersect bounds
&& currentSeries->IntersectWorldBounds(series)) {
cb(v, callData);
@@ -181,7 +181,7 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
if (v == sourceView) return;
if (!v->hasSeries()) return;
//same series
if (v->CompareWorldSliceOrientation(sourceView)) {
if (v->CompareReconPlane(sourceView)) {
cb(v, callData);
}
else if (otherCb) otherCb(v, callData);
@@ -199,14 +199,14 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
//same series
if (series == currentSeries
//equal slice orientation
&& v->getSliceOrientation() != sourceView->getSliceOrientation()) {
&& v->getReconPlane() != sourceView->getReconPlane()) {
cb(v, callData);
return;
}
//equal study
else if (strcmp(currentSeries->getStudyUID(), series->getStudyUID()) == 0
//no equal world slice orientation
&& !v->CompareWorldSliceOrientation(sourceView)
&& !v->CompareReconPlane(sourceView)
//Intersect bounds
&& currentSeries->IntersectWorldBounds(series)) {
cb(v, callData);
@@ -425,8 +425,8 @@ void ImageViewManager::deleteMeasure(EventObject* deleteType){
}
}
void ImageViewManager::switchSliceOrientation() {
currentView->setSliceOrientation((currentView->getSliceOrientation() + 1) % 3);
void ImageViewManager::changeReconPlane(int plane) {
currentView->setReconPlane(plane);
reloadCurrentView(currentView);
}

View File

@@ -86,7 +86,7 @@ public:
void deleteMeasure(EventObject* deleteType);
void switchSliceOrientation();
void changeReconPlane(int plane);
void switchReferenceLineVisibility(bool v);

View File

@@ -21,7 +21,7 @@ void ImageViewStateCheckWorker::checkImageViewState(DicomImageView *view) {
ViewFunctionState state;
if (view->hasSeries()){
state.canSync=mManager->checkSyncAbility(view);
state.canMPR=view->checkMPRAble();
state.canMPR= view->checkMPRAble() ? view->getReconPlane() : -1;
state.canFusion=mManager->checkViewFusion(view);
emit imageViewStateChanged(state);
}

View File

@@ -12,7 +12,7 @@ class ImageViewManager;
struct ViewFunctionState{
int canSync;
bool canMPR;
int canMPR;
bool canFusion;
};

View File

@@ -22,8 +22,8 @@
DicomImageView::DicomImageView(QWidget *parent)
: QFrame(parent), mGLRenWin(vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New()), mImageViewer(nullptr),
mSeries(nullptr), mScrollBar(new ClickableScrollBar(Qt::Orientation::Vertical, this)),
mTitleBar(createMyTitleBar()), mGLWidget(new QVTKOpenGLNativeWidget),mVcrToolbar(nullptr), mVcrController(nullptr),
mOverlayView(nullptr), mBaseView(nullptr), mSliceOrientation(2), mIsCine(false), mIsNegative(false),
mTitleBar(createMyTitleBar()), mGLWidget(new QVTKOpenGLNativeWidget), mVcrToolbar(nullptr), mVcrController(nullptr),
mOverlayView(nullptr), mBaseView(nullptr), mIsCine(false), mIsNegative(false),
mIsOverlay(false), mIsSlotInited(false)
{
//main container
@@ -467,14 +467,15 @@ void DicomImageView::render() {
}
int DicomImageView::getSliceOrientation() {
return mSliceOrientation;
int DicomImageView::getReconPlane() {
return mImageViewer->GetReconPlane();
}
void DicomImageView::setSliceOrientation(int orientation) {
void DicomImageView::setReconPlane(int plane) {
if (mImageViewer->GetReconPlane() == plane) return;
unloadFusion();
mSliceOrientation = orientation;
mImageViewer->SetSliceOrientation(orientation);
mImageViewer->SetReconPlane(plane);
int max = 0;
int min = 0;
mImageViewer->GetSliceRange(min, max);
@@ -627,7 +628,7 @@ void DicomImageView::ClearTransformations() {
if (hasSeries()) {
int slice = mImageViewer->GetSlice();
//reset flip and rotation
mImageViewer->UpdateOrientation();
mImageViewer->UpdateReconPlane();
resetPanZoom();
//avoid black out problem
mImageViewer->GetRenderer()->ResetCameraClippingRange();
@@ -765,7 +766,7 @@ bool DicomImageView::checkFusion(DicomImageView *base, DicomImageView *overlap)
// check intersect
if(!baseSeries->IntersectWorldBounds(overlapSeries)) return false;
// check current slice orientation
return base->CompareWorldSliceOrientation(overlap);
return base->CompareReconPlane(overlap);
}
bool DicomImageView::checkFusion(DicomImageView *overlap) {

View File

@@ -158,12 +158,12 @@ public:
void negativeWindow();
//MPR
void setSliceOrientation(int orientation);
void setReconPlane(int plane);
int getSliceOrientation();
int getReconPlane();
bool CompareWorldSliceOrientation(DicomImageView *view) {
return this->mImageViewer->GetWorldSliceOrientation() == view->mImageViewer->GetWorldSliceOrientation();
bool CompareReconPlane(DicomImageView *view) {
return this->mImageViewer->GetReconPlane() == view->mImageViewer->GetReconPlane();
}
void syncSlicePoint(double *point) {
@@ -334,8 +334,6 @@ private:
DicomImageView *mOverlayView;
DicomImageView *mBaseView;
int mSliceOrientation;
bool mIsCine;
bool mIsNegative;
bool mIsOverlay;

View File

@@ -6,6 +6,7 @@
#include <QToolButton>
#include <QMenu>
#include <QButtonGroup>
#include <QActionGroup>
#include "Rendering/Measure/Measure.h"
#include "Common/QGlobals.h"
@@ -407,12 +408,36 @@ void DefaultToolBar::initTransformButton() {
}
void DefaultToolBar::initMPRButton(){
connect(mBtnMPR, &QToolButton::clicked, [=](){
SyncHelper::setSyncState(DIS_SYNC);
syncStateChanged();
emit changeSliceOrientation();
mBtnMPR->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
mBtnMPR->setToolTip(QString("MPR"));
QMenu *m = new QMenu(this);
auto group = new QActionGroup(this);
auto actionCoronal = m->addAction(tr("Coronal"));
auto actionSagittal =m->addAction(tr("Sagittal"));
auto actionAxial = m->addAction(tr("Axial"));
actionCoronal->setCheckable(true);
actionSagittal->setCheckable(true);
actionAxial->setCheckable(true);
connect(group, &QActionGroup::triggered, this, [=](QAction* action) {
for (int i = 0; i < 3; ++i) {
if (m->actions()[i]==action){
emit changeReconPlane(i);
return;
}
}
});
group->addAction(actionCoronal);
group->addAction(actionSagittal);
group->addAction(actionAxial);
group->setExclusive(true);
mBtnMPR->setEnabled(false);
mBtnMPR->setPopupMode(QToolButton::MenuButtonPopup);
mBtnMPR->setMenu(m);
connect(mBtnMPR, &QToolButton::clicked,[=](){
m->popup( mBtnMPR->mapToGlobal({0, mBtnMPR->geometry().bottom()}));
});
}
void DefaultToolBar::resetNeedCheckFunctionButtons(){
@@ -425,7 +450,18 @@ void DefaultToolBar::resetNeedCheckFunctionButtons(){
void DefaultToolBar::updateNeedCheckFunctionButtons(ViewFunctionState state)
{
mBtnMPR->setEnabled(state.canMPR);
mBtnMPR->setEnabled(state.canMPR!=-1);
if (state.canMPR!=-1){
for (int i = 0; i < 3; ++i) {
if (i==state.canMPR){
mBtnMPR->menu()->actions()[i]->setEnabled(false);
}
else{
mBtnMPR->menu()->actions()[i]->setEnabled(true);
}
}
mBtnMPR->menu()->actions()[state.canMPR]->setChecked(true);
}
mBtnFusion->setEnabled(state.canFusion);
// SyncHelper::setSyncState((SyncState)state.canSync);
// syncStateChanged();

View File

@@ -33,7 +33,7 @@ signals:
void negativeWindow();
void fusion(bool on = false);
void cine(bool on = false);
void changeSliceOrientation();
void changeReconPlane(int plane);
void clear();
void parentWindowStateChange(Qt::WindowState state);
void parentWindowClose();

View File

@@ -172,8 +172,8 @@ void QDicomViewer::initViewOperation() {
}
});
// MPR
connect(ui->toolBar, &DefaultToolBar::changeSliceOrientation,
ui->viewContainer->getViewManager(), &ImageViewManager::switchSliceOrientation);
connect(ui->toolBar, &DefaultToolBar::changeReconPlane,
ui->viewContainer->getViewManager(), &ImageViewManager::changeReconPlane);
connect(ui->toolBar, &DefaultToolBar::volumeRendering,[=](){
auto volumeWin = new VolumeRenderingWindow(this);
connect(volumeWin,&QDialog::finished,[=](){