feat: rebuild window sync logic

This commit is contained in:
kradchen
2025-06-16 14:46:03 +08:00
parent 6f835c9597
commit 641f63a6ee
11 changed files with 101 additions and 144 deletions

View File

@@ -17,9 +17,9 @@ int MeasureHelper::measureType = 0;
bool FlipExportHelper::flip = false; bool FlipExportHelper::flip = false;
SyncState SyncHelper::_syc_state = SyncState::DIS_SYNC; unsigned int SyncHelper::_syc_item = 0x0000;
bool SyncHelper::_syc_item[SYNC_STATE_NUM][SYNC_ITEM_NUM] = {true,true,true,true,true,true,false,false,false}; bool SyncHelper::_syc_state = false;
bool SyncHelper::_sync_flag =false; //for just zoom and pan const QString SyncHelper::SyncStateName[SYNC_STATE_NUM] = { "AUTO_SYNC","DIS_SYNC" };
const QString SyncHelper::SyncStateName[SYNC_STATE_NUM] = { "AUTO_SYNC","MANUAL_SYNC","DIS_SYNC" };
const QString SyncHelper::SyncItemName[SYNC_ITEM_NUM] = { "SLICE_LOC","ZOOM_PAN","WIDTH_LEVEL" }; const QString SyncHelper::SyncItemName[SYNC_ITEM_NUM] = { "SLICE_LOC","ZOOM_PAN","WIDTH_LEVEL" };
LanguageOption LanguageHelper::lang = English; LanguageOption LanguageHelper::lang = English;

View File

@@ -123,23 +123,6 @@ typedef struct DicomCornerInfo
std::string ConstAnno[CORNER_NUM]; std::string ConstAnno[CORNER_NUM];
}DicomCornerInfo_t; }DicomCornerInfo_t;
enum SyncState
{
AUTO_SYNC,
MANUAL_SYNC,
DIS_SYNC
};
enum SyncItem
{
SLICE_POS,
ZOOM_PAN,
WIDTH_LEVEL
};
enum AddDicomType enum AddDicomType
{ {
DUPLICATE_TYPE, DUPLICATE_TYPE,
@@ -303,41 +286,43 @@ private:
#define SYNC_ITEM_NUM 3 #define SYNC_ITEM_NUM 3
#define SYNC_STATE_NUM 3 #define SYNC_STATE_NUM 3
enum SyncType
{
SYNC_SLICE = 0x0001,
SYNC_PAN_ZOOM = 0x0002,
SYNC_WINDOW = 0x0004
};
class SyncHelper class SyncHelper
{ {
public: public:
static bool getSyncItem(SyncItem index) static bool getSyncItem(SyncType aType)
{ {
return _syc_item[_syc_state][index]; return _syc_item&aType;
} }
static void setSyncItem(SyncItem index, bool sync) static void setSyncItem(unsigned int aSyncSetting,bool aValue)
{ {
_syc_item[_syc_state][index] = sync; _syc_item = _syc_item | (aValue? aSyncSetting:(!aSyncSetting));
} }
static void setSyncItems(bool sync) static void setSyncItems(unsigned int aSyncSetting)
{ {
for (int i = 0; i < SYNC_ITEM_NUM; i++) _syc_item = _syc_item&aSyncSetting;
{
_syc_item[_syc_state][i] = sync;
} }
} static bool getSyncState()
static SyncState getSyncState()
{ {
return _syc_state; return _syc_state;
} }
static void setSyncState(SyncState curState) static void setSyncState(bool aState)
{ {
_syc_state = curState; _syc_state = aState;
EventsCenter::TriggerEvent(SyncStateChanged); EventsCenter::TriggerEvent(SyncStateChanged);
} }
static const QString SyncStateName[SYNC_STATE_NUM];// = { "AUTO_SYNC","MANUAL_SYNC","DIS_SYNC" }; static const QString SyncStateName[SYNC_STATE_NUM];// = { "AUTO_SYNC","MANUAL_SYNC","DIS_SYNC" };
static const QString SyncItemName[SYNC_ITEM_NUM];// = { "SLICE_LOC","ZOOM_PAN","WIDTH_LEVEL" }; static const QString SyncItemName[SYNC_ITEM_NUM];// = { "SLICE_LOC","ZOOM_PAN","WIDTH_LEVEL" };
private: private:
static SyncState _syc_state; static unsigned int _syc_item;
static bool _syc_item[SYNC_STATE_NUM][SYNC_ITEM_NUM]; static bool _syc_state;
static bool _sync_flag; //for just zoom and pan
}; };
enum LanguageOption enum LanguageOption

View File

@@ -366,6 +366,7 @@ void DICOMImageViewer::Render() {
int currentIndex = ImageMapper->GetSliceNumber(); int currentIndex = ImageMapper->GetSliceNumber();
if (currentIndex != lastIndex) this->SetSlice(lastIndex); if (currentIndex != lastIndex) this->SetSlice(lastIndex);
ResetZoomScaleToFitWindowSize(); ResetZoomScaleToFitWindowSize();
this->InteractorStyle->SetCurrentImageNumber(0);
} }
this->FirstRender = 0; this->FirstRender = 0;
return; return;
@@ -469,6 +470,10 @@ void DICOMImageViewer::SetSlice(int slice) {
// this->Render(); // this->Render();
UpdateTopLeftCornerInfo(); UpdateTopLeftCornerInfo();
if (InteractorStyle){ if (InteractorStyle){
if (slice == 0){
InteractorStyle->SetCurrentRenderer(this->Renderer);
InteractorStyle->SetCurrentImageNumber(0);
}
double direction = (double)(slice - lastSliceNumber); double direction = (double)(slice - lastSliceNumber);
double focusPoint[5] = {.0, .0, .0 }; double focusPoint[5] = {.0, .0, .0 };
GetSlicePoint(focusPoint); GetSlicePoint(focusPoint);
@@ -574,7 +579,8 @@ void DICOMImageViewer::modifiedReferenceLine(){
Render(); Render();
} }
void DICOMImageViewer::SyncSlicePoint(double *point) { void DICOMImageViewer::SyncSliceWithFocus(double *point)
{
double focusPoint[4] = {point[0], point[1], point[2], 1.0}; double focusPoint[4] = {point[0], point[1], point[2], 1.0};
WorldToModelMatrix->MultiplyPoint(focusPoint, focusPoint); WorldToModelMatrix->MultiplyPoint(focusPoint, focusPoint);
double f[3] = {.0, .0, .0}; double f[3] = {.0, .0, .0};
@@ -584,6 +590,7 @@ void DICOMImageViewer::SyncSlicePoint(double *point) {
f[SliceIJK] = focusPoint[SliceIJK]; f[SliceIJK] = focusPoint[SliceIJK];
Renderer->GetActiveCamera()->SetFocalPoint(f); Renderer->GetActiveCamera()->SetFocalPoint(f);
this->Render(); this->Render();
Slice = ImageMapper->GetSliceNumber();
UpdateTopLeftCornerInfo(); UpdateTopLeftCornerInfo();
} }

View File

@@ -369,7 +369,8 @@ public:
return &raiser; return &raiser;
} }
void SyncSlicePoint(double *point); void SyncSliceWithFocus(double *point);
void GetSlicePoint(double *point); void GetSlicePoint(double *point);

View File

@@ -137,8 +137,9 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
if (!v->hasSeries()) return; if (!v->hasSeries()) return;
//check series //check series
auto series = sourceView->getSeriesInstance(); auto series = sourceView->getSeriesInstance();
if (v->getSeriesInstance() == series && v->getReconPlane() == sourceView->getReconPlane()) { if ( v->getSeriesInstance() == series) {
cb(v, callData); if(cb)cb(v, callData);
else if(otherCb) otherCb(v, callData);
} }
else{ else{
if (otherCb) otherCb(v, callData); if (otherCb) otherCb(v, callData);
@@ -147,6 +148,24 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
}); });
break; break;
} }
case DoScope::SameSeriesSameOrientation: {
std::for_each(vList.begin(), vList.end(), [=](auto v) {
if (v == sourceView) return;
if (!v->hasSeries()) return;
//check series
auto series = sourceView->getSeriesInstance();
if ( v->getSeriesInstance() == series && v->getReconPlane() == sourceView->getReconPlane()) {
if(cb)cb(v, callData);
else if(otherCb) otherCb(v, callData);
}
else
{
if (otherCb) otherCb(v, callData);
}
});
break;
}
case DoScope::SameStudySameOrientation: { case DoScope::SameStudySameOrientation: {
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;
@@ -254,25 +273,15 @@ void ImageViewManager::viewDoubleClicked(DicomImageView *view) {
void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) { void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) {
//Sync slice //Sync slice
if (sliceData && SyncHelper::getSyncItem(SLICE_POS)) { if (sliceData && SyncHelper::getSyncItem(SYNC_SLICE)) {
if (SyncHelper::getSyncState() == AUTO_SYNC) { if (SyncHelper::getSyncState() == SYNC_SLICE) {
this->smartDo([](auto v, auto callData) { this->smartDo([](auto v, auto callData) {
if (v->hasSeries()) { if (v->hasSeries()) {
double *r = (double *) callData; double *r = (double *) callData;
v->syncSlicePoint(r); v->syncSliceFocus(r);
v->SyncScrollBar(); v->SyncScrollBar();
} }
}, src, sliceData, ImageViewManager::SameStudySameOrientation); }, src, sliceData, ImageViewManager::SameSeriesSameOrientation);
}
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();
}
}, src, sliceData, ImageViewManager::SameOrientationSeries);
} }
} }
//reference line //reference line
@@ -300,57 +309,37 @@ void ImageViewManager::renderReferenceLine() {
} }
void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) { void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) {
if (SyncHelper::getSyncItem(ZOOM_PAN)) { if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_PAN_ZOOM))
if (SyncHelper::getSyncState() == MANUAL_SYNC) { {
this->smartDo([](auto v, auto callData){ this->smartDo([](auto v, auto callData){
if (v->hasSeries()) { if (v->hasSeries()) {
double *d = (double *) callData; double *d = (double *) callData;
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::SameSeriesSameOrientation);
}, src, offsetVector, ImageViewManager::SameOrientationSeries);
} else if (SyncHelper::getSyncState() == AUTO_SYNC) {
this->smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double *d = (double *) callData;
double vector[3] = {d[3], d[4] , d[5]};
v->shiftCamera(vector);
}
}, src, offsetVector, ImageViewManager::SameStudySameOrientation);
}
} }
} }
void ImageViewManager::viewZoomed(DicomImageView *src, double* scaleFactor) { void ImageViewManager::viewZoomed(DicomImageView *src, double* scaleFactor) {
if (SyncHelper::getSyncItem(ZOOM_PAN)) { if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_PAN_ZOOM)){
if (SyncHelper::getSyncState() == MANUAL_SYNC){
this->smartDo([](auto v, auto callData) { this->smartDo([](auto v, auto callData) {
if (v->hasSeries()) { if (v->hasSeries()) {
double* d = ((double *) callData); double* d = ((double *) callData);
v->setZoomFactor(d[1]/d[0]); v->setZoomFactor(d[1]/d[0]);
} }
}, src, scaleFactor, ImageViewManager::SameOrientationSeries); }, src, scaleFactor, ImageViewManager::SameSeriesSameOrientation);
}
else if (SyncHelper::getSyncState() == AUTO_SYNC) {
this->smartDo([](auto v, auto callData) {
if (v->hasSeries()) {
double d = ((double *) callData)[1];
v->setZoomScale(d);
}
}, src, scaleFactor, ImageViewManager::SameStudySameOrientation);
}
} }
} }
void ImageViewManager::viewEndWindowLevel(DicomImageView *src, double level, double window) { void ImageViewManager::viewEndWindowLevel(DicomImageView *src, double level, double window) {
double data[2] = {level, window}; double data[2] = {level, window};
if (SyncHelper::getSyncItem(WIDTH_LEVEL)) { if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_WINDOW)) {
this->smartDo([](auto v, auto callData) { this->smartDo([](auto v, auto callData) {
if (v->hasSeries()) { if (v->hasSeries()) {
double *d = (double *) callData; double *d = (double *) callData;
v->setWindowLevel(d[0], d[1]); v->setWindowLevel(d[0], d[1]);
} }
}, src, data, ImageViewManager::SameStudySameOrientation); }, src, data, ImageViewManager::SameSeriesSameOrientation);
} }
} }
@@ -481,7 +470,7 @@ bool ImageViewManager::checkViewFusion(DicomImageView *view) {
return false; return false;
} }
int ImageViewManager::checkSyncAbility(DicomImageView* view) { bool ImageViewManager::checkSyncAbility(DicomImageView* view) {
bool flag = false; bool flag = false;
this->smartDo([](auto v, auto callData) { this->smartDo([](auto v, auto callData) {
bool *d = (bool *) callData; bool *d = (bool *) callData;
@@ -490,7 +479,7 @@ int ImageViewManager::checkSyncAbility(DicomImageView* view) {
d[0] = true; d[0] = true;
} }
}, view, &flag, ImageViewManager::SameStudySameOrientation); }, view, &flag, ImageViewManager::SameStudySameOrientation);
if (flag) return AUTO_SYNC; if (flag) return true;
this->smartDo([](auto v, auto callData) { this->smartDo([](auto v, auto callData) {
bool *d = (bool *) callData; bool *d = (bool *) callData;
if (d[0]) return; if (d[0]) return;
@@ -499,8 +488,8 @@ int ImageViewManager::checkSyncAbility(DicomImageView* view) {
} }
}, view, &flag, ImageViewManager::SameOrientationSeries); }, view, &flag, ImageViewManager::SameOrientationSeries);
if (flag) return MANUAL_SYNC; if (flag) return true;
return DIS_SYNC; return false;
} }
void ImageViewManager::clearCurrentView() { void ImageViewManager::clearCurrentView() {

View File

@@ -97,11 +97,12 @@ public:
void switchFusion(); void switchFusion();
int checkSyncAbility(DicomImageView* view); bool checkSyncAbility(DicomImageView* view);
enum DoScope { enum DoScope {
Current, Current,
SameSeries, SameSeries,
SameSeriesSameOrientation,
//Equal Study, Equal World Bounds series //Equal Study, Equal World Bounds series
SameStudySameOrientation, SameStudySameOrientation,
SameOrientationSeries, SameOrientationSeries,

View File

@@ -171,8 +171,8 @@ public:
return this->mImageViewer->GetReconPlane() == view->mImageViewer->GetReconPlane(); return this->mImageViewer->GetReconPlane() == view->mImageViewer->GetReconPlane();
} }
void syncSlicePoint(double *point) { void syncSliceFocus(double *point) {
mImageViewer->SyncSlicePoint(point); mImageViewer->SyncSliceWithFocus(point);
} }
void applySliceOffset(double offset, double direction){ void applySliceOffset(double offset, double direction){

View File

@@ -227,11 +227,6 @@ void DefaultToolBar::initSyncButton() {
// Menu // Menu
QMenu * m = new QMenu(this); QMenu * m = new QMenu(this);
// SyncState curst = SyncHelper::getSyncState();
// mActionSyncState = m->addAction(QString(tr("CUR STATE: %1")).arg(SyncHelper::SyncStateName[curst]));
// mActionSyncState->setCheckable(false);
// addSeparator();
#define ADD_SYNC_ITEM(index,text,type)\ #define ADD_SYNC_ITEM(index,text,type)\
mSyncActions[index] = m->addAction(text, this, [&](bool value) {\ mSyncActions[index] = m->addAction(text, this, [&](bool value) {\
SyncHelper::setSyncItem(type, value);\ SyncHelper::setSyncItem(type, value);\
@@ -240,9 +235,9 @@ void DefaultToolBar::initSyncButton() {
mSyncActions[index]->setChecked(false);\ mSyncActions[index]->setChecked(false);\
mSyncActions[index]->setDisabled(true); mSyncActions[index]->setDisabled(true);
ADD_SYNC_ITEM(0,tr("Sychronize slice"),SyncItem::SLICE_POS) ADD_SYNC_ITEM(0,tr("Sychronize slice"), SYNC_SLICE)
ADD_SYNC_ITEM(1,tr("Sychronize zoom & pan"),SyncItem::ZOOM_PAN) ADD_SYNC_ITEM(1,tr("Sychronize zoom & pan"), SYNC_PAN_ZOOM)
ADD_SYNC_ITEM(2,tr("Sychronize window level & width"),SyncItem::WIDTH_LEVEL) ADD_SYNC_ITEM(2,tr("Sychronize window level & width"), SYNC_WINDOW)
//hide zoom& pan action //hide zoom& pan action
mSyncActions[1]->setVisible(false); mSyncActions[1]->setVisible(false);
@@ -250,43 +245,22 @@ void DefaultToolBar::initSyncButton() {
mBtnSync->setPopupMode(QToolButton::MenuButtonPopup); mBtnSync->setPopupMode(QToolButton::MenuButtonPopup);
mBtnSync->setMenu(m); mBtnSync->setMenu(m);
connect(mBtnSync, &QToolButton::clicked,[](){ connect(mBtnSync, &QToolButton::clicked,[](){
SyncHelper::setSyncState((SyncState)((SyncHelper::getSyncState()+1)%3)); SyncHelper::setSyncState(!SyncHelper::getSyncState());
}); });
connect(EventsCenter::Default(), &EventsCenter::SyncStateChanged, this, &DefaultToolBar::syncStateChanged); connect(EventsCenter::Default(), &EventsCenter::SyncStateChanged, this, &DefaultToolBar::syncStateChanged);
} }
void DefaultToolBar::syncStateChanged() const { void DefaultToolBar::syncStateChanged() const {
switch (SyncHelper::getSyncState()) {
case AUTO_SYNC:
mBtnSync->setIcon(mAutoIcon);
mActionSyncState->setText(QString(tr("CUR STATE: %1")).arg(SyncHelper::SyncStateName[AUTO_SYNC]));
for (int i = 0; i < SYNC_ITEM_NUM; i++) {
mSyncActions[i]->setDisabled(false);
}
mSyncActions[SLICE_POS]->setChecked(SyncHelper::getSyncItem(SLICE_POS));
mSyncActions[WIDTH_LEVEL]->setChecked(SyncHelper::getSyncItem(WIDTH_LEVEL));
mSyncActions[ZOOM_PAN]->setChecked(SyncHelper::getSyncItem(ZOOM_PAN));
break;
case MANUAL_SYNC:{ mBtnSync->setIcon(SyncHelper::getSyncState()?mAutoIcon:mDisIcon);
mBtnSync->setIcon(mManualIcon);
mActionSyncState->setText(QString(tr("CUR STATE: %1")).arg(SyncHelper::SyncStateName[MANUAL_SYNC])); unsigned int v = 1;
mSyncActions[SLICE_POS]->setChecked(SyncHelper::getSyncItem(SLICE_POS)); for (unsigned int i = 0; i < SYNC_ITEM_NUM; i++) {
mSyncActions[WIDTH_LEVEL]->setChecked(SyncHelper::getSyncItem(WIDTH_LEVEL)); mSyncActions[i]->setChecked(SyncHelper::getSyncState());
mSyncActions[ZOOM_PAN]->setChecked(SyncHelper::getSyncItem(ZOOM_PAN)); mSyncActions[i]->setEnabled(SyncHelper::getSyncState());
break; SyncHelper::setSyncItem(v <<i, SyncHelper::getSyncState());
}
case DIS_SYNC:
mBtnSync->setIcon(mDisIcon);
mActionSyncState->setText(QString(tr("CUR STATE: %1")).arg(SyncHelper::SyncStateName[DIS_SYNC]));
for (int i = 0; i < SYNC_ITEM_NUM; i++) {
mSyncActions[i]->setChecked(false);
mSyncActions[i]->setDisabled(true);
}
break;
default:
break;
} }
} }
void DefaultToolBar::initModeButtons() { void DefaultToolBar::initModeButtons() {

View File

@@ -95,7 +95,6 @@ private:
QAction *mActionMaximize; QAction *mActionMaximize;
QAction *mActionClose; QAction *mActionClose;
QAction *mActionFullScreen; QAction *mActionFullScreen;
QAction *mActionSyncState;
QAction *mActionHideAnnotations; QAction *mActionHideAnnotations;
QAction *mActionHideReferenceLine; QAction *mActionHideReferenceLine;
QAction *mActionHideMeasure; QAction *mActionHideMeasure;

View File

@@ -175,6 +175,7 @@ void QDicomViewer::initViewOperation() {
default: default:
break; break;
} }
SyncHelper::setSyncState(false);
} }
}); });
// MPR // MPR