feat: rebuild window sync logic
This commit is contained in:
@@ -17,9 +17,9 @@ int MeasureHelper::measureType = 0;
|
||||
|
||||
bool FlipExportHelper::flip = false;
|
||||
|
||||
SyncState SyncHelper::_syc_state = SyncState::DIS_SYNC;
|
||||
bool SyncHelper::_syc_item[SYNC_STATE_NUM][SYNC_ITEM_NUM] = {true,true,true,true,true,true,false,false,false};
|
||||
bool SyncHelper::_sync_flag =false; //for just zoom and pan
|
||||
const QString SyncHelper::SyncStateName[SYNC_STATE_NUM] = { "AUTO_SYNC","MANUAL_SYNC","DIS_SYNC" };
|
||||
unsigned int SyncHelper::_syc_item = 0x0000;
|
||||
bool SyncHelper::_syc_state = false;
|
||||
const QString SyncHelper::SyncStateName[SYNC_STATE_NUM] = { "AUTO_SYNC","DIS_SYNC" };
|
||||
const QString SyncHelper::SyncItemName[SYNC_ITEM_NUM] = { "SLICE_LOC","ZOOM_PAN","WIDTH_LEVEL" };
|
||||
|
||||
LanguageOption LanguageHelper::lang = English;
|
||||
@@ -123,23 +123,6 @@ typedef struct DicomCornerInfo
|
||||
std::string ConstAnno[CORNER_NUM];
|
||||
}DicomCornerInfo_t;
|
||||
|
||||
|
||||
|
||||
|
||||
enum SyncState
|
||||
{
|
||||
AUTO_SYNC,
|
||||
MANUAL_SYNC,
|
||||
DIS_SYNC
|
||||
};
|
||||
|
||||
enum SyncItem
|
||||
{
|
||||
SLICE_POS,
|
||||
ZOOM_PAN,
|
||||
WIDTH_LEVEL
|
||||
};
|
||||
|
||||
enum AddDicomType
|
||||
{
|
||||
DUPLICATE_TYPE,
|
||||
@@ -303,41 +286,43 @@ private:
|
||||
|
||||
#define SYNC_ITEM_NUM 3
|
||||
#define SYNC_STATE_NUM 3
|
||||
|
||||
enum SyncType
|
||||
{
|
||||
SYNC_SLICE = 0x0001,
|
||||
SYNC_PAN_ZOOM = 0x0002,
|
||||
SYNC_WINDOW = 0x0004
|
||||
};
|
||||
|
||||
class SyncHelper
|
||||
{
|
||||
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_state][i] = sync;
|
||||
}
|
||||
_syc_item = _syc_item&aSyncSetting;
|
||||
}
|
||||
static SyncState getSyncState()
|
||||
static bool getSyncState()
|
||||
{
|
||||
return _syc_state;
|
||||
}
|
||||
static void setSyncState(SyncState curState)
|
||||
static void setSyncState(bool aState)
|
||||
{
|
||||
_syc_state = curState;
|
||||
_syc_state = aState;
|
||||
EventsCenter::TriggerEvent(SyncStateChanged);
|
||||
}
|
||||
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" };
|
||||
private:
|
||||
static SyncState _syc_state;
|
||||
static bool _syc_item[SYNC_STATE_NUM][SYNC_ITEM_NUM];
|
||||
static bool _sync_flag; //for just zoom and pan
|
||||
|
||||
|
||||
static unsigned int _syc_item;
|
||||
static bool _syc_state;
|
||||
};
|
||||
|
||||
enum LanguageOption
|
||||
|
||||
@@ -366,6 +366,7 @@ void DICOMImageViewer::Render() {
|
||||
int currentIndex = ImageMapper->GetSliceNumber();
|
||||
if (currentIndex != lastIndex) this->SetSlice(lastIndex);
|
||||
ResetZoomScaleToFitWindowSize();
|
||||
this->InteractorStyle->SetCurrentImageNumber(0);
|
||||
}
|
||||
this->FirstRender = 0;
|
||||
return;
|
||||
@@ -469,6 +470,10 @@ void DICOMImageViewer::SetSlice(int slice) {
|
||||
// this->Render();
|
||||
UpdateTopLeftCornerInfo();
|
||||
if (InteractorStyle){
|
||||
if (slice == 0){
|
||||
InteractorStyle->SetCurrentRenderer(this->Renderer);
|
||||
InteractorStyle->SetCurrentImageNumber(0);
|
||||
}
|
||||
double direction = (double)(slice - lastSliceNumber);
|
||||
double focusPoint[5] = {.0, .0, .0 };
|
||||
GetSlicePoint(focusPoint);
|
||||
@@ -574,7 +579,8 @@ void DICOMImageViewer::modifiedReferenceLine(){
|
||||
Render();
|
||||
}
|
||||
|
||||
void DICOMImageViewer::SyncSlicePoint(double *point) {
|
||||
void DICOMImageViewer::SyncSliceWithFocus(double *point)
|
||||
{
|
||||
double focusPoint[4] = {point[0], point[1], point[2], 1.0};
|
||||
WorldToModelMatrix->MultiplyPoint(focusPoint, focusPoint);
|
||||
double f[3] = {.0, .0, .0};
|
||||
@@ -584,6 +590,7 @@ void DICOMImageViewer::SyncSlicePoint(double *point) {
|
||||
f[SliceIJK] = focusPoint[SliceIJK];
|
||||
Renderer->GetActiveCamera()->SetFocalPoint(f);
|
||||
this->Render();
|
||||
Slice = ImageMapper->GetSliceNumber();
|
||||
UpdateTopLeftCornerInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -369,7 +369,8 @@ public:
|
||||
return &raiser;
|
||||
}
|
||||
|
||||
void SyncSlicePoint(double *point);
|
||||
void SyncSliceWithFocus(double *point);
|
||||
|
||||
|
||||
void GetSlicePoint(double *point);
|
||||
|
||||
|
||||
@@ -137,8 +137,9 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
|
||||
if (!v->hasSeries()) return;
|
||||
//check series
|
||||
auto series = sourceView->getSeriesInstance();
|
||||
if (v->getSeriesInstance() == series && v->getReconPlane() == sourceView->getReconPlane()) {
|
||||
cb(v, callData);
|
||||
if ( v->getSeriesInstance() == series) {
|
||||
if(cb)cb(v, callData);
|
||||
else if(otherCb) otherCb(v, callData);
|
||||
}
|
||||
else{
|
||||
if (otherCb) otherCb(v, callData);
|
||||
@@ -147,6 +148,24 @@ void ImageViewManager::smartDo(SmartDoCallback cb,SmartDoCallback otherCb, Dico
|
||||
});
|
||||
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: {
|
||||
std::for_each(vList.begin(), vList.end(), [=](auto v) {
|
||||
if (v == sourceView) return;
|
||||
@@ -254,25 +273,15 @@ void ImageViewManager::viewDoubleClicked(DicomImageView *view) {
|
||||
|
||||
void ImageViewManager::viewSliced(DicomImageView *src, void *sliceData) {
|
||||
//Sync slice
|
||||
if (sliceData && SyncHelper::getSyncItem(SLICE_POS)) {
|
||||
if (SyncHelper::getSyncState() == AUTO_SYNC) {
|
||||
if (sliceData && SyncHelper::getSyncItem(SYNC_SLICE)) {
|
||||
if (SyncHelper::getSyncState() == SYNC_SLICE) {
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
if (v->hasSeries()) {
|
||||
double *r = (double *) callData;
|
||||
v->syncSlicePoint(r);
|
||||
v->syncSliceFocus(r);
|
||||
v->SyncScrollBar();
|
||||
}
|
||||
}, src, sliceData, ImageViewManager::SameStudySameOrientation);
|
||||
}
|
||||
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);
|
||||
}, src, sliceData, ImageViewManager::SameSeriesSameOrientation);
|
||||
}
|
||||
}
|
||||
//reference line
|
||||
@@ -300,57 +309,37 @@ void ImageViewManager::renderReferenceLine() {
|
||||
}
|
||||
|
||||
void ImageViewManager::viewPaned(DicomImageView *src, void* offsetVector) {
|
||||
if (SyncHelper::getSyncItem(ZOOM_PAN)) {
|
||||
if (SyncHelper::getSyncState() == MANUAL_SYNC) {
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_PAN_ZOOM))
|
||||
{
|
||||
this->smartDo([](auto v, auto callData){
|
||||
if (v->hasSeries()) {
|
||||
double *d = (double *) callData;
|
||||
double vector[3] = {d[3] - d[0], d[4] - d[1], d[5] - d[2]};
|
||||
v->applyPanOffset(vector);
|
||||
}
|
||||
}, 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);
|
||||
}
|
||||
} }, src, offsetVector, ImageViewManager::SameSeriesSameOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewManager::viewZoomed(DicomImageView *src, double* scaleFactor) {
|
||||
if (SyncHelper::getSyncItem(ZOOM_PAN)) {
|
||||
if (SyncHelper::getSyncState() == MANUAL_SYNC){
|
||||
if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_PAN_ZOOM)){
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
if (v->hasSeries()) {
|
||||
double* d = ((double *) callData);
|
||||
v->setZoomFactor(d[1]/d[0]);
|
||||
}
|
||||
}, src, scaleFactor, ImageViewManager::SameOrientationSeries);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}, src, scaleFactor, ImageViewManager::SameSeriesSameOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewManager::viewEndWindowLevel(DicomImageView *src, double level, double window) {
|
||||
double data[2] = {level, window};
|
||||
if (SyncHelper::getSyncItem(WIDTH_LEVEL)) {
|
||||
if (SyncHelper::getSyncState() && SyncHelper::getSyncItem(SYNC_WINDOW)) {
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
if (v->hasSeries()) {
|
||||
double *d = (double *) callData;
|
||||
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;
|
||||
}
|
||||
|
||||
int ImageViewManager::checkSyncAbility(DicomImageView* view) {
|
||||
bool ImageViewManager::checkSyncAbility(DicomImageView* view) {
|
||||
bool flag = false;
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
bool *d = (bool *) callData;
|
||||
@@ -490,7 +479,7 @@ int ImageViewManager::checkSyncAbility(DicomImageView* view) {
|
||||
d[0] = true;
|
||||
}
|
||||
}, view, &flag, ImageViewManager::SameStudySameOrientation);
|
||||
if (flag) return AUTO_SYNC;
|
||||
if (flag) return true;
|
||||
this->smartDo([](auto v, auto callData) {
|
||||
bool *d = (bool *) callData;
|
||||
if (d[0]) return;
|
||||
@@ -499,8 +488,8 @@ int ImageViewManager::checkSyncAbility(DicomImageView* view) {
|
||||
}
|
||||
}, view, &flag, ImageViewManager::SameOrientationSeries);
|
||||
|
||||
if (flag) return MANUAL_SYNC;
|
||||
return DIS_SYNC;
|
||||
if (flag) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageViewManager::clearCurrentView() {
|
||||
|
||||
@@ -97,11 +97,12 @@ public:
|
||||
|
||||
void switchFusion();
|
||||
|
||||
int checkSyncAbility(DicomImageView* view);
|
||||
bool checkSyncAbility(DicomImageView* view);
|
||||
|
||||
enum DoScope {
|
||||
Current,
|
||||
SameSeries,
|
||||
SameSeriesSameOrientation,
|
||||
//Equal Study, Equal World Bounds series
|
||||
SameStudySameOrientation,
|
||||
SameOrientationSeries,
|
||||
|
||||
@@ -171,8 +171,8 @@ public:
|
||||
return this->mImageViewer->GetReconPlane() == view->mImageViewer->GetReconPlane();
|
||||
}
|
||||
|
||||
void syncSlicePoint(double *point) {
|
||||
mImageViewer->SyncSlicePoint(point);
|
||||
void syncSliceFocus(double *point) {
|
||||
mImageViewer->SyncSliceWithFocus(point);
|
||||
}
|
||||
|
||||
void applySliceOffset(double offset, double direction){
|
||||
|
||||
@@ -227,11 +227,6 @@ void DefaultToolBar::initSyncButton() {
|
||||
// Menu
|
||||
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)\
|
||||
mSyncActions[index] = m->addAction(text, this, [&](bool value) {\
|
||||
SyncHelper::setSyncItem(type, value);\
|
||||
@@ -240,9 +235,9 @@ void DefaultToolBar::initSyncButton() {
|
||||
mSyncActions[index]->setChecked(false);\
|
||||
mSyncActions[index]->setDisabled(true);
|
||||
|
||||
ADD_SYNC_ITEM(0,tr("Sychronize slice"),SyncItem::SLICE_POS)
|
||||
ADD_SYNC_ITEM(1,tr("Sychronize zoom & pan"),SyncItem::ZOOM_PAN)
|
||||
ADD_SYNC_ITEM(2,tr("Sychronize window level & width"),SyncItem::WIDTH_LEVEL)
|
||||
ADD_SYNC_ITEM(0,tr("Sychronize slice"), SYNC_SLICE)
|
||||
ADD_SYNC_ITEM(1,tr("Sychronize zoom & pan"), SYNC_PAN_ZOOM)
|
||||
ADD_SYNC_ITEM(2,tr("Sychronize window level & width"), SYNC_WINDOW)
|
||||
|
||||
//hide zoom& pan action
|
||||
mSyncActions[1]->setVisible(false);
|
||||
@@ -250,43 +245,22 @@ void DefaultToolBar::initSyncButton() {
|
||||
mBtnSync->setPopupMode(QToolButton::MenuButtonPopup);
|
||||
mBtnSync->setMenu(m);
|
||||
connect(mBtnSync, &QToolButton::clicked,[](){
|
||||
SyncHelper::setSyncState((SyncState)((SyncHelper::getSyncState()+1)%3));
|
||||
SyncHelper::setSyncState(!SyncHelper::getSyncState());
|
||||
});
|
||||
connect(EventsCenter::Default(), &EventsCenter::SyncStateChanged, this, &DefaultToolBar::syncStateChanged);
|
||||
}
|
||||
|
||||
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(mManualIcon);
|
||||
mActionSyncState->setText(QString(tr("CUR STATE: %1")).arg(SyncHelper::SyncStateName[MANUAL_SYNC]));
|
||||
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 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;
|
||||
mBtnSync->setIcon(SyncHelper::getSyncState()?mAutoIcon:mDisIcon);
|
||||
|
||||
unsigned int v = 1;
|
||||
for (unsigned int i = 0; i < SYNC_ITEM_NUM; i++) {
|
||||
mSyncActions[i]->setChecked(SyncHelper::getSyncState());
|
||||
mSyncActions[i]->setEnabled(SyncHelper::getSyncState());
|
||||
SyncHelper::setSyncItem(v <<i, SyncHelper::getSyncState());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DefaultToolBar::initModeButtons() {
|
||||
@@ -551,20 +525,20 @@ void DefaultToolBar::updateNeedCheckFunctionButtons(ViewFunctionState state)
|
||||
mBtnClear->setEnabled(true);
|
||||
mBtnFlip->setEnabled(true);
|
||||
mBtnCine->setEnabled(true);
|
||||
mBtnMPR->setEnabled(state.canMPR!=-1);
|
||||
mBtnVR->setEnabled(state.canMPR!=-1);
|
||||
if (state.canMPR!=-1){
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (i==state.canMPR){
|
||||
mMPRActions[i]->setEnabled(false);
|
||||
}
|
||||
else{
|
||||
mMPRActions[i]->setEnabled(true);
|
||||
mBtnMPR->setEnabled(state.canMPR!=-1);
|
||||
mBtnVR->setEnabled(state.canMPR!=-1);
|
||||
if (state.canMPR!=-1){
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (i==state.canMPR){
|
||||
mMPRActions[i]->setEnabled(false);
|
||||
}
|
||||
else{
|
||||
mMPRActions[i]->setEnabled(true);
|
||||
}
|
||||
}
|
||||
mMPRActions[state.canMPR]->setChecked(true);
|
||||
}
|
||||
mMPRActions[state.canMPR]->setChecked(true);
|
||||
}
|
||||
mBtnFusion->setEnabled(state.canFusion);
|
||||
mBtnFusion->setEnabled(state.canFusion);
|
||||
}
|
||||
// SyncHelper::setSyncState((SyncState)state.canSync);
|
||||
// syncStateChanged();
|
||||
|
||||
@@ -95,7 +95,6 @@ private:
|
||||
QAction *mActionMaximize;
|
||||
QAction *mActionClose;
|
||||
QAction *mActionFullScreen;
|
||||
QAction *mActionSyncState;
|
||||
QAction *mActionHideAnnotations;
|
||||
QAction *mActionHideReferenceLine;
|
||||
QAction *mActionHideMeasure;
|
||||
|
||||
@@ -175,6 +175,7 @@ void QDicomViewer::initViewOperation() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SyncHelper::setSyncState(false);
|
||||
}
|
||||
});
|
||||
// MPR
|
||||
|
||||
@@ -81,8 +81,8 @@ int main(int argc, char* argv[])
|
||||
LanguageHelper::setLanguage(ChineseSimple);
|
||||
}
|
||||
QApplication::installTranslator(&translator);
|
||||
QDicomViewer w;
|
||||
w.show();
|
||||
QDicomViewer w;
|
||||
w.show();
|
||||
exitCode = a.exec();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user