@cornerstonejs/tools 0.56.7 → 0.57.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 (101) hide show
  1. package/dist/cjs/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -1
  2. package/dist/cjs/stateManagement/segmentation/SegmentationStateManager.js +5 -2
  3. package/dist/cjs/stateManagement/segmentation/SegmentationStateManager.js.map +1 -1
  4. package/dist/cjs/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
  5. package/dist/cjs/stateManagement/segmentation/config/segmentationVisibility.js +23 -5
  6. package/dist/cjs/stateManagement/segmentation/config/segmentationVisibility.js.map +1 -1
  7. package/dist/cjs/stateManagement/segmentation/segmentationState.js +0 -10
  8. package/dist/cjs/stateManagement/segmentation/segmentationState.js.map +1 -1
  9. package/dist/cjs/tools/displayTools/Contour/addContourSetsToElement.d.ts +3 -0
  10. package/dist/cjs/tools/displayTools/Contour/addContourSetsToElement.js +70 -0
  11. package/dist/cjs/tools/displayTools/Contour/addContourSetsToElement.js.map +1 -0
  12. package/dist/cjs/tools/displayTools/Contour/addOrUpdateContourSets.d.ts +3 -0
  13. package/dist/cjs/tools/displayTools/Contour/addOrUpdateContourSets.js +14 -0
  14. package/dist/cjs/tools/displayTools/Contour/addOrUpdateContourSets.js.map +1 -0
  15. package/dist/cjs/tools/displayTools/Contour/contourConfig.d.ts +3 -0
  16. package/dist/cjs/tools/displayTools/Contour/contourConfig.js +14 -0
  17. package/dist/cjs/tools/displayTools/Contour/contourConfig.js.map +1 -0
  18. package/dist/cjs/tools/displayTools/Contour/contourConfigCache.d.ts +9 -0
  19. package/dist/cjs/tools/displayTools/Contour/contourConfigCache.js +17 -0
  20. package/dist/cjs/tools/displayTools/Contour/contourConfigCache.js.map +1 -0
  21. package/dist/cjs/tools/displayTools/Contour/contourDisplay.d.ts +1 -1
  22. package/dist/cjs/tools/displayTools/Contour/contourDisplay.js +4 -52
  23. package/dist/cjs/tools/displayTools/Contour/contourDisplay.js.map +1 -1
  24. package/dist/cjs/tools/displayTools/Contour/updateContourSets.d.ts +3 -0
  25. package/dist/cjs/tools/displayTools/Contour/updateContourSets.js +78 -0
  26. package/dist/cjs/tools/displayTools/Contour/updateContourSets.js.map +1 -0
  27. package/dist/cjs/tools/displayTools/Contour/utils.d.ts +6 -0
  28. package/dist/cjs/tools/displayTools/Contour/utils.js +63 -0
  29. package/dist/cjs/tools/displayTools/Contour/utils.js.map +1 -0
  30. package/dist/cjs/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  31. package/dist/cjs/types/ContourTypes.d.ts +1 -0
  32. package/dist/cjs/types/SegmentationStateTypes.d.ts +4 -4
  33. package/dist/cjs/types/index.d.ts +2 -2
  34. package/dist/cjs/utilities/cine/playClip.js +0 -1
  35. package/dist/cjs/utilities/cine/playClip.js.map +1 -1
  36. package/dist/cjs/utilities/planar/filterAnnotationsWithinSlice.js +10 -1
  37. package/dist/cjs/utilities/planar/filterAnnotationsWithinSlice.js.map +1 -1
  38. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -1
  39. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +5 -2
  40. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js.map +1 -1
  41. package/dist/esm/stateManagement/segmentation/config/segmentationColor.js.map +1 -1
  42. package/dist/esm/stateManagement/segmentation/config/segmentationVisibility.js +19 -5
  43. package/dist/esm/stateManagement/segmentation/config/segmentationVisibility.js.map +1 -1
  44. package/dist/esm/stateManagement/segmentation/segmentationState.js +1 -11
  45. package/dist/esm/stateManagement/segmentation/segmentationState.js.map +1 -1
  46. package/dist/esm/tools/displayTools/Contour/addContourSetsToElement.d.ts +3 -0
  47. package/dist/esm/tools/displayTools/Contour/addContourSetsToElement.js +63 -0
  48. package/dist/esm/tools/displayTools/Contour/addContourSetsToElement.js.map +1 -0
  49. package/dist/esm/tools/displayTools/Contour/addOrUpdateContourSets.d.ts +3 -0
  50. package/dist/esm/tools/displayTools/Contour/addOrUpdateContourSets.js +10 -0
  51. package/dist/esm/tools/displayTools/Contour/addOrUpdateContourSets.js.map +1 -0
  52. package/dist/esm/tools/displayTools/Contour/contourConfig.d.ts +3 -0
  53. package/dist/esm/tools/displayTools/Contour/contourConfig.js +12 -0
  54. package/dist/esm/tools/displayTools/Contour/contourConfig.js.map +1 -0
  55. package/dist/esm/tools/displayTools/Contour/contourConfigCache.d.ts +9 -0
  56. package/dist/esm/tools/displayTools/Contour/contourConfigCache.js +11 -0
  57. package/dist/esm/tools/displayTools/Contour/contourConfigCache.js.map +1 -0
  58. package/dist/esm/tools/displayTools/Contour/contourDisplay.d.ts +1 -1
  59. package/dist/esm/tools/displayTools/Contour/contourDisplay.js +6 -54
  60. package/dist/esm/tools/displayTools/Contour/contourDisplay.js.map +1 -1
  61. package/dist/esm/tools/displayTools/Contour/updateContourSets.d.ts +3 -0
  62. package/dist/esm/tools/displayTools/Contour/updateContourSets.js +71 -0
  63. package/dist/esm/tools/displayTools/Contour/updateContourSets.js.map +1 -0
  64. package/dist/esm/tools/displayTools/Contour/utils.d.ts +6 -0
  65. package/dist/esm/tools/displayTools/Contour/utils.js +53 -0
  66. package/dist/esm/tools/displayTools/Contour/utils.js.map +1 -0
  67. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js.map +1 -1
  68. package/dist/esm/types/ContourTypes.d.ts +1 -0
  69. package/dist/esm/types/SegmentationStateTypes.d.ts +4 -4
  70. package/dist/esm/types/index.d.ts +2 -2
  71. package/dist/esm/utilities/cine/playClip.js +0 -1
  72. package/dist/esm/utilities/cine/playClip.js.map +1 -1
  73. package/dist/esm/utilities/planar/filterAnnotationsWithinSlice.js +11 -2
  74. package/dist/esm/utilities/planar/filterAnnotationsWithinSlice.js.map +1 -1
  75. package/dist/umd/index.js +1 -1
  76. package/dist/umd/index.js.map +1 -1
  77. package/package.json +3 -3
  78. package/src/stateManagement/segmentation/SegmentationStateManager.ts +10 -7
  79. package/src/stateManagement/segmentation/config/segmentationColor.ts +1 -0
  80. package/src/stateManagement/segmentation/config/segmentationVisibility.ts +25 -7
  81. package/src/stateManagement/segmentation/segmentationState.ts +7 -23
  82. package/src/tools/displayTools/Contour/addContourSetsToElement.ts +110 -0
  83. package/src/tools/displayTools/Contour/addOrUpdateContourSets.ts +28 -0
  84. package/src/tools/displayTools/Contour/contourConfig.ts +15 -0
  85. package/src/tools/displayTools/Contour/contourConfigCache.ts +37 -0
  86. package/src/tools/displayTools/Contour/contourDisplay.ts +11 -91
  87. package/src/tools/displayTools/Contour/updateContourSets.ts +111 -0
  88. package/src/tools/displayTools/Contour/utils.ts +117 -0
  89. package/src/tools/displayTools/Labelmap/labelmapDisplay.ts +5 -2
  90. package/src/types/ContourTypes.ts +2 -0
  91. package/src/types/SegmentationStateTypes.ts +22 -8
  92. package/src/types/index.ts +2 -0
  93. package/src/utilities/cine/playClip.ts +2 -1
  94. package/src/utilities/planar/filterAnnotationsWithinSlice.ts +29 -3
  95. package/dist/cjs/tools/displayTools/Contour/addContourToElement.d.ts +0 -4
  96. package/dist/cjs/tools/displayTools/Contour/addContourToElement.js +0 -87
  97. package/dist/cjs/tools/displayTools/Contour/addContourToElement.js.map +0 -1
  98. package/dist/esm/tools/displayTools/Contour/addContourToElement.d.ts +0 -4
  99. package/dist/esm/tools/displayTools/Contour/addContourToElement.js +0 -80
  100. package/dist/esm/tools/displayTools/Contour/addContourToElement.js.map +0 -1
  101. package/src/tools/displayTools/Contour/addContourToElement.ts +0 -135
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "0.56.7",
3
+ "version": "0.57.1",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "main": "dist/umd/index.js",
6
6
  "types": "dist/esm/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
27
27
  },
28
28
  "dependencies": {
29
- "@cornerstonejs/core": "^0.36.6",
29
+ "@cornerstonejs/core": "^0.37.0",
30
30
  "lodash.clonedeep": "4.5.0",
31
31
  "lodash.get": "^4.4.2"
32
32
  },
@@ -52,5 +52,5 @@
52
52
  "type": "individual",
53
53
  "url": "https://ohif.org/donate"
54
54
  },
55
- "gitHead": "0eec4b306b9ff822ddac722f5eab2dd3161d0821"
55
+ "gitHead": "c340fede4008457cd754df259b40a9dfff912668"
56
56
  }
@@ -1,29 +1,32 @@
1
- import cloneDeep from 'lodash.clonedeep';
2
1
  import { utilities as csUtils } from '@cornerstonejs/core';
2
+ import cloneDeep from 'lodash.clonedeep';
3
3
 
4
4
  import CORNERSTONE_COLOR_LUT from '../../constants/COLOR_LUT';
5
5
 
6
+ import { SegmentationRepresentations } from '../../enums';
7
+ import getDefaultContourConfig from '../../tools/displayTools/Contour/contourConfig';
8
+ import getDefaultLabelmapConfig from '../../tools/displayTools/Labelmap/labelmapConfig';
6
9
  import type {
7
- SegmentationState,
8
10
  ColorLUT,
11
+ RepresentationConfig,
9
12
  Segmentation,
10
- ToolGroupSpecificRepresentation,
11
13
  SegmentationRepresentationConfig,
12
- ToolGroupSpecificRepresentations,
13
- RepresentationConfig,
14
+ SegmentationState,
14
15
  SegmentSpecificRepresentationConfig,
16
+ ToolGroupSpecificRepresentation,
17
+ ToolGroupSpecificRepresentations,
15
18
  } from '../../types/SegmentationStateTypes';
16
- import getDefaultLabelmapConfig from '../../tools/displayTools/Labelmap/labelmapConfig';
17
- import { SegmentationRepresentations } from '../../enums';
18
19
 
19
20
  // Initialize the default configuration
20
21
  // Note: when we get other representations, we should set their default representations too.
21
22
  const defaultLabelmapConfig = getDefaultLabelmapConfig();
23
+ const defaultContourConfig = getDefaultContourConfig();
22
24
 
23
25
  const newGlobalConfig: SegmentationRepresentationConfig = {
24
26
  renderInactiveSegmentations: true,
25
27
  representations: {
26
28
  [SegmentationRepresentations.Labelmap]: defaultLabelmapConfig,
29
+ [SegmentationRepresentations.Contour]: defaultContourConfig,
27
30
  },
28
31
  };
29
32
 
@@ -3,6 +3,7 @@ import * as SegmentationState from '../../../stateManagement/segmentation/segmen
3
3
  import { Color } from '../../../types/SegmentationStateTypes';
4
4
  import { ColorLUT } from '../../../types/SegmentationStateTypes';
5
5
  import { triggerSegmentationRepresentationModified } from '../triggerSegmentationEvents';
6
+ import { SegmentationRepresentations } from '../../../enums';
6
7
 
7
8
  /**
8
9
  * addColorLUT - Adds a new color LUT to the state at the given colorLUTIndex.
@@ -1,16 +1,34 @@
1
- import { cache } from '@cornerstonejs/core';
1
+ import { cache, Types } from '@cornerstonejs/core';
2
2
  import * as SegmentationState from '../../../stateManagement/segmentation/segmentationState';
3
3
  import { getSegmentationRepresentations } from '../../../stateManagement/segmentation/segmentationState';
4
4
  import { ToolGroupSpecificRepresentation } from '../../../types/SegmentationStateTypes';
5
5
  import { triggerSegmentationRepresentationModified } from '../triggerSegmentationEvents';
6
+ import SegmentationRepresentations from '../../../enums/SegmentationRepresentations';
6
7
 
7
8
  function getSegmentationIndices(segmentationId) {
8
- const volume = cache.getVolume(segmentationId);
9
- const scalarData = volume.getScalarData();
10
-
11
- const keySet = {};
12
- scalarData.forEach((it) => (keySet[it] = it));
13
- return Object.keys(keySet).map((it) => parseInt(it, 10));
9
+ const segmentation = SegmentationState.getSegmentation(segmentationId);
10
+
11
+ if (segmentation.type === SegmentationRepresentations.Labelmap) {
12
+ const volume = cache.getVolume(segmentationId);
13
+ const scalarData = volume.getScalarData();
14
+
15
+ const keySet = {};
16
+ scalarData.forEach((it) => (keySet[it] = it));
17
+ return Object.keys(keySet).map((it) => parseInt(it, 10));
18
+ } else if (segmentation.type === SegmentationRepresentations.Contour) {
19
+ const geometryIds = segmentation.representationData.CONTOUR?.geometryIds;
20
+
21
+ if (!geometryIds) {
22
+ throw new Error(
23
+ `No geometryIds found for segmentationId ${segmentationId}`
24
+ );
25
+ }
26
+
27
+ return geometryIds.map((geometryId) => {
28
+ const geometry = cache.getGeometry(geometryId) as Types.IGeometry;
29
+ return (geometry.data as Types.IContourSet).getSegmentIndex();
30
+ });
31
+ }
14
32
  }
15
33
 
16
34
  /**
@@ -1,10 +1,3 @@
1
- import { defaultSegmentationStateManager } from './SegmentationStateManager';
2
- import {
3
- triggerSegmentationRepresentationModified,
4
- triggerSegmentationModified,
5
- triggerSegmentationRepresentationRemoved,
6
- triggerSegmentationRemoved,
7
- } from './triggerSegmentationEvents';
8
1
  import type {
9
2
  ColorLUT,
10
3
  RepresentationConfig,
@@ -15,10 +8,15 @@ import type {
15
8
  ToolGroupSpecificRepresentation,
16
9
  ToolGroupSpecificRepresentations,
17
10
  } from '../../types/SegmentationStateTypes';
11
+ import { defaultSegmentationStateManager } from './SegmentationStateManager';
12
+ import {
13
+ triggerSegmentationModified,
14
+ triggerSegmentationRemoved,
15
+ triggerSegmentationRepresentationModified,
16
+ triggerSegmentationRepresentationRemoved,
17
+ } from './triggerSegmentationEvents';
18
18
 
19
19
  import normalizeSegmentationInput from './helpers/normalizeSegmentationInput';
20
- import getDefaultLabelmapConfig from '../../tools/displayTools/Labelmap/labelmapConfig';
21
- import { SegmentationRepresentations } from '../../enums';
22
20
 
23
21
  /**
24
22
  * It returns the defaultSegmentationStateManager.
@@ -385,21 +383,7 @@ function addColorLUT(colorLUT: ColorLUT, index: number): void {
385
383
  // Todo: trigger event color LUT added
386
384
  }
387
385
 
388
- // Initialize the default configuration
389
- // Note: when we get other representations, we should set their default representations too.
390
- const defaultLabelmapConfig = getDefaultLabelmapConfig();
391
-
392
- const newGlobalConfig: SegmentationRepresentationConfig = {
393
- renderInactiveSegmentations: true,
394
- representations: {
395
- [SegmentationRepresentations.Labelmap]: defaultLabelmapConfig,
396
- },
397
- };
398
-
399
- setGlobalConfig(newGlobalConfig, true);
400
-
401
386
  export {
402
- // state manager
403
387
  getDefaultSegmentationStateManager,
404
388
  // Segmentation
405
389
  getSegmentation,
@@ -0,0 +1,110 @@
1
+ import { cache, Types } from '@cornerstonejs/core';
2
+ import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
3
+ import vtkAppendPolyData from '@kitware/vtk.js/Filters/General/AppendPolyData';
4
+ import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
5
+ import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
6
+
7
+ import {
8
+ getPolyData,
9
+ getSegmentSpecificConfig,
10
+ validateGeometry,
11
+ } from './utils';
12
+
13
+ import {
14
+ SegmentationRepresentationConfig,
15
+ ToolGroupSpecificContourRepresentation,
16
+ } from '../../../types';
17
+ import { getConfigCache, setConfigCache } from './contourConfigCache';
18
+
19
+ export function addContourSetsToElement(
20
+ viewport: Types.IVolumeViewport,
21
+ geometryIds: string[],
22
+ contourRepresentation: ToolGroupSpecificContourRepresentation,
23
+ contourRepresentationConfig: SegmentationRepresentationConfig,
24
+ contourActorUID: string
25
+ ) {
26
+ const { segmentationRepresentationUID, segmentsHidden } =
27
+ contourRepresentation;
28
+ const appendPolyData = vtkAppendPolyData.newInstance();
29
+
30
+ const scalarToColorMap = new Map();
31
+ const segmentSpecificMap = new Map();
32
+
33
+ geometryIds.forEach((geometryId) => {
34
+ const geometry = cache.getGeometry(geometryId);
35
+
36
+ if (!geometry) {
37
+ console.warn(
38
+ `No geometry found for geometryId ${geometryId}. Skipping render.`
39
+ );
40
+ return;
41
+ }
42
+
43
+ const segmentIndex = (geometry.data as Types.IContourSet).getSegmentIndex();
44
+
45
+ validateGeometry(geometry);
46
+
47
+ const segmentSpecificConfig = getSegmentSpecificConfig(
48
+ contourRepresentation,
49
+ geometryId,
50
+ segmentIndex
51
+ );
52
+
53
+ const contourSet = geometry.data;
54
+ const polyData = getPolyData(contourSet);
55
+ const color = contourSet.getColor();
56
+
57
+ const size = polyData.getPoints().getNumberOfPoints();
58
+
59
+ const scalars = vtkDataArray.newInstance({
60
+ size: size * 4,
61
+ numberOfComponents: 4,
62
+ dataType: 'Uint8Array',
63
+ });
64
+ for (let i = 0; i < size; ++i) {
65
+ scalars.setTuple(i, [...color, 255]);
66
+ }
67
+ polyData.getPointData().setScalars(scalars);
68
+
69
+ if (segmentSpecificConfig) {
70
+ segmentSpecificMap.set(segmentIndex, segmentSpecificConfig);
71
+ }
72
+
73
+ scalarToColorMap.set(segmentIndex, [
74
+ ...color,
75
+ segmentsHidden.has(segmentIndex) ? 0 : 255,
76
+ ]);
77
+
78
+ segmentIndex === 0
79
+ ? appendPolyData.setInputData(polyData)
80
+ : appendPolyData.addInputData(polyData);
81
+ });
82
+
83
+ const polyDataOutput = appendPolyData.getOutputData();
84
+
85
+ const outlineWidthActive =
86
+ contourRepresentationConfig.representations.CONTOUR.outlineWidthActive;
87
+
88
+ const mapper = vtkMapper.newInstance();
89
+ mapper.setInputData(polyDataOutput);
90
+
91
+ const actor = vtkActor.newInstance();
92
+ actor.setMapper(mapper);
93
+ actor.getProperty().setLineWidth(outlineWidthActive);
94
+
95
+ // set the config cache for later update of the contour
96
+ setConfigCache(
97
+ segmentationRepresentationUID,
98
+ Object.assign({}, getConfigCache(segmentationRepresentationUID), {
99
+ segmentsHidden: new Set(segmentsHidden),
100
+ segmentSpecificMap,
101
+ outlineWidthActive,
102
+ })
103
+ );
104
+
105
+ actor.setForceOpaque(true);
106
+
107
+ viewport.addActor({ uid: contourActorUID, actor });
108
+ viewport.resetCamera();
109
+ viewport.render();
110
+ }
@@ -0,0 +1,28 @@
1
+ import { Types } from '@cornerstonejs/core';
2
+
3
+ import {
4
+ SegmentationRepresentationConfig,
5
+ ToolGroupSpecificContourRepresentation,
6
+ } from '../../../types';
7
+ import { addContourSetsToElement } from './addContourSetsToElement';
8
+ import { updateContourSets } from './updateContourSets';
9
+
10
+ export function addOrUpdateContourSets(
11
+ viewport: Types.IVolumeViewport,
12
+ geometryIds: string[],
13
+ contourRepresentation: ToolGroupSpecificContourRepresentation,
14
+ contourRepresentationConfig: SegmentationRepresentationConfig
15
+ ) {
16
+ const { segmentationRepresentationUID } = contourRepresentation;
17
+ const actorUID = `CONTOUR_${segmentationRepresentationUID}`;
18
+ const actor = viewport.getActor(actorUID);
19
+
20
+ const addOrUpdateFn = actor ? updateContourSets : addContourSetsToElement;
21
+ addOrUpdateFn(
22
+ viewport,
23
+ geometryIds,
24
+ contourRepresentation,
25
+ contourRepresentationConfig,
26
+ actorUID
27
+ );
28
+ }
@@ -0,0 +1,15 @@
1
+ import { ContourConfig } from '../../../types/ContourTypes';
2
+
3
+ const defaultContourConfig: ContourConfig = {
4
+ renderOutline: true,
5
+ outlineWidthActive: 2,
6
+ outlineWidthInactive: 2,
7
+ outlineOpacity: 1,
8
+ outlineOpacityInactive: 0.85,
9
+ };
10
+
11
+ function getDefaultContourConfig(): ContourConfig {
12
+ return defaultContourConfig;
13
+ }
14
+
15
+ export default getDefaultContourConfig;
@@ -0,0 +1,37 @@
1
+ type ConfigCache = {
2
+ segmentsHidden: Set<number>;
3
+ outlineWidthActive: number;
4
+ visibility: boolean;
5
+ };
6
+
7
+ /**
8
+ * Config cache is used to store the config for a given segmentation
9
+ * representation. This is used to avoid having to recompute the config
10
+ * every time the user changes the active segment, and also for performance
11
+ * reasons.
12
+ */
13
+ const configCachePerSegmentationRepresentationUID = new Map();
14
+
15
+ export function getConfigCache(
16
+ segmentationRepresentationUID: string
17
+ ): ConfigCache {
18
+ return configCachePerSegmentationRepresentationUID.get(
19
+ segmentationRepresentationUID
20
+ );
21
+ }
22
+
23
+ export function setConfigCache(
24
+ segmentationRepresentationUID: string,
25
+ config: ConfigCache
26
+ ) {
27
+ configCachePerSegmentationRepresentationUID.set(
28
+ segmentationRepresentationUID,
29
+ config
30
+ );
31
+ }
32
+
33
+ export function deleteConfigCache(segmentationRepresentationUID: string) {
34
+ configCachePerSegmentationRepresentationUID.delete(
35
+ segmentationRepresentationUID
36
+ );
37
+ }
@@ -1,6 +1,4 @@
1
1
  import {
2
- cache,
3
- Enums,
4
2
  getEnabledElementByIds,
5
3
  Types,
6
4
  utilities as csUtils,
@@ -15,12 +13,8 @@ import {
15
13
  SegmentationRepresentationConfig,
16
14
  ToolGroupSpecificRepresentation,
17
15
  } from '../../../types/SegmentationStateTypes';
18
-
19
- import {
20
- addContourSetToElement,
21
- addContourToElement,
22
- } from './addContourToElement';
23
- import { default as removeContourFromElement } from './removeContourFromElement';
16
+ import { addOrUpdateContourSets } from './addOrUpdateContourSets';
17
+ import removeContourFromElement from './removeContourFromElement';
24
18
 
25
19
  /**
26
20
  * It adds a new segmentation representation to the segmentation state
@@ -123,17 +117,10 @@ function removeSegmentationRepresentation(
123
117
  */
124
118
  async function render(
125
119
  viewport: Types.IVolumeViewport,
126
- representation: ToolGroupSpecificRepresentation,
120
+ representationConfig: ToolGroupSpecificRepresentation,
127
121
  toolGroupConfig: SegmentationRepresentationConfig
128
122
  ): Promise<void> {
129
- const {
130
- colorLUTIndex,
131
- active,
132
- segmentationId,
133
- segmentationRepresentationUID,
134
- segmentsHidden,
135
- } = representation;
136
-
123
+ const { segmentationId } = representationConfig;
137
124
  const segmentation = SegmentationState.getSegmentation(segmentationId);
138
125
  const contourData = segmentation.representationData[Representations.Contour];
139
126
  const { geometryIds } = contourData;
@@ -144,80 +131,13 @@ async function render(
144
131
  );
145
132
  }
146
133
 
147
- _renderContourSets(viewport, geometryIds, segmentationRepresentationUID);
148
- }
149
-
150
- function _renderContourSets(
151
- viewport,
152
- geometryIds,
153
- segmentationRepresentationUID
154
- ) {
155
- geometryIds.forEach((geometryId) => {
156
- const geometry = cache.getGeometry(geometryId);
157
- if (!geometry) {
158
- throw new Error(`No contours found for geometryId ${geometryId}`);
159
- }
160
-
161
- if (geometry.type !== Enums.GeometryType.CONTOUR) {
162
- // Todo: later we can support converting other geometries to contours
163
- throw new Error(
164
- `Geometry type ${geometry.type} not supported for rendering.`
165
- );
166
- }
167
-
168
- if (!geometry.data) {
169
- console.warn(
170
- `No contours found for geometryId ${geometryId}. Skipping render.`
171
- );
172
- return;
173
- }
174
-
175
- const contourSet = geometry.data;
176
-
177
- _renderContourSet(viewport, contourSet, segmentationRepresentationUID);
178
- });
179
- }
180
-
181
- function _renderContourSet(
182
- viewport: Types.IVolumeViewport,
183
- contourSet: Types.IContourSet,
184
- segmentationRepresentationUID: string,
185
- separated = false
186
- ): void {
187
- if (separated) {
188
- contourSet.getContours().forEach((contour: Types.IContour, index) => {
189
- const contourUID = `${segmentationRepresentationUID}_${contourSet.id}_${index}}`;
190
- _renderContour(viewport, contour, contourUID);
191
- });
192
- } else {
193
- const contourUID = `${segmentationRepresentationUID}_${contourSet.id}`;
194
- const actorUID = contourUID;
195
- const actorEntry = viewport.getActor(actorUID);
196
-
197
- if (!actorEntry) {
198
- addContourSetToElement(viewport.element, contourSet, actorUID);
199
- } else {
200
- throw new Error('Not implemented yet. (Update contour)');
201
- }
202
- }
203
-
204
- viewport.resetCamera();
205
- viewport.render();
206
- }
207
-
208
- function _renderContour(
209
- viewport: Types.IVolumeViewport,
210
- contour: Types.IContour,
211
- contourUID: string
212
- ): void {
213
- const actorUID = contourUID;
214
- const actorEntry = viewport.getActor(actorUID);
215
-
216
- if (!actorEntry) {
217
- addContourToElement(viewport.element, contour, actorUID);
218
- } else {
219
- throw new Error('Not implemented yet. (Update contour)');
220
- }
134
+ // add the contour sets to the viewport
135
+ addOrUpdateContourSets(
136
+ viewport,
137
+ geometryIds,
138
+ representationConfig,
139
+ toolGroupConfig
140
+ );
221
141
  }
222
142
 
223
143
  function _removeContourFromToolGroupViewports(
@@ -0,0 +1,111 @@
1
+ import { cache, Types } from '@cornerstonejs/core';
2
+ import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
3
+ import vtkAppendPolyData from '@kitware/vtk.js/Filters/General/AppendPolyData';
4
+ import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
5
+
6
+ import {
7
+ SegmentationRepresentationConfig,
8
+ ToolGroupSpecificContourRepresentation,
9
+ } from '../../../types';
10
+ import { getConfigCache, setConfigCache } from './contourConfigCache';
11
+ import { getPolyData } from './utils';
12
+
13
+ export function updateContourSets(
14
+ viewport: Types.IVolumeViewport,
15
+ geometryIds: string[],
16
+ contourRepresentation: ToolGroupSpecificContourRepresentation,
17
+ contourRepresentationConfig: SegmentationRepresentationConfig,
18
+ contourActorUID: string
19
+ ) {
20
+ const { segmentationRepresentationUID, segmentsHidden } =
21
+ contourRepresentation;
22
+ const newContourConfig = contourRepresentationConfig.representations.CONTOUR;
23
+ const cachedConfig = getConfigCache(segmentationRepresentationUID);
24
+
25
+ const contourSetsActor = viewport.getActor(contourActorUID);
26
+
27
+ if (!contourSetsActor) {
28
+ console.warn(
29
+ `No contour actor found for actorUID ${contourActorUID}. Skipping render.`
30
+ );
31
+ return;
32
+ }
33
+
34
+ const { actor } = contourSetsActor;
35
+
36
+ const newOutlineWithActive = newContourConfig.outlineWidthActive;
37
+
38
+ if (cachedConfig?.outlineWidthActive !== newOutlineWithActive) {
39
+ (actor as vtkActor).getProperty().setLineWidth(newOutlineWithActive);
40
+
41
+ setConfigCache(
42
+ segmentationRepresentationUID,
43
+ Object.assign({}, cachedConfig, {
44
+ outlineWidthActive: newOutlineWithActive,
45
+ })
46
+ );
47
+ }
48
+
49
+ const mapper = (actor as vtkActor).getMapper();
50
+ const lut = mapper.getLookupTable();
51
+
52
+ const segmentsToSetToInvisible = [];
53
+ const segmentsToSetToVisible = [];
54
+
55
+ for (const segmentIndex of segmentsHidden) {
56
+ if (!cachedConfig?.segmentsHidden.has(segmentIndex)) {
57
+ segmentsToSetToInvisible.push(segmentIndex);
58
+ }
59
+ }
60
+
61
+ // the other way around
62
+ for (const segmentIndex of cachedConfig.segmentsHidden) {
63
+ if (!segmentsHidden.has(segmentIndex)) {
64
+ segmentsToSetToVisible.push(segmentIndex);
65
+ }
66
+ }
67
+ if (segmentsToSetToInvisible.length || segmentsToSetToVisible.length) {
68
+ const appendPolyData = vtkAppendPolyData.newInstance();
69
+
70
+ geometryIds.forEach((geometryId) => {
71
+ const geometry = cache.getGeometry(geometryId);
72
+ const { data: contourSet } = geometry;
73
+ const segmentIndex = (contourSet as Types.IContourSet).getSegmentIndex();
74
+ const color = contourSet.getColor();
75
+ const visibility = segmentsToSetToInvisible.includes(segmentIndex)
76
+ ? 0
77
+ : 255;
78
+ const polyData = getPolyData(contourSet);
79
+
80
+ const size = polyData.getPoints().getNumberOfPoints();
81
+
82
+ const scalars = vtkDataArray.newInstance({
83
+ size: size * 4,
84
+ numberOfComponents: 4,
85
+ dataType: 'Uint8Array',
86
+ });
87
+ for (let i = 0; i < size; ++i) {
88
+ scalars.setTuple(i, [...color, visibility]);
89
+ }
90
+ polyData.getPointData().setScalars(scalars);
91
+
92
+ segmentIndex === 0
93
+ ? appendPolyData.setInputData(polyData)
94
+ : appendPolyData.addInputData(polyData);
95
+ });
96
+
97
+ const polyDataOutput = appendPolyData.getOutputData();
98
+ mapper.setInputData(polyDataOutput);
99
+
100
+ setConfigCache(
101
+ segmentationRepresentationUID,
102
+ Object.assign({}, cachedConfig, {
103
+ segmentsHidden: new Set(segmentsHidden),
104
+ })
105
+ );
106
+
107
+ mapper.setLookupTable(lut);
108
+ }
109
+
110
+ viewport.render();
111
+ }