From 0a07a078e12ad2de8e98626f963c9b7a9851baa7 Mon Sep 17 00:00:00 2001 From: Krad Date: Wed, 27 Jul 2022 13:29:23 +0800 Subject: [PATCH] Slice sync logic refactor, add manual slice sync logic(camera focal point distance incremental sync). --- src/src/Rendering/infinitiViewer.cxx | 43 ++++++++++++---- src/src/Rendering/infinitiViewer.h | 7 +++ src/src/UI/Manager/ImageViewManager.cpp | 66 ++++++++++++++----------- src/src/UI/Manager/ImageViewManager.h | 4 +- src/src/UI/Widget/dicomimageview.cpp | 8 ++- src/src/UI/Widget/dicomimageview.h | 5 ++ 6 files changed, 87 insertions(+), 46 deletions(-) diff --git a/src/src/Rendering/infinitiViewer.cxx b/src/src/Rendering/infinitiViewer.cxx index 6fdbbcc..16693f6 100644 --- a/src/src/Rendering/infinitiViewer.cxx +++ b/src/src/Rendering/infinitiViewer.cxx @@ -211,6 +211,7 @@ void infinitiViewer::SetRenderer(vtkRenderer *arg) { } void infinitiViewer::SetInputData(vtkImageData *in) { + if (!in) return; #ifdef _DEBUG printf("fusion imageDataOrigin:%f,%f,%f", in->GetOrigin()[0], in->GetOrigin()[1], in->GetOrigin()[2]); printf("fusion spacing:%f,%f,%f", in->GetSpacing()[0], in->GetSpacing()[1], in->GetSpacing()[2]); @@ -219,7 +220,8 @@ void infinitiViewer::SetInputData(vtkImageData *in) { this->ImageActor->GetMapper()->SetInputData(in); this->RemoveFusionData(); this->ActiveRuler(); - // this->UpdateDisplayExtent(); + double zVec = in->GetSpacing()[2]; + defaultProjection[2][2] = zVec>0.0?1.0:-1.0; } void infinitiViewer::SetInputConnection(vtkAlgorithmOutput *input) { @@ -452,15 +454,22 @@ void infinitiViewer::SetSlice(int slice) { double *origin = outInfo->Get(vtkDataObject::ORIGIN()); double *pos = camera->GetPosition(); - double npv = origin[this->SliceOrientation] + this->Slice * spacing[this->SliceOrientation]; - camera->SetDistance(fabs(npv - pos[this->SliceOrientation])); + double newFocalPoint = origin[SliceOrientation] + Slice * spacing[SliceOrientation]; + double newDistance = fabs(newFocalPoint - pos[SliceOrientation]); + double offset = fabs(newDistance - camera->GetDistance()); + camera->SetDistance(newDistance); if (Fusion && FusionMapper) { FusionMapper->SetClippingPlanes(ImageMapper->GetClippingPlanes()); } this->Render(); - if (InteractorStyle) - InteractorStyle->InvokeEvent(ActorDraggableInteractorStyle::SlicedEvent, &this->Slice); + if (InteractorStyle){ + double direction = (double)(slice - lastSliceNumber); + double focusPoint[5] = {.0, .0, .0 }; + GetSlicePoint(focusPoint); + double sliceData[5] ={focusPoint[0], focusPoint[1], focusPoint[2], offset, direction}; + InteractorStyle->InvokeEvent(ActorDraggableInteractorStyle::SlicedEvent, sliceData); + } } void infinitiViewer::ChangeSlice(vtkObject *, unsigned long eventid, void *calldata) { @@ -483,6 +492,19 @@ void infinitiViewer::GetSlicePoint(double *point) { point[2] = focusPoint[2]; } +void infinitiViewer::applySliceOffset(double offset, double direction){ + double projV = Renderer->GetActiveCamera()->GetDirectionOfProjection()[SliceOrientation]; + double defaultProjV = defaultProjection[SliceOrientation][SliceOrientation]; + // 根据投影向量判断当前镜头方向, innerDirection>0 与默认同向, innerDirection<0 与默认反向 + // 与默认相同时距离额的正增长为slice+ + double innerDirection = projV * defaultProjV; + // 否则距离的负增长会导致Slice++(即使distance + offset为slice++) + if (innerDirection < 0 ) offset = offset * -1.0;; + // 假设原数据为slice--则需要唯一 + if (direction < 0) offset = offset * -1.0; + Renderer->GetActiveCamera()->SetDistance(Renderer->GetActiveCamera()->GetDistance() + offset); +} + vtkSmartPointer infinitiViewer::GetSliceBoundPoints() { double bounds[6] = {.0, .0, .0, .0, .0, .0}; ImageMapper->GetBounds(bounds); @@ -1207,19 +1229,20 @@ void infinitiViewer::UpdateOrientation() { vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : nullptr; if (cam) { - - switch (this->SliceOrientation) { + switch (SliceOrientation) { case infinitiViewer::SLICE_ORIENTATION_XY: { cam->SetFocalPoint(0, 0, 0); - cam->SetPosition(0, 0, -1); // -1 if medical ? + cam->SetPosition(0, 0, -1); cam->SetViewUp(0, -1, 0); break; } + //Z轴负数间隔,则Z轴的slice为反方向堆叠 + //初始的朝向和ViewUp都需要调整 case infinitiViewer::SLICE_ORIENTATION_XZ: { double zVec = GetInput()->GetSpacing()[2]; double upVal = (zVec > 0.0 ? 1.0 : -1.0); cam->SetFocalPoint(0, 0, 0); - cam->SetPosition(0, 1 * upVal, 0); // 1 if medical ? + cam->SetPosition(0, 1 * upVal, 0); cam->SetViewUp(0, 0, -1.0 * upVal); break; } @@ -1227,7 +1250,7 @@ void infinitiViewer::UpdateOrientation() { double zVec = GetInput()->GetSpacing()[2]; double upVal = (zVec > 0.0 ? 1.0 : -1.0); cam->SetFocalPoint(0, 0, 0); - cam->SetPosition(-1 * upVal, 0, 0); // -1 if medical ? + cam->SetPosition(-1 * upVal, 0, 0); cam->SetViewUp(0, 0, -1.0 * upVal); break; } diff --git a/src/src/Rendering/infinitiViewer.h b/src/src/Rendering/infinitiViewer.h index 4152aa2..f321bb8 100644 --- a/src/src/Rendering/infinitiViewer.h +++ b/src/src/Rendering/infinitiViewer.h @@ -378,6 +378,8 @@ vtkTypeMacro(infinitiViewer, vtkObject); void GetSlicePoint(double *point); + void applySliceOffset(double offset, double direction); + virtual void UpdateOrientation(); protected: @@ -458,6 +460,11 @@ private: bool rulerActive = false; char SOP_UID[20] = {0}; double imageDataOrigin[3] = {.0, .0, .0}; + double defaultProjection[3][3] = { + {1.,0.,0.}, + {0.,1.,0.}, + {0.,0.,1.} + }; }; #endif diff --git a/src/src/UI/Manager/ImageViewManager.cpp b/src/src/UI/Manager/ImageViewManager.cpp index 38268f5..f149523 100644 --- a/src/src/UI/Manager/ImageViewManager.cpp +++ b/src/src/UI/Manager/ImageViewManager.cpp @@ -116,7 +116,7 @@ void ImageViewManager::smartDo(SmartDoCallback cb, DicomImageView *sourceView, v }); break; } - case DoScope::EStudyEBoundsSeries: { + case DoScope::SameStudySeries: { std::for_each(vList.begin(), vList.end(), [=](auto v) { if (v == sourceView) return; if (!v->hasSeries()) return; @@ -140,6 +140,17 @@ void ImageViewManager::smartDo(SmartDoCallback cb, DicomImageView *sourceView, v }); break; } + case DoScope::SameOrientationSeries: { + std::for_each(vList.begin(), vList.end(), [=](auto v) { + if (v == sourceView) return; + if (!v->hasSeries()) return; + //same series + if (v->CompareWorldSliceOrientation(sourceView)) { + cb(v, callData); + } + }); + break; + } case DoScope::AllExceptSelf: { std::for_each(vList.begin(), vList.end(), [=](auto v) { if (v == sourceView) return; @@ -177,33 +188,30 @@ void ImageViewManager::viewDoubleClicked(DicomImageView *view) { } } -void ImageViewManager::viewSynced(DicomImageView *src, int interactionMode, void *data) { - - switch (interactionMode) { - case VTKIS_IMAGE_SLICING: - if (SyncHelper::getSyncItem(SLICE_POS)) { - if (SyncHelper::getSyncState() == AUTO_SYNC) { - this->smartDo([](auto v, auto callData) { - if (v->hasSeries()) { - double *r = (double *) callData; - v->syncSlicePoint(r); - v->SyncScrollBar(); - } - }, src, data, ImageViewManager::EStudyEBoundsSeries); +void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) { + //Sync slice + if (SyncHelper::getSyncItem(SLICE_POS)) { + if (SyncHelper::getSyncState() == AUTO_SYNC) { + this->smartDo([](auto v, auto callData) { + if (v->hasSeries()) { + double *r = (double *) callData; + v->syncSlicePoint(r); + v->SyncScrollBar(); } - if (SyncHelper::getSyncState() == MANUAL_SYNC) { - this->smartDo([](auto v, auto callData) { - if (v->hasSeries()) { - //disable global trigger slot - int *r = (int *) callData; - v->addSlice(r[1]); - } - }, src, data, ImageViewManager::EStudyEBoundsSeries); + }, src, sliceData, ImageViewManager::SameStudySeries); + } + else if (SyncHelper::getSyncState() == MANUAL_SYNC) { + this->smartDo([](auto v, auto callData) { + if (v->hasSeries()) { + //disable global trigger slot + double * r = (double *) callData; + v->applySliceOffset(r[3], r[4]); + v->SyncScrollBar(); } - - } - break; + }, src, sliceData, ImageViewManager::SameOrientationSeries); + } } + //TODO: reference line } void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) { @@ -215,7 +223,7 @@ void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) { double vector[3] = {d[3] - d[0], d[4] - d[1], d[5] - d[2]}; v->applyPanOffset(vector); } - }, src, offsetVector, ImageViewManager::EStudyEBoundsSeries); + }, src, offsetVector, ImageViewManager::SameStudySeries); } else if (SyncHelper::getSyncState() == AUTO_SYNC) { this->smartDo([](auto v, auto callData) { if (v->hasSeries()) { @@ -223,7 +231,7 @@ void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) { double vector[3] = {d[3], d[4] , d[5]}; v->shiftCamera(vector); } - }, src, offsetVector, ImageViewManager::EStudyEBoundsSeries); + }, src, offsetVector, ImageViewManager::SameStudySeries); } } } @@ -235,7 +243,7 @@ void ImageViewManager::viewZoomed(DicomImageView *src, double scaleFactor) { double d = *(double *) callData; v->setZoomScale(d); } - }, src, &scaleFactor, ImageViewManager::EStudyEBoundsSeries); + }, src, &scaleFactor, ImageViewManager::SameStudySeries); } } @@ -247,7 +255,7 @@ void ImageViewManager::viewEndWindowLevel(DicomImageView *src, double level, dou double *d = (double *) callData; v->setWindowLevel(d[0], d[1]); } - }, src, data, ImageViewManager::EStudyEBoundsSeries); + }, src, data, ImageViewManager::SameStudySeries); } } diff --git a/src/src/UI/Manager/ImageViewManager.h b/src/src/UI/Manager/ImageViewManager.h index 38dbddc..678f884 100644 --- a/src/src/UI/Manager/ImageViewManager.h +++ b/src/src/UI/Manager/ImageViewManager.h @@ -98,8 +98,8 @@ public: Current, SameSeries, //Equal Study, Equal World Bounds series - EStudyEBoundsSeries, - EqualBoundsSeriesExceptSelf, + SameStudySeries, + SameOrientationSeries, AllExceptSelf, All }; diff --git a/src/src/UI/Widget/dicomimageview.cpp b/src/src/UI/Widget/dicomimageview.cpp index abf8618..83fb379 100644 --- a/src/src/UI/Widget/dicomimageview.cpp +++ b/src/src/UI/Widget/dicomimageview.cpp @@ -1,4 +1,4 @@ -#include "dicomimageview.h" +#include "dicomimageview.h" #include #include @@ -420,11 +420,9 @@ void DicomImageView::dispatchEvent(vtkObject *, unsigned long eid, void *callDat break; } case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): { - mScrollBar->SetValueSilently(r[0]); + mScrollBar->SetValueSilently(mImageViewer->GetSlice()); //invoke event - double focusPoint[3] = {.0, .0, .0}; - mImageViewer->GetSlicePoint(focusPoint); - emit onSlice(this, focusPoint); + emit onSlice(this, callData); break; } default: diff --git a/src/src/UI/Widget/dicomimageview.h b/src/src/UI/Widget/dicomimageview.h index 165b144..72c446e 100644 --- a/src/src/UI/Widget/dicomimageview.h +++ b/src/src/UI/Widget/dicomimageview.h @@ -165,6 +165,11 @@ public: mImageViewer->Render(); } + void applySliceOffset(double offset, double direction){ + mImageViewer->applySliceOffset(offset, direction); + mImageViewer->Render(); + } + void loadSeries(SeriesImageSet *series); signals: