Slice sync logic refactor, add manual slice sync logic(camera focal point distance incremental sync).

This commit is contained in:
Krad
2022-07-27 13:29:23 +08:00
parent 74a1817c1e
commit 0a07a078e1
6 changed files with 87 additions and 46 deletions

View File

@@ -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<vtkPoints> 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;
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -98,8 +98,8 @@ public:
Current,
SameSeries,
//Equal Study, Equal World Bounds series
EStudyEBoundsSeries,
EqualBoundsSeriesExceptSelf,
SameStudySeries,
SameOrientationSeries,
AllExceptSelf,
All
};

View File

@@ -1,4 +1,4 @@
#include "dicomimageview.h"
#include "dicomimageview.h"
#include <QMessageBox>
#include <QDebug>
@@ -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:

View File

@@ -165,6 +165,11 @@ public:
mImageViewer->Render();
}
void applySliceOffset(double offset, double direction){
mImageViewer->applySliceOffset(offset, direction);
mImageViewer->Render();
}
void loadSeries(SeriesImageSet *series);
signals: