@cornerstonejs/core 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 (79) hide show
  1. package/dist/esm/RenderingEngine/BaseVolumeViewport.d.ts +4 -0
  2. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +24 -0
  3. package/dist/esm/RenderingEngine/ContextPoolRenderingEngine.d.ts +1 -0
  4. package/dist/esm/RenderingEngine/ContextPoolRenderingEngine.js +16 -6
  5. package/dist/esm/RenderingEngine/ECGViewport.d.ts +4 -0
  6. package/dist/esm/RenderingEngine/ECGViewport.js +8 -0
  7. package/dist/esm/RenderingEngine/GenericViewport/ECG/DefaultECGDataProvider.js +1 -1
  8. package/dist/esm/RenderingEngine/GenericViewport/GenericViewport.d.ts +24 -15
  9. package/dist/esm/RenderingEngine/GenericViewport/GenericViewport.js +26 -0
  10. package/dist/esm/RenderingEngine/GenericViewport/Planar/CpuImageSliceRenderPath.js +12 -3
  11. package/dist/esm/RenderingEngine/GenericViewport/Planar/CpuVolumeSliceRenderPath.js +3 -1
  12. package/dist/esm/RenderingEngine/GenericViewport/Planar/DefaultPlanarDataProvider.js +7 -4
  13. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarLegacyCompatibilityController.js +3 -3
  14. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarRenderPathDecisionService.d.ts +1 -0
  15. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarRenderPathDecisionService.js +26 -9
  16. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewport.d.ts +15 -2
  17. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewport.js +182 -18
  18. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewportLegacyAdapter.js +2 -2
  19. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewportTypes.d.ts +4 -2
  20. package/dist/esm/RenderingEngine/GenericViewport/Planar/VtkImageMapperRenderPath.js +42 -9
  21. package/dist/esm/RenderingEngine/GenericViewport/Planar/VtkVolumeSliceRenderPath.js +3 -1
  22. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarImageEvents.d.ts +1 -0
  23. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarImageEvents.js +11 -2
  24. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarVolumePresentation.js +30 -3
  25. package/dist/esm/RenderingEngine/GenericViewport/Video/DefaultVideoDataProvider.js +1 -1
  26. package/dist/esm/RenderingEngine/GenericViewport/Video/VideoViewport.d.ts +1 -0
  27. package/dist/esm/RenderingEngine/GenericViewport/Video/VideoViewport.js +4 -1
  28. package/dist/esm/RenderingEngine/GenericViewport/ViewportArchitectureTypes.d.ts +12 -8
  29. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/DefaultVolume3DDataProvider.js +3 -3
  30. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/VolumeViewport3DLegacyAdapter.js +4 -4
  31. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/viewport3D.d.ts +5 -1
  32. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/viewport3D.js +18 -4
  33. package/dist/esm/RenderingEngine/GenericViewport/WSI/DefaultWSIDataProvider.js +2 -2
  34. package/dist/esm/RenderingEngine/GenericViewport/WSI/WSIViewportLegacyAdapter.js +2 -2
  35. package/dist/esm/RenderingEngine/GenericViewport/genericViewportDisplaySetAccess.d.ts +35 -0
  36. package/dist/esm/RenderingEngine/GenericViewport/{genericViewportDataSetAccess.js → genericViewportDisplaySetAccess.js} +19 -19
  37. package/dist/esm/RenderingEngine/GenericViewport/genericViewportReferenceCompatibility.js +26 -4
  38. package/dist/esm/RenderingEngine/GenericViewport/index.d.ts +1 -1
  39. package/dist/esm/RenderingEngine/StackViewport.d.ts +4 -0
  40. package/dist/esm/RenderingEngine/StackViewport.js +14 -0
  41. package/dist/esm/RenderingEngine/VideoViewport.d.ts +10 -0
  42. package/dist/esm/RenderingEngine/VideoViewport.js +13 -0
  43. package/dist/esm/RenderingEngine/Viewport.d.ts +17 -0
  44. package/dist/esm/RenderingEngine/Viewport.js +18 -0
  45. package/dist/esm/RenderingEngine/WSIViewport.d.ts +4 -0
  46. package/dist/esm/RenderingEngine/WSIViewport.js +15 -1
  47. package/dist/esm/RenderingEngine/helpers/planarImageRendering.d.ts +5 -1
  48. package/dist/esm/RenderingEngine/helpers/planarImageRendering.js +19 -5
  49. package/dist/esm/RenderingEngine/helpers/stats/RenderModesPanel.d.ts +4 -0
  50. package/dist/esm/RenderingEngine/helpers/stats/RenderModesPanel.js +48 -1
  51. package/dist/esm/RenderingEngine/helpers/stats/StatsOverlay.js +66 -9
  52. package/dist/esm/init.js +1 -1
  53. package/dist/esm/types/IGenericViewport.d.ts +24 -0
  54. package/dist/esm/types/IGenericViewport.js +0 -0
  55. package/dist/esm/types/ScalingDescriptor.d.ts +5 -0
  56. package/dist/esm/types/ScalingDescriptor.js +0 -0
  57. package/dist/esm/types/index.d.ts +4 -1
  58. package/dist/esm/utilities/VoxelManager.d.ts +2 -0
  59. package/dist/esm/utilities/VoxelManager.js +12 -1
  60. package/dist/esm/utilities/genericViewportDisplaySetMetadataProvider.d.ts +8 -0
  61. package/dist/esm/utilities/genericViewportDisplaySetMetadataProvider.js +23 -0
  62. package/dist/esm/utilities/getScalingDescriptor.d.ts +10 -0
  63. package/dist/esm/utilities/getScalingDescriptor.js +41 -0
  64. package/dist/esm/utilities/getTargetVolumeAndSpacingInNormalDir.js +4 -5
  65. package/dist/esm/utilities/getViewportModality.js +5 -14
  66. package/dist/esm/utilities/index.d.ts +5 -3
  67. package/dist/esm/utilities/index.js +6 -3
  68. package/dist/esm/utilities/isPTPrescaledWithSUV.d.ts +1 -1
  69. package/dist/esm/utilities/isPTPrescaledWithSUV.js +1 -1
  70. package/dist/esm/utilities/resolveGenericViewportVolumeId.d.ts +2 -0
  71. package/dist/esm/utilities/resolveGenericViewportVolumeId.js +12 -0
  72. package/dist/esm/utilities/viewportCapabilities.d.ts +10 -1
  73. package/dist/esm/utilities/viewportCapabilities.js +22 -0
  74. package/dist/esm/version.d.ts +1 -1
  75. package/dist/esm/version.js +1 -1
  76. package/package.json +6 -6
  77. package/dist/esm/RenderingEngine/GenericViewport/genericViewportDataSetAccess.d.ts +0 -35
  78. package/dist/esm/utilities/genericViewportDataSetMetadataProvider.d.ts +0 -8
  79. package/dist/esm/utilities/genericViewportDataSetMetadataProvider.js +0 -23
@@ -65,6 +65,10 @@ declare abstract class BaseVolumeViewport extends Viewport {
65
65
  getProperties: (volumeId?: string) => VolumeViewportProperties | undefined | null;
66
66
  private getColormap;
67
67
  setVolumes(volumeInputArray: IVolumeInput[], immediate?: boolean, suppressEvents?: boolean): Promise<void>;
68
+ setDisplaySets(...entries: Array<{
69
+ displaySetId: string;
70
+ options?: unknown;
71
+ }>): Promise<void>;
68
72
  addVolumes(volumeInputArray: IVolumeInput[], immediate?: boolean, suppressEvents?: boolean): Promise<void>;
69
73
  removeVolumeActors(actorUIDs: string[], immediate?: boolean): void;
70
74
  setOrientation(_orientation: OrientationAxis | OrientationVectors, _immediate?: boolean, _suppressEvents?: boolean): void;
@@ -14,6 +14,9 @@ import transformWorldToIndex from '../utilities/transformWorldToIndex';
14
14
  import { findMatchingColormap, updateOpacity as colormapUpdateOpacity, updateThreshold as colormapUpdateThreshold, updateOpacityMapping as colormapUpdateOpacityMapping, getOpacityState, } from '../utilities/colormap';
15
15
  import getAcquisitionPlaneOrientation from '../utilities/getAcquisitionPlaneOrientation';
16
16
  import { getTransferFunctionNodes, setTransferFunctionNodes, } from '../utilities/transferFunctionUtils';
17
+ import { createAndCacheVolume } from '../loaders/volumeLoader';
18
+ import resolveViewportVolumeId from './helpers/resolveViewportVolumeId';
19
+ import { getGenericViewportImageDisplaySet } from './GenericViewport/genericViewportDisplaySetAccess';
17
20
  import createVolumeActor from './helpers/createVolumeActor';
18
21
  import volumeNewImageEventDispatcher, { resetVolumeNewImageState, } from './helpers/volumeNewImageEventDispatcher';
19
22
  import Viewport from './Viewport';
@@ -912,6 +915,7 @@ class BaseVolumeViewport extends Viewport {
912
915
  }
913
916
  setSampleDistanceMultiplier(multiplier) { }
914
917
  async setVolumes(volumeInputArray, immediate = false, suppressEvents = false) {
918
+ this.clearDisplaySets();
915
919
  const volumeId = volumeInputArray[0].volumeId;
916
920
  const firstImageVolume = cache.getVolume(volumeId);
917
921
  if (!firstImageVolume) {
@@ -947,6 +951,26 @@ class BaseVolumeViewport extends Viewport {
947
951
  this.render();
948
952
  }
949
953
  }
954
+ async setDisplaySets(...entries) {
955
+ await this.mountDisplaySets(entries, async (entry) => {
956
+ const dataSet = getGenericViewportImageDisplaySet(entry.displaySetId);
957
+ if (!dataSet?.imageIds?.length) {
958
+ throw new Error(`[VolumeViewport] No registered imageIds for display set ${entry.displaySetId}`);
959
+ }
960
+ const volumeId = resolveViewportVolumeId(dataSet.volumeId ?? entry.displaySetId);
961
+ if (!cache.getVolume(volumeId)) {
962
+ const volume = await createAndCacheVolume(volumeId, {
963
+ imageIds: dataSet.imageIds,
964
+ });
965
+ volume.load();
966
+ }
967
+ const volumeInput = {
968
+ volumeId,
969
+ ...(entry.options ?? {}),
970
+ };
971
+ await this.setVolumes([volumeInput]);
972
+ });
973
+ }
950
974
  async addVolumes(volumeInputArray, immediate = false, suppressEvents = false) {
951
975
  const firstImageVolume = cache.getVolume(volumeInputArray[0].volumeId);
952
976
  if (!firstImageVolume) {
@@ -10,6 +10,7 @@ declare class ContextPoolRenderingEngine extends BaseRenderingEngine {
10
10
  protected enableVTKjsDrivenViewport(viewportInputEntry: NormalizedViewportInput): void;
11
11
  protected addVtkjsDrivenViewport(viewportInputEntry: InternalViewportInput): void;
12
12
  protected setVtkjsDrivenViewports(viewportInputEntries: NormalizedViewportInput[]): void;
13
+ private _getDisplayedSize;
13
14
  protected _resizeVTKViewports(vtkDrivenViewports: IViewport[], keepCamera?: boolean, immediate?: boolean): void;
14
15
  protected _renderFlaggedViewports: () => void;
15
16
  private renderViewportUsingCustomOrVtkPipeline;
@@ -8,6 +8,7 @@ import ViewportType from '../enums/ViewportType';
8
8
  import viewportTypeUsesCustomRenderingPipeline, { viewportUsesCustomRenderingPipeline, } from './helpers/viewportTypeUsesCustomRenderingPipeline';
9
9
  import getOrCreateCanvas, { updateCanvasSizeAndAspectRatio, } from './helpers/getOrCreateCanvas';
10
10
  import { getViewportClassForInput } from './helpers/viewportTypeToViewportClass';
11
+ import { isGenericViewport } from '../utilities/viewportCapabilities';
11
12
  class ContextPoolRenderingEngine extends BaseRenderingEngine {
12
13
  constructor(id) {
13
14
  super(id);
@@ -124,13 +125,21 @@ class ContextPoolRenderingEngine extends BaseRenderingEngine {
124
125
  }
125
126
  }
126
127
  }
127
- _resizeVTKViewports(vtkDrivenViewports, keepCamera = true, immediate = true) {
128
+ _getDisplayedSize(vp) {
128
129
  const devicePixelRatio = window.devicePixelRatio || 1;
130
+ const sizeSource = isGenericViewport(vp)
131
+ ? vp.element
132
+ : getOrCreateCanvas(vp.element);
133
+ return {
134
+ displayedWidth: Math.round(sizeSource.clientWidth * devicePixelRatio),
135
+ displayedHeight: Math.round(sizeSource.clientHeight * devicePixelRatio),
136
+ };
137
+ }
138
+ _resizeVTKViewports(vtkDrivenViewports, keepCamera = true, immediate = true) {
129
139
  const viewportsNeedingResize = [];
130
140
  for (const vp of vtkDrivenViewports) {
131
141
  const canvas = getOrCreateCanvas(vp.element);
132
- const displayedWidth = Math.round(canvas.clientWidth * devicePixelRatio);
133
- const displayedHeight = Math.round(canvas.clientHeight * devicePixelRatio);
142
+ const { displayedWidth, displayedHeight } = this._getDisplayedSize(vp);
134
143
  if (displayedWidth === 0 || displayedHeight === 0) {
135
144
  continue;
136
145
  }
@@ -146,9 +155,7 @@ class ContextPoolRenderingEngine extends BaseRenderingEngine {
146
155
  return;
147
156
  }
148
157
  for (const vp of viewportsNeedingResize) {
149
- const canvas = getOrCreateCanvas(vp.element);
150
- const displayedWidth = Math.round(canvas.clientWidth * devicePixelRatio);
151
- const displayedHeight = Math.round(canvas.clientHeight * devicePixelRatio);
158
+ const { displayedWidth, displayedHeight } = this._getDisplayedSize(vp);
152
159
  const targetWidth = Math.max(VIEWPORT_MIN_SIZE, displayedWidth);
153
160
  const targetHeight = Math.max(VIEWPORT_MIN_SIZE, displayedHeight);
154
161
  vp.sWidth = targetWidth;
@@ -162,6 +169,9 @@ class ContextPoolRenderingEngine extends BaseRenderingEngine {
162
169
  }
163
170
  vtkDrivenViewports.forEach((vp) => {
164
171
  vp.resize?.();
172
+ if (isGenericViewport(vp)) {
173
+ return;
174
+ }
165
175
  const prevCamera = vp.getCamera();
166
176
  const rotation = vp.getRotation?.() ?? 0;
167
177
  const { flipHorizontal } = prevCamera;
@@ -19,6 +19,10 @@ declare class ECGViewport extends Viewport {
19
19
  private removeEventListeners;
20
20
  private elementDisabledHandler;
21
21
  setEcg(imageId: string): Promise<void>;
22
+ setDisplaySets(...entries: Array<{
23
+ displaySetId: string;
24
+ options?: unknown;
25
+ }>): Promise<void>;
22
26
  setChannelVisibility(index: number, visible: boolean): void;
23
27
  getVisibleChannels(): {
24
28
  name: string;
@@ -3,6 +3,7 @@ import { Transform } from './helpers/cpuFallback/rendering/transform';
3
3
  import triggerEvent from '../utilities/triggerEvent';
4
4
  import Viewport from './Viewport';
5
5
  import { getOrCreateCanvas } from './helpers';
6
+ import { getGenericViewportSourceDataId } from './GenericViewport/genericViewportDisplaySetAccess';
6
7
  import { ECG_CHANNEL_SPACING, computeECGChannelLayouts, computeECGHeight, drawECGGrid, drawECGLabels, drawECGTraces, ECG_RENDERING_COLORS, ECG_SECONDS_WIDTH, getVisibleECGChannelsByFlag, loadECGWaveform, } from '../utilities/ECGUtilities';
7
8
  const ECG_AMPLITUDE_INDEX_SIZE = 65536;
8
9
  class ECGViewport extends Viewport {
@@ -173,6 +174,7 @@ class ECGViewport extends Viewport {
173
174
  this.removeEventListeners();
174
175
  }
175
176
  async setEcg(imageId) {
177
+ this.clearDisplaySets();
176
178
  this.imageId = imageId;
177
179
  const { waveform, calibration } = await loadECGWaveform(imageId);
178
180
  this.channels = waveform.channels.map((channel) => ({
@@ -192,6 +194,12 @@ class ECGViewport extends Viewport {
192
194
  this.refreshRenderValues();
193
195
  this.renderFrame();
194
196
  }
197
+ async setDisplaySets(...entries) {
198
+ await this.mountDisplaySets(entries, async (entry) => {
199
+ const sourceDataId = getGenericViewportSourceDataId(entry.displaySetId);
200
+ await this.setEcg(sourceDataId);
201
+ });
202
+ }
195
203
  setChannelVisibility(index, visible) {
196
204
  if (index >= 0 && index < this.channels.length) {
197
205
  this.channels[index].visible = visible;
@@ -1,5 +1,5 @@
1
1
  import { loadECGWaveform } from '../../../utilities/ECGUtilities';
2
- import { getGenericViewportSourceDataId } from '../genericViewportDataSetAccess';
2
+ import { getGenericViewportSourceDataId } from '../genericViewportDisplaySetAccess';
3
3
  export class DefaultECGDataProvider {
4
4
  async load(dataId) {
5
5
  const sourceDataId = getGenericViewportSourceDataId(dataId);
@@ -1,7 +1,8 @@
1
1
  import type ICamera from '../../types/ICamera';
2
- import type { Point2, Point3 } from '../../types';
2
+ import type { Point2, Point3, ViewportContentMode } from '../../types';
3
3
  import ViewportStatus from '../../enums/ViewportStatus';
4
- import type { BaseViewportRenderContext, BindingRole, DataAddOptions, DataId, DataProvider, LoadedData, ViewportDataBinding, RenderPathResolver, ViewportController, ViewportId } from './ViewportArchitectureTypes';
4
+ import type { IRenderingEngine } from '../../types';
5
+ import type { BaseViewportRenderContext, BindingRole, DataAddOptions, DisplaySetId, DataProvider, LoadedData, ViewportDataBinding, RenderPathResolver, ViewportController, ViewportId } from './ViewportArchitectureTypes';
5
6
  import type ViewportType from '../../enums/ViewportType';
6
7
  import type ResolvedViewportView from './ResolvedViewportView';
7
8
  import type { ReferenceCompatibleOptions, ViewReference, ViewReferenceSpecifier, RenderingEngineResizeOptions } from '../../types/IViewport';
@@ -27,19 +28,25 @@ declare abstract class GenericViewport<TViewState extends object, TDataPresentat
27
28
  element: HTMLDivElement;
28
29
  });
29
30
  setDisplaySets(...entries: Array<{
30
- displaySetId: DataId;
31
+ displaySetId: DisplaySetId;
31
32
  options?: unknown;
32
33
  }>): Promise<void>;
33
- addDisplaySet(displaySetId: DataId, options: DataAddOptions): Promise<void>;
34
- removeData(displaySetId: DataId): void;
34
+ addDisplaySet(displaySetId: DisplaySetId, options: DataAddOptions): Promise<void>;
35
+ getDisplaySets(): Array<{
36
+ displaySetId: DisplaySetId;
37
+ options?: unknown;
38
+ }>;
39
+ removeData(displaySetId: DisplaySetId): void;
35
40
  setDisplaySetPresentation(props: Partial<TDataPresentation>): void;
36
- setDisplaySetPresentation(displaySetId: DataId, props: Partial<TDataPresentation>): void;
37
- getDisplaySetPresentation(displaySetId: DataId): TDataPresentation | undefined;
41
+ setDisplaySetPresentation(displaySetId: DisplaySetId, props: Partial<TDataPresentation>): void;
42
+ getDisplaySetPresentation(displaySetId: DisplaySetId): TDataPresentation | undefined;
43
+ getCurrentMode(): ViewportContentMode;
38
44
  getViewReference(_specifier?: ViewReferenceSpecifier): ViewReference;
39
45
  getViewReferenceId(_specifier?: ViewReferenceSpecifier): string;
40
46
  setViewReference(_viewReference: ViewReference): void;
41
47
  isReferenceViewable(viewReference: ViewReference, options?: ReferenceCompatibleOptions): boolean;
42
48
  getFrameOfReferenceUID(): string;
49
+ getRenderingEngine(): IRenderingEngine;
43
50
  abstract getResolvedView(): ResolvedViewportView<unknown, ICamera<unknown>> | undefined;
44
51
  canvasToWorld(canvasPos: Point2): Point3;
45
52
  worldToCanvas(worldPos: Point3): Point2;
@@ -56,21 +63,23 @@ declare abstract class GenericViewport<TViewState extends object, TDataPresentat
56
63
  resize(): void;
57
64
  resetViewState(_options?: unknown): boolean;
58
65
  resizeForRenderingEngine({ keepCamera, }?: RenderingEngineResizeOptions): void;
59
- protected addLoadedData(displaySetId: DataId, data: LoadedData, options: DataAddOptions, shouldIgnore?: () => boolean): Promise<boolean>;
66
+ protected addLoadedData(displaySetId: DisplaySetId, data: LoadedData, options: DataAddOptions, shouldIgnore?: () => boolean): Promise<boolean>;
60
67
  protected removeAllData(): void;
61
- protected setDataPresentationState(displaySetId: DataId, props: TDataPresentation): void;
62
- protected getDataPresentationState(displaySetId: DataId): TDataPresentation | undefined;
63
- protected setDefaultDataPresentation(displaySetId: DataId, defaults: TDataPresentation): TDataPresentation;
64
- protected mergeDataPresentation(displaySetId: DataId, props: Partial<TDataPresentation>): TDataPresentation;
68
+ protected setDataPresentationState(displaySetId: DisplaySetId, props: TDataPresentation): void;
69
+ protected getDataPresentationState(displaySetId: DisplaySetId): TDataPresentation | undefined;
70
+ protected setDefaultDataPresentation(displaySetId: DisplaySetId, defaults: TDataPresentation): TDataPresentation;
71
+ protected mergeDataPresentation(displaySetId: DisplaySetId, props: Partial<TDataPresentation>): TDataPresentation;
72
+ protected notifyDataPresentationModified(_displaySetId: DisplaySetId, _props: Partial<TDataPresentation>): void;
65
73
  protected normalizeViewState(viewState: TViewState): TViewState;
66
74
  protected modified(previousCamera?: ICamera): void;
67
75
  protected getCameraForEvent(): ICamera;
68
76
  protected triggerCameraModifiedEvent(previousCamera: ICamera): void;
69
77
  protected triggerCameraResetEvent(): void;
70
- protected getBinding(displaySetId: DataId): ViewportDataBinding<TDataPresentation> | undefined;
71
- protected getDisplaySetRenderMode(displaySetId: DataId): string | undefined;
72
- protected getDisplaySetRole(displaySetId: DataId): BindingRole | undefined;
78
+ protected getBinding(displaySetId: DisplaySetId): ViewportDataBinding<TDataPresentation> | undefined;
79
+ protected getDisplaySetRenderMode(displaySetId: DisplaySetId): string | undefined;
80
+ protected getDisplaySetRole(displaySetId: DisplaySetId): BindingRole | undefined;
73
81
  protected getFirstBinding(): ViewportDataBinding<TDataPresentation> | undefined;
82
+ protected getSourceBinding(): ViewportDataBinding<TDataPresentation> | undefined;
74
83
  protected getCurrentBinding(): ViewportDataBinding<TDataPresentation> | undefined;
75
84
  protected forEachBinding(visitor: (binding: ViewportDataBinding<TDataPresentation>) => void): void;
76
85
  protected getReferenceViewContexts(_viewReference?: ViewReference): GenericViewportReferenceContext[];
@@ -1,6 +1,7 @@
1
1
  import Events from '../../enums/Events';
2
2
  import ViewportStatus from '../../enums/ViewportStatus';
3
3
  import triggerEvent from '../../utilities/triggerEvent';
4
+ import renderingEngineCache from '../renderingEngineCache';
4
5
  import { isGenericViewportReferenceViewable, } from './genericViewportReferenceCompatibility';
5
6
  class GenericViewport {
6
7
  constructor(args) {
@@ -34,6 +35,12 @@ class GenericViewport {
34
35
  const data = await this.dataProvider.load(displaySetId, options);
35
36
  await this.addLoadedData(displaySetId, data, options);
36
37
  }
38
+ getDisplaySets() {
39
+ return Array.from(this.bindings.entries()).map(([displaySetId, binding]) => ({
40
+ displaySetId,
41
+ options: { role: binding.role },
42
+ }));
43
+ }
37
44
  removeData(displaySetId) {
38
45
  const binding = this.bindings.get(displaySetId);
39
46
  if (!binding) {
@@ -61,6 +68,9 @@ class GenericViewport {
61
68
  getDisplaySetPresentation(displaySetId) {
62
69
  return this.getDataPresentationState(displaySetId);
63
70
  }
71
+ getCurrentMode() {
72
+ return this.getSourceBinding() ? 'unknown' : 'empty';
73
+ }
64
74
  getViewReference(_specifier = {}) {
65
75
  return {
66
76
  FrameOfReferenceUID: this.getFrameOfReferenceUID(),
@@ -79,6 +89,9 @@ class GenericViewport {
79
89
  return (this.getResolvedView()?.getFrameOfReferenceUID() ??
80
90
  `${this.type}-viewport-${this.id}`);
81
91
  }
92
+ getRenderingEngine() {
93
+ return renderingEngineCache.get(this.renderingEngineId);
94
+ }
82
95
  canvasToWorld(canvasPos) {
83
96
  const cc = this.getResolvedView();
84
97
  if (!cc) {
@@ -255,8 +268,13 @@ class GenericViewport {
255
268
  ...props,
256
269
  };
257
270
  this.setDataPresentationState(displaySetId, nextPresentation);
271
+ if (this.bindings.has(displaySetId)) {
272
+ this.notifyDataPresentationModified(displaySetId, props);
273
+ }
258
274
  return nextPresentation;
259
275
  }
276
+ notifyDataPresentationModified(_displaySetId, _props) {
277
+ }
260
278
  normalizeViewState(viewState) {
261
279
  return viewState;
262
280
  }
@@ -307,6 +325,14 @@ class GenericViewport {
307
325
  getFirstBinding() {
308
326
  return this.bindings.values().next().value;
309
327
  }
328
+ getSourceBinding() {
329
+ for (const binding of this.bindings.values()) {
330
+ if (binding.role === 'source') {
331
+ return binding;
332
+ }
333
+ }
334
+ return this.getFirstBinding();
335
+ }
310
336
  getCurrentBinding() {
311
337
  return this.getFirstBinding();
312
338
  }
@@ -28,6 +28,7 @@ export class CpuImageSliceRenderPath {
28
28
  }
29
29
  ctx.display.activateRenderMode(ActorRenderMode.CPU_IMAGE);
30
30
  let rendering;
31
+ markCpuImagePreScaled(payload.image);
31
32
  const compatibilityActor = new CanvasActor({
32
33
  getImageData: () => this.getImageData(rendering),
33
34
  }, payload.image);
@@ -47,7 +48,7 @@ export class CpuImageSliceRenderPath {
47
48
  actorEntryUID: uuidv4(),
48
49
  enabledElement,
49
50
  compatibilityActor,
50
- currentImageIdIndex: payload.initialImageIdIndex,
51
+ currentImageIdIndex: payload.initialImageIdIndex ?? 0,
51
52
  defaultVOIRange: getDefaultImageVOIRange(payload.image),
52
53
  dataPresentation: undefined,
53
54
  fitScale: getCPUFallbackScalarScale(enabledElement.viewport.scale),
@@ -56,7 +57,7 @@ export class CpuImageSliceRenderPath {
56
57
  };
57
58
  triggerPlanarNewImage(ctx, {
58
59
  image: payload.image,
59
- imageIdIndex: payload.initialImageIdIndex,
60
+ imageIdIndex: payload.initialImageIdIndex ?? 0,
60
61
  });
61
62
  return {
62
63
  rendering,
@@ -355,9 +356,16 @@ function worldToCPUImageDrawPoint(enabledElement, worldPos) {
355
356
  sourceY,
356
357
  ];
357
358
  }
359
+ function markCpuImagePreScaled(image) {
360
+ image.isPreScaled = image.preScale?.scaled;
361
+ }
358
362
  export function buildPlanarImageData(image, frameOfReferenceUID) {
359
363
  const metadata = getImageDataMetadata(image);
360
- const { calibration, dimensions, direction, modality, origin, spacing } = metadata;
364
+ const { dimensions, direction, modality, origin, spacing } = metadata;
365
+ const userCalibration = metaData.get('calibratedPixelSpacing', image.imageId);
366
+ const calibration = userCalibration
367
+ ? { ...metadata.calibration, ...userCalibration }
368
+ : metadata.calibration;
361
369
  const rowVector = direction.slice(0, 3);
362
370
  const columnVector = direction.slice(3, 6);
363
371
  const scalarData = image.voxelManager?.getScalarData() || image.getPixelData?.();
@@ -418,6 +426,7 @@ function renderCompatibilityOverlayActors(ctx) {
418
426
  async function updateRenderedImage(args) {
419
427
  const { ctx, dataId, image, imageIdIndex, props, rendering } = args;
420
428
  const enabledElement = rendering.enabledElement;
429
+ markCpuImagePreScaled(image);
421
430
  const camera = ctx.viewport.getViewState();
422
431
  const defaultViewport = getDefaultViewport(ctx.cpu.canvas, image);
423
432
  const previousViewport = enabledElement.viewport;
@@ -40,7 +40,7 @@ export class CpuVolumeSliceRenderPath {
40
40
  imageIds: payload.imageIds,
41
41
  acquisitionOrientation: payload.acquisitionOrientation,
42
42
  layerCanvas: createCanvas(null, ctx.cpu.canvas.width, ctx.cpu.canvas.height),
43
- currentImageIdIndex: payload.initialImageIdIndex,
43
+ currentImageIdIndex: payload.initialImageIdIndex ?? 0,
44
44
  maxImageIdIndex: payload.imageIds.length - 1,
45
45
  defaultVOIRange,
46
46
  renderingInvalidated: true,
@@ -145,6 +145,7 @@ export class CpuVolumeSliceRenderPath {
145
145
  acquisitionOrientation: rendering.acquisitionOrientation,
146
146
  imageIds: rendering.imageIds,
147
147
  imageIdIndex: rendering.currentImageIdIndex,
148
+ maxImageIdIndex: rendering.maxImageIdIndex,
148
149
  });
149
150
  return {
150
151
  rendering,
@@ -361,6 +362,7 @@ export class CpuVolumeSliceRenderPath {
361
362
  acquisitionOrientation: rendering.acquisitionOrientation,
362
363
  imageIds: rendering.imageIds,
363
364
  imageIdIndex: rendering.currentImageIdIndex,
365
+ maxImageIdIndex: rendering.maxImageIdIndex,
364
366
  });
365
367
  }
366
368
  }
@@ -2,7 +2,7 @@ import { loadAndCacheImage } from '../../../loaders/imageLoader';
2
2
  import { createAndCacheVolume } from '../../../loaders/volumeLoader';
3
3
  import { ActorRenderMode } from '../../../types';
4
4
  import resolveViewportVolumeId from '../../helpers/resolveViewportVolumeId';
5
- import { getGenericViewportPlanarDataSet } from '../genericViewportDataSetAccess';
5
+ import { getGenericViewportPlanarDisplaySet } from '../genericViewportDisplaySetAccess';
6
6
  export class DefaultPlanarDataProvider {
7
7
  async load(dataId, options) {
8
8
  const dataSet = this.getDataSet(dataId);
@@ -16,6 +16,9 @@ export class DefaultPlanarDataProvider {
16
16
  throw new Error('[PlanarViewport] Cannot load an empty planar dataset');
17
17
  }
18
18
  const clampedImageIdIndex = Math.min(Math.max(0, dataSet.initialImageIdIndex ?? 0), dataSet.imageIds.length - 1);
19
+ const initialImageIdIndex = dataSet.initialImageIdIndex === undefined
20
+ ? undefined
21
+ : clampedImageIdIndex;
19
22
  if (options.renderMode === ActorRenderMode.VTK_VOLUME_SLICE ||
20
23
  options.renderMode === ActorRenderMode.CPU_VOLUME) {
21
24
  const volumeId = resolveViewportVolumeId(options.volumeId);
@@ -30,7 +33,7 @@ export class DefaultPlanarDataProvider {
30
33
  id: dataId,
31
34
  type: 'image',
32
35
  imageIds,
33
- initialImageIdIndex: clampedImageIdIndex,
36
+ initialImageIdIndex,
34
37
  acquisitionOrientation: options.acquisitionOrientation,
35
38
  imageData: dataSet.imageData,
36
39
  imageVolume,
@@ -50,7 +53,7 @@ export class DefaultPlanarDataProvider {
50
53
  imageIds: dataSet.imageIds,
51
54
  image,
52
55
  imageData: dataSet.imageData,
53
- initialImageIdIndex: clampedImageIdIndex,
56
+ initialImageIdIndex,
54
57
  acquisitionOrientation: options.acquisitionOrientation,
55
58
  reference: dataSet.reference,
56
59
  renderMode: options.renderMode,
@@ -59,7 +62,7 @@ export class DefaultPlanarDataProvider {
59
62
  };
60
63
  }
61
64
  getDataSet(dataId) {
62
- const dataSet = getGenericViewportPlanarDataSet(dataId);
65
+ const dataSet = getGenericViewportPlanarDisplaySet(dataId);
63
66
  if (!isPlanarRegisteredDataSet(dataSet)) {
64
67
  return;
65
68
  }
@@ -4,7 +4,7 @@ import { ActorRenderMode } from '../../../types';
4
4
  import triggerEvent from '../../../utilities/triggerEvent';
5
5
  import { findMatchingColormap, getMaxOpacity, getThresholdValue, } from '../../../utilities/colormap';
6
6
  import { getTransferFunctionNodes } from '../../../utilities/transferFunctionUtils';
7
- import genericViewportDataSetMetadataProvider from '../../../utilities/genericViewportDataSetMetadataProvider';
7
+ import genericViewportDisplaySetMetadataProvider from '../../../utilities/genericViewportDisplaySetMetadataProvider';
8
8
  import { clonePlanarLegacyProperties, mergePlanarLegacyProperties, clonePlanarOrientation, toPlanarDataPresentation, } from './planarLegacyCompatibility';
9
9
  import { mapSlabTypeToBlendMode } from './planarVolumeSliceBlendMode';
10
10
  export const PLANAR_LEGACY_PER_IMAGE_DEFAULT_PROPERTIES_LIMIT = 2048;
@@ -255,7 +255,7 @@ class PlanarLegacyCompatibilityController {
255
255
  return `__planar_v2__:${this.host.getViewportId()}:volume:${volumeId}`;
256
256
  }
257
257
  registerDataSet(dataId, dataSet) {
258
- genericViewportDataSetMetadataProvider.add(dataId, dataSet);
258
+ genericViewportDisplaySetMetadataProvider.add(dataId, dataSet);
259
259
  this.managedDataIds.add(dataId);
260
260
  }
261
261
  async mountVolumes(volumeInputArray, replaceExisting, suppressEvents) {
@@ -507,7 +507,7 @@ class PlanarLegacyCompatibilityController {
507
507
  }
508
508
  unregisterDataId(dataId) {
509
509
  try {
510
- genericViewportDataSetMetadataProvider.remove(dataId);
510
+ genericViewportDisplaySetMetadataProvider.remove(dataId);
511
511
  }
512
512
  finally {
513
513
  this.properties.delete(dataId);
@@ -17,6 +17,7 @@ export interface PlanarRenderPathDecisionOptions {
17
17
  }
18
18
  export declare class PlanarRenderPathDecisionService {
19
19
  select(dataSet: PlanarRegisteredDataSet, options?: PlanarRenderPathDecisionOptions): SelectedPlanarRenderPath;
20
+ canRender(dataSet: PlanarRegisteredDataSet, options?: PlanarRenderPathDecisionOptions): boolean;
20
21
  private selectImageRenderMode;
21
22
  private selectVolumeRenderMode;
22
23
  private shouldUseCPUForImage;
@@ -7,7 +7,7 @@ import { ActorRenderMode } from '../../../types';
7
7
  import { isValidVolume } from '../../../utilities/isValidVolume';
8
8
  import { getOrientationFromScanAxisNormal } from '../../helpers/getCameraVectors';
9
9
  export const DEFAULT_PLANAR_CPU_IMAGE_THRESHOLD = 64 * 1024 * 1024;
10
- export const DEFAULT_PLANAR_CPU_VOLUME_THRESHOLD = 64 * 1024 * 1024;
10
+ export const DEFAULT_PLANAR_CPU_VOLUME_THRESHOLD = Number.POSITIVE_INFINITY;
11
11
  export class PlanarRenderPathDecisionService {
12
12
  select(dataSet, options = {}) {
13
13
  if (!dataSet.imageIds.length) {
@@ -32,12 +32,32 @@ export class PlanarRenderPathDecisionService {
32
32
  acquisitionOrientation,
33
33
  renderMode: useVolumePath
34
34
  ? this.selectVolumeRenderMode(dataSet, options)
35
- : this.selectImageRenderMode(dataSet, options),
35
+ : this.selectImageRenderMode(options),
36
36
  volumeId,
37
37
  };
38
38
  }
39
- selectImageRenderMode(dataSet, options) {
40
- return this.shouldUseCPUForImage(dataSet, options)
39
+ canRender(dataSet, options = {}) {
40
+ if (!dataSet.imageIds.length) {
41
+ return false;
42
+ }
43
+ const orientation = options.orientation || OrientationAxis.ACQUISITION;
44
+ const acquisitionOrientation = getPlanarAcquisitionOrientation(dataSet.imageIds);
45
+ const isAcquisitionPath = orientation === OrientationAxis.ACQUISITION ||
46
+ (acquisitionOrientation !== undefined &&
47
+ orientation === acquisitionOrientation);
48
+ const useVolumePath = isVolumeBackedDataSet(dataSet, isAcquisitionPath);
49
+ if (!isAcquisitionPath &&
50
+ !useVolumePath &&
51
+ !dataSet.useWorldCoordinateImageData) {
52
+ return false;
53
+ }
54
+ if (useVolumePath && !supportsVolumeRendering(dataSet)) {
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+ selectImageRenderMode(options) {
60
+ return this.shouldUseCPUForImage(options)
41
61
  ? ActorRenderMode.CPU_IMAGE
42
62
  : ActorRenderMode.VTK_IMAGE;
43
63
  }
@@ -46,14 +66,11 @@ export class PlanarRenderPathDecisionService {
46
66
  ? ActorRenderMode.CPU_VOLUME
47
67
  : ActorRenderMode.VTK_VOLUME_SLICE;
48
68
  }
49
- shouldUseCPUForImage(dataSet, options) {
69
+ shouldUseCPUForImage(options) {
50
70
  if (options.webGLAvailable === false) {
51
71
  return true;
52
72
  }
53
- const configuredCpuThresholds = getConfiguredPlanarCpuThresholds();
54
- return shouldUseCPU(dataSet.imageIds, options.cpuThresholds?.image ??
55
- configuredCpuThresholds?.image ??
56
- DEFAULT_PLANAR_CPU_IMAGE_THRESHOLD);
73
+ return getShouldUseCPURendering();
57
74
  }
58
75
  shouldUseCPUForVolume(dataSet, options) {
59
76
  if (options.webGLAvailable === false) {
@@ -1,5 +1,5 @@
1
1
  import { OrientationAxis, ViewportType, VOILUTFunctionType } from '../../../enums';
2
- import type { ActorEntry, ICamera, IImage, IStackInput, OrientationVectors, Point2, Point3, ReferenceCompatibleOptions, VOIRange, ViewReference, ViewReferenceSpecifier } from '../../../types';
2
+ import type { ActorEntry, ICamera, IImage, IStackInput, ImageActor, OrientationVectors, Point2, Point3, ReferenceCompatibleOptions, VOIRange, ViewReference, ViewReferenceSpecifier, ViewportContentMode } from '../../../types';
3
3
  import type { PlaneRestriction } from '../../../types/IViewport';
4
4
  import type ViewportInputOptions from '../../../types/ViewportInputOptions';
5
5
  import GenericViewport from '../GenericViewport';
@@ -33,6 +33,7 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
33
33
  private renderImageObjectDataId?;
34
34
  private resolvedViewCache?;
35
35
  private resolvedViewCacheRevision;
36
+ private cachedCanvasDimensions?;
36
37
  private setDataRequestId;
37
38
  static get useCustomRenderingPipeline(): boolean;
38
39
  constructor(args: PlanarViewportInput);
@@ -45,6 +46,8 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
45
46
  removeData(dataId: string): void;
46
47
  getActors(): ActorEntry[];
47
48
  getDefaultActor(): ActorEntry | undefined;
49
+ getImageActor(volumeId?: string): ImageActor | null;
50
+ getDefaultImageData(): any;
48
51
  renderImageObject(image: IImage): Promise<void>;
49
52
  getCanvas(): HTMLCanvasElement;
50
53
  addImages(stackInputs: IStackInput[]): Promise<void>;
@@ -67,10 +70,14 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
67
70
  getImageIds(): string[];
68
71
  getVolumeId(viewRefSpecifier?: ViewReferenceSpecifier): string | undefined;
69
72
  getSourceDataId(): string | undefined;
73
+ getCurrentMode(): ViewportContentMode;
74
+ protected notifyDataPresentationModified(displaySetId: string, props: Partial<PlanarDataPresentation>): void;
70
75
  getDefaultVOIRange(dataId?: string): VOIRange | undefined;
71
76
  getCurrentImageIdIndex(): number;
72
77
  getCurrentImageId(viewRefSpecifier?: ViewReferenceSpecifier): string | undefined;
73
78
  getSliceIndex(): number;
79
+ getNumberOfSlices(): number;
80
+ calibrateSpacing(imageId: string): void;
74
81
  protected normalizeViewState(viewState: PlanarViewState): PlanarViewState;
75
82
  setViewState(viewStatePatch: Partial<PlanarViewState>): void;
76
83
  setDisplaySetPresentation(props: Partial<PlanarDataPresentation>): void;
@@ -112,8 +119,10 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
112
119
  setImageIdIndex(imageIdIndex: number): Promise<string>;
113
120
  scroll(delta: number): Promise<string>;
114
121
  setOrientation(orientation: PlanarSetOrientationInput): void;
122
+ canRenderOrientation(orientation: PlanarSetOrientationInput, dataId?: string): boolean;
115
123
  resetViewState(options?: PlanarResetViewStateOptions): boolean;
116
124
  resetViewStateForResize(): boolean;
125
+ resetDisplaySetPresentation(dataId?: string): void;
117
126
  getUseCustomRenderingPipeline(): boolean;
118
127
  setRendered(): void;
119
128
  resize(): void;
@@ -154,6 +163,9 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
154
163
  private getVolumeSliceWorldPointForImageIdIndex;
155
164
  private getPlanarData;
156
165
  protected getCurrentBinding(): import("./PlanarMountedData").PlanarDataBinding;
166
+ private removeReplaceableData;
167
+ private resolveNextSourceId;
168
+ private isSegmentationOverlayBinding;
157
169
  private getDataSet;
158
170
  private loadPlanarData;
159
171
  private applyLoadedPlanarViewState;
@@ -165,10 +177,11 @@ declare class PlanarViewport extends GenericViewport<PlanarViewState, PlanarData
165
177
  private resolveOverlayReference;
166
178
  private resolveOverlayDataId;
167
179
  protected findBindingDataIdByActorEntryUID(actorEntryUID: string): string | undefined;
168
- protected findDataIdByVolumeId(volumeId: string): string | undefined;
180
+ findDataIdByVolumeId(volumeId: string): string | undefined;
169
181
  protected getCurrentPlanarRendering(): PlanarRendering | undefined;
170
182
  private resolveViewState;
171
183
  private getProjectionSnapshot;
184
+ private getCachedPlanarCanvasDimensions;
172
185
  private resolveCachedViewState;
173
186
  private clearResolvedViewCache;
174
187
  private resolveFrameOfReferenceUID;