All files / tools/src/utilities/spatial areViewportsSpatiallyLinked.ts

0% Statements 0/24
0% Branches 0/28
0% Functions 0/4
0% Lines 0/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                                                                                                                                                                                                                               
import type { Types } from '@cornerstonejs/core';
import { getToolGroupForViewport } from '../../store/ToolGroupManager';
import type { SpatialLinkOptions } from './types';
 
function getFrameOfReferenceUID(
  viewport: Types.IViewport
): string | undefined {
  return viewport.getFrameOfReferenceUID?.();
}
 
function hasRegistrationTransform(
  sourceFrameOfReferenceUID: string,
  targetFrameOfReferenceUID: string,
  options: SpatialLinkOptions
): boolean {
  const { registrationTransforms } = options;
  if (!registrationTransforms?.size) {
    return false;
  }
 
  return (
    registrationTransforms.has(
      `${sourceFrameOfReferenceUID}:${targetFrameOfReferenceUID}`
    ) ||
    registrationTransforms.has(
      `${targetFrameOfReferenceUID}:${sourceFrameOfReferenceUID}`
    )
  );
}
 
/**
 * Decides whether two viewports are spatially linked, i.e. whether it is
 * meaningful to draw spatially authoritative overlays (reference points,
 * slice intersection lines) from one viewport into the other.
 *
 * - policy 'frameOfReferenceUID': both viewports must report the same
 *   FrameOfReferenceUID, unless a registration transform is provided for the
 *   pair of frames of reference. Viewports without a FrameOfReferenceUID are
 *   never considered linked under this policy.
 * - policy 'explicit': the pair must appear in `options.explicitLinks`
 *   (either direction).
 * - policy 'toolGroup': both viewports must belong to the same tool group.
 *
 * Note this deliberately does not compare volume/image IDs: two viewports
 * showing different series of the same study share a FrameOfReferenceUID and
 * are spatially comparable.
 */
export default function areViewportsSpatiallyLinked(
  source: Types.IViewport,
  target: Types.IViewport,
  options: SpatialLinkOptions
): boolean {
  if (!source || !target || !options?.policy) {
    return false;
  }
 
  switch (options.policy) {
    case 'frameOfReferenceUID': {
      const sourceFrameOfReferenceUID = getFrameOfReferenceUID(source);
      const targetFrameOfReferenceUID = getFrameOfReferenceUID(target);
 
      if (!sourceFrameOfReferenceUID || !targetFrameOfReferenceUID) {
        return false;
      }
 
      if (sourceFrameOfReferenceUID === targetFrameOfReferenceUID) {
        return true;
      }
 
      return hasRegistrationTransform(
        sourceFrameOfReferenceUID,
        targetFrameOfReferenceUID,
        options
      );
    }
 
    case 'explicit': {
      const { explicitLinks } = options;
      if (!explicitLinks?.length) {
        return false;
      }
 
      return explicitLinks.some(
        (link) =>
          (link.sourceViewportId === source.id &&
            link.targetViewportId === target.id) ||
          (link.sourceViewportId === target.id &&
            link.targetViewportId === source.id)
      );
    }
 
    case 'toolGroup': {
      const sourceToolGroup = getToolGroupForViewport(
        source.id,
        source.renderingEngineId
      );
      const targetToolGroup = getToolGroupForViewport(
        target.id,
        target.renderingEngineId
      );
 
      return (
        !!sourceToolGroup && !!targetToolGroup &&
        sourceToolGroup.id === targetToolGroup.id
      );
    }
 
    default:
      return false;
  }
}