@cornerstonejs/core 1.69.0 → 1.70.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 (115) hide show
  1. package/dist/cjs/RenderingEngine/BaseVolumeViewport.d.ts +3 -3
  2. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +36 -17
  3. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  4. package/dist/cjs/RenderingEngine/CanvasActor/index.js +1 -1
  5. package/dist/cjs/RenderingEngine/CanvasActor/index.js.map +1 -1
  6. package/dist/cjs/RenderingEngine/RenderingEngine.js +8 -26
  7. package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
  8. package/dist/cjs/RenderingEngine/StackViewport.d.ts +5 -4
  9. package/dist/cjs/RenderingEngine/StackViewport.js +46 -24
  10. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  11. package/dist/cjs/RenderingEngine/VideoViewport.d.ts +2 -2
  12. package/dist/cjs/RenderingEngine/VideoViewport.js +5 -9
  13. package/dist/cjs/RenderingEngine/VideoViewport.js.map +1 -1
  14. package/dist/cjs/RenderingEngine/Viewport.d.ts +17 -7
  15. package/dist/cjs/RenderingEngine/Viewport.js +173 -64
  16. package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
  17. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.d.ts +1 -0
  18. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.js +15 -2
  19. package/dist/cjs/RenderingEngine/helpers/getOrCreateCanvas.js.map +1 -1
  20. package/dist/cjs/cache/cache.js +0 -1
  21. package/dist/cjs/cache/cache.js.map +1 -1
  22. package/dist/cjs/loaders/volumeLoader.js +1 -1
  23. package/dist/cjs/loaders/volumeLoader.js.map +1 -1
  24. package/dist/cjs/types/IViewport.d.ts +18 -0
  25. package/dist/cjs/types/ViewportProperties.d.ts +1 -2
  26. package/dist/cjs/types/displayArea.d.ts +5 -1
  27. package/dist/cjs/types/index.d.ts +2 -2
  28. package/dist/cjs/utilities/index.d.ts +2 -1
  29. package/dist/cjs/utilities/index.js +3 -1
  30. package/dist/cjs/utilities/index.js.map +1 -1
  31. package/dist/cjs/utilities/loadImageToCanvas.d.ts +6 -2
  32. package/dist/cjs/utilities/loadImageToCanvas.js +14 -2
  33. package/dist/cjs/utilities/loadImageToCanvas.js.map +1 -1
  34. package/dist/cjs/utilities/renderToCanvasCPU.d.ts +2 -2
  35. package/dist/cjs/utilities/renderToCanvasCPU.js +1 -1
  36. package/dist/cjs/utilities/renderToCanvasCPU.js.map +1 -1
  37. package/dist/cjs/utilities/renderToCanvasGPU.d.ts +2 -2
  38. package/dist/cjs/utilities/renderToCanvasGPU.js +31 -12
  39. package/dist/cjs/utilities/renderToCanvasGPU.js.map +1 -1
  40. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +37 -18
  41. package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  42. package/dist/esm/RenderingEngine/CanvasActor/index.js +1 -1
  43. package/dist/esm/RenderingEngine/CanvasActor/index.js.map +1 -1
  44. package/dist/esm/RenderingEngine/RenderingEngine.js +8 -26
  45. package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
  46. package/dist/esm/RenderingEngine/StackViewport.js +47 -25
  47. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  48. package/dist/esm/RenderingEngine/VideoViewport.js +5 -9
  49. package/dist/esm/RenderingEngine/VideoViewport.js.map +1 -1
  50. package/dist/esm/RenderingEngine/Viewport.js +173 -64
  51. package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
  52. package/dist/esm/RenderingEngine/helpers/getOrCreateCanvas.js +14 -1
  53. package/dist/esm/RenderingEngine/helpers/getOrCreateCanvas.js.map +1 -1
  54. package/dist/esm/cache/cache.js +0 -1
  55. package/dist/esm/cache/cache.js.map +1 -1
  56. package/dist/esm/loaders/volumeLoader.js +1 -1
  57. package/dist/esm/loaders/volumeLoader.js.map +1 -1
  58. package/dist/esm/utilities/index.js +2 -1
  59. package/dist/esm/utilities/index.js.map +1 -1
  60. package/dist/esm/utilities/loadImageToCanvas.js +14 -2
  61. package/dist/esm/utilities/loadImageToCanvas.js.map +1 -1
  62. package/dist/esm/utilities/renderToCanvasCPU.js +1 -1
  63. package/dist/esm/utilities/renderToCanvasCPU.js.map +1 -1
  64. package/dist/esm/utilities/renderToCanvasGPU.js +8 -9
  65. package/dist/esm/utilities/renderToCanvasGPU.js.map +1 -1
  66. package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts +3 -3
  67. package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts.map +1 -1
  68. package/dist/types/RenderingEngine/CanvasActor/index.d.ts.map +1 -1
  69. package/dist/types/RenderingEngine/RenderingEngine.d.ts.map +1 -1
  70. package/dist/types/RenderingEngine/StackViewport.d.ts +5 -4
  71. package/dist/types/RenderingEngine/StackViewport.d.ts.map +1 -1
  72. package/dist/types/RenderingEngine/VideoViewport.d.ts +2 -2
  73. package/dist/types/RenderingEngine/VideoViewport.d.ts.map +1 -1
  74. package/dist/types/RenderingEngine/Viewport.d.ts +17 -7
  75. package/dist/types/RenderingEngine/Viewport.d.ts.map +1 -1
  76. package/dist/types/RenderingEngine/helpers/getOrCreateCanvas.d.ts +1 -0
  77. package/dist/types/RenderingEngine/helpers/getOrCreateCanvas.d.ts.map +1 -1
  78. package/dist/types/cache/cache.d.ts.map +1 -1
  79. package/dist/types/loaders/volumeLoader.d.ts.map +1 -1
  80. package/dist/types/types/IViewport.d.ts +18 -0
  81. package/dist/types/types/IViewport.d.ts.map +1 -1
  82. package/dist/types/types/ViewportProperties.d.ts +1 -2
  83. package/dist/types/types/ViewportProperties.d.ts.map +1 -1
  84. package/dist/types/types/displayArea.d.ts +5 -1
  85. package/dist/types/types/displayArea.d.ts.map +1 -1
  86. package/dist/types/types/index.d.ts +2 -2
  87. package/dist/types/types/index.d.ts.map +1 -1
  88. package/dist/types/utilities/index.d.ts +2 -1
  89. package/dist/types/utilities/index.d.ts.map +1 -1
  90. package/dist/types/utilities/loadImageToCanvas.d.ts +6 -2
  91. package/dist/types/utilities/loadImageToCanvas.d.ts.map +1 -1
  92. package/dist/types/utilities/renderToCanvasCPU.d.ts +2 -2
  93. package/dist/types/utilities/renderToCanvasCPU.d.ts.map +1 -1
  94. package/dist/types/utilities/renderToCanvasGPU.d.ts +2 -2
  95. package/dist/types/utilities/renderToCanvasGPU.d.ts.map +1 -1
  96. package/dist/umd/index.js +1 -1
  97. package/dist/umd/index.js.map +1 -1
  98. package/package.json +2 -2
  99. package/src/RenderingEngine/BaseVolumeViewport.ts +30 -6
  100. package/src/RenderingEngine/CanvasActor/index.ts +2 -1
  101. package/src/RenderingEngine/RenderingEngine.ts +11 -35
  102. package/src/RenderingEngine/StackViewport.ts +55 -14
  103. package/src/RenderingEngine/VideoViewport.ts +14 -9
  104. package/src/RenderingEngine/Viewport.ts +353 -91
  105. package/src/RenderingEngine/helpers/getOrCreateCanvas.ts +32 -1
  106. package/src/cache/cache.ts +2 -1
  107. package/src/loaders/volumeLoader.ts +2 -1
  108. package/src/types/IViewport.ts +130 -10
  109. package/src/types/ViewportProperties.ts +1 -3
  110. package/src/types/displayArea.ts +6 -1
  111. package/src/types/index.ts +4 -0
  112. package/src/utilities/index.ts +2 -0
  113. package/src/utilities/loadImageToCanvas.ts +38 -3
  114. package/src/utilities/renderToCanvasCPU.ts +7 -2
  115. package/src/utilities/renderToCanvasGPU.ts +20 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "1.69.0",
3
+ "version": "1.70.1",
4
4
  "description": "",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -47,5 +47,5 @@
47
47
  "type": "individual",
48
48
  "url": "https://ohif.org/donate"
49
49
  },
50
- "gitHead": "ac8dc9249f6c25fc8de8c1f716af606a9301dd54"
50
+ "gitHead": "374a9dd49081ea9f87c8af202ca07e2e10a63170"
51
51
  }
@@ -3,7 +3,7 @@ import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransf
3
3
  import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps';
4
4
  import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
5
5
 
6
- import { vec3 } from 'gl-matrix';
6
+ import { vec2, vec3 } from 'gl-matrix';
7
7
 
8
8
  import cache from '../cache';
9
9
  import {
@@ -399,7 +399,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
399
399
  return newRGBTransferFunction;
400
400
  }
401
401
 
402
- private setInterpolationType(
402
+ protected setInterpolationType(
403
403
  interpolationType: InterpolationType,
404
404
  volumeId?: string
405
405
  ) {
@@ -491,10 +491,34 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
491
491
  this.viewportProperties.voiRange = voiRangeToUse;
492
492
  }
493
493
 
494
- private setRotation(rotation: number): void {
494
+ protected setRotation = (rotation: number) => {
495
+ const panFit = this.getPan(this.fitToCanvasCamera);
496
+ const pan = this.getPan();
495
497
  const previousCamera = this.getCamera();
498
+ const panSub = vec2.sub([0, 0], panFit, pan) as Point2;
499
+ this.setPan(panSub, false);
500
+ const { flipVertical } = this.getCamera();
496
501
 
502
+ // Moving back to zero rotation, for new scrolled slice rotation is 0 after camera reset
503
+ const initialViewUp = flipVertical
504
+ ? vec3.negate([0, 0, 0], this.initialViewUp)
505
+ : this.initialViewUp;
506
+
507
+ this.setCameraNoEvent({
508
+ viewUp: initialViewUp as Point3,
509
+ });
510
+
511
+ // rotating camera to the new value
497
512
  this.rotateCamera(rotation);
513
+ const afterPan = this.getPan();
514
+ const afterPanFit = this.getPan(this.fitToCanvasCamera);
515
+ const newCenter = vec2.sub([0, 0], afterPan, afterPanFit);
516
+ const newOffset = vec2.add([0, 0], panFit, newCenter) as Point2;
517
+ this.setPan(newOffset, false);
518
+
519
+ if (this._suppressCameraModifiedEvents) {
520
+ return;
521
+ }
498
522
 
499
523
  // New camera after rotation
500
524
  const camera = this.getCamera();
@@ -510,7 +534,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
510
534
 
511
535
  triggerEvent(this.element, Events.CAMERA_MODIFIED, eventDetail);
512
536
  this.viewportProperties.rotation = rotation;
513
- }
537
+ };
514
538
 
515
539
  private rotateCamera(rotation: number): void {
516
540
  const rotationToApply = rotation - this.getRotation();
@@ -1148,7 +1172,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
1148
1172
 
1149
1173
  // The initial view up vector without any rotation, but incorporating vertical flip.
1150
1174
  const initialViewUp = flipVertical
1151
- ? vec3.negate(vec3.create(), this.initialViewUp)
1175
+ ? vec3.negate([0, 0, 0], this.initialViewUp)
1152
1176
  : this.initialViewUp;
1153
1177
 
1154
1178
  if (!initialViewUp) {
@@ -1165,7 +1189,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
1165
1189
  // viewPlaneNormal.
1166
1190
 
1167
1191
  const initialToCurrentViewUpCross = vec3.cross(
1168
- vec3.create(),
1192
+ [0, 0, 0],
1169
1193
  initialViewUp,
1170
1194
  currentViewUp
1171
1195
  );
@@ -209,7 +209,8 @@ export default class CanvasActor implements ICanvasActor {
209
209
  const imageData = this.viewport.getImageData();
210
210
  Object.assign(this.image, {
211
211
  worldToIndex: (worldPos) => imageData.imageData.worldToIndex(worldPos),
212
- indexToWorld: (index) => imageData.imageData.indexToWorld(index),
212
+ indexToWorld: (index, destPoint) =>
213
+ imageData.imageData.indexToWorld(index, destPoint),
213
214
  getDimensions: () => imageData.dimensions,
214
215
  getScalarData: () => this.derivedImage?.getPixelData(),
215
216
  getDirection: () => imageData.direction,
@@ -48,6 +48,7 @@ const VIEWPORT_MIN_SIZE = 2;
48
48
  * to leverage the power of vtk.js whilst only using one WebGL context for the processing, and allowing
49
49
  * us to share texture memory across on-screen viewports that show the same data.
50
50
  *
51
+ *
51
52
  * Instantiating a rendering engine:
52
53
  * ```js
53
54
  * const renderingEngine = new RenderingEngine('pet-ct-rendering-engine');
@@ -74,7 +75,7 @@ const VIEWPORT_MIN_SIZE = 2;
74
75
  class RenderingEngine implements IRenderingEngine {
75
76
  /** Unique identifier for renderingEngine */
76
77
  readonly id: string;
77
- /** A flag which tells if the renderingEngine has been destroyed */
78
+ /** A flag which tells if the renderingEngine has been destroyed or not */
78
79
  public hasBeenDestroyed: boolean;
79
80
  public offscreenMultiRenderWindow: any;
80
81
  readonly offScreenCanvasContainer: any; // WebGL
@@ -154,9 +155,7 @@ class RenderingEngine implements IRenderingEngine {
154
155
 
155
156
  // 1.a) If there is a found viewport, we remove the viewport and create a new viewport
156
157
  if (viewport) {
157
- console.log('Viewport already exists, disabling it first');
158
158
  this.disableElement(viewportId);
159
- console.log(`Viewport ${viewportId} disabled`);
160
159
  }
161
160
 
162
161
  // 2.a) See if viewport uses a custom rendering pipeline.
@@ -603,6 +602,10 @@ class RenderingEngine implements IRenderingEngine {
603
602
  keepCamera = true,
604
603
  immediate = true
605
604
  ) {
605
+ // Ensure all the canvases are ready for rendering
606
+ vtkDrivenViewports.forEach((vp: IStackViewport | IVolumeViewport) => {
607
+ getOrCreateCanvas(vp.element);
608
+ });
606
609
  const canvasesDrivenByVtkJs = vtkDrivenViewports.map((vp) => vp.canvas);
607
610
 
608
611
  if (canvasesDrivenByVtkJs.length) {
@@ -620,16 +623,8 @@ class RenderingEngine implements IRenderingEngine {
620
623
 
621
624
  // 3. Reset viewport cameras
622
625
  vtkDrivenViewports.forEach((vp: IStackViewport | IVolumeViewport) => {
623
- const canvas = getOrCreateCanvas(vp.element);
624
- const rect = canvas.getBoundingClientRect();
625
- const devicePixelRatio = window.devicePixelRatio || 1;
626
- canvas.width = rect.width * devicePixelRatio;
627
- canvas.height = rect.height * devicePixelRatio;
628
-
629
626
  const prevCamera = vp.getCamera();
630
627
  const rotation = vp.getRotation();
631
- const pan = vp.getPan();
632
- const zoom = vp.getZoom();
633
628
  const { flipHorizontal } = prevCamera;
634
629
  vp.resetCamera();
635
630
 
@@ -645,7 +640,6 @@ class RenderingEngine implements IRenderingEngine {
645
640
  if (rotation) {
646
641
  vp.setProperties({ rotation });
647
642
  }
648
- console.log('What to do with pan and zoom', pan[0], pan[1], zoom);
649
643
  } else {
650
644
  vp.setCamera(prevCamera);
651
645
  }
@@ -677,12 +671,6 @@ class RenderingEngine implements IRenderingEngine {
677
671
  const canvas = getOrCreateCanvas(viewportInputEntry.element);
678
672
  canvasesDrivenByVtkJs.push(canvas);
679
673
 
680
- const devicePixelRatio = window.devicePixelRatio || 1;
681
-
682
- const rect = canvas.getBoundingClientRect();
683
- canvas.width = rect.width * devicePixelRatio;
684
- canvas.height = rect.height * devicePixelRatio;
685
-
686
674
  // 2.c Calculating the new size for offScreen Canvas
687
675
  const { offScreenCanvasWidth, offScreenCanvasHeight } =
688
676
  this._resizeOffScreenCanvas(canvasesDrivenByVtkJs);
@@ -769,7 +757,6 @@ class RenderingEngine implements IRenderingEngine {
769
757
  offScreenCanvasHeight,
770
758
  xOffset
771
759
  );
772
-
773
760
  // 2. Add a renderer to the offScreenMultiRenderWindow
774
761
  this.offscreenMultiRenderWindow.addRenderer({
775
762
  viewport: [
@@ -966,21 +953,17 @@ class RenderingEngine implements IRenderingEngine {
966
953
  ): { offScreenCanvasWidth: number; offScreenCanvasHeight: number } {
967
954
  const { offScreenCanvasContainer, offscreenMultiRenderWindow } = this;
968
955
 
969
- const devicePixelRatio = window.devicePixelRatio || 1;
970
-
971
956
  // 1. Calculated the height of the offScreen canvas to be the maximum height
972
957
  // between canvases
973
958
  const offScreenCanvasHeight = Math.max(
974
- ...canvasesDrivenByVtkJs.map(
975
- (canvas) => canvas.clientHeight * devicePixelRatio
976
- )
959
+ ...canvasesDrivenByVtkJs.map((canvas) => canvas.height)
977
960
  );
978
961
 
979
962
  // 2. Calculating the width of the offScreen canvas to be the sum of all
980
963
  let offScreenCanvasWidth = 0;
981
964
 
982
965
  canvasesDrivenByVtkJs.forEach((canvas) => {
983
- offScreenCanvasWidth += canvas.clientWidth * devicePixelRatio;
966
+ offScreenCanvasWidth += canvas.width;
984
967
  });
985
968
 
986
969
  offScreenCanvasContainer.width = offScreenCanvasWidth;
@@ -1009,8 +992,6 @@ class RenderingEngine implements IRenderingEngine {
1009
992
  // Redefine viewport properties
1010
993
  let _xOffset = 0;
1011
994
 
1012
- const devicePixelRatio = window.devicePixelRatio || 1;
1013
-
1014
995
  for (let i = 0; i < viewportsDrivenByVtkJs.length; i++) {
1015
996
  const viewport = viewportsDrivenByVtkJs[i];
1016
997
  const {
@@ -1029,7 +1010,7 @@ class RenderingEngine implements IRenderingEngine {
1029
1010
  _xOffset
1030
1011
  );
1031
1012
 
1032
- _xOffset += viewport.canvas.clientWidth * devicePixelRatio;
1013
+ _xOffset += viewport.canvas.width;
1033
1014
 
1034
1015
  viewport.sx = sx;
1035
1016
  viewport.sy = sy;
@@ -1065,22 +1046,17 @@ class RenderingEngine implements IRenderingEngine {
1065
1046
  _xOffset: number
1066
1047
  ): ViewportDisplayCoords {
1067
1048
  const { canvas } = viewport;
1068
- const { clientWidth, clientHeight } = canvas;
1069
- const devicePixelRatio = window.devicePixelRatio || 1;
1070
- const height = clientHeight * devicePixelRatio;
1071
- const width = clientWidth * devicePixelRatio;
1049
+ const { width: sWidth, height: sHeight } = canvas;
1072
1050
 
1073
1051
  // Update the canvas drawImage offsets.
1074
1052
  const sx = _xOffset;
1075
1053
  const sy = 0;
1076
- const sWidth = width;
1077
- const sHeight = height;
1078
1054
 
1079
1055
  const sxStartDisplayCoords = sx / offScreenCanvasWidth;
1080
1056
 
1081
1057
  // Need to offset y if it not max height
1082
1058
  const syStartDisplayCoords =
1083
- sy + (offScreenCanvasHeight - height) / offScreenCanvasHeight;
1059
+ sy + (offScreenCanvasHeight - sHeight) / offScreenCanvasHeight;
1084
1060
 
1085
1061
  const sWidthDisplayCoords = sWidth / offScreenCanvasWidth;
1086
1062
  const sHeightDisplayCoords = sHeight / offScreenCanvasHeight;
@@ -7,9 +7,9 @@ import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/C
7
7
  import vtkImageMapper from '@kitware/vtk.js/Rendering/Core/ImageMapper';
8
8
  import vtkImageSlice from '@kitware/vtk.js/Rendering/Core/ImageSlice';
9
9
  import { mat4, vec2, vec3 } from 'gl-matrix';
10
- import _cloneDeep from 'lodash.clonedeep';
11
10
  import eventTarget from '../eventTarget';
12
11
  import * as metaData from '../metaData';
12
+ import cloneDeep from 'lodash.clonedeep';
13
13
  import type {
14
14
  ActorEntry,
15
15
  CPUFallbackColormapData,
@@ -34,6 +34,7 @@ import type {
34
34
  StackViewportProperties,
35
35
  VOIRange,
36
36
  ViewReference,
37
+ ViewPresentation,
37
38
  VolumeActor,
38
39
  } from '../types';
39
40
  import {
@@ -382,7 +383,9 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
382
383
 
383
384
  private setVOI: (voiRange: VOIRange, options?: SetVOIOptions) => void;
384
385
 
385
- private setInterpolationType: (interpolationType: InterpolationType) => void;
386
+ protected setInterpolationType: (
387
+ interpolationType: InterpolationType
388
+ ) => void;
386
389
 
387
390
  private setInvertColor: (invert: boolean) => void;
388
391
 
@@ -480,12 +483,12 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
480
483
  );
481
484
  return [pixelCoord[0], pixelCoord[1], 0];
482
485
  },
483
- indexToWorld: (point: Point3) => {
486
+ indexToWorld: (point: Point3, destPoint?: Point3) => {
484
487
  const canvasPoint = pixelToCanvas(this._cpuFallbackEnabledElement, [
485
488
  point[0],
486
489
  point[1],
487
490
  ]);
488
- return this.canvasToWorldCPU(canvasPoint);
491
+ return this.canvasToWorldCPU(canvasPoint, destPoint);
489
492
  },
490
493
  },
491
494
  scalarData: this.cpuImagePixelData,
@@ -551,7 +554,6 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
551
554
  const { preferSizeOverAccuracy } = getConfiguration().rendering;
552
555
 
553
556
  if (preferSizeOverAccuracy) {
554
- // @ts-ignore for now until vtk is updated
555
557
  mapper.setPreferSizeOverAccuracy(true);
556
558
  }
557
559
 
@@ -1151,13 +1153,17 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
1151
1153
  : (360 - initialToCurrentViewUpAngle) % 360;
1152
1154
  };
1153
1155
 
1154
- private setRotation(rotation: number): void {
1156
+ protected setRotation = (rotation: number) => {
1155
1157
  const previousCamera = this.getCamera();
1156
1158
 
1157
1159
  this.useCPURendering
1158
1160
  ? this.setRotationCPU(rotation)
1159
1161
  : this.setRotationGPU(rotation);
1160
1162
 
1163
+ if (this._suppressCameraModifiedEvents) {
1164
+ return;
1165
+ }
1166
+
1161
1167
  // New camera after rotation
1162
1168
  const camera = this.getCamera();
1163
1169
 
@@ -1171,7 +1177,7 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
1171
1177
  };
1172
1178
 
1173
1179
  triggerEvent(this.element, Events.CAMERA_MODIFIED, eventDetail);
1174
- }
1180
+ };
1175
1181
 
1176
1182
  private setVOILUTFunction(
1177
1183
  voiLUTFunction: VOILUTFunctionType,
@@ -1200,9 +1206,18 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
1200
1206
  viewport.rotation = rotation;
1201
1207
  }
1202
1208
 
1209
+ /**
1210
+ * The rotation that is being set is intended to be around the currently
1211
+ * display center of the image. However, the roll operation does it around
1212
+ * another point which can result in the image disappearing. The set/get
1213
+ * pan values move the center of rotation to the center of the image as
1214
+ * currently actually displayed.
1215
+ */
1203
1216
  private setRotationGPU(rotation: number): void {
1217
+ const panFit = this.getPan(this.fitToCanvasCamera);
1204
1218
  const pan = this.getPan();
1205
- this.setPan([0, 0]);
1219
+ const panSub = vec2.sub([0, 0], panFit, pan) as Point2;
1220
+ this.setPan(panSub, false);
1206
1221
  const { flipVertical } = this.getCamera();
1207
1222
 
1208
1223
  // Moving back to zero rotation, for new scrolled slice rotation is 0 after camera reset
@@ -1216,7 +1231,11 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
1216
1231
 
1217
1232
  // rotating camera to the new value
1218
1233
  this.getVtkActiveCamera().roll(-rotation);
1219
- this.setPan(pan);
1234
+ const afterPan = this.getPan();
1235
+ const afterPanFit = this.getPan(this.fitToCanvasCamera);
1236
+ const newCenter = vec2.sub([0, 0], afterPan, afterPanFit);
1237
+ const newOffset = vec2.add([0, 0], panFit, newCenter) as Point2;
1238
+ this.setPan(newOffset, false);
1220
1239
  }
1221
1240
 
1222
1241
  private setInterpolationTypeGPU(interpolationType: InterpolationType): void {
@@ -2232,7 +2251,7 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
2232
2251
 
2233
2252
  // Cache camera props so we can trigger one camera changed event after
2234
2253
  // The full transition.
2235
- const previousCameraProps = _cloneDeep(this.getCamera());
2254
+ const previousCameraProps = cloneDeep(this.getCamera());
2236
2255
  if (sameImageData && !this.stackInvalidated) {
2237
2256
  // 3a. If we can reuse it, replace the scalar data under the hood
2238
2257
  this._updateVTKImageDataFromCornerstoneImage(image);
@@ -2673,7 +2692,10 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
2673
2692
  this._publishCalibratedEvent = false;
2674
2693
  }
2675
2694
 
2676
- private canvasToWorldCPU = (canvasPos: Point2): Point3 => {
2695
+ private canvasToWorldCPU = (
2696
+ canvasPos: Point2,
2697
+ worldPos: Point3 = [0, 0, 0]
2698
+ ): Point3 => {
2677
2699
  if (!this._cpuFallbackEnabledElement.image) {
2678
2700
  return;
2679
2701
  }
@@ -2683,8 +2705,6 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
2683
2705
  // convert pixel coordinate to world coordinate
2684
2706
  const { origin, spacing, direction } = this.getImageData();
2685
2707
 
2686
- const worldPos = vec3.fromValues(0, 0, 0);
2687
-
2688
2708
  // Calculate size of spacing vector in normal direction
2689
2709
  const iVector = direction.slice(0, 3) as Point3;
2690
2710
  const jVector = direction.slice(3, 6) as Point3;
@@ -2693,7 +2713,7 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
2693
2713
  vec3.scaleAndAdd(worldPos, origin, iVector, px * spacing[0]);
2694
2714
  vec3.scaleAndAdd(worldPos, worldPos, jVector, py * spacing[1]);
2695
2715
 
2696
- return [worldPos[0], worldPos[1], worldPos[2]] as Point3;
2716
+ return worldPos;
2697
2717
  };
2698
2718
 
2699
2719
  private worldToCanvasCPU = (worldPos: Point3): Point2 => {
@@ -2881,6 +2901,27 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
2881
2901
  };
2882
2902
  }
2883
2903
 
2904
+ /**
2905
+ * Applies the view reference, which may navigate the slice index and apply
2906
+ * other camera modifications
2907
+ */
2908
+ public setView(viewRef?: ViewReference, viewPres?: ViewPresentation): void {
2909
+ const camera = this.getCamera();
2910
+ super.setView(viewRef, viewPres);
2911
+ if (viewRef) {
2912
+ const { viewPlaneNormal, sliceIndex } = viewRef;
2913
+ if (
2914
+ viewPlaneNormal &&
2915
+ !isEqual(viewPlaneNormal, camera.viewPlaneNormal)
2916
+ ) {
2917
+ return;
2918
+ }
2919
+ if (sliceIndex || sliceIndex === 0) {
2920
+ this.setImageIdIndex(sliceIndex as number);
2921
+ }
2922
+ }
2923
+ }
2924
+
2884
2925
  public getReferenceId(specifier: ViewReferenceSpecifier = {}): string {
2885
2926
  const { sliceIndex: sliceIndex = this.currentImageIdIndex } = specifier;
2886
2927
  if (Array.isArray(sliceIndex)) {
@@ -543,9 +543,9 @@ class VideoViewport extends Viewport implements IVideoViewport {
543
543
  const pixelCoord = this.canvasToIndex(canvasPoint);
544
544
  return [pixelCoord[0], pixelCoord[1], 0];
545
545
  },
546
- indexToWorld: (point: Point3) => {
546
+ indexToWorld: (point: Point2, destPoint?: Point3) => {
547
547
  const canvasPoint = this.indexToCanvas([point[0], point[1]]);
548
- return this.canvasToWorld(canvasPoint);
548
+ return this.canvasToWorld(canvasPoint, destPoint);
549
549
  },
550
550
  },
551
551
  hasPixelSpacing: this.hasPixelSpacing,
@@ -856,7 +856,10 @@ class VideoViewport extends Viewport implements IVideoViewport {
856
856
  * @param canvasPos - to convert to world
857
857
  * @returns World position
858
858
  */
859
- public canvasToWorld = (canvasPos: Point2): Point3 => {
859
+ public canvasToWorld = (
860
+ canvasPos: Point2,
861
+ destPos: Point3 = [0, 0, 0]
862
+ ): Point3 => {
860
863
  const pan: Point2 = this.videoCamera.panWorld; // In world coordinates
861
864
  const worldToCanvasRatio: number = this.getWorldToCanvasRatio();
862
865
 
@@ -870,13 +873,15 @@ class VideoViewport extends Viewport implements IVideoViewport {
870
873
  canvasPos[1] - panOffsetCanvas[1],
871
874
  ];
872
875
 
873
- const worldPos: Point3 = [
874
- subCanvasPos[0] / worldToCanvasRatio,
875
- subCanvasPos[1] / worldToCanvasRatio,
876
+ // Replace the x,y values only in place in the world position
877
+ // as the z is unchanging for video display
878
+ destPos.splice(
876
879
  0,
877
- ];
878
-
879
- return worldPos;
880
+ 2,
881
+ subCanvasPos[0] / worldToCanvasRatio,
882
+ subCanvasPos[1] / worldToCanvasRatio
883
+ );
884
+ return destPos;
880
885
  };
881
886
 
882
887
  /**