@cornerstonejs/tools 5.0.16 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/esm/stateManagement/segmentation/helpers/labelmapImageMapperSupport.js +1 -1
  2. package/dist/esm/stateManagement/segmentation/labelmapModel/normalizeLabelmapSegmentationData.js +1 -1
  3. package/dist/esm/stateManagement/segmentation/labelmapModel/privateLabelmap.js +2 -2
  4. package/dist/esm/stateManagement/segmentation/utilities/getViewportAssociatedToSegmentation.js +2 -1
  5. package/dist/esm/synchronizers/callbacks/cameraSyncCallback.js +19 -2
  6. package/dist/esm/synchronizers/callbacks/imageSliceSyncCallback.js +3 -0
  7. package/dist/esm/synchronizers/callbacks/voiSyncCallback.js +13 -1
  8. package/dist/esm/tools/AdvancedMagnifyTool.js +36 -10
  9. package/dist/esm/tools/CrosshairsTool.js +100 -49
  10. package/dist/esm/tools/MagnifyTool.d.ts +1 -1
  11. package/dist/esm/tools/MagnifyTool.js +27 -6
  12. package/dist/esm/tools/OrientationControllerTool.js +3 -2
  13. package/dist/esm/tools/OrientationMarkerTool.js +3 -0
  14. package/dist/esm/tools/OverlayGridTool.js +2 -1
  15. package/dist/esm/tools/ReferenceCursors.d.ts +1 -1
  16. package/dist/esm/tools/ReferenceCursors.js +24 -3
  17. package/dist/esm/tools/ReferenceLinesTool.js +5 -4
  18. package/dist/esm/tools/ScaleOverlayTool.js +2 -1
  19. package/dist/esm/tools/TrackballRotateTool.js +6 -4
  20. package/dist/esm/tools/VolumeCroppingControlTool.js +11 -6
  21. package/dist/esm/tools/VolumeCroppingTool.js +6 -4
  22. package/dist/esm/tools/VolumeRotateTool.js +4 -2
  23. package/dist/esm/tools/WindowLevelRegionTool.js +27 -3
  24. package/dist/esm/tools/WindowLevelTool.js +4 -8
  25. package/dist/esm/tools/annotation/DragProbeTool.js +2 -1
  26. package/dist/esm/tools/annotation/ETDRSGridTool.js +3 -2
  27. package/dist/esm/tools/annotation/EllipticalROITool.js +2 -1
  28. package/dist/esm/tools/annotation/LabelTool.js +2 -1
  29. package/dist/esm/tools/annotation/LivewireContourTool.js +12 -1
  30. package/dist/esm/tools/annotation/RectangleROITool.js +2 -1
  31. package/dist/esm/tools/annotation/UltrasoundPleuraBLineTool/UltrasoundPleuraBLineTool.js +2 -1
  32. package/dist/esm/tools/annotation/WholeBodySegmentTool.js +3 -2
  33. package/dist/esm/tools/annotation/planarFreehandROITool/drawLoop.js +1 -1
  34. package/dist/esm/tools/base/AnnotationTool.js +6 -0
  35. package/dist/esm/tools/base/GrowCutBaseTool.js +3 -2
  36. package/dist/esm/tools/displayTools/Contour/contourDisplay.js +2 -1
  37. package/dist/esm/tools/displayTools/Contour/contourHandler/handleContourSegmentation.js +3 -2
  38. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/legacyVolumePlan.js +21 -9
  39. package/dist/esm/tools/displayTools/Labelmap/labelmapRenderPlan/planarGenericVolumeLabelmap.js +1 -1
  40. package/dist/esm/tools/displayTools/Labelmap/removeLabelmapRepresentationData.js +1 -1
  41. package/dist/esm/tools/displayTools/Labelmap/syncStackLabelmapActors.js +36 -0
  42. package/dist/esm/tools/segmentation/CircleScissorsTool.js +2 -1
  43. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +2 -1
  44. package/dist/esm/tools/segmentation/SegmentBidirectionalTool.js +2 -1
  45. package/dist/esm/tools/segmentation/strategies/fillRectangle.js +2 -1
  46. package/dist/esm/types/LabelmapTypes.d.ts +1 -1
  47. package/dist/esm/utilities/cine/playClip.js +28 -0
  48. package/dist/esm/utilities/genericViewportToolHelpers.d.ts +11 -0
  49. package/dist/esm/utilities/genericViewportToolHelpers.js +37 -0
  50. package/dist/esm/utilities/getVOIMultipliers.js +1 -3
  51. package/dist/esm/utilities/getViewportICamera.js +3 -2
  52. package/dist/esm/utilities/index.d.ts +2 -1
  53. package/dist/esm/utilities/index.js +2 -1
  54. package/dist/esm/utilities/math/polyline/getSubPixelSpacingAndXYDirections.js +7 -3
  55. package/dist/esm/utilities/planar/filterAnnotationsForDisplay.js +7 -2
  56. package/dist/esm/utilities/segmentation/getSegmentIndexAtWorldPoint.js +2 -1
  57. package/dist/esm/utilities/segmentation/growCut/runGrowCutForSphere.js +3 -2
  58. package/dist/esm/utilities/setViewportCamera.d.ts +3 -0
  59. package/dist/esm/utilities/setViewportCamera.js +58 -0
  60. package/dist/esm/utilities/stackPrefetch/stackPrefetchUtils.js +6 -2
  61. package/dist/esm/utilities/viewport/isViewportPreScaled.js +2 -13
  62. package/dist/esm/utilities/voi/colorbar/ViewportColorbar.js +17 -5
  63. package/dist/esm/utilities/voi/windowlevel/extractWindowLevelRegionToolData.d.ts +1 -1
  64. package/dist/esm/utilities/voi/windowlevel/extractWindowLevelRegionToolData.js +28 -1
  65. package/dist/esm/version.d.ts +1 -1
  66. package/dist/esm/version.js +1 -1
  67. package/package.json +4 -4
@@ -135,7 +135,7 @@ export function shouldUseSliceRendering(segmentation, options) {
135
135
  return false;
136
136
  }
137
137
  const layers = getLabelmaps(segmentation);
138
- return layers.length > 1 && layers.some((layer) => layer.type === 'stack');
138
+ return (layers.length > 1 && layers.some((layer) => layer.storageKind === 'stack'));
139
139
  }
140
140
  export function canRenderVolumeViewportLabelmapAsImage(viewport) {
141
141
  const isLegacyVolumeViewport = viewport instanceof VolumeViewport;
@@ -16,7 +16,7 @@ function getPrimaryLabelmapType(labelmapData) {
16
16
  function createPrimaryLabelmapLayer(segmentation, labelmapData, labelmapId = getPrimaryLabelmapId(segmentation.segmentationId)) {
17
17
  const layer = {
18
18
  labelmapId,
19
- type: getPrimaryLabelmapType(labelmapData),
19
+ storageKind: getPrimaryLabelmapType(labelmapData),
20
20
  labelToSegmentIndex: {},
21
21
  };
22
22
  if (labelmapData.volumeId != null) {
@@ -13,7 +13,7 @@ function createPrivateVolumeLabelmap(segmentation, sourceLabelmap) {
13
13
  });
14
14
  return {
15
15
  labelmapId: volumeId,
16
- type: 'volume',
16
+ storageKind: 'volume',
17
17
  volumeId,
18
18
  imageIds: volume.imageIds,
19
19
  referencedVolumeId,
@@ -36,7 +36,7 @@ function createPrivateStackLabelmap(segmentation, sourceLabelmap) {
36
36
  });
37
37
  return {
38
38
  labelmapId: `${segmentation.segmentationId}-storage-${csUtils.uuidv4()}`,
39
- type: 'stack',
39
+ storageKind: 'stack',
40
40
  imageIds: images.map((image) => image.imageId),
41
41
  referencedVolumeId: sourceLabelmap.referencedVolumeId,
42
42
  referencedImageIds,
@@ -1,5 +1,6 @@
1
1
  import { vec3 } from 'gl-matrix';
2
2
  import { getEnabledElementByViewportId } from '@cornerstonejs/core';
3
+ import getViewportICamera from '../../../utilities/getViewportICamera';
3
4
  import { getViewportIdsWithSegmentation } from '../getViewportIdsWithSegmentation';
4
5
  export function getViewportsAssociatedToSegmentation(segmentationId) {
5
6
  const viewportIds = getViewportIdsWithSegmentation(segmentationId);
@@ -27,7 +28,7 @@ export function getViewportWithMatchingViewPlaneNormal(viewports, annotation, do
27
28
  const normalizedAnnotationNormal = vec3.create();
28
29
  vec3.normalize(normalizedAnnotationNormal, annotationViewPlaneNormal);
29
30
  for (const viewport of viewports) {
30
- const camera = viewport.getCamera();
31
+ const camera = getViewportICamera(viewport);
31
32
  if (!camera?.viewPlaneNormal) {
32
33
  continue;
33
34
  }
@@ -1,4 +1,9 @@
1
- import { getRenderingEngine } from '@cornerstonejs/core';
1
+ import { getRenderingEngine, utilities } from '@cornerstonejs/core';
2
+ import { applyViewportPresentation, getViewportPresentation, } from '../../utilities/viewportPresentation';
3
+ const ZOOM_PAN_SELECTOR = {
4
+ pan: true,
5
+ zoom: true,
6
+ };
2
7
  export default function cameraSyncCallback(synchronizerInstance, sourceViewport, targetViewport, cameraModifiedEvent) {
3
8
  const { camera } = cameraModifiedEvent.detail;
4
9
  const renderingEngine = getRenderingEngine(targetViewport.renderingEngineId);
@@ -6,6 +11,18 @@ export default function cameraSyncCallback(synchronizerInstance, sourceViewport,
6
11
  throw new Error(`No RenderingEngine for Id: ${targetViewport.renderingEngineId}`);
7
12
  }
8
13
  const tViewport = renderingEngine.getViewport(targetViewport.viewportId);
9
- tViewport.setCamera(camera);
14
+ if (utilities.isGenericViewport(tViewport)) {
15
+ const sourceRenderingEngine = getRenderingEngine(sourceViewport.renderingEngineId);
16
+ const sViewport = sourceRenderingEngine?.getViewport(sourceViewport.viewportId);
17
+ if (!sViewport) {
18
+ return;
19
+ }
20
+ tViewport.setViewReference(sViewport.getViewReference());
21
+ const zoomPanPresentation = getViewportPresentation(sViewport, ZOOM_PAN_SELECTOR);
22
+ applyViewportPresentation(tViewport, zoomPanPresentation);
23
+ }
24
+ else {
25
+ tViewport.setCamera(camera);
26
+ }
10
27
  tViewport.render();
11
28
  }
@@ -6,6 +6,9 @@ function isVolumeSliceViewport(viewport) {
6
6
  if (viewport instanceof VolumeViewport) {
7
7
  return true;
8
8
  }
9
+ if (utilities.viewportIsInVolumeMode(viewport)) {
10
+ return true;
11
+ }
9
12
  const getDefaultActor = viewport.getDefaultActor;
10
13
  const renderMode = getDefaultActor?.call(viewport)?.actorMapper?.renderMode;
11
14
  return (renderMode === ActorRenderMode.CPU_VOLUME ||
@@ -1,4 +1,4 @@
1
- import { BaseVolumeViewport, getRenderingEngine, StackViewport, } from '@cornerstonejs/core';
1
+ import { BaseVolumeViewport, getRenderingEngine, StackViewport, utilities, } from '@cornerstonejs/core';
2
2
  export default function voiSyncCallback(synchronizerInstance, sourceViewport, targetViewport, modifiedEvent, options) {
3
3
  const eventDetail = modifiedEvent.detail;
4
4
  const { volumeId, range, invertStateChanged, invert, colormap } = eventDetail;
@@ -28,6 +28,18 @@ export default function voiSyncCallback(synchronizerInstance, sourceViewport, ta
28
28
  else if (tViewport instanceof StackViewport) {
29
29
  tViewport.setProperties(tProperties);
30
30
  }
31
+ else if (utilities.isGenericViewport(tViewport)) {
32
+ const genericViewport = tViewport;
33
+ const dataId = volumeId
34
+ ? genericViewport.findDataIdByVolumeId?.(volumeId)
35
+ : undefined;
36
+ if (dataId) {
37
+ genericViewport.setDisplaySetPresentation(dataId, tProperties);
38
+ }
39
+ else if (!volumeId) {
40
+ genericViewport.setDisplaySetPresentation(tProperties);
41
+ }
42
+ }
31
43
  else {
32
44
  throw new Error('Viewport type not supported.');
33
45
  }
@@ -10,6 +10,8 @@ import { Events, MouseBindings, KeyboardBindings, Events as cstEvents, Segmentat
10
10
  import { getViewportIdsWithToolToRender } from '../utilities/viewportFilters';
11
11
  import { resetElementCursor, hideElementCursor, } from '../cursors/elementCursor';
12
12
  import triggerAnnotationRenderForViewportIds from '../utilities/triggerAnnotationRenderForViewportIds';
13
+ import getViewportICamera from '../utilities/getViewportICamera';
14
+ import { getNativeSourceProperties } from '../utilities/genericViewportToolHelpers';
13
15
  import { getCanvasCircleRadius } from '../utilities/math/circle';
14
16
  import { vec2, vec3 } from 'gl-matrix';
15
17
  import { getToolGroupForViewport } from '../store/ToolGroupManager';
@@ -64,9 +66,13 @@ class AdvancedMagnifyTool extends AnnotationTool {
64
66
  const { magnifyingGlass: config } = this.configuration;
65
67
  const { radius, zoomFactor, autoPan } = config;
66
68
  const worldHandlePoints = this._getWorldHandlePoints(viewport, canvasPos, radius);
67
- const camera = viewport.getCamera();
68
- const { viewPlaneNormal, viewUp } = camera;
69
- const referencedImageId = this.getReferencedImageId(viewport, worldPos, viewPlaneNormal, viewUp);
69
+ const isNativeSource = csUtils.isGenericViewport(viewport);
70
+ const { viewPlaneNormal, viewUp } = isNativeSource
71
+ ? getViewportICamera(viewport)
72
+ : viewport.getCamera();
73
+ const referencedImageId = isNativeSource
74
+ ? getNativeSourceProperties(viewport).currentImageId
75
+ : this.getReferencedImageId(viewport, worldPos, viewPlaneNormal, viewUp);
70
76
  const annotationUID = csUtils.uuidv4();
71
77
  const magnifyViewportId = csUtils.uuidv4();
72
78
  const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
@@ -500,7 +506,9 @@ class AdvancedMagnifyViewportManager {
500
506
  const { renderingEngineId, viewportId: sourceViewportId } = evt.detail;
501
507
  const renderingEngine = getRenderingEngine(renderingEngineId);
502
508
  const sourceViewport = renderingEngine.getViewport(sourceViewportId);
503
- const { viewPlaneNormal: currentViewPlaneNormal } = sourceViewport.getCamera();
509
+ const { viewPlaneNormal: currentViewPlaneNormal } = csUtils.isGenericViewport(sourceViewport)
510
+ ? getViewportICamera(sourceViewport)
511
+ : sourceViewport.getCamera();
504
512
  const magnifyViewportsMapEntries = this._getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId);
505
513
  magnifyViewportsMapEntries.forEach(({ annotation }) => {
506
514
  const { viewPlaneNormal } = annotation.metadata;
@@ -728,6 +736,17 @@ class AdvancedMagnifyViewport {
728
736
  return magnifyElement;
729
737
  }
730
738
  _convertZoomFactorToParallelScale(viewport, magnifyViewport, zoomFactor) {
739
+ if (csUtils.isGenericViewport(viewport)) {
740
+ const sourceElement = viewport.element;
741
+ const sourceWidth = sourceElement.clientWidth;
742
+ const sourceHeight = sourceElement.clientHeight;
743
+ const worldTop = viewport.canvasToWorld([0, 0]);
744
+ const worldBottom = viewport.canvasToWorld([0, 1]);
745
+ const worldPerPixel = vec3.distance(worldTop, worldBottom);
746
+ const parallelScaleSource = (worldPerPixel * sourceHeight) / 2;
747
+ const canvasRatio = magnifyViewport.canvas.offsetWidth / sourceWidth;
748
+ return parallelScaleSource * (1 / zoomFactor) * canvasRatio;
749
+ }
731
750
  const { parallelScale } = viewport.getCamera();
732
751
  const canvasRatio = magnifyViewport.canvas.offsetWidth / viewport.canvas.offsetWidth;
733
752
  return parallelScale * (1 / zoomFactor) * canvasRatio;
@@ -781,15 +800,16 @@ class AdvancedMagnifyViewport {
781
800
  const { viewportId: magnifyViewportId } = this;
782
801
  const renderingEngine = sourceViewport.getRenderingEngine();
783
802
  const { options: sourceViewportOptions } = sourceViewport;
803
+ const isNativeSource = csUtils.isGenericViewport(sourceViewport);
784
804
  const viewportInput = {
785
805
  element: magnifyElement,
786
806
  viewportId: magnifyViewportId,
787
- type: sourceViewport.type,
788
- defaultOptions: { ...sourceViewportOptions },
807
+ type: isNativeSource ? Enums.ViewportType.STACK : sourceViewport.type,
808
+ defaultOptions: isNativeSource ? {} : { ...sourceViewportOptions },
789
809
  };
790
810
  renderingEngine.enableElement(viewportInput);
791
811
  const magnifyViewport = (renderingEngine.getViewport(magnifyViewportId));
792
- if (this._isStackViewport(sourceViewport)) {
812
+ if (isNativeSource || this._isStackViewport(sourceViewport)) {
793
813
  this._cloneStack(sourceViewport, magnifyViewport);
794
814
  }
795
815
  else if (this._isVolumeViewport(sourceViewport)) {
@@ -902,7 +922,10 @@ class AdvancedMagnifyViewport {
902
922
  _syncViewportsCameras(sourceViewport, magnifyViewport) {
903
923
  const worldPos = sourceViewport.canvasToWorld(this.position);
904
924
  const parallelScale = this._convertZoomFactorToParallelScale(sourceViewport, magnifyViewport, this.zoomFactor);
905
- const { flipHorizontal, flipVertical } = sourceViewport.getCamera();
925
+ const native = csUtils.isGenericViewport(sourceViewport)
926
+ ? getNativeSourceProperties(sourceViewport)
927
+ : undefined;
928
+ const { flipHorizontal, flipVertical } = native ?? sourceViewport.getCamera();
906
929
  const { focalPoint, position, viewPlaneNormal } = magnifyViewport.getCamera();
907
930
  const distance = Math.sqrt(Math.pow(focalPoint[0] - position[0], 2) +
908
931
  Math.pow(focalPoint[1] - position[1], 2) +
@@ -931,14 +954,17 @@ class AdvancedMagnifyViewport {
931
954
  _syncViewports() {
932
955
  const { viewport: sourceViewport } = this._sourceEnabledElement;
933
956
  const { viewport: magnifyViewport } = this._enabledElement;
934
- const sourceProperties = sourceViewport.getProperties();
957
+ const isNativeSource = csUtils.isGenericViewport(sourceViewport);
958
+ const sourceProperties = isNativeSource
959
+ ? getNativeSourceProperties(sourceViewport).properties
960
+ : sourceViewport.getProperties();
935
961
  const imageData = magnifyViewport.getImageData();
936
962
  if (!imageData) {
937
963
  return;
938
964
  }
939
965
  magnifyViewport.setProperties(sourceProperties);
940
966
  this._syncViewportsCameras(sourceViewport, magnifyViewport);
941
- if (this._isStackViewport(sourceViewport)) {
967
+ if (isNativeSource || this._isStackViewport(sourceViewport)) {
942
968
  this._syncStackViewports(sourceViewport, magnifyViewport);
943
969
  }
944
970
  this._syncViewportsCameras(sourceViewport, magnifyViewport);
@@ -10,12 +10,25 @@ import { drawCircle as drawCircleSvg, drawHandles as drawHandlesSvg, drawLine as
10
10
  import { state } from '../store/state';
11
11
  import { Events } from '../enums';
12
12
  import { getViewportIdsWithToolToRender } from '../utilities/viewportFilters';
13
+ import getViewportICamera from '../utilities/getViewportICamera';
13
14
  import { resetElementCursor, hideElementCursor, } from '../cursors/elementCursor';
14
15
  import liangBarksyClip from '../utilities/math/vec2/liangBarksyClip';
16
+ import { getSlabThicknessOrDefault, jumpToFocalPoint, } from '../utilities/genericViewportToolHelpers';
15
17
  import * as lineSegment from '../utilities/math/line';
16
18
  import { isAnnotationLocked } from '../stateManagement/annotation/annotationLocking';
17
19
  import triggerAnnotationRenderForViewportIds from '../utilities/triggerAnnotationRenderForViewportIds';
18
20
  const { RENDERING_DEFAULTS } = CONSTANTS;
21
+ function getDisplayedCanvasSize(viewport) {
22
+ if (csUtils.isGenericViewport(viewport)) {
23
+ const { element } = viewport;
24
+ return {
25
+ clientWidth: element.clientWidth,
26
+ clientHeight: element.clientHeight,
27
+ };
28
+ }
29
+ const { clientWidth, clientHeight } = viewport.canvas;
30
+ return { clientWidth, clientHeight };
31
+ }
19
32
  function defaultReferenceLineColor() {
20
33
  return 'rgb(0, 200, 0)';
21
34
  }
@@ -84,7 +97,7 @@ class CrosshairsTool extends AnnotationTool {
84
97
  }
85
98
  const { FrameOfReferenceUID, viewport } = enabledElement;
86
99
  const { element } = viewport;
87
- const { position, focalPoint, viewPlaneNormal } = viewport.getCamera();
100
+ const { position, focalPoint, viewPlaneNormal } = getViewportICamera(viewport);
88
101
  let annotations = this._getAnnotations(enabledElement);
89
102
  annotations = this.filterInteractableAnnotationsForElement(element, annotations);
90
103
  if (annotations?.length) {
@@ -110,12 +123,10 @@ class CrosshairsTool extends AnnotationTool {
110
123
  },
111
124
  };
112
125
  addAnnotation(annotation, element);
126
+ const { clientWidth, clientHeight } = getDisplayedCanvasSize(viewport);
113
127
  return {
114
128
  normal: viewPlaneNormal,
115
- point: viewport.canvasToWorld([
116
- viewport.canvas.clientWidth / 2,
117
- viewport.canvas.clientHeight / 2,
118
- ]),
129
+ point: viewport.canvasToWorld([clientWidth / 2, clientHeight / 2]),
119
130
  };
120
131
  };
121
132
  this._getViewportsInfo = () => {
@@ -143,14 +154,24 @@ class CrosshairsTool extends AnnotationTool {
143
154
  const resetToCenter = true;
144
155
  const resetRotation = true;
145
156
  const suppressEvents = true;
146
- viewport.resetCamera({
147
- resetPan,
148
- resetZoom,
149
- resetToCenter,
150
- resetRotation,
151
- suppressEvents,
152
- });
153
- viewport.resetSlabThickness();
157
+ if (csUtils.isGenericViewport(viewport)) {
158
+ viewport.resetViewState({
159
+ resetPan,
160
+ resetZoom,
161
+ resetOrientation: resetRotation,
162
+ resetFlip: true,
163
+ });
164
+ }
165
+ else {
166
+ viewport.resetCamera({
167
+ resetPan,
168
+ resetZoom,
169
+ resetToCenter,
170
+ resetRotation,
171
+ suppressEvents,
172
+ });
173
+ viewport.resetSlabThickness();
174
+ }
154
175
  const { element } = viewport;
155
176
  let annotations = this._getAnnotations(enabledElement);
156
177
  annotations = this.filterInteractableAnnotationsForElement(element, annotations);
@@ -258,7 +279,7 @@ class CrosshairsTool extends AnnotationTool {
258
279
  const annotations = this._getAnnotations(enabledElement);
259
280
  const filteredToolAnnotations = this.filterInteractableAnnotationsForElement(element, annotations);
260
281
  const viewportAnnotation = filteredToolAnnotations[0];
261
- const currentCamera = viewport.getCamera();
282
+ const currentCamera = getViewportICamera(viewport);
262
283
  if (viewportAnnotation) {
263
284
  viewportAnnotation.metadata.cameraPosition = [...currentCamera.position];
264
285
  viewportAnnotation.metadata.cameraFocalPoint = [
@@ -339,14 +360,14 @@ class CrosshairsTool extends AnnotationTool {
339
360
  const { viewport, renderingEngine } = enabledElement;
340
361
  const { element } = viewport;
341
362
  const annotations = this._getAnnotations(enabledElement);
342
- const camera = viewport.getCamera();
363
+ const camera = getViewportICamera(viewport);
343
364
  const filteredToolAnnotations = this.filterInteractableAnnotationsForElement(element, annotations);
344
365
  const viewportAnnotation = filteredToolAnnotations[0];
345
366
  if (!annotations?.length || !viewportAnnotation?.data) {
346
367
  return renderStatus;
347
368
  }
348
369
  const annotationUID = viewportAnnotation.annotationUID;
349
- const { clientWidth, clientHeight } = viewport.canvas;
370
+ const { clientWidth, clientHeight } = getDisplayedCanvasSize(viewport);
350
371
  const canvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
351
372
  const canvasMinDimensionLength = Math.min(clientWidth, clientHeight);
352
373
  const data = viewportAnnotation.data;
@@ -358,11 +379,11 @@ class CrosshairsTool extends AnnotationTool {
358
379
  const { data } = annotation;
359
380
  data.handles.toolCenter = this.toolCenter;
360
381
  const otherViewport = renderingEngine.getViewport(data.viewportId);
361
- const otherCamera = otherViewport.getCamera();
382
+ const otherCamera = getViewportICamera(otherViewport);
362
383
  const otherViewportControllable = this._getReferenceLineControllable(otherViewport.id);
363
384
  const otherViewportDraggableRotatable = this._getReferenceLineDraggableRotatable(otherViewport.id);
364
385
  const otherViewportSlabThicknessControlsOn = this._getReferenceLineSlabThicknessControlsOn(otherViewport.id);
365
- const { clientWidth, clientHeight } = otherViewport.canvas;
386
+ const { clientWidth, clientHeight } = getDisplayedCanvasSize(otherViewport);
366
387
  const otherCanvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
367
388
  const otherCanvasCenter = [
368
389
  clientWidth * 0.5,
@@ -442,7 +463,7 @@ class CrosshairsTool extends AnnotationTool {
442
463
  .rotate(90, viewPlaneNormal);
443
464
  const worldUnitOrthoVectorFromCenter = [0, 0, 0];
444
465
  vec3.transformMat4(worldUnitOrthoVectorFromCenter, worldUnitVectorFromCenter, matrix);
445
- const slabThicknessValue = otherViewport.getSlabThickness();
466
+ const slabThicknessValue = getSlabThicknessOrDefault(otherViewport);
446
467
  const worldOrthoVectorFromCenter = [
447
468
  ...worldUnitOrthoVectorFromCenter,
448
469
  ];
@@ -665,7 +686,7 @@ class CrosshairsTool extends AnnotationTool {
665
686
  type: 'rect',
666
687
  });
667
688
  }
668
- const slabThicknessValue = otherViewport.getSlabThickness();
689
+ const slabThicknessValue = getSlabThicknessOrDefault(otherViewport);
669
690
  if (slabThicknessValue > 0.5 && viewportSlabThicknessControlsOn) {
670
691
  lineUID = `${lineIndex}STOne`;
671
692
  drawLineSvg(svgDrawingHelper, annotationUID, lineUID, line[5], line[6], {
@@ -752,12 +773,12 @@ class CrosshairsTool extends AnnotationTool {
752
773
  if (!otherViewportAnnotations || !otherViewportAnnotations.length) {
753
774
  return [];
754
775
  }
755
- const camera = viewport.getCamera();
776
+ const camera = getViewportICamera(viewport);
756
777
  const { viewPlaneNormal, position } = camera;
757
778
  const viewportsWithDifferentCameras = otherViewportAnnotations.filter((annotation) => {
758
779
  const { viewportId } = annotation.data;
759
780
  const targetViewport = renderingEngine.getViewport(viewportId);
760
- const cameraOfTarget = targetViewport.getCamera();
781
+ const cameraOfTarget = getViewportICamera(targetViewport);
761
782
  return !(csUtils.isEqual(cameraOfTarget.viewPlaneNormal, viewPlaneNormal, 1e-2) && csUtils.isEqual(cameraOfTarget.position, position, 1));
762
783
  });
763
784
  return viewportsWithDifferentCameras;
@@ -775,13 +796,13 @@ class CrosshairsTool extends AnnotationTool {
775
796
  if (!linkedViewportAnnotations || !linkedViewportAnnotations.length) {
776
797
  return [];
777
798
  }
778
- const camera = viewport.getCamera();
799
+ const camera = getViewportICamera(viewport);
779
800
  const viewPlaneNormal = camera.viewPlaneNormal;
780
801
  vtkMath.normalize(viewPlaneNormal);
781
802
  const otherViewportsAnnotationsWithSameCameraDirection = linkedViewportAnnotations.filter((annotation) => {
782
803
  const { viewportId } = annotation.data;
783
804
  const otherViewport = renderingEngine.getViewport(viewportId);
784
- const otherCamera = otherViewport.getCamera();
805
+ const otherCamera = getViewportICamera(otherViewport);
785
806
  const otherViewPlaneNormal = otherCamera.viewPlaneNormal;
786
807
  vtkMath.normalize(otherViewPlaneNormal);
787
808
  return (csUtils.isEqual(viewPlaneNormal, otherViewPlaneNormal, 1e-2) &&
@@ -791,7 +812,7 @@ class CrosshairsTool extends AnnotationTool {
791
812
  };
792
813
  this._filterAnnotationsByUniqueViewportOrientations = (enabledElement, annotations) => {
793
814
  const { renderingEngine, viewport } = enabledElement;
794
- const camera = viewport.getCamera();
815
+ const camera = getViewportICamera(viewport);
795
816
  const viewPlaneNormal = camera.viewPlaneNormal;
796
817
  vtkMath.normalize(viewPlaneNormal);
797
818
  const otherLinkedViewportAnnotationsFromSameScene = annotations.filter((annotation) => {
@@ -806,7 +827,7 @@ class CrosshairsTool extends AnnotationTool {
806
827
  const annotation = otherLinkedViewportAnnotationsFromSameScene[i];
807
828
  const { viewportId } = annotation.data;
808
829
  const otherViewport = renderingEngine.getViewport(viewportId);
809
- const otherCamera = otherViewport.getCamera();
830
+ const otherCamera = getViewportICamera(otherViewport);
810
831
  const otherViewPlaneNormal = otherCamera.viewPlaneNormal;
811
832
  vtkMath.normalize(otherViewPlaneNormal);
812
833
  if (csUtils.isEqual(viewPlaneNormal, otherViewPlaneNormal, 1e-2) ||
@@ -818,7 +839,7 @@ class CrosshairsTool extends AnnotationTool {
818
839
  const annotation = otherViewportsAnnotationsWithUniqueCameras[jj];
819
840
  const { viewportId } = annotation.data;
820
841
  const stockedViewport = renderingEngine.getViewport(viewportId);
821
- const cameraOfStocked = stockedViewport.getCamera();
842
+ const cameraOfStocked = getViewportICamera(stockedViewport);
822
843
  if (csUtils.isEqual(cameraOfStocked.viewPlaneNormal, otherCamera.viewPlaneNormal, 1e-2) &&
823
844
  csUtils.isEqual(cameraOfStocked.position, otherCamera.position, 1)) {
824
845
  cameraFound = true;
@@ -839,7 +860,7 @@ class CrosshairsTool extends AnnotationTool {
839
860
  const annotation = otherNonLinkedViewportAnnotationsFromSameScene[i];
840
861
  const { viewportId } = annotation.data;
841
862
  const otherViewport = renderingEngine.getViewport(viewportId);
842
- const otherCamera = otherViewport.getCamera();
863
+ const otherCamera = getViewportICamera(otherViewport);
843
864
  const otherViewPlaneNormal = otherCamera.viewPlaneNormal;
844
865
  vtkMath.normalize(otherViewPlaneNormal);
845
866
  if (csUtils.isEqual(viewPlaneNormal, otherViewPlaneNormal, 1e-2) ||
@@ -851,7 +872,7 @@ class CrosshairsTool extends AnnotationTool {
851
872
  const annotation = otherViewportsAnnotationsWithUniqueCameras[jj];
852
873
  const { viewportId } = annotation.data;
853
874
  const stockedViewport = renderingEngine.getViewport(viewportId);
854
- const cameraOfStocked = stockedViewport.getCamera();
875
+ const cameraOfStocked = getViewportICamera(stockedViewport);
855
876
  if (csUtils.isEqual(cameraOfStocked.viewPlaneNormal, otherCamera.viewPlaneNormal, 1e-2) &&
856
877
  csUtils.isEqual(cameraOfStocked.position, otherCamera.position, 1)) {
857
878
  cameraFound = true;
@@ -869,7 +890,7 @@ class CrosshairsTool extends AnnotationTool {
869
890
  }
870
891
  const { viewportId } = annotation.data;
871
892
  const otherViewport = renderingEngine.getViewport(viewportId);
872
- const otherCamera = otherViewport.getCamera();
893
+ const otherCamera = getViewportICamera(otherViewport);
873
894
  const otherViewPlaneNormal = otherCamera.viewPlaneNormal;
874
895
  vtkMath.normalize(otherViewPlaneNormal);
875
896
  if (csUtils.isEqual(viewPlaneNormal, otherViewPlaneNormal, 1e-2) ||
@@ -881,7 +902,7 @@ class CrosshairsTool extends AnnotationTool {
881
902
  const annotation = otherViewportsAnnotationsWithUniqueCameras[jj];
882
903
  const { viewportId } = annotation.data;
883
904
  const stockedViewport = renderingEngine.getViewport(viewportId);
884
- const cameraOfStocked = stockedViewport.getCamera();
905
+ const cameraOfStocked = getViewportICamera(stockedViewport);
885
906
  if (csUtils.isEqual(cameraOfStocked.viewPlaneNormal, otherCamera.viewPlaneNormal, 1e-2) &&
886
907
  csUtils.isEqual(cameraOfStocked.position, otherCamera.position, 1)) {
887
908
  cameraFound = true;
@@ -894,6 +915,14 @@ class CrosshairsTool extends AnnotationTool {
894
915
  return otherViewportsAnnotationsWithUniqueCameras;
895
916
  };
896
917
  this._checkIfViewportsRenderingSameScene = (viewport, otherViewport) => {
918
+ if (csUtils.isGenericViewport(viewport) ||
919
+ csUtils.isGenericViewport(otherViewport)) {
920
+ const ref = viewport.getViewReference?.();
921
+ const otherRef = otherViewport.getViewReference?.();
922
+ const a = ref?.dataId ?? ref?.FrameOfReferenceUID;
923
+ const b = otherRef?.dataId ?? otherRef?.FrameOfReferenceUID;
924
+ return !!a && a === b;
925
+ }
897
926
  const volumeIds = viewport.getAllVolumeIds();
898
927
  const otherVolumeIds = otherViewport.getAllVolumeIds();
899
928
  return (volumeIds.length === otherVolumeIds.length &&
@@ -1006,6 +1035,9 @@ class CrosshairsTool extends AnnotationTool {
1006
1035
  });
1007
1036
  }
1008
1037
  else if (handles.activeOperation === OPERATION.ROTATE) {
1038
+ if (csUtils.isGenericViewport(enabledElement.viewport)) {
1039
+ return;
1040
+ }
1009
1041
  const otherViewportAnnotations = this._getAnnotationsForViewportsWithDifferentCameras(enabledElement, annotations);
1010
1042
  const viewportsAnnotationsToUpdate = otherViewportAnnotations.filter((annotation) => {
1011
1043
  const { data } = annotation;
@@ -1033,7 +1065,7 @@ class CrosshairsTool extends AnnotationTool {
1033
1065
  angle *= -1;
1034
1066
  }
1035
1067
  angle = Math.round(angle * 100) / 100;
1036
- const rotationAxis = viewport.getCamera().viewPlaneNormal;
1068
+ const rotationAxis = getViewportICamera(viewport).viewPlaneNormal;
1037
1069
  const { matrix } = vtkMatrixBuilder
1038
1070
  .buildFromRadian()
1039
1071
  .translate(center[0], center[1], center[2])
@@ -1047,7 +1079,7 @@ class CrosshairsTool extends AnnotationTool {
1047
1079
  const { data } = annotation;
1048
1080
  data.handles.toolCenter = center;
1049
1081
  const otherViewport = renderingEngine.getViewport(data.viewportId);
1050
- const camera = otherViewport.getCamera();
1082
+ const camera = getViewportICamera(otherViewport);
1051
1083
  const { viewUp, position, focalPoint } = camera;
1052
1084
  viewUp[0] += position[0];
1053
1085
  viewUp[1] += position[1];
@@ -1076,6 +1108,9 @@ class CrosshairsTool extends AnnotationTool {
1076
1108
  });
1077
1109
  }
1078
1110
  else if (handles.activeOperation === OPERATION.SLAB) {
1111
+ if (csUtils.isGenericViewport(enabledElement.viewport)) {
1112
+ return;
1113
+ }
1079
1114
  const otherViewportAnnotations = this._getAnnotationsForViewportsWithDifferentCameras(enabledElement, annotations);
1080
1115
  const referenceAnnotations = otherViewportAnnotations.filter((annotation) => {
1081
1116
  const { data } = annotation;
@@ -1095,7 +1130,7 @@ class CrosshairsTool extends AnnotationTool {
1095
1130
  viewportsAnnotationsToUpdate.forEach((annotation) => {
1096
1131
  const { data } = annotation;
1097
1132
  const otherViewport = renderingEngine.getViewport(data.viewportId);
1098
- const camera = otherViewport.getCamera();
1133
+ const camera = getViewportICamera(otherViewport);
1099
1134
  const normal = camera.viewPlaneNormal;
1100
1135
  const dotProd = vtkMath.dot(delta, normal);
1101
1136
  const projectedDelta = [...normal];
@@ -1140,7 +1175,7 @@ class CrosshairsTool extends AnnotationTool {
1140
1175
  projectedDelta[2],
1141
1176
  ];
1142
1177
  vec3.normalize(normalizedProjectedDelta, normalizedProjectedDelta);
1143
- let slabThicknessValue = otherViewport.getSlabThickness();
1178
+ let slabThicknessValue = getSlabThicknessOrDefault(otherViewport);
1144
1179
  if (csUtils.isOpposite(normalizedProjectedDirection, normalizedProjectedDelta, 1e-3)) {
1145
1180
  slabThicknessValue -= mod;
1146
1181
  }
@@ -1310,7 +1345,7 @@ class CrosshairsTool extends AnnotationTool {
1310
1345
  if (!enabledElement) {
1311
1346
  return;
1312
1347
  }
1313
- const camera = enabledElement.viewport.getCamera();
1348
+ const camera = getViewportICamera(enabledElement.viewport);
1314
1349
  const normal = [...camera.viewPlaneNormal];
1315
1350
  const point = [...camera.focalPoint];
1316
1351
  if (!this._isFinitePoint3(normal) || !this._isFinitePoint3(point)) {
@@ -1430,7 +1465,7 @@ class CrosshairsTool extends AnnotationTool {
1430
1465
  if (!viewport) {
1431
1466
  return;
1432
1467
  }
1433
- const camera = viewport.getCamera();
1468
+ const camera = getViewportICamera(viewport);
1434
1469
  const { focalPoint, position, viewPlaneNormal } = camera;
1435
1470
  const delta = [
1436
1471
  toolCenter[0] - focalPoint[0],
@@ -1455,10 +1490,15 @@ class CrosshairsTool extends AnnotationTool {
1455
1490
  position[1] + scrollDelta[1],
1456
1491
  position[2] + scrollDelta[2],
1457
1492
  ];
1458
- viewport.setCamera({
1459
- focalPoint: newFocalPoint,
1460
- position: newPosition,
1461
- });
1493
+ if (csUtils.isGenericViewport(viewport)) {
1494
+ jumpToFocalPoint(viewport, newFocalPoint);
1495
+ }
1496
+ else {
1497
+ viewport.setCamera({
1498
+ focalPoint: newFocalPoint,
1499
+ position: newPosition,
1500
+ });
1501
+ }
1462
1502
  viewport.render();
1463
1503
  });
1464
1504
  }
@@ -1493,7 +1533,10 @@ class CrosshairsTool extends AnnotationTool {
1493
1533
  }
1494
1534
  _autoPanViewportIfNecessary(viewportId, renderingEngine) {
1495
1535
  const viewport = renderingEngine.getViewport(viewportId);
1496
- const { clientWidth, clientHeight } = viewport.canvas;
1536
+ if (csUtils.isGenericViewport(viewport)) {
1537
+ return;
1538
+ }
1539
+ const { clientWidth, clientHeight } = getDisplayedCanvasSize(viewport);
1497
1540
  const toolCenterCanvas = viewport.worldToCanvas(this.toolCenter);
1498
1541
  const pan = this.configuration.autoPan.panSize;
1499
1542
  const visiblePointCanvas = [
@@ -1522,7 +1565,7 @@ class CrosshairsTool extends AnnotationTool {
1522
1565
  visiblePointWorld[1] - this.toolCenter[1],
1523
1566
  visiblePointWorld[2] - this.toolCenter[2],
1524
1567
  ];
1525
- const camera = viewport.getCamera();
1568
+ const camera = getViewportICamera(viewport);
1526
1569
  const { focalPoint, position } = camera;
1527
1570
  const updatedPosition = [
1528
1571
  position[0] - deltaPointsWorld[0],
@@ -1548,6 +1591,9 @@ class CrosshairsTool extends AnnotationTool {
1548
1591
  viewport.render();
1549
1592
  }
1550
1593
  setSlabThickness(viewport, slabThickness) {
1594
+ if (csUtils.isGenericViewport(viewport)) {
1595
+ return;
1596
+ }
1551
1597
  let actorUIDs;
1552
1598
  const { filterActorUIDsToSetSlabThickness } = this.configuration;
1553
1599
  if (filterActorUIDsToSetSlabThickness &&
@@ -1573,7 +1619,7 @@ class CrosshairsTool extends AnnotationTool {
1573
1619
  _applyDeltaShiftToViewportCamera(renderingEngine, annotation, delta) {
1574
1620
  const { data } = annotation;
1575
1621
  const viewport = renderingEngine.getViewport(data.viewportId);
1576
- const camera = viewport.getCamera();
1622
+ const camera = getViewportICamera(viewport);
1577
1623
  const normal = camera.viewPlaneNormal;
1578
1624
  const dotProd = vtkMath.dot(delta, normal);
1579
1625
  const projectedDelta = [...normal];
@@ -1588,10 +1634,15 @@ class CrosshairsTool extends AnnotationTool {
1588
1634
  const previousIgnoreFiredEvents = this._ignoreFiredEvents;
1589
1635
  this._ignoreFiredEvents = true;
1590
1636
  try {
1591
- viewport.setCamera({
1592
- focalPoint: newFocalPoint,
1593
- position: newPosition,
1594
- });
1637
+ if (csUtils.isGenericViewport(viewport)) {
1638
+ jumpToFocalPoint(viewport, newFocalPoint);
1639
+ }
1640
+ else {
1641
+ viewport.setCamera({
1642
+ focalPoint: newFocalPoint,
1643
+ position: newPosition,
1644
+ });
1645
+ }
1595
1646
  }
1596
1647
  finally {
1597
1648
  this._ignoreFiredEvents = previousIgnoreFiredEvents;
@@ -1658,7 +1709,7 @@ class CrosshairsTool extends AnnotationTool {
1658
1709
  const minimalCrosshairConfig = getMinimalCrosshairConfig(this.configuration);
1659
1710
  const enabledElement = getEnabledElement(element);
1660
1711
  const { viewport } = enabledElement;
1661
- const { clientWidth, clientHeight } = viewport.canvas;
1712
+ const { clientWidth, clientHeight } = getDisplayedCanvasSize(viewport);
1662
1713
  const canvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
1663
1714
  const { data } = annotation;
1664
1715
  const { rotationPoints } = data.handles;
@@ -12,7 +12,7 @@ declare class MagnifyTool extends BaseTool {
12
12
  } | null;
13
13
  constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
14
14
  private _hasBeenRemoved;
15
- _getReferencedImageId(viewport: Types.IStackViewport | Types.IVolumeViewport): string;
15
+ _getReferencedImageId(viewport: Types.IViewport): string | undefined;
16
16
  preMouseDownCallback: (evt: EventTypes.InteractionEventType) => boolean;
17
17
  preTouchStartCallback: (evt: EventTypes.InteractionEventType) => void;
18
18
  _createMagnificationViewport: () => void;