2024-05-08 12:12:49 -04:00
|
|
|
import { DisplaySetService, ViewportGridService } from '@ohif/core';
|
|
|
|
|
|
2024-01-22 09:44:35 -05:00
|
|
|
const IMAGE_SLICE_SYNC_NAME = 'IMAGE_SLICE_SYNC';
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2024-01-22 09:44:35 -05:00
|
|
|
export default function toggleImageSliceSync({
|
2023-10-03 10:59:09 -04:00
|
|
|
servicesManager,
|
|
|
|
|
viewports: providedViewports,
|
2024-03-27 16:01:32 -04:00
|
|
|
syncId,
|
2024-05-08 12:12:49 -04:00
|
|
|
}: withAppTypes) {
|
2023-09-01 16:19:39 -04:00
|
|
|
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
|
|
|
|
|
servicesManager.services;
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2024-03-27 16:01:32 -04:00
|
|
|
syncId ||= IMAGE_SLICE_SYNC_NAME;
|
|
|
|
|
|
2023-10-10 13:21:17 -04:00
|
|
|
const viewports =
|
|
|
|
|
providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2024-03-27 16:01:32 -04:00
|
|
|
// Todo: right now we don't have a proper way to define specific
|
|
|
|
|
// viewports to add to synchronizers, and right now it is global or not
|
|
|
|
|
// after we do that, we should do fine grained control of the synchronizers
|
|
|
|
|
const someViewportHasSync = viewports.some(viewport => {
|
|
|
|
|
const syncStates = syncGroupService.getSynchronizersForViewport(
|
|
|
|
|
viewport.viewportOptions.viewportId
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const imageSync = syncStates.find(syncState => syncState.id === syncId);
|
|
|
|
|
|
|
|
|
|
return !!imageSync;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (someViewportHasSync) {
|
|
|
|
|
return disableSync(syncId, servicesManager);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
// create synchronization group and add the viewports to it.
|
|
|
|
|
viewports.forEach(gridViewport => {
|
|
|
|
|
const { viewportId } = gridViewport.viewportOptions;
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
syncGroupService.addViewportToSyncGroup(viewportId, viewport.getRenderingEngine().id, {
|
2024-03-27 16:01:32 -04:00
|
|
|
type: 'imageSlice',
|
|
|
|
|
id: syncId,
|
2023-10-03 10:59:09 -04:00
|
|
|
source: true,
|
|
|
|
|
target: true,
|
2022-11-21 10:44:19 -05:00
|
|
|
});
|
2023-10-03 10:59:09 -04:00
|
|
|
});
|
|
|
|
|
}
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2024-05-08 12:12:49 -04:00
|
|
|
function disableSync(syncName, servicesManager: AppTypes.ServicesManager) {
|
2023-10-03 10:59:09 -04:00
|
|
|
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
|
|
|
|
|
servicesManager.services;
|
|
|
|
|
const viewports = getReconstructableStackViewports(viewportGridService, displaySetService);
|
|
|
|
|
viewports.forEach(gridViewport => {
|
|
|
|
|
const { viewportId } = gridViewport.viewportOptions;
|
|
|
|
|
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
|
|
|
if (!viewport) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
syncGroupService.removeViewportFromSyncGroup(
|
|
|
|
|
viewport.id,
|
|
|
|
|
viewport.getRenderingEngine().id,
|
|
|
|
|
syncName
|
|
|
|
|
);
|
|
|
|
|
});
|
2023-10-10 13:21:17 -04:00
|
|
|
}
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
/**
|
|
|
|
|
* Gets the consistent spacing stack viewport types, which are the ones which
|
|
|
|
|
* can be navigated using the stack image sync right now.
|
|
|
|
|
*/
|
2024-05-08 12:12:49 -04:00
|
|
|
function getReconstructableStackViewports(
|
|
|
|
|
viewportGridService: ViewportGridService,
|
|
|
|
|
displaySetService: DisplaySetService
|
|
|
|
|
) {
|
2023-10-03 10:59:09 -04:00
|
|
|
let { viewports } = viewportGridService.getState();
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
viewports = [...viewports.values()];
|
2022-11-21 10:44:19 -05:00
|
|
|
// filter empty viewports
|
2023-10-03 10:59:09 -04:00
|
|
|
viewports = viewports.filter(
|
|
|
|
|
viewport => viewport.displaySetInstanceUIDs && viewport.displaySetInstanceUIDs.length
|
|
|
|
|
);
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
// filter reconstructable viewports
|
|
|
|
|
viewports = viewports.filter(viewport => {
|
|
|
|
|
const { displaySetInstanceUIDs } = viewport;
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
for (const displaySetInstanceUID of displaySetInstanceUIDs) {
|
|
|
|
|
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
// TODO - add a better test than isReconstructable
|
|
|
|
|
if (displaySet && displaySet.isReconstructable) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-11-21 10:44:19 -05:00
|
|
|
|
2023-10-03 10:59:09 -04:00
|
|
|
return false;
|
2022-11-21 10:44:19 -05:00
|
|
|
}
|
|
|
|
|
});
|
2023-10-03 10:59:09 -04:00
|
|
|
return viewports;
|
2023-10-10 13:21:17 -04:00
|
|
|
}
|