@cornerstonejs/core 1.21.1 → 1.22.0

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 (48) hide show
  1. package/dist/cjs/RenderingEngine/BaseVolumeViewport.d.ts +10 -4
  2. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +112 -16
  3. package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  4. package/dist/cjs/RenderingEngine/StackViewport.d.ts +12 -3
  5. package/dist/cjs/RenderingEngine/StackViewport.js +113 -7
  6. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  7. package/dist/cjs/RenderingEngine/VolumeViewport.js +9 -0
  8. package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
  9. package/dist/cjs/types/IStackViewport.d.ts +5 -4
  10. package/dist/cjs/types/IVolumeViewport.d.ts +5 -2
  11. package/dist/cjs/types/ViewportProperties.d.ts +2 -0
  12. package/dist/cjs/types/VolumeViewportProperties.d.ts +1 -2
  13. package/dist/cjs/utilities/index.d.ts +2 -1
  14. package/dist/cjs/utilities/index.js +3 -1
  15. package/dist/cjs/utilities/index.js.map +1 -1
  16. package/dist/cjs/utilities/transferFunctionUtils.d.ts +3 -0
  17. package/dist/cjs/utilities/transferFunctionUtils.js +22 -0
  18. package/dist/cjs/utilities/transferFunctionUtils.js.map +1 -0
  19. package/dist/esm/RenderingEngine/BaseVolumeViewport.d.ts +10 -4
  20. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +112 -16
  21. package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
  22. package/dist/esm/RenderingEngine/StackViewport.d.ts +12 -3
  23. package/dist/esm/RenderingEngine/StackViewport.js +116 -8
  24. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  25. package/dist/esm/RenderingEngine/VolumeViewport.js +10 -1
  26. package/dist/esm/RenderingEngine/VolumeViewport.js.map +1 -1
  27. package/dist/esm/types/IStackViewport.d.ts +5 -4
  28. package/dist/esm/types/IVolumeViewport.d.ts +5 -2
  29. package/dist/esm/types/ViewportProperties.d.ts +2 -0
  30. package/dist/esm/types/VolumeViewportProperties.d.ts +1 -2
  31. package/dist/esm/utilities/index.d.ts +2 -1
  32. package/dist/esm/utilities/index.js +2 -1
  33. package/dist/esm/utilities/index.js.map +1 -1
  34. package/dist/esm/utilities/transferFunctionUtils.d.ts +3 -0
  35. package/dist/esm/utilities/transferFunctionUtils.js +18 -0
  36. package/dist/esm/utilities/transferFunctionUtils.js.map +1 -0
  37. package/dist/umd/index.js +1 -1
  38. package/dist/umd/index.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/RenderingEngine/BaseVolumeViewport.ts +182 -19
  41. package/src/RenderingEngine/StackViewport.ts +204 -22
  42. package/src/RenderingEngine/VolumeViewport.ts +22 -1
  43. package/src/types/IStackViewport.ts +31 -8
  44. package/src/types/IVolumeViewport.ts +27 -5
  45. package/src/types/ViewportProperties.ts +3 -0
  46. package/src/types/VolumeViewportProperties.ts +2 -3
  47. package/src/utilities/index.ts +2 -0
  48. package/src/utilities/transferFunctionUtils.ts +23 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
4
4
  "description": "",
5
5
  "main": "dist/umd/index.js",
6
6
  "types": "dist/esm/index.d.ts",
@@ -46,5 +46,5 @@
46
46
  "type": "individual",
47
47
  "url": "https://ohif.org/donate"
48
48
  },
49
- "gitHead": "e0cd0dfada076421daa18efa66489b3695f84617"
49
+ "gitHead": "ff226c7a2ed426dc568b8043d3bbbb1cdc993281"
50
50
  }
@@ -31,6 +31,7 @@ import type {
31
31
  Point2,
32
32
  Point3,
33
33
  VOIRange,
34
+ ViewportProperties,
34
35
  VolumeViewportProperties,
35
36
  } from '../types';
36
37
  import { VoiModifiedEventDetail } from '../types/EventTypes';
@@ -45,6 +46,7 @@ import {
45
46
  invertRgbTransferFunction,
46
47
  triggerEvent,
47
48
  colormap as colormapUtils,
49
+ isImageActor,
48
50
  } from '../utilities';
49
51
  import { createVolumeActor } from './helpers';
50
52
  import volumeNewImageEventDispatcher, {
@@ -54,6 +56,7 @@ import Viewport from './Viewport';
54
56
  import type { vtkSlabCamera as vtkSlabCameraType } from './vtkClasses/vtkSlabCamera';
55
57
  import vtkSlabCamera from './vtkClasses/vtkSlabCamera';
56
58
  import transformWorldToIndex from '../utilities/transformWorldToIndex';
59
+ import { getTransferFunctionNodes } from '../utilities/transferFunctionUtils';
57
60
 
58
61
  /**
59
62
  * Abstract base class for volume viewports. VolumeViewports are used to render
@@ -68,11 +71,16 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
68
71
  useCPURendering = false;
69
72
  use16BitTexture = false;
70
73
  private _FrameOfReferenceUID: string;
71
- private inverted = false;
72
74
 
75
+ protected initialTransferFunctionNodes: any;
73
76
  // Viewport Properties
74
- // TODO: similar to setVoi, this is only applicable to first volume
75
- private VOILUTFunction: VOILUTFunctionType;
77
+ private globalDefaultProperties: VolumeViewportProperties;
78
+ private perVolumeIdDefaultProperties = new Map<
79
+ string,
80
+ VolumeViewportProperties
81
+ >();
82
+
83
+ private viewportProperties: VolumeViewportProperties = {};
76
84
 
77
85
  constructor(props: ViewportInput) {
78
86
  super(props);
@@ -217,8 +225,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
217
225
  voiLUTFunction = VOILUTFunctionType.LINEAR;
218
226
  }
219
227
  const { voiRange } = this.getProperties();
220
- this.VOILUTFunction = voiLUTFunction;
221
228
  this.setVOI(voiRange, volumeId, suppressEvents);
229
+ this.viewportProperties.VOILUTFunction = voiLUTFunction;
222
230
  }
223
231
 
224
232
  /**
@@ -236,7 +244,6 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
236
244
  suppressEvents?: boolean
237
245
  ) {
238
246
  const applicableVolumeActorInfo = this._getApplicableVolumeActor(volumeId);
239
-
240
247
  if (!applicableVolumeActorInfo) {
241
248
  return;
242
249
  }
@@ -267,6 +274,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
267
274
  cfun.applyColorMap(colormapObj);
268
275
  cfun.setMappingRange(range[0], range[1]);
269
276
  volumeActor.getProperty().setRGBTransferFunction(0, cfun);
277
+
278
+ this.viewportProperties.colormap = colormap;
270
279
  }
271
280
 
272
281
  /**
@@ -283,6 +292,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
283
292
  return;
284
293
  }
285
294
  const { volumeActor } = applicableVolumeActorInfo;
295
+
286
296
  const ofun = vtkPiecewiseFunction.newInstance();
287
297
  if (typeof colormap.opacity === 'number') {
288
298
  const range = volumeActor
@@ -298,6 +308,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
298
308
  });
299
309
  }
300
310
  volumeActor.getProperty().setScalarOpacity(0, ofun);
311
+
312
+ this.viewportProperties.colormap.opacity = colormap.opacity;
301
313
  }
302
314
 
303
315
  /**
@@ -310,7 +322,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
310
322
  * @returns void
311
323
  */
312
324
  private setInvert(
313
- invert: boolean,
325
+ inverted: boolean,
314
326
  volumeId?: string,
315
327
  suppressEvents?: boolean
316
328
  ) {
@@ -325,17 +337,18 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
325
337
  const cfun = this._getOrCreateColorTransferFunction(volumeIdToUse);
326
338
  invertRgbTransferFunction(cfun);
327
339
 
328
- this.inverted = invert;
340
+ const { voiRange, VOILUTFunction, invert } =
341
+ this.getProperties(volumeIdToUse);
329
342
 
330
- const { voiRange } = this.getProperties();
343
+ this.viewportProperties.invert = invert;
331
344
 
332
345
  if (!suppressEvents) {
333
346
  const eventDetail: VoiModifiedEventDetail = {
334
347
  viewportId: this.id,
335
348
  range: voiRange,
336
349
  volumeId: volumeIdToUse,
337
- VOILUTFunction: this.VOILUTFunction,
338
- invert: this.inverted,
350
+ VOILUTFunction: VOILUTFunction,
351
+ invert: invert,
339
352
  invertStateChanged: true,
340
353
  };
341
354
 
@@ -383,6 +396,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
383
396
 
384
397
  // @ts-ignore
385
398
  volumeProperty.setInterpolationType(interpolationType);
399
+ this.viewportProperties.interpolationType = interpolationType;
386
400
  }
387
401
 
388
402
  /**
@@ -415,9 +429,11 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
415
429
  voiRangeToUse = maxVoiRange;
416
430
  }
417
431
 
432
+ const { VOILUTFunction } = this.getProperties(volumeIdToUse);
433
+
418
434
  // scaling logic here
419
435
  // https://github.com/Kitware/vtk-js/blob/c6f2e12cddfe5c0386a73f0793eb6d9ab20d573e/Sources/Rendering/OpenGL/VolumeMapper/index.js#L957-L972
420
- if (this.VOILUTFunction === VOILUTFunctionType.SAMPLED_SIGMOID) {
436
+ if (VOILUTFunction === VOILUTFunctionType.SAMPLED_SIGMOID) {
421
437
  const cfun = createSigmoidRGBTransferFunction(voiRangeToUse);
422
438
  volumeActor.getProperty().setRGBTransferFunction(0, cfun);
423
439
  } else {
@@ -433,6 +449,14 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
433
449
  .getProperty()
434
450
  .getRGBTransferFunction(0)
435
451
  .setRange(lower, upper);
452
+
453
+ if (!this.initialTransferFunctionNodes) {
454
+ const transferFunction = volumeActor
455
+ .getProperty()
456
+ .getRGBTransferFunction(0);
457
+ this.initialTransferFunctionNodes =
458
+ getTransferFunctionNodes(transferFunction);
459
+ }
436
460
  }
437
461
 
438
462
  if (!suppressEvents) {
@@ -440,15 +464,49 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
440
464
  viewportId: this.id,
441
465
  range: voiRange,
442
466
  volumeId: volumeIdToUse,
443
- VOILUTFunction: this.VOILUTFunction,
467
+ VOILUTFunction: VOILUTFunction,
444
468
  };
445
469
 
446
470
  triggerEvent(this.element, Events.VOI_MODIFIED, eventDetail);
447
471
  }
472
+
473
+ this.viewportProperties.voiRange = voiRangeToUse;
474
+ }
475
+
476
+ /**
477
+ * Update the default properties for the volume viewport on the volume
478
+ * @param ViewportProperties - The properties to set
479
+ * @param volumeId - The volume id to set the default properties for (if undefined, we set the global default viewport properties)
480
+ */
481
+ public setDefaultProperties(
482
+ ViewportProperties: VolumeViewportProperties,
483
+ volumeId?: string
484
+ ): void {
485
+ if (volumeId == null) {
486
+ this.globalDefaultProperties = ViewportProperties;
487
+ } else {
488
+ this.perVolumeIdDefaultProperties.set(volumeId, ViewportProperties);
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Remove the global default properties of the viewport or remove default properties for a volumeId if specified
494
+ * @param volumeId If given, we remove the default properties only for this volumeId, if not
495
+ * the global default properties will be removed
496
+ */
497
+ public clearDefaultProperties(volumeId?: string): void {
498
+ if (volumeId == null) {
499
+ this.globalDefaultProperties = {};
500
+ this.resetProperties();
501
+ } else {
502
+ this.perVolumeIdDefaultProperties.delete(volumeId);
503
+ this.resetToDefaultProperties(volumeId);
504
+ }
448
505
  }
449
506
 
450
507
  /**
451
508
  * Sets the properties for the volume viewport on the volume
509
+ * and if setProperties is called for the first time, the properties will also become the default one.
452
510
  * (if fusion, it sets it for the first volume in the fusion)
453
511
  *
454
512
  * @param VolumeViewportProperties - The properties to set
@@ -456,7 +514,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
456
514
  * @param [VolumeViewportProperties.VOILUTFunction] - Sets the voi mode (LINEAR, or SAMPLED_SIGMOID)
457
515
  * @param [VolumeViewportProperties.invert] - Inverts the color transfer function
458
516
  * @param [VolumeViewportProperties.colormap] - Sets the colormap
459
- * @param [VolumeViewportProperties.preset] - Sets the colormap
517
+ * @param [VolumeViewportProperties.preset] - Sets the colormap preset
460
518
  * @param volumeId - The volume id to set the properties for (if undefined, the first volume)
461
519
  * @param suppressEvents - If true, the viewport will not emit events
462
520
  */
@@ -468,10 +526,23 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
468
526
  colormap,
469
527
  preset,
470
528
  interpolationType,
529
+ slabThickness,
471
530
  }: VolumeViewportProperties = {},
472
531
  volumeId?: string,
473
532
  suppressEvents = false
474
533
  ): void {
534
+ //If the viewport hasn't been initialized, we need to set the default properties
535
+ if (this.globalDefaultProperties == null) {
536
+ this.setDefaultProperties({
537
+ voiRange,
538
+ VOILUTFunction,
539
+ invert,
540
+ colormap,
541
+ preset,
542
+ slabThickness,
543
+ });
544
+ }
545
+
475
546
  // Note: colormap should always be done first, since we can then
476
547
  // modify the voiRange
477
548
 
@@ -494,13 +565,55 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
494
565
  this.setVOILUTFunction(VOILUTFunction, volumeId, suppressEvents);
495
566
  }
496
567
 
497
- if (invert !== undefined && this.inverted !== invert) {
568
+ if (invert !== undefined) {
498
569
  this.setInvert(invert, volumeId, suppressEvents);
499
570
  }
500
571
 
501
572
  if (preset !== undefined) {
502
573
  this.setPreset(preset, volumeId, suppressEvents);
503
574
  }
575
+
576
+ if (slabThickness !== undefined) {
577
+ this.setSlabThickness(slabThickness);
578
+ //We need to set the current slab thickness here since setSlabThickness is define in VolumeViewport
579
+ this.viewportProperties.slabThickness = slabThickness;
580
+ }
581
+ }
582
+
583
+ /**
584
+ * Reset the viewport properties to the default values
585
+ */
586
+ public resetToDefaultProperties(volumeId: string): void {
587
+ const properties = this.globalDefaultProperties;
588
+
589
+ if (properties.colormap?.name) {
590
+ this.setColormap(properties.colormap, volumeId);
591
+ }
592
+ if (properties.colormap?.opacity != null) {
593
+ this.setOpacity(properties.colormap, volumeId);
594
+ }
595
+
596
+ if (properties.voiRange !== undefined) {
597
+ this.setVOI(properties.voiRange, volumeId);
598
+ }
599
+
600
+ if (properties.VOILUTFunction !== undefined) {
601
+ this.setVOILUTFunction(properties.VOILUTFunction, volumeId);
602
+ }
603
+
604
+ if (properties.invert !== undefined) {
605
+ this.setInvert(properties.invert, volumeId);
606
+ }
607
+
608
+ if (properties.slabThickness !== undefined) {
609
+ this.setSlabThickness(properties.slabThickness);
610
+ //We need to set the current slabthickness here since setSlabThickness is define in VolumeViewport
611
+ // this.currentViewportProperties.get(volumeId).slabThickness =
612
+ // properties.slabThickness;
613
+ this.viewportProperties.slabThickness = properties.slabThickness;
614
+ }
615
+
616
+ this.render();
504
617
  }
505
618
 
506
619
  /**
@@ -530,13 +643,52 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
530
643
  }
531
644
 
532
645
  applyPreset(volumeActor, preset);
646
+
647
+ this.viewportProperties.preset = presetName;
533
648
  }
534
649
 
650
+ /**
651
+ * Retrieve the viewport default properties
652
+ * @param volumeId If given, we retrieve the default properties of a volumeId if it exists
653
+ * If not given,we return the global properties of the viewport
654
+ * @returns default viewport properties including voi, invert, interpolation type, colormap
655
+ */
656
+ public getDefaultProperties = (
657
+ volumeId?: string
658
+ ): VolumeViewportProperties => {
659
+ let volumeProperties;
660
+ if (volumeId !== undefined) {
661
+ volumeProperties = this.perVolumeIdDefaultProperties.get(volumeId);
662
+ }
663
+
664
+ if (volumeProperties !== undefined) {
665
+ return volumeProperties;
666
+ }
667
+
668
+ return {
669
+ ...this.globalDefaultProperties,
670
+ };
671
+ };
672
+
535
673
  /**
536
674
  * Retrieve the viewport properties
675
+ * @param volumeId - The volume id to get the properties for (if undefined, the first volume)
537
676
  * @returns viewport properties including voi, interpolation type: TODO: slabThickness, invert, rotation, flip
538
677
  */
539
- public getProperties = (): VolumeViewportProperties => {
678
+ public getProperties = (volumeId?: string): VolumeViewportProperties => {
679
+ const applicableVolumeActorInfo = this._getApplicableVolumeActor(volumeId);
680
+ if (!applicableVolumeActorInfo) {
681
+ return;
682
+ }
683
+
684
+ const {
685
+ colormap,
686
+ VOILUTFunction,
687
+ interpolationType,
688
+ invert,
689
+ slabThickness,
690
+ } = this.viewportProperties;
691
+
540
692
  const voiRanges = this.getActors()
541
693
  .map((actorEntry) => {
542
694
  const volumeActor = actorEntry.actor as vtkVolume;
@@ -547,7 +699,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
547
699
  }
548
700
  const cfun = volumeActor.getProperty().getRGBTransferFunction(0);
549
701
  const [lower, upper] =
550
- this.VOILUTFunction === 'SIGMOID'
702
+ this.viewportProperties?.VOILUTFunction === 'SIGMOID'
551
703
  ? getVoiFromSigmoidRGBTransferFunction(cfun)
552
704
  : cfun.getRange();
553
705
  return { volumeId, voiRange: { lower, upper } };
@@ -555,9 +707,15 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
555
707
  .filter(Boolean);
556
708
 
557
709
  const voiRange = voiRanges.length ? voiRanges[0].voiRange : null;
558
- const VOILUTFunction = this.VOILUTFunction;
559
710
 
560
- return { voiRange, VOILUTFunction, invert: this.inverted };
711
+ return {
712
+ colormap: colormap,
713
+ voiRange: voiRange,
714
+ VOILUTFunction: VOILUTFunction,
715
+ interpolationType: interpolationType,
716
+ invert: invert,
717
+ slabThickness: slabThickness,
718
+ };
561
719
  };
562
720
 
563
721
  /**
@@ -873,7 +1031,12 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
873
1031
  */
874
1032
  private _setVolumeActors(volumeActorEntries: Array<ActorEntry>): void {
875
1033
  // New volume actors implies resetting the inverted flag (i.e. like starting from scratch).
876
- this.inverted = false;
1034
+
1035
+ for (let i = 0; i < volumeActorEntries.length; i++) {
1036
+ const volumeId = volumeActorEntries[i].uid;
1037
+
1038
+ this.viewportProperties.invert = false;
1039
+ }
877
1040
  this.setActors(volumeActorEntries);
878
1041
  }
879
1042