Slice sync logic refactor, add manual slice sync logic(camera focal point distance incremental sync).
This commit is contained in:
@@ -211,6 +211,7 @@ void infinitiViewer::SetRenderer(vtkRenderer *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void infinitiViewer::SetInputData(vtkImageData *in) {
|
void infinitiViewer::SetInputData(vtkImageData *in) {
|
||||||
|
if (!in) return;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
printf("fusion imageDataOrigin:%f,%f,%f", in->GetOrigin()[0], in->GetOrigin()[1], in->GetOrigin()[2]);
|
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]);
|
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->ImageActor->GetMapper()->SetInputData(in);
|
||||||
this->RemoveFusionData();
|
this->RemoveFusionData();
|
||||||
this->ActiveRuler();
|
this->ActiveRuler();
|
||||||
// this->UpdateDisplayExtent();
|
double zVec = in->GetSpacing()[2];
|
||||||
|
defaultProjection[2][2] = zVec>0.0?1.0:-1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void infinitiViewer::SetInputConnection(vtkAlgorithmOutput *input) {
|
void infinitiViewer::SetInputConnection(vtkAlgorithmOutput *input) {
|
||||||
@@ -452,15 +454,22 @@ void infinitiViewer::SetSlice(int slice) {
|
|||||||
double *origin = outInfo->Get(vtkDataObject::ORIGIN());
|
double *origin = outInfo->Get(vtkDataObject::ORIGIN());
|
||||||
double *pos = camera->GetPosition();
|
double *pos = camera->GetPosition();
|
||||||
|
|
||||||
double npv = origin[this->SliceOrientation] + this->Slice * spacing[this->SliceOrientation];
|
double newFocalPoint = origin[SliceOrientation] + Slice * spacing[SliceOrientation];
|
||||||
camera->SetDistance(fabs(npv - pos[this->SliceOrientation]));
|
double newDistance = fabs(newFocalPoint - pos[SliceOrientation]);
|
||||||
|
double offset = fabs(newDistance - camera->GetDistance());
|
||||||
|
camera->SetDistance(newDistance);
|
||||||
if (Fusion && FusionMapper) {
|
if (Fusion && FusionMapper) {
|
||||||
FusionMapper->SetClippingPlanes(ImageMapper->GetClippingPlanes());
|
FusionMapper->SetClippingPlanes(ImageMapper->GetClippingPlanes());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Render();
|
this->Render();
|
||||||
if (InteractorStyle)
|
if (InteractorStyle){
|
||||||
InteractorStyle->InvokeEvent(ActorDraggableInteractorStyle::SlicedEvent, &this->Slice);
|
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) {
|
void infinitiViewer::ChangeSlice(vtkObject *, unsigned long eventid, void *calldata) {
|
||||||
@@ -483,6 +492,19 @@ void infinitiViewer::GetSlicePoint(double *point) {
|
|||||||
point[2] = focusPoint[2];
|
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() {
|
vtkSmartPointer<vtkPoints> infinitiViewer::GetSliceBoundPoints() {
|
||||||
double bounds[6] = {.0, .0, .0, .0, .0, .0};
|
double bounds[6] = {.0, .0, .0, .0, .0, .0};
|
||||||
ImageMapper->GetBounds(bounds);
|
ImageMapper->GetBounds(bounds);
|
||||||
@@ -1207,19 +1229,20 @@ void infinitiViewer::UpdateOrientation() {
|
|||||||
|
|
||||||
vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : nullptr;
|
vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : nullptr;
|
||||||
if (cam) {
|
if (cam) {
|
||||||
|
switch (SliceOrientation) {
|
||||||
switch (this->SliceOrientation) {
|
|
||||||
case infinitiViewer::SLICE_ORIENTATION_XY: {
|
case infinitiViewer::SLICE_ORIENTATION_XY: {
|
||||||
cam->SetFocalPoint(0, 0, 0);
|
cam->SetFocalPoint(0, 0, 0);
|
||||||
cam->SetPosition(0, 0, -1); // -1 if medical ?
|
cam->SetPosition(0, 0, -1);
|
||||||
cam->SetViewUp(0, -1, 0);
|
cam->SetViewUp(0, -1, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
//Z轴负数间隔,则Z轴的slice为反方向堆叠
|
||||||
|
//初始的朝向和ViewUp都需要调整
|
||||||
case infinitiViewer::SLICE_ORIENTATION_XZ: {
|
case infinitiViewer::SLICE_ORIENTATION_XZ: {
|
||||||
double zVec = GetInput()->GetSpacing()[2];
|
double zVec = GetInput()->GetSpacing()[2];
|
||||||
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
|
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
|
||||||
cam->SetFocalPoint(0, 0, 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);
|
cam->SetViewUp(0, 0, -1.0 * upVal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1227,7 +1250,7 @@ void infinitiViewer::UpdateOrientation() {
|
|||||||
double zVec = GetInput()->GetSpacing()[2];
|
double zVec = GetInput()->GetSpacing()[2];
|
||||||
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
|
double upVal = (zVec > 0.0 ? 1.0 : -1.0);
|
||||||
cam->SetFocalPoint(0, 0, 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);
|
cam->SetViewUp(0, 0, -1.0 * upVal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -378,6 +378,8 @@ vtkTypeMacro(infinitiViewer, vtkObject);
|
|||||||
|
|
||||||
void GetSlicePoint(double *point);
|
void GetSlicePoint(double *point);
|
||||||
|
|
||||||
|
void applySliceOffset(double offset, double direction);
|
||||||
|
|
||||||
virtual void UpdateOrientation();
|
virtual void UpdateOrientation();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -458,6 +460,11 @@ private:
|
|||||||
bool rulerActive = false;
|
bool rulerActive = false;
|
||||||
char SOP_UID[20] = {0};
|
char SOP_UID[20] = {0};
|
||||||
double imageDataOrigin[3] = {.0, .0, .0};
|
double imageDataOrigin[3] = {.0, .0, .0};
|
||||||
|
double defaultProjection[3][3] = {
|
||||||
|
{1.,0.,0.},
|
||||||
|
{0.,1.,0.},
|
||||||
|
{0.,0.,1.}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void ImageViewManager::smartDo(SmartDoCallback cb, DicomImageView *sourceView, v
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DoScope::EStudyEBoundsSeries: {
|
case DoScope::SameStudySeries: {
|
||||||
std::for_each(vList.begin(), vList.end(), [=](auto v) {
|
std::for_each(vList.begin(), vList.end(), [=](auto v) {
|
||||||
if (v == sourceView) return;
|
if (v == sourceView) return;
|
||||||
if (!v->hasSeries()) return;
|
if (!v->hasSeries()) return;
|
||||||
@@ -140,6 +140,17 @@ void ImageViewManager::smartDo(SmartDoCallback cb, DicomImageView *sourceView, v
|
|||||||
});
|
});
|
||||||
break;
|
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: {
|
case DoScope::AllExceptSelf: {
|
||||||
std::for_each(vList.begin(), vList.end(), [=](auto v) {
|
std::for_each(vList.begin(), vList.end(), [=](auto v) {
|
||||||
if (v == sourceView) return;
|
if (v == sourceView) return;
|
||||||
@@ -177,33 +188,30 @@ void ImageViewManager::viewDoubleClicked(DicomImageView *view) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageViewManager::viewSynced(DicomImageView *src, int interactionMode, void *data) {
|
void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) {
|
||||||
|
//Sync slice
|
||||||
switch (interactionMode) {
|
if (SyncHelper::getSyncItem(SLICE_POS)) {
|
||||||
case VTKIS_IMAGE_SLICING:
|
if (SyncHelper::getSyncState() == AUTO_SYNC) {
|
||||||
if (SyncHelper::getSyncItem(SLICE_POS)) {
|
this->smartDo([](auto v, auto callData) {
|
||||||
if (SyncHelper::getSyncState() == AUTO_SYNC) {
|
if (v->hasSeries()) {
|
||||||
this->smartDo([](auto v, auto callData) {
|
double *r = (double *) callData;
|
||||||
if (v->hasSeries()) {
|
v->syncSlicePoint(r);
|
||||||
double *r = (double *) callData;
|
v->SyncScrollBar();
|
||||||
v->syncSlicePoint(r);
|
|
||||||
v->SyncScrollBar();
|
|
||||||
}
|
|
||||||
}, src, data, ImageViewManager::EStudyEBoundsSeries);
|
|
||||||
}
|
}
|
||||||
if (SyncHelper::getSyncState() == MANUAL_SYNC) {
|
}, src, sliceData, ImageViewManager::SameStudySeries);
|
||||||
this->smartDo([](auto v, auto callData) {
|
}
|
||||||
if (v->hasSeries()) {
|
else if (SyncHelper::getSyncState() == MANUAL_SYNC) {
|
||||||
//disable global trigger slot
|
this->smartDo([](auto v, auto callData) {
|
||||||
int *r = (int *) callData;
|
if (v->hasSeries()) {
|
||||||
v->addSlice(r[1]);
|
//disable global trigger slot
|
||||||
}
|
double * r = (double *) callData;
|
||||||
}, src, data, ImageViewManager::EStudyEBoundsSeries);
|
v->applySliceOffset(r[3], r[4]);
|
||||||
|
v->SyncScrollBar();
|
||||||
}
|
}
|
||||||
|
}, src, sliceData, ImageViewManager::SameOrientationSeries);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
//TODO: reference line
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) {
|
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]};
|
double vector[3] = {d[3] - d[0], d[4] - d[1], d[5] - d[2]};
|
||||||
v->applyPanOffset(vector);
|
v->applyPanOffset(vector);
|
||||||
}
|
}
|
||||||
}, src, offsetVector, ImageViewManager::EStudyEBoundsSeries);
|
}, src, offsetVector, ImageViewManager::SameStudySeries);
|
||||||
} else if (SyncHelper::getSyncState() == AUTO_SYNC) {
|
} else if (SyncHelper::getSyncState() == AUTO_SYNC) {
|
||||||
this->smartDo([](auto v, auto callData) {
|
this->smartDo([](auto v, auto callData) {
|
||||||
if (v->hasSeries()) {
|
if (v->hasSeries()) {
|
||||||
@@ -223,7 +231,7 @@ void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) {
|
|||||||
double vector[3] = {d[3], d[4] , d[5]};
|
double vector[3] = {d[3], d[4] , d[5]};
|
||||||
v->shiftCamera(vector);
|
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;
|
double d = *(double *) callData;
|
||||||
v->setZoomScale(d);
|
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;
|
double *d = (double *) callData;
|
||||||
v->setWindowLevel(d[0], d[1]);
|
v->setWindowLevel(d[0], d[1]);
|
||||||
}
|
}
|
||||||
}, src, data, ImageViewManager::EStudyEBoundsSeries);
|
}, src, data, ImageViewManager::SameStudySeries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ public:
|
|||||||
Current,
|
Current,
|
||||||
SameSeries,
|
SameSeries,
|
||||||
//Equal Study, Equal World Bounds series
|
//Equal Study, Equal World Bounds series
|
||||||
EStudyEBoundsSeries,
|
SameStudySeries,
|
||||||
EqualBoundsSeriesExceptSelf,
|
SameOrientationSeries,
|
||||||
AllExceptSelf,
|
AllExceptSelf,
|
||||||
All
|
All
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "dicomimageview.h"
|
#include "dicomimageview.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -420,11 +420,9 @@ void DicomImageView::dispatchEvent(vtkObject *, unsigned long eid, void *callDat
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): {
|
case (ActorDraggableInteractorStyle::DraggableStyleEvents::SlicedEvent): {
|
||||||
mScrollBar->SetValueSilently(r[0]);
|
mScrollBar->SetValueSilently(mImageViewer->GetSlice());
|
||||||
//invoke event
|
//invoke event
|
||||||
double focusPoint[3] = {.0, .0, .0};
|
emit onSlice(this, callData);
|
||||||
mImageViewer->GetSlicePoint(focusPoint);
|
|
||||||
emit onSlice(this, focusPoint);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -165,6 +165,11 @@ public:
|
|||||||
mImageViewer->Render();
|
mImageViewer->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applySliceOffset(double offset, double direction){
|
||||||
|
mImageViewer->applySliceOffset(offset, direction);
|
||||||
|
mImageViewer->Render();
|
||||||
|
}
|
||||||
|
|
||||||
void loadSeries(SeriesImageSet *series);
|
void loadSeries(SeriesImageSet *series);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|||||||
Reference in New Issue
Block a user