diff --git a/extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts b/extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts index 8bebf6439..81ed9a5aa 100644 --- a/extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts +++ b/extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts @@ -6,6 +6,8 @@ import { Types as ToolsTypes, } from '@cornerstonejs/tools'; +import { isAnyDisplaySetCommon } from '../../utils/isAnyDisplaySetCommon'; + const { createSynchronizer } = SynchronizerManager; const { SEGMENTATION_REPRESENTATION_MODIFIED } = Enums.Events; const { BlendModes } = CoreEnums; @@ -34,6 +36,12 @@ export default function createHydrateSegmentationSynchronizer( return stackImageSynchronizer; } +/** + * This method will add the segmentation representation to any target viewports having: + * + * 1. the same FrameOfReferenceUID (FOR) as the segmentation representation, or + * 2. a shared DisplaySet with the source viewport when no FOR is present. + */ const segmentationRepresentationModifiedCallback = async ( synchronizerInstance: Synchronizer, sourceViewport: Types.IViewportId, @@ -44,15 +52,21 @@ const segmentationRepresentationModifiedCallback = async ( const event = sourceEvent as ToolsTypes.EventTypes.SegmentationRepresentationModifiedEventType; const { segmentationId, type: segmentationRepresentationType } = event.detail; - const { segmentationService } = servicesManager.services; + const { segmentationService, cornerstoneViewportService } = servicesManager.services; const targetViewportId = targetViewport.viewportId; + const sourceViewportId = sourceViewport.viewportId; const { viewport } = getEnabledElementByViewportId(targetViewportId); + const sourceViewportInfo = cornerstoneViewportService.getViewportInfo(sourceViewportId); + const targetViewportInfo = cornerstoneViewportService.getViewportInfo(targetViewportId); - const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID(); + const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo); + const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo); - if (!targetFrameOfReferenceUID) { + const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs); + + if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) { return; } @@ -81,3 +95,10 @@ const segmentationRepresentationModifiedCallback = async ( }, }); }; + +/** + * Extracts the displaySetInstanceUIDs from a viewportInfo. + */ +function extractDisplaySetUIDs(viewportInfo) { + return viewportInfo.getViewportData().data.map(ds => ds.displaySetInstanceUID); +} diff --git a/extensions/cornerstone/src/utils/isAnyDisplaySetCommon.ts b/extensions/cornerstone/src/utils/isAnyDisplaySetCommon.ts new file mode 100644 index 000000000..b28755879 --- /dev/null +++ b/extensions/cornerstone/src/utils/isAnyDisplaySetCommon.ts @@ -0,0 +1,18 @@ +/** + * Checks whether two viewports share at least one common display set. + * + * This method checks to see if the source and target share a display set. + * It performs an O(n * m) comparison between the display sets of each viewport. + * Since each viewport typically contains only a small number of display sets (≤ 5), + * the computational cost is negligible. + * + * @param sourceDisplaySetUIDs - Array of displaySetInstanceUID from the source viewport. + * @param targetDisplaySetUIDs - Array of displaySetInstanceUID from the target viewport. + * @returns true if at least one display set is common; false otherwise. + */ +export function isAnyDisplaySetCommon( + sourceDisplaySetUIDs: string[], + targetDisplaySetUIDs: string[] +): boolean { + return sourceDisplaySetUIDs.some(uid => targetDisplaySetUIDs.includes(uid)); +}