@cornerstonejs/core 3.29.1 → 3.29.2
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.
- package/dist/esm/RenderingEngine/BaseRenderingEngine.d.ts +53 -0
- package/dist/esm/RenderingEngine/BaseRenderingEngine.js +341 -0
- package/dist/esm/RenderingEngine/BaseVolumeViewport.d.ts +18 -0
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js +77 -0
- package/dist/esm/RenderingEngine/RenderingEngine.d.ts +4 -38
- package/dist/esm/RenderingEngine/RenderingEngine.js +37 -614
- package/dist/esm/RenderingEngine/SequentialRenderingEngine.d.ts +18 -0
- package/dist/esm/RenderingEngine/SequentialRenderingEngine.js +235 -0
- package/dist/esm/RenderingEngine/StackViewport.d.ts +2 -0
- package/dist/esm/RenderingEngine/StackViewport.js +71 -3
- package/dist/esm/RenderingEngine/StandardRenderingEngine.d.ts +23 -0
- package/dist/esm/RenderingEngine/StandardRenderingEngine.js +285 -0
- package/dist/esm/RenderingEngine/helpers/isSequentialRenderingEngine.d.ts +1 -0
- package/dist/esm/RenderingEngine/helpers/isSequentialRenderingEngine.js +6 -0
- package/dist/esm/RenderingEngine/index.d.ts +4 -1
- package/dist/esm/RenderingEngine/index.js +4 -1
- package/dist/esm/enums/RenderingEngineModeEnum.d.ts +5 -0
- package/dist/esm/enums/RenderingEngineModeEnum.js +6 -0
- package/dist/esm/enums/index.d.ts +2 -1
- package/dist/esm/enums/index.js +2 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/init.js +2 -0
- package/dist/esm/types/Cornerstone3DConfig.d.ts +9 -7
- package/dist/esm/types/IRenderingEngine.d.ts +1 -1
- package/dist/esm/types/RenderingEngineMode.d.ts +2 -0
- package/dist/esm/types/RenderingEngineMode.js +0 -0
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +2 -2
|
@@ -1,645 +1,68 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import triggerEvent from '../utilities/triggerEvent';
|
|
6
|
-
import { vtkOffscreenMultiRenderWindow } from './vtkClasses';
|
|
7
|
-
import ViewportType from '../enums/ViewportType';
|
|
8
|
-
import VolumeViewport from './VolumeViewport';
|
|
9
|
-
import BaseVolumeViewport from './BaseVolumeViewport';
|
|
10
|
-
import StackViewport from './StackViewport';
|
|
11
|
-
import viewportTypeUsesCustomRenderingPipeline from './helpers/viewportTypeUsesCustomRenderingPipeline';
|
|
12
|
-
import getOrCreateCanvas from './helpers/getOrCreateCanvas';
|
|
13
|
-
import { getShouldUseCPURendering, isCornerstoneInitialized } from '../init';
|
|
14
|
-
import viewportTypeToViewportClass from './helpers/viewportTypeToViewportClass';
|
|
15
|
-
import { OrientationAxis } from '../enums';
|
|
16
|
-
import VolumeViewport3D from './VolumeViewport3D';
|
|
17
|
-
const VIEWPORT_MIN_SIZE = 2;
|
|
1
|
+
import { getConfiguration } from '../init';
|
|
2
|
+
import StandardRenderingEngine from './StandardRenderingEngine';
|
|
3
|
+
import SequentialRenderingEngine from './SequentialRenderingEngine';
|
|
4
|
+
import { RenderingEngineModeEnum } from '../enums';
|
|
18
5
|
class RenderingEngine {
|
|
19
6
|
constructor(id) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const viewports = this._getViewportsAsArray();
|
|
38
|
-
const eventDetailArray = [];
|
|
39
|
-
for (let i = 0; i < viewports.length; i++) {
|
|
40
|
-
const viewport = viewports[i];
|
|
41
|
-
if (this._needsRender.has(viewport.id)) {
|
|
42
|
-
const eventDetail = this.renderViewportUsingCustomOrVtkPipeline(viewport);
|
|
43
|
-
eventDetailArray.push(eventDetail);
|
|
44
|
-
viewport.setRendered();
|
|
45
|
-
this._needsRender.delete(viewport.id);
|
|
46
|
-
if (this._needsRender.size === 0) {
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
this._animationFrameSet = false;
|
|
52
|
-
this._animationFrameHandle = null;
|
|
53
|
-
eventDetailArray.forEach((eventDetail) => {
|
|
54
|
-
if (!eventDetail?.element) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
triggerEvent(eventDetail.element, Events.IMAGE_RENDERED, eventDetail);
|
|
58
|
-
});
|
|
59
|
-
};
|
|
60
|
-
this.id = id ? id : uuidv4();
|
|
61
|
-
this.useCPURendering = getShouldUseCPURendering();
|
|
62
|
-
renderingEngineCache.set(this);
|
|
63
|
-
if (!isCornerstoneInitialized()) {
|
|
64
|
-
throw new Error('@cornerstonejs/core is not initialized, run init() first');
|
|
65
|
-
}
|
|
66
|
-
if (!this.useCPURendering) {
|
|
67
|
-
this.offscreenMultiRenderWindow =
|
|
68
|
-
vtkOffscreenMultiRenderWindow.newInstance();
|
|
69
|
-
this.offScreenCanvasContainer = document.createElement('div');
|
|
70
|
-
this.offscreenMultiRenderWindow.setContainer(this.offScreenCanvasContainer);
|
|
71
|
-
}
|
|
72
|
-
this._viewports = new Map();
|
|
73
|
-
this.hasBeenDestroyed = false;
|
|
7
|
+
const config = getConfiguration();
|
|
8
|
+
const renderingEngineMode = config?.rendering?.renderingEngineMode;
|
|
9
|
+
switch (renderingEngineMode) {
|
|
10
|
+
case RenderingEngineModeEnum.Standard:
|
|
11
|
+
this._implementation = new StandardRenderingEngine(id);
|
|
12
|
+
break;
|
|
13
|
+
case RenderingEngineModeEnum.Next:
|
|
14
|
+
this._implementation = new SequentialRenderingEngine(id);
|
|
15
|
+
break;
|
|
16
|
+
default:
|
|
17
|
+
console.warn(`RenderingEngine: Unknown rendering engine mode "${renderingEngineMode}". Defaulting to Next rendering engine.`);
|
|
18
|
+
this._implementation = new SequentialRenderingEngine(id);
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
get id() {
|
|
23
|
+
return this._implementation.id;
|
|
74
24
|
}
|
|
75
25
|
enableElement(viewportInputEntry) {
|
|
76
|
-
|
|
77
|
-
this._throwIfDestroyed();
|
|
78
|
-
const { element, viewportId } = viewportInput;
|
|
79
|
-
if (!element) {
|
|
80
|
-
throw new Error('No element provided');
|
|
81
|
-
}
|
|
82
|
-
const viewport = this.getViewport(viewportId);
|
|
83
|
-
if (viewport) {
|
|
84
|
-
this.disableElement(viewportId);
|
|
85
|
-
}
|
|
86
|
-
const { type } = viewportInput;
|
|
87
|
-
const viewportUsesCustomRenderingPipeline = viewportTypeUsesCustomRenderingPipeline(type);
|
|
88
|
-
if (!this.useCPURendering && !viewportUsesCustomRenderingPipeline) {
|
|
89
|
-
this.enableVTKjsDrivenViewport(viewportInput);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
this.addCustomViewport(viewportInput);
|
|
93
|
-
}
|
|
94
|
-
const canvas = getOrCreateCanvas(element);
|
|
95
|
-
const { background } = viewportInput.defaultOptions;
|
|
96
|
-
this.fillCanvasWithBackgroundColor(canvas, background);
|
|
26
|
+
return this._implementation.enableElement(viewportInputEntry);
|
|
97
27
|
}
|
|
98
28
|
disableElement(viewportId) {
|
|
99
|
-
this.
|
|
100
|
-
const viewport = this.getViewport(viewportId);
|
|
101
|
-
if (!viewport) {
|
|
102
|
-
console.warn(`viewport ${viewportId} does not exist`);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
this._resetViewport(viewport);
|
|
106
|
-
if (!viewportTypeUsesCustomRenderingPipeline(viewport.type) &&
|
|
107
|
-
!this.useCPURendering) {
|
|
108
|
-
this.offscreenMultiRenderWindow.removeRenderer(viewportId);
|
|
109
|
-
}
|
|
110
|
-
this._removeViewport(viewportId);
|
|
111
|
-
viewport.isDisabled = true;
|
|
112
|
-
this._needsRender.delete(viewportId);
|
|
113
|
-
const viewports = this.getViewports();
|
|
114
|
-
if (!viewports.length) {
|
|
115
|
-
this._clearAnimationFrame();
|
|
116
|
-
}
|
|
29
|
+
return this._implementation.disableElement(viewportId);
|
|
117
30
|
}
|
|
118
31
|
setViewports(publicViewportInputEntries) {
|
|
119
|
-
|
|
120
|
-
this._throwIfDestroyed();
|
|
121
|
-
this._reset();
|
|
122
|
-
const vtkDrivenViewportInputEntries = [];
|
|
123
|
-
const customRenderingViewportInputEntries = [];
|
|
124
|
-
viewportInputEntries.forEach((vpie) => {
|
|
125
|
-
if (!this.useCPURendering &&
|
|
126
|
-
!viewportTypeUsesCustomRenderingPipeline(vpie.type)) {
|
|
127
|
-
vtkDrivenViewportInputEntries.push(vpie);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
customRenderingViewportInputEntries.push(vpie);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
this.setVtkjsDrivenViewports(vtkDrivenViewportInputEntries);
|
|
134
|
-
this.setCustomViewports(customRenderingViewportInputEntries);
|
|
135
|
-
viewportInputEntries.forEach((vp) => {
|
|
136
|
-
const canvas = getOrCreateCanvas(vp.element);
|
|
137
|
-
const { background } = vp.defaultOptions;
|
|
138
|
-
this.fillCanvasWithBackgroundColor(canvas, background);
|
|
139
|
-
});
|
|
32
|
+
return this._implementation.setViewports(publicViewportInputEntries);
|
|
140
33
|
}
|
|
141
34
|
resize(immediate = true, keepCamera = true) {
|
|
142
|
-
this.
|
|
143
|
-
const viewports = this._getViewportsAsArray();
|
|
144
|
-
const vtkDrivenViewports = [];
|
|
145
|
-
const customRenderingViewports = [];
|
|
146
|
-
viewports.forEach((vpie) => {
|
|
147
|
-
if (!viewportTypeUsesCustomRenderingPipeline(vpie.type)) {
|
|
148
|
-
vtkDrivenViewports.push(vpie);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
customRenderingViewports.push(vpie);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
if (vtkDrivenViewports.length) {
|
|
155
|
-
this._resizeVTKViewports(vtkDrivenViewports, keepCamera, immediate);
|
|
156
|
-
}
|
|
157
|
-
if (customRenderingViewports.length) {
|
|
158
|
-
this._resizeUsingCustomResizeHandler(customRenderingViewports, keepCamera, immediate);
|
|
159
|
-
}
|
|
35
|
+
return this._implementation.resize(immediate, keepCamera);
|
|
160
36
|
}
|
|
161
37
|
getViewport(viewportId) {
|
|
162
|
-
return this.
|
|
38
|
+
return this._implementation.getViewport(viewportId);
|
|
163
39
|
}
|
|
164
40
|
getViewports() {
|
|
165
|
-
this.
|
|
166
|
-
return this._getViewportsAsArray();
|
|
41
|
+
return this._implementation.getViewports();
|
|
167
42
|
}
|
|
168
43
|
getStackViewport(viewportId) {
|
|
169
|
-
this.
|
|
170
|
-
const viewport = this.getViewport(viewportId);
|
|
171
|
-
if (!viewport) {
|
|
172
|
-
throw new Error(`Viewport with Id ${viewportId} does not exist`);
|
|
173
|
-
}
|
|
174
|
-
if (!(viewport instanceof StackViewport)) {
|
|
175
|
-
throw new Error(`Viewport with Id ${viewportId} is not a StackViewport.`);
|
|
176
|
-
}
|
|
177
|
-
return viewport;
|
|
44
|
+
return this._implementation.getStackViewport(viewportId);
|
|
178
45
|
}
|
|
179
46
|
getStackViewports() {
|
|
180
|
-
this.
|
|
181
|
-
const viewports = this.getViewports();
|
|
182
|
-
return viewports.filter((vp) => vp instanceof StackViewport);
|
|
47
|
+
return this._implementation.getStackViewports();
|
|
183
48
|
}
|
|
184
49
|
getVolumeViewports() {
|
|
185
|
-
this.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
};
|
|
190
|
-
return viewports.filter(isVolumeViewport);
|
|
50
|
+
return this._implementation.getVolumeViewports();
|
|
51
|
+
}
|
|
52
|
+
fillCanvasWithBackgroundColor(canvas, backgroundColor) {
|
|
53
|
+
return this._implementation.fillCanvasWithBackgroundColor(canvas, backgroundColor);
|
|
191
54
|
}
|
|
192
55
|
render() {
|
|
193
|
-
|
|
194
|
-
const viewportIds = viewports.map((vp) => vp.id);
|
|
195
|
-
this._setViewportsToBeRenderedNextFrame(viewportIds);
|
|
56
|
+
return this._implementation.render();
|
|
196
57
|
}
|
|
197
58
|
renderViewports(viewportIds) {
|
|
198
|
-
this.
|
|
59
|
+
return this._implementation.renderViewports(viewportIds);
|
|
199
60
|
}
|
|
200
61
|
renderViewport(viewportId) {
|
|
201
|
-
this.
|
|
62
|
+
return this._implementation.renderViewport(viewportId);
|
|
202
63
|
}
|
|
203
64
|
destroy() {
|
|
204
|
-
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
if (!this.useCPURendering) {
|
|
208
|
-
const viewports = this._getViewportsAsArray();
|
|
209
|
-
viewports.forEach((vp) => {
|
|
210
|
-
this.offscreenMultiRenderWindow.removeRenderer(vp.id);
|
|
211
|
-
});
|
|
212
|
-
this.offscreenMultiRenderWindow.delete();
|
|
213
|
-
delete this.offscreenMultiRenderWindow;
|
|
214
|
-
}
|
|
215
|
-
this._reset();
|
|
216
|
-
renderingEngineCache.delete(this.id);
|
|
217
|
-
this.hasBeenDestroyed = true;
|
|
218
|
-
}
|
|
219
|
-
fillCanvasWithBackgroundColor(canvas, backgroundColor) {
|
|
220
|
-
const ctx = canvas.getContext('2d');
|
|
221
|
-
let fillStyle;
|
|
222
|
-
if (backgroundColor) {
|
|
223
|
-
const rgb = backgroundColor.map((f) => Math.floor(255 * f));
|
|
224
|
-
fillStyle = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
fillStyle = 'black';
|
|
228
|
-
}
|
|
229
|
-
ctx.fillStyle = fillStyle;
|
|
230
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
231
|
-
}
|
|
232
|
-
_normalizeViewportInputEntry(viewportInputEntry) {
|
|
233
|
-
const { type, defaultOptions } = viewportInputEntry;
|
|
234
|
-
let options = defaultOptions;
|
|
235
|
-
if (!options || Object.keys(options).length === 0) {
|
|
236
|
-
options = {
|
|
237
|
-
background: [0, 0, 0],
|
|
238
|
-
orientation: null,
|
|
239
|
-
displayArea: null,
|
|
240
|
-
};
|
|
241
|
-
if (type === ViewportType.ORTHOGRAPHIC) {
|
|
242
|
-
options = {
|
|
243
|
-
...options,
|
|
244
|
-
orientation: OrientationAxis.AXIAL,
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return {
|
|
249
|
-
...viewportInputEntry,
|
|
250
|
-
defaultOptions: options,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
_normalizeViewportInputEntries(viewportInputEntries) {
|
|
254
|
-
const normalizedViewportInputs = [];
|
|
255
|
-
viewportInputEntries.forEach((viewportInput) => {
|
|
256
|
-
normalizedViewportInputs.push(this._normalizeViewportInputEntry(viewportInput));
|
|
257
|
-
});
|
|
258
|
-
return normalizedViewportInputs;
|
|
259
|
-
}
|
|
260
|
-
_resizeUsingCustomResizeHandler(customRenderingViewports, keepCamera = true, immediate = true) {
|
|
261
|
-
customRenderingViewports.forEach((vp) => {
|
|
262
|
-
if (typeof vp.resize === 'function') {
|
|
263
|
-
vp.resize();
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
customRenderingViewports.forEach((vp) => {
|
|
267
|
-
const prevCamera = vp.getCamera();
|
|
268
|
-
vp.resetCamera();
|
|
269
|
-
if (keepCamera) {
|
|
270
|
-
vp.setCamera(prevCamera);
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
if (immediate) {
|
|
274
|
-
this.render();
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
_resizeVTKViewports(vtkDrivenViewports, keepCamera = true, immediate = true) {
|
|
278
|
-
const canvasesDrivenByVtkJs = vtkDrivenViewports.map((vp) => {
|
|
279
|
-
return getOrCreateCanvas(vp.element);
|
|
280
|
-
});
|
|
281
|
-
canvasesDrivenByVtkJs.forEach((canvas) => {
|
|
282
|
-
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
283
|
-
canvas.width = canvas.clientWidth * devicePixelRatio;
|
|
284
|
-
canvas.height = canvas.clientHeight * devicePixelRatio;
|
|
285
|
-
});
|
|
286
|
-
if (canvasesDrivenByVtkJs.length) {
|
|
287
|
-
const { offScreenCanvasWidth, offScreenCanvasHeight } = this._resizeOffScreenCanvas(canvasesDrivenByVtkJs);
|
|
288
|
-
this._resize(vtkDrivenViewports, offScreenCanvasWidth, offScreenCanvasHeight);
|
|
289
|
-
}
|
|
290
|
-
vtkDrivenViewports.forEach((vp) => {
|
|
291
|
-
const prevCamera = vp.getCamera();
|
|
292
|
-
const rotation = vp.getRotation();
|
|
293
|
-
const { flipHorizontal } = prevCamera;
|
|
294
|
-
vp.resetCameraForResize();
|
|
295
|
-
const displayArea = vp.getDisplayArea();
|
|
296
|
-
if (keepCamera) {
|
|
297
|
-
if (displayArea) {
|
|
298
|
-
if (flipHorizontal) {
|
|
299
|
-
vp.setCamera({ flipHorizontal });
|
|
300
|
-
}
|
|
301
|
-
if (rotation) {
|
|
302
|
-
vp.setViewPresentation({ rotation });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
vp.setCamera(prevCamera);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
if (immediate) {
|
|
311
|
-
this.render();
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
enableVTKjsDrivenViewport(viewportInputEntry) {
|
|
315
|
-
const viewports = this._getViewportsAsArray();
|
|
316
|
-
const viewportsDrivenByVtkJs = viewports.filter((vp) => viewportTypeUsesCustomRenderingPipeline(vp.type) === false);
|
|
317
|
-
const canvasesDrivenByVtkJs = viewportsDrivenByVtkJs.map((vp) => vp.canvas);
|
|
318
|
-
const canvas = getOrCreateCanvas(viewportInputEntry.element);
|
|
319
|
-
canvasesDrivenByVtkJs.push(canvas);
|
|
320
|
-
const { offScreenCanvasWidth, offScreenCanvasHeight } = this._resizeOffScreenCanvas(canvasesDrivenByVtkJs);
|
|
321
|
-
const xOffset = this._resize(viewportsDrivenByVtkJs, offScreenCanvasWidth, offScreenCanvasHeight);
|
|
322
|
-
const internalViewportEntry = { ...viewportInputEntry, canvas };
|
|
323
|
-
this.addVtkjsDrivenViewport(internalViewportEntry, {
|
|
324
|
-
offScreenCanvasWidth,
|
|
325
|
-
offScreenCanvasHeight,
|
|
326
|
-
xOffset,
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
_removeViewport(viewportId) {
|
|
330
|
-
const viewport = this.getViewport(viewportId);
|
|
331
|
-
if (!viewport) {
|
|
332
|
-
console.warn(`viewport ${viewportId} does not exist`);
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
this._viewports.delete(viewportId);
|
|
336
|
-
}
|
|
337
|
-
addVtkjsDrivenViewport(viewportInputEntry, offscreenCanvasProperties) {
|
|
338
|
-
const { element, canvas, viewportId, type, defaultOptions } = viewportInputEntry;
|
|
339
|
-
element.tabIndex = -1;
|
|
340
|
-
const { offScreenCanvasWidth, offScreenCanvasHeight, xOffset } = offscreenCanvasProperties;
|
|
341
|
-
const { sxStartDisplayCoords, syStartDisplayCoords, sxEndDisplayCoords, syEndDisplayCoords, sx, sy, sWidth, sHeight, } = this._getViewportCoordsOnOffScreenCanvas(viewportInputEntry, offScreenCanvasWidth, offScreenCanvasHeight, xOffset);
|
|
342
|
-
this.offscreenMultiRenderWindow.addRenderer({
|
|
343
|
-
viewport: [
|
|
344
|
-
sxStartDisplayCoords,
|
|
345
|
-
syStartDisplayCoords,
|
|
346
|
-
sxEndDisplayCoords,
|
|
347
|
-
syEndDisplayCoords,
|
|
348
|
-
],
|
|
349
|
-
id: viewportId,
|
|
350
|
-
background: defaultOptions.background
|
|
351
|
-
? defaultOptions.background
|
|
352
|
-
: [0, 0, 0],
|
|
353
|
-
});
|
|
354
|
-
const viewportInput = {
|
|
355
|
-
id: viewportId,
|
|
356
|
-
element,
|
|
357
|
-
renderingEngineId: this.id,
|
|
358
|
-
type,
|
|
359
|
-
canvas,
|
|
360
|
-
sx,
|
|
361
|
-
sy,
|
|
362
|
-
sWidth,
|
|
363
|
-
sHeight,
|
|
364
|
-
defaultOptions: defaultOptions || {},
|
|
365
|
-
};
|
|
366
|
-
let viewport;
|
|
367
|
-
if (type === ViewportType.STACK) {
|
|
368
|
-
viewport = new StackViewport(viewportInput);
|
|
369
|
-
}
|
|
370
|
-
else if (type === ViewportType.ORTHOGRAPHIC ||
|
|
371
|
-
type === ViewportType.PERSPECTIVE) {
|
|
372
|
-
viewport = new VolumeViewport(viewportInput);
|
|
373
|
-
}
|
|
374
|
-
else if (type === ViewportType.VOLUME_3D) {
|
|
375
|
-
viewport = new VolumeViewport3D(viewportInput);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
throw new Error(`Viewport Type ${type} is not supported`);
|
|
379
|
-
}
|
|
380
|
-
this._viewports.set(viewportId, viewport);
|
|
381
|
-
const eventDetail = {
|
|
382
|
-
element,
|
|
383
|
-
viewportId,
|
|
384
|
-
renderingEngineId: this.id,
|
|
385
|
-
};
|
|
386
|
-
if (!viewport.suppressEvents) {
|
|
387
|
-
triggerEvent(eventTarget, Events.ELEMENT_ENABLED, eventDetail);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
addCustomViewport(viewportInputEntry) {
|
|
391
|
-
const { element, viewportId, type, defaultOptions } = viewportInputEntry;
|
|
392
|
-
element.tabIndex = -1;
|
|
393
|
-
const canvas = getOrCreateCanvas(element);
|
|
394
|
-
const { clientWidth, clientHeight } = canvas;
|
|
395
|
-
if (canvas.width !== clientWidth || canvas.height !== clientHeight) {
|
|
396
|
-
canvas.width = clientWidth;
|
|
397
|
-
canvas.height = clientHeight;
|
|
398
|
-
}
|
|
399
|
-
const viewportInput = {
|
|
400
|
-
id: viewportId,
|
|
401
|
-
renderingEngineId: this.id,
|
|
402
|
-
element,
|
|
403
|
-
type,
|
|
404
|
-
canvas,
|
|
405
|
-
sx: 0,
|
|
406
|
-
sy: 0,
|
|
407
|
-
sWidth: clientWidth,
|
|
408
|
-
sHeight: clientHeight,
|
|
409
|
-
defaultOptions: defaultOptions || {},
|
|
410
|
-
};
|
|
411
|
-
const ViewportType = viewportTypeToViewportClass[type];
|
|
412
|
-
const viewport = new ViewportType(viewportInput);
|
|
413
|
-
this._viewports.set(viewportId, viewport);
|
|
414
|
-
const eventDetail = {
|
|
415
|
-
element,
|
|
416
|
-
viewportId,
|
|
417
|
-
renderingEngineId: this.id,
|
|
418
|
-
};
|
|
419
|
-
triggerEvent(eventTarget, Events.ELEMENT_ENABLED, eventDetail);
|
|
420
|
-
}
|
|
421
|
-
setCustomViewports(viewportInputEntries) {
|
|
422
|
-
viewportInputEntries.forEach((vpie) => {
|
|
423
|
-
this.addCustomViewport(vpie);
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
setVtkjsDrivenViewports(viewportInputEntries) {
|
|
427
|
-
if (viewportInputEntries.length) {
|
|
428
|
-
const vtkDrivenCanvases = viewportInputEntries.map((vp) => getOrCreateCanvas(vp.element));
|
|
429
|
-
vtkDrivenCanvases.forEach((canvas) => {
|
|
430
|
-
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
431
|
-
const rect = canvas.getBoundingClientRect();
|
|
432
|
-
canvas.width = rect.width * devicePixelRatio;
|
|
433
|
-
canvas.height = rect.height * devicePixelRatio;
|
|
434
|
-
});
|
|
435
|
-
const { offScreenCanvasWidth, offScreenCanvasHeight } = this._resizeOffScreenCanvas(vtkDrivenCanvases);
|
|
436
|
-
let xOffset = 0;
|
|
437
|
-
for (let i = 0; i < viewportInputEntries.length; i++) {
|
|
438
|
-
const vtkDrivenViewportInputEntry = viewportInputEntries[i];
|
|
439
|
-
const canvas = vtkDrivenCanvases[i];
|
|
440
|
-
const internalViewportEntry = {
|
|
441
|
-
...vtkDrivenViewportInputEntry,
|
|
442
|
-
canvas,
|
|
443
|
-
};
|
|
444
|
-
this.addVtkjsDrivenViewport(internalViewportEntry, {
|
|
445
|
-
offScreenCanvasWidth,
|
|
446
|
-
offScreenCanvasHeight,
|
|
447
|
-
xOffset,
|
|
448
|
-
});
|
|
449
|
-
xOffset += canvas.width;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
_resizeOffScreenCanvas(canvasesDrivenByVtkJs) {
|
|
454
|
-
const { offScreenCanvasContainer, offscreenMultiRenderWindow } = this;
|
|
455
|
-
const offScreenCanvasHeight = Math.max(...canvasesDrivenByVtkJs.map((canvas) => canvas.height));
|
|
456
|
-
let offScreenCanvasWidth = 0;
|
|
457
|
-
canvasesDrivenByVtkJs.forEach((canvas) => {
|
|
458
|
-
offScreenCanvasWidth += canvas.width;
|
|
459
|
-
});
|
|
460
|
-
offScreenCanvasContainer.width = offScreenCanvasWidth;
|
|
461
|
-
offScreenCanvasContainer.height = offScreenCanvasHeight;
|
|
462
|
-
offscreenMultiRenderWindow.resize();
|
|
463
|
-
return { offScreenCanvasWidth, offScreenCanvasHeight };
|
|
464
|
-
}
|
|
465
|
-
_resize(viewportsDrivenByVtkJs, offScreenCanvasWidth, offScreenCanvasHeight) {
|
|
466
|
-
let _xOffset = 0;
|
|
467
|
-
for (let i = 0; i < viewportsDrivenByVtkJs.length; i++) {
|
|
468
|
-
const viewport = viewportsDrivenByVtkJs[i];
|
|
469
|
-
const { sxStartDisplayCoords, syStartDisplayCoords, sxEndDisplayCoords, syEndDisplayCoords, sx, sy, sWidth, sHeight, } = this._getViewportCoordsOnOffScreenCanvas(viewport, offScreenCanvasWidth, offScreenCanvasHeight, _xOffset);
|
|
470
|
-
_xOffset += viewport.canvas.width;
|
|
471
|
-
viewport.sx = sx;
|
|
472
|
-
viewport.sy = sy;
|
|
473
|
-
viewport.sWidth = sWidth;
|
|
474
|
-
viewport.sHeight = sHeight;
|
|
475
|
-
const renderer = this.offscreenMultiRenderWindow.getRenderer(viewport.id);
|
|
476
|
-
renderer.setViewport([
|
|
477
|
-
sxStartDisplayCoords,
|
|
478
|
-
syStartDisplayCoords,
|
|
479
|
-
sxEndDisplayCoords,
|
|
480
|
-
syEndDisplayCoords,
|
|
481
|
-
]);
|
|
482
|
-
}
|
|
483
|
-
return _xOffset;
|
|
484
|
-
}
|
|
485
|
-
_getViewportCoordsOnOffScreenCanvas(viewport, offScreenCanvasWidth, offScreenCanvasHeight, _xOffset) {
|
|
486
|
-
const { canvas } = viewport;
|
|
487
|
-
const { width: sWidth, height: sHeight } = canvas;
|
|
488
|
-
const sx = _xOffset;
|
|
489
|
-
const sy = 0;
|
|
490
|
-
const sxStartDisplayCoords = sx / offScreenCanvasWidth;
|
|
491
|
-
const syStartDisplayCoords = sy + (offScreenCanvasHeight - sHeight) / offScreenCanvasHeight;
|
|
492
|
-
const sWidthDisplayCoords = sWidth / offScreenCanvasWidth;
|
|
493
|
-
const sHeightDisplayCoords = sHeight / offScreenCanvasHeight;
|
|
494
|
-
return {
|
|
495
|
-
sxStartDisplayCoords,
|
|
496
|
-
syStartDisplayCoords,
|
|
497
|
-
sxEndDisplayCoords: sxStartDisplayCoords + sWidthDisplayCoords,
|
|
498
|
-
syEndDisplayCoords: syStartDisplayCoords + sHeightDisplayCoords,
|
|
499
|
-
sx,
|
|
500
|
-
sy,
|
|
501
|
-
sWidth,
|
|
502
|
-
sHeight,
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
_getViewportsAsArray() {
|
|
506
|
-
return Array.from(this._viewports.values());
|
|
507
|
-
}
|
|
508
|
-
_setViewportsToBeRenderedNextFrame(viewportIds) {
|
|
509
|
-
viewportIds.forEach((viewportId) => {
|
|
510
|
-
this._needsRender.add(viewportId);
|
|
511
|
-
});
|
|
512
|
-
this._render();
|
|
513
|
-
}
|
|
514
|
-
_render() {
|
|
515
|
-
if (this._needsRender.size > 0 && !this._animationFrameSet) {
|
|
516
|
-
this._animationFrameHandle = window.requestAnimationFrame(this._renderFlaggedViewports);
|
|
517
|
-
this._animationFrameSet = true;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
performVtkDrawCall() {
|
|
521
|
-
const { offscreenMultiRenderWindow } = this;
|
|
522
|
-
const renderWindow = offscreenMultiRenderWindow.getRenderWindow();
|
|
523
|
-
const renderers = offscreenMultiRenderWindow.getRenderers();
|
|
524
|
-
if (!renderers.length) {
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
for (let i = 0; i < renderers.length; i++) {
|
|
528
|
-
const { renderer, id } = renderers[i];
|
|
529
|
-
if (this._needsRender.has(id)) {
|
|
530
|
-
renderer.setDraw(true);
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
renderer.setDraw(false);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
renderWindow.render();
|
|
537
|
-
for (let i = 0; i < renderers.length; i++) {
|
|
538
|
-
renderers[i].renderer.setDraw(false);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
renderViewportUsingCustomOrVtkPipeline(viewport) {
|
|
542
|
-
let eventDetail;
|
|
543
|
-
if (viewport.sWidth < VIEWPORT_MIN_SIZE ||
|
|
544
|
-
viewport.sHeight < VIEWPORT_MIN_SIZE) {
|
|
545
|
-
console.warn('Viewport is too small', viewport.sWidth, viewport.sHeight);
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
if (viewportTypeUsesCustomRenderingPipeline(viewport.type) === true) {
|
|
549
|
-
eventDetail =
|
|
550
|
-
viewport.customRenderViewportToCanvas();
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
if (this.useCPURendering) {
|
|
554
|
-
throw new Error('GPU not available, and using a viewport with no custom render pipeline.');
|
|
555
|
-
}
|
|
556
|
-
const { offscreenMultiRenderWindow } = this;
|
|
557
|
-
const openGLRenderWindow = offscreenMultiRenderWindow.getOpenGLRenderWindow();
|
|
558
|
-
const context = openGLRenderWindow.get3DContext();
|
|
559
|
-
const offScreenCanvas = context.canvas;
|
|
560
|
-
eventDetail = this._renderViewportFromVtkCanvasToOnscreenCanvas(viewport, offScreenCanvas);
|
|
561
|
-
}
|
|
562
|
-
return eventDetail;
|
|
563
|
-
}
|
|
564
|
-
_renderViewportFromVtkCanvasToOnscreenCanvas(viewport, offScreenCanvas) {
|
|
565
|
-
const { element, canvas, sx, sy, sWidth, sHeight, id: viewportId, renderingEngineId, suppressEvents, } = viewport;
|
|
566
|
-
const { width: dWidth, height: dHeight } = canvas;
|
|
567
|
-
const onScreenContext = canvas.getContext('2d');
|
|
568
|
-
onScreenContext.drawImage(offScreenCanvas, sx, sy, sWidth, sHeight, 0, 0, dWidth, dHeight);
|
|
569
|
-
return {
|
|
570
|
-
element,
|
|
571
|
-
suppressEvents,
|
|
572
|
-
viewportId,
|
|
573
|
-
renderingEngineId,
|
|
574
|
-
viewportStatus: viewport.viewportStatus,
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
_resetViewport(viewport) {
|
|
578
|
-
const renderingEngineId = this.id;
|
|
579
|
-
const { element, canvas, id: viewportId } = viewport;
|
|
580
|
-
const eventDetail = {
|
|
581
|
-
element,
|
|
582
|
-
viewportId,
|
|
583
|
-
renderingEngineId,
|
|
584
|
-
};
|
|
585
|
-
viewport.removeWidgets();
|
|
586
|
-
triggerEvent(eventTarget, Events.ELEMENT_DISABLED, eventDetail);
|
|
587
|
-
element.removeAttribute('data-viewport-uid');
|
|
588
|
-
element.removeAttribute('data-rendering-engine-uid');
|
|
589
|
-
const context = canvas.getContext('2d');
|
|
590
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
591
|
-
}
|
|
592
|
-
_clearAnimationFrame() {
|
|
593
|
-
window.cancelAnimationFrame(this._animationFrameHandle);
|
|
594
|
-
this._needsRender.clear();
|
|
595
|
-
this._animationFrameSet = false;
|
|
596
|
-
this._animationFrameHandle = null;
|
|
597
|
-
}
|
|
598
|
-
_reset() {
|
|
599
|
-
const viewports = this._getViewportsAsArray();
|
|
600
|
-
viewports.forEach((viewport) => {
|
|
601
|
-
this._resetViewport(viewport);
|
|
602
|
-
});
|
|
603
|
-
this._clearAnimationFrame();
|
|
604
|
-
this._viewports = new Map();
|
|
605
|
-
}
|
|
606
|
-
_throwIfDestroyed() {
|
|
607
|
-
if (this.hasBeenDestroyed) {
|
|
608
|
-
throw new Error('this.destroy() has been manually called to free up memory, can not longer use this instance. Instead make a new one.');
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
_downloadOffScreenCanvas() {
|
|
612
|
-
const dataURL = this._debugRender();
|
|
613
|
-
_TEMPDownloadURI(dataURL);
|
|
614
|
-
}
|
|
615
|
-
_debugRender() {
|
|
616
|
-
const { offscreenMultiRenderWindow } = this;
|
|
617
|
-
const renderWindow = offscreenMultiRenderWindow.getRenderWindow();
|
|
618
|
-
const renderers = offscreenMultiRenderWindow.getRenderers();
|
|
619
|
-
for (let i = 0; i < renderers.length; i++) {
|
|
620
|
-
renderers[i].renderer.setDraw(true);
|
|
621
|
-
}
|
|
622
|
-
renderWindow.render();
|
|
623
|
-
const openGLRenderWindow = offscreenMultiRenderWindow.getOpenGLRenderWindow();
|
|
624
|
-
const context = openGLRenderWindow.get3DContext();
|
|
625
|
-
const offScreenCanvas = context.canvas;
|
|
626
|
-
const dataURL = offScreenCanvas.toDataURL();
|
|
627
|
-
this._getViewportsAsArray().forEach((viewport) => {
|
|
628
|
-
const { sx, sy, sWidth, sHeight } = viewport;
|
|
629
|
-
const canvas = viewport.canvas;
|
|
630
|
-
const { width: dWidth, height: dHeight } = canvas;
|
|
631
|
-
const onScreenContext = canvas.getContext('2d');
|
|
632
|
-
onScreenContext.drawImage(offScreenCanvas, sx, sy, sWidth, sHeight, 0, 0, dWidth, dHeight);
|
|
633
|
-
});
|
|
634
|
-
return dataURL;
|
|
65
|
+
return this._implementation.destroy();
|
|
635
66
|
}
|
|
636
67
|
}
|
|
637
68
|
export default RenderingEngine;
|
|
638
|
-
function _TEMPDownloadURI(uri) {
|
|
639
|
-
const link = document.createElement('a');
|
|
640
|
-
link.download = 'viewport.png';
|
|
641
|
-
link.href = uri;
|
|
642
|
-
document.body.appendChild(link);
|
|
643
|
-
link.click();
|
|
644
|
-
document.body.removeChild(link);
|
|
645
|
-
}
|