@cornerstonejs/tools 2.0.0-beta.17 → 2.0.0-beta.18

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 (103) hide show
  1. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +11 -14
  2. package/dist/esm/eventListeners/segmentation/labelmap/onLabelmapSegmentationDataModified.js +26 -27
  3. package/dist/esm/eventListeners/segmentation/segmentationDataModifiedEventListener.js +1 -4
  4. package/dist/esm/eventListeners/segmentation/segmentationModifiedEventListener.js +2 -11
  5. package/dist/esm/eventListeners/segmentation/segmentationRepresentationModifiedEventListener.js +10 -2
  6. package/dist/esm/eventListeners/segmentation/segmentationRepresentationRemovedEventListener.js +2 -2
  7. package/dist/esm/index.d.ts +2 -2
  8. package/dist/esm/index.js +2 -2
  9. package/dist/esm/stateManagement/index.d.ts +3 -3
  10. package/dist/esm/stateManagement/index.js +2 -2
  11. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +19 -18
  12. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +87 -130
  13. package/dist/esm/stateManagement/segmentation/activeSegmentation.d.ts +4 -5
  14. package/dist/esm/stateManagement/segmentation/activeSegmentation.js +6 -23
  15. package/dist/esm/stateManagement/segmentation/addRepresentation.d.ts +3 -0
  16. package/dist/esm/stateManagement/segmentation/addRepresentation.js +51 -0
  17. package/dist/esm/stateManagement/segmentation/addRepresentations.d.ts +3 -0
  18. package/dist/esm/stateManagement/segmentation/addRepresentations.js +9 -0
  19. package/dist/esm/stateManagement/segmentation/config/index.d.ts +2 -2
  20. package/dist/esm/stateManagement/segmentation/config/index.js +2 -2
  21. package/dist/esm/stateManagement/segmentation/config/segmentationColor.d.ts +4 -4
  22. package/dist/esm/stateManagement/segmentation/config/segmentationColor.js +10 -10
  23. package/dist/esm/stateManagement/segmentation/config/segmentationConfig.d.ts +8 -8
  24. package/dist/esm/stateManagement/segmentation/config/segmentationConfig.js +19 -13
  25. package/dist/esm/stateManagement/segmentation/config/segmentationVisibility.d.ts +7 -6
  26. package/dist/esm/stateManagement/segmentation/config/segmentationVisibility.js +29 -54
  27. package/dist/esm/stateManagement/segmentation/convertStackToVolumeSegmentation.d.ts +1 -1
  28. package/dist/esm/stateManagement/segmentation/convertStackToVolumeSegmentation.js +5 -5
  29. package/dist/esm/stateManagement/segmentation/convertVolumeToStackSegmentation.d.ts +3 -3
  30. package/dist/esm/stateManagement/segmentation/convertVolumeToStackSegmentation.js +5 -5
  31. package/dist/esm/stateManagement/segmentation/helpers/getRepresentationRenderingConfig.d.ts +2 -0
  32. package/dist/esm/stateManagement/segmentation/helpers/{getRepresentationSpecificConfig.js → getRepresentationRenderingConfig.js} +1 -1
  33. package/dist/esm/stateManagement/segmentation/index.d.ts +3 -3
  34. package/dist/esm/stateManagement/segmentation/index.js +3 -3
  35. package/dist/esm/stateManagement/segmentation/polySeg/Contour/contourComputationStrategies.js +2 -4
  36. package/dist/esm/stateManagement/segmentation/polySeg/Surface/createAndCacheSurfacesFromRaw.js +5 -6
  37. package/dist/esm/stateManagement/segmentation/polySeg/Surface/updateSurfaceData.js +4 -4
  38. package/dist/esm/stateManagement/segmentation/polySeg/canComputeRequestedRepresentation.js +2 -6
  39. package/dist/esm/stateManagement/segmentation/removeRepresentationsFromViewport.d.ts +2 -0
  40. package/dist/esm/stateManagement/segmentation/removeRepresentationsFromViewport.js +23 -0
  41. package/dist/esm/stateManagement/segmentation/segmentIndex.js +6 -4
  42. package/dist/esm/stateManagement/segmentation/segmentationState.d.ts +23 -20
  43. package/dist/esm/stateManagement/segmentation/segmentationState.js +68 -95
  44. package/dist/esm/stateManagement/segmentation/triggerSegmentationEvents.d.ts +2 -2
  45. package/dist/esm/stateManagement/segmentation/triggerSegmentationEvents.js +4 -18
  46. package/dist/esm/store/ToolGroupManager/destroyToolGroup.js +0 -4
  47. package/dist/esm/tools/AdvancedMagnifyViewport.js +3 -3
  48. package/dist/esm/tools/annotation/PlanarFreehandROITool.js +0 -2
  49. package/dist/esm/tools/base/ContourSegmentationBaseTool.d.ts +0 -1
  50. package/dist/esm/tools/base/ContourSegmentationBaseTool.js +42 -33
  51. package/dist/esm/tools/displayTools/Contour/contourDisplay.d.ts +4 -4
  52. package/dist/esm/tools/displayTools/Contour/contourDisplay.js +17 -30
  53. package/dist/esm/tools/displayTools/Contour/contourHandler/handleContourSegmentation.d.ts +4 -4
  54. package/dist/esm/tools/displayTools/Contour/contourHandler/handleContourSegmentation.js +20 -11
  55. package/dist/esm/tools/displayTools/Contour/contourHandler/utils.d.ts +0 -2
  56. package/dist/esm/tools/displayTools/Contour/contourHandler/utils.js +0 -11
  57. package/dist/esm/tools/displayTools/Contour/removeContourFromElement.d.ts +1 -1
  58. package/dist/esm/tools/displayTools/Contour/removeContourFromElement.js +3 -3
  59. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.d.ts +5 -5
  60. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +51 -54
  61. package/dist/esm/tools/displayTools/SegmentationRenderingEngine.d.ts +19 -0
  62. package/dist/esm/tools/displayTools/SegmentationRenderingEngine.js +136 -0
  63. package/dist/esm/tools/displayTools/Surface/surfaceDisplay.d.ts +5 -5
  64. package/dist/esm/tools/displayTools/Surface/surfaceDisplay.js +14 -25
  65. package/dist/esm/tools/index.d.ts +1 -2
  66. package/dist/esm/tools/index.js +1 -2
  67. package/dist/esm/tools/segmentation/BrushTool.d.ts +15 -2
  68. package/dist/esm/tools/segmentation/BrushTool.js +13 -14
  69. package/dist/esm/tools/segmentation/CircleScissorsTool.js +3 -4
  70. package/dist/esm/tools/segmentation/PaintFillTool.js +1 -2
  71. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +3 -4
  72. package/dist/esm/tools/segmentation/SegmentSelectTool.d.ts +3 -2
  73. package/dist/esm/tools/segmentation/SegmentSelectTool.js +5 -5
  74. package/dist/esm/tools/segmentation/SphereScissorsTool.js +4 -5
  75. package/dist/esm/tools/segmentation/strategies/compositions/preview.js +2 -2
  76. package/dist/esm/types/EventTypes.d.ts +0 -3
  77. package/dist/esm/types/SegmentationStateTypes.d.ts +24 -23
  78. package/dist/esm/types/index.d.ts +2 -2
  79. package/dist/esm/utilities/segmentation/getSegmentIndexAtLabelmapBorder.d.ts +7 -0
  80. package/dist/esm/utilities/segmentation/{getSegmentAtLabelmapBorder.js → getSegmentIndexAtLabelmapBorder.js} +3 -3
  81. package/dist/esm/utilities/segmentation/getSegmentIndexAtWorldPoint.d.ts +11 -0
  82. package/dist/esm/utilities/segmentation/{getSegmentAtWorldPoint.js → getSegmentIndexAtWorldPoint.js} +7 -7
  83. package/dist/esm/utilities/segmentation/index.d.ts +3 -3
  84. package/dist/esm/utilities/segmentation/index.js +3 -3
  85. package/dist/esm/utilities/segmentation/triggerSegmentationRender.d.ts +2 -17
  86. package/dist/esm/utilities/segmentation/triggerSegmentationRender.js +4 -106
  87. package/dist/esm/utilities/segmentation/triggerSegmentationRenderForViewports.d.ts +3 -0
  88. package/dist/esm/utilities/segmentation/triggerSegmentationRenderForViewports.js +6 -0
  89. package/dist/esm/utilities/triggerAnnotationRenderForViewportIds.js +7 -2
  90. package/dist/umd/index.js +1 -1
  91. package/dist/umd/index.js.map +1 -1
  92. package/package.json +3 -4
  93. package/dist/esm/stateManagement/segmentation/addSegmentationRepresentation.d.ts +0 -3
  94. package/dist/esm/stateManagement/segmentation/addSegmentationRepresentation.js +0 -63
  95. package/dist/esm/stateManagement/segmentation/addSegmentationRepresentations.d.ts +0 -3
  96. package/dist/esm/stateManagement/segmentation/addSegmentationRepresentations.js +0 -14
  97. package/dist/esm/stateManagement/segmentation/helpers/getRepresentationSpecificConfig.d.ts +0 -2
  98. package/dist/esm/stateManagement/segmentation/removeSegmentationsFromToolGroup.d.ts +0 -2
  99. package/dist/esm/stateManagement/segmentation/removeSegmentationsFromToolGroup.js +0 -39
  100. package/dist/esm/tools/displayTools/SegmentationDisplayTool.d.ts +0 -13
  101. package/dist/esm/tools/displayTools/SegmentationDisplayTool.js +0 -101
  102. package/dist/esm/utilities/segmentation/getSegmentAtLabelmapBorder.d.ts +0 -7
  103. package/dist/esm/utilities/segmentation/getSegmentAtWorldPoint.d.ts +0 -11
@@ -1,37 +1,36 @@
1
- import { getEnabledElementByIds, } from '@cornerstonejs/core';
1
+ import { getEnabledElementByViewportId, } from '@cornerstonejs/core';
2
2
  import Representations from '../../../enums/SegmentationRepresentations';
3
3
  import * as SegmentationState from '../../../stateManagement/segmentation/segmentationState';
4
- import { getToolGroup } from '../../../store/ToolGroupManager';
5
- import removeContourFromElement from './removeContourFromElement';
6
4
  import { deleteConfigCache } from './contourHandler/contourConfigCache';
7
5
  import { polySeg } from '../../../stateManagement/segmentation';
8
6
  import { handleContourSegmentation } from './contourHandler/handleContourSegmentation';
9
7
  let polySegConversionInProgress = false;
10
- function removeSegmentationRepresentation(toolGroupId, segmentationRepresentationUID, renderImmediate = false) {
11
- _removeContourFromToolGroupViewports(toolGroupId, segmentationRepresentationUID);
12
- SegmentationState.removeSegmentationRepresentation(toolGroupId, segmentationRepresentationUID);
8
+ function removeRepresentation(viewportId, segmentationRepresentationUID, renderImmediate = false) {
9
+ const enabledElement = getEnabledElementByViewportId(viewportId);
10
+ if (!enabledElement) {
11
+ return;
12
+ }
13
+ const { viewport } = enabledElement;
14
+ SegmentationState.removeRepresentation(segmentationRepresentationUID);
13
15
  deleteConfigCache(segmentationRepresentationUID);
14
- if (renderImmediate) {
15
- const viewportsInfo = getToolGroup(toolGroupId).getViewportsInfo();
16
- viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
17
- const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
18
- enabledElement.viewport.render();
19
- });
16
+ if (!renderImmediate) {
17
+ return;
20
18
  }
19
+ viewport.render();
21
20
  }
22
- async function render(viewport, representationConfig, toolGroupConfig) {
23
- const { segmentationId } = representationConfig;
21
+ async function render(viewport, contourRepresentation) {
22
+ const { segmentationId } = contourRepresentation;
24
23
  const segmentation = SegmentationState.getSegmentation(segmentationId);
25
24
  if (!segmentation) {
26
25
  return;
27
26
  }
28
27
  let contourData = segmentation.representationData[Representations.Contour];
29
28
  if (!contourData &&
30
- polySeg.canComputeRequestedRepresentation(representationConfig.segmentationRepresentationUID) &&
29
+ polySeg.canComputeRequestedRepresentation(contourRepresentation.segmentationRepresentationUID) &&
31
30
  !polySegConversionInProgress) {
32
31
  polySegConversionInProgress = true;
33
32
  contourData = await polySeg.computeAndAddContourRepresentation(segmentationId, {
34
- segmentationRepresentationUID: representationConfig.segmentationRepresentationUID,
33
+ segmentationRepresentationUID: contourRepresentation.segmentationRepresentationUID,
35
34
  viewport,
36
35
  });
37
36
  }
@@ -39,22 +38,10 @@ async function render(viewport, representationConfig, toolGroupConfig) {
39
38
  return;
40
39
  }
41
40
  if (contourData?.geometryIds?.length) {
42
- handleContourSegmentation(viewport, contourData.geometryIds, contourData.annotationUIDsMap, representationConfig, toolGroupConfig);
43
- }
44
- }
45
- function _removeContourFromToolGroupViewports(toolGroupId, segmentationRepresentationUID) {
46
- const toolGroup = getToolGroup(toolGroupId);
47
- if (toolGroup === undefined) {
48
- throw new Error(`ToolGroup with ToolGroupId ${toolGroupId} does not exist`);
49
- }
50
- const { viewportsInfo } = toolGroup;
51
- for (const viewportInfo of viewportsInfo) {
52
- const { viewportId, renderingEngineId } = viewportInfo;
53
- const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
54
- removeContourFromElement(segmentationRepresentationUID, toolGroupId);
41
+ handleContourSegmentation(viewport, contourData.geometryIds, contourData.annotationUIDsMap, contourRepresentation);
55
42
  }
56
43
  }
57
44
  export default {
58
45
  render,
59
- removeSegmentationRepresentation,
46
+ removeRepresentation,
60
47
  };
@@ -1,6 +1,6 @@
1
1
  import { Types, StackViewport } from '@cornerstonejs/core';
2
- import { SegmentationRepresentationConfig, ToolGroupSpecificContourRepresentation } from '../../../../types';
3
- declare function handleContourSegmentation(viewport: StackViewport | Types.IVolumeViewport, geometryIds: string[], annotationUIDsMap: Map<number, Set<string>>, contourRepresentation: ToolGroupSpecificContourRepresentation, contourRepresentationConfig: SegmentationRepresentationConfig): void;
4
- declare function updateContourSets(viewport: Types.IVolumeViewport | StackViewport, geometryIds: string[], contourRepresentation: ToolGroupSpecificContourRepresentation, contourRepresentationConfig: SegmentationRepresentationConfig): void;
5
- declare function addContourSetsToElement(viewport: StackViewport | Types.IVolumeViewport, geometryIds: string[], contourRepresentation: ToolGroupSpecificContourRepresentation, contourRepresentationConfig: SegmentationRepresentationConfig): void;
2
+ import { ContourRepresentation } from '../../../../types/SegmentationStateTypes';
3
+ declare function handleContourSegmentation(viewport: StackViewport | Types.IVolumeViewport, geometryIds: string[], annotationUIDsMap: Map<number, Set<string>>, contourRepresentation: ContourRepresentation): void;
4
+ declare function updateContourSets(viewport: Types.IVolumeViewport | StackViewport, geometryIds: string[], contourRepresentation: ContourRepresentation): void;
5
+ declare function addContourSetsToElement(viewport: StackViewport | Types.IVolumeViewport, geometryIds: string[], contourRepresentation: ContourRepresentation): void;
6
6
  export { handleContourSegmentation, updateContourSets, addContourSetsToElement, };
@@ -2,18 +2,22 @@ import { addAnnotation } from '../../../../stateManagement';
2
2
  import { cache, utilities } from '@cornerstonejs/core';
3
3
  import { getClosestImageIdForStackViewport } from '../../../../utilities/annotationHydration';
4
4
  import { getConfigCache, setConfigCache } from './contourConfigCache';
5
- import { getSegmentSpecificConfig } from './utils';
6
5
  import { addContourSegmentationAnnotation } from '../../../../utilities/contourSegmentation';
7
6
  import { validateGeometry } from './utils';
8
- function handleContourSegmentation(viewport, geometryIds, annotationUIDsMap, contourRepresentation, contourRepresentationConfig) {
7
+ import { getGlobalConfig, } from '../../../../stateManagement/segmentation/segmentationState';
8
+ import { getSegmentsHidden } from '../../../../stateManagement/segmentation/config/segmentationVisibility';
9
+ import { getSegmentIndexConfig } from '../../../../stateManagement/segmentation/config';
10
+ function handleContourSegmentation(viewport, geometryIds, annotationUIDsMap, contourRepresentation) {
9
11
  const addOrUpdateFn = annotationUIDsMap.size
10
12
  ? updateContourSets
11
13
  : addContourSetsToElement;
12
- addOrUpdateFn(viewport, geometryIds, contourRepresentation, contourRepresentationConfig);
14
+ addOrUpdateFn(viewport, geometryIds, contourRepresentation);
13
15
  }
14
- function updateContourSets(viewport, geometryIds, contourRepresentation, contourRepresentationConfig) {
15
- const { segmentationRepresentationUID, segmentsHidden } = contourRepresentation;
16
- const newContourConfig = contourRepresentationConfig.representations.CONTOUR;
16
+ function updateContourSets(viewport, geometryIds, contourRepresentation) {
17
+ const { segmentationRepresentationUID, config } = contourRepresentation;
18
+ const baseConfig = config?.allSegments?.CONTOUR;
19
+ const globalContourConfig = getGlobalConfig().representations.CONTOUR;
20
+ const newContourConfig = utilities.deepMerge(globalContourConfig, baseConfig);
17
21
  const cachedConfig = getConfigCache(segmentationRepresentationUID);
18
22
  const newOutlineWithActive = newContourConfig.outlineWidthActive;
19
23
  if (cachedConfig?.outlineWidthActive !== newOutlineWithActive) {
@@ -23,6 +27,7 @@ function updateContourSets(viewport, geometryIds, contourRepresentation, contour
23
27
  }
24
28
  const segmentsToSetToInvisible = [];
25
29
  const segmentsToSetToVisible = [];
30
+ const segmentsHidden = getSegmentsHidden(viewport.id, segmentationRepresentationUID);
26
31
  for (const segmentIndex of segmentsHidden) {
27
32
  if (!cachedConfig.segmentsHidden.has(segmentIndex)) {
28
33
  segmentsToSetToInvisible.push(segmentIndex);
@@ -40,7 +45,7 @@ function updateContourSets(viewport, geometryIds, contourRepresentation, contour
40
45
  const geometry = cache.getGeometry(geometryId);
41
46
  const { data: contourSet } = geometry;
42
47
  const segmentIndex = contourSet.getSegmentIndex();
43
- const segmentSpecificConfig = getSegmentSpecificConfig(contourRepresentation, geometryId, segmentIndex);
48
+ const segmentSpecificConfig = getSegmentIndexConfig(segmentationRepresentationUID, segmentIndex);
44
49
  acc.segmentSpecificConfigs[segmentIndex] = segmentSpecificConfig ?? {};
45
50
  return acc;
46
51
  }, { contourSets: [], segmentSpecificConfigs: {} });
@@ -56,8 +61,8 @@ function updateContourSets(viewport, geometryIds, contourRepresentation, contour
56
61
  }
57
62
  viewport.render();
58
63
  }
59
- function addContourSetsToElement(viewport, geometryIds, contourRepresentation, contourRepresentationConfig) {
60
- const { segmentationRepresentationUID, segmentationId, segmentsHidden } = contourRepresentation;
64
+ function addContourSetsToElement(viewport, geometryIds, contourRepresentation) {
65
+ const { segmentationRepresentationUID, segmentationId } = contourRepresentation;
61
66
  const segmentSpecificMap = new Map();
62
67
  geometryIds.forEach((geometryId) => {
63
68
  const geometry = cache.getGeometry(geometryId);
@@ -67,7 +72,7 @@ function addContourSetsToElement(viewport, geometryIds, contourRepresentation, c
67
72
  }
68
73
  const segmentIndex = geometry.data.getSegmentIndex();
69
74
  validateGeometry(geometry);
70
- const segmentSpecificConfig = getSegmentSpecificConfig(contourRepresentation, geometryId, segmentIndex);
75
+ const segmentSpecificConfig = getSegmentIndexConfig(segmentationRepresentationUID, segmentIndex);
71
76
  const contourSet = geometry.data;
72
77
  contourSet.contours.forEach((contour) => {
73
78
  const { points, color, id } = contour;
@@ -107,7 +112,11 @@ function addContourSetsToElement(viewport, geometryIds, contourRepresentation, c
107
112
  segmentSpecificMap.set(segmentIndex, segmentSpecificConfig);
108
113
  }
109
114
  });
110
- const outlineWidthActive = contourRepresentationConfig.representations.CONTOUR.outlineWidthActive;
115
+ const baseConfig = contourRepresentation.config?.allSegments.CONTOUR;
116
+ const globalContourConfig = getGlobalConfig().representations.CONTOUR;
117
+ const newContourConfig = utilities.deepMerge(globalContourConfig, baseConfig);
118
+ const outlineWidthActive = newContourConfig.outlineWidthActive;
119
+ const segmentsHidden = getSegmentsHidden(viewport.id, segmentationRepresentationUID);
111
120
  setConfigCache(segmentationRepresentationUID, Object.assign({}, getConfigCache(segmentationRepresentationUID), {
112
121
  segmentsHidden: new Set(segmentsHidden),
113
122
  segmentSpecificMap,
@@ -1,6 +1,4 @@
1
1
  import { Types } from '@cornerstonejs/core';
2
2
  import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
3
- import { ToolGroupSpecificContourRepresentation } from '../../../../types';
4
- export declare function getSegmentSpecificConfig(contourRepresentation: ToolGroupSpecificContourRepresentation, segmentId: string, index: number): import("../../../../types/ContourTypes").ContourConfig;
5
3
  export declare function validateGeometry(geometry: Types.IGeometry): void;
6
4
  export declare function getPolyData(contourSet: Types.IContourSet): vtkPolyData;
@@ -2,17 +2,6 @@ import { Enums } from '@cornerstonejs/core';
2
2
  import vtkCellArray from '@kitware/vtk.js/Common/Core/CellArray';
3
3
  import vtkPoints from '@kitware/vtk.js/Common/Core/Points';
4
4
  import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
5
- export function getSegmentSpecificConfig(contourRepresentation, segmentId, index) {
6
- let segmentSpecificConfig = contourRepresentation.segmentSpecificConfig?.[segmentId];
7
- if (!segmentSpecificConfig) {
8
- segmentSpecificConfig =
9
- contourRepresentation.segmentSpecificConfig?.[index];
10
- }
11
- if (!segmentSpecificConfig) {
12
- return null;
13
- }
14
- return segmentSpecificConfig.CONTOUR;
15
- }
16
5
  export function validateGeometry(geometry) {
17
6
  if (!geometry) {
18
7
  throw new Error(`No contours found for geometryId ${geometry.id}`);
@@ -1,2 +1,2 @@
1
- declare function removeContourFromElement(segmentationRepresentationUID: string, toolGroupId: string, removeFromCache?: boolean): void;
1
+ declare function removeContourFromElement(element: HTMLDivElement, segmentationRepresentationUID: string, removeFromCache?: boolean): void;
2
2
  export default removeContourFromElement;
@@ -1,7 +1,7 @@
1
- import { getSegmentationRepresentationByUID, getSegmentation, } from '../../../stateManagement/segmentation/segmentationState';
1
+ import { getRepresentation, getSegmentation, } from '../../../stateManagement/segmentation/segmentationState';
2
2
  import { removeAnnotation } from '../../../stateManagement';
3
- function removeContourFromElement(segmentationRepresentationUID, toolGroupId, removeFromCache = false) {
4
- const segmentationRepresentation = getSegmentationRepresentationByUID(toolGroupId, segmentationRepresentationUID);
3
+ function removeContourFromElement(element, segmentationRepresentationUID, removeFromCache = false) {
4
+ const segmentationRepresentation = getRepresentation(segmentationRepresentationUID);
5
5
  const { segmentationId } = segmentationRepresentation;
6
6
  const segmentation = getSegmentation(segmentationId);
7
7
  const { annotationUIDsMap } = segmentation.representationData.CONTOUR;
@@ -1,17 +1,17 @@
1
1
  import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
2
2
  import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
3
3
  import { Types } from '@cornerstonejs/core';
4
- import { SegmentationRepresentationConfig, ToolGroupSpecificRepresentation } from '../../../types/SegmentationStateTypes';
4
+ import { LabelmapRepresentation } from '../../../types/SegmentationStateTypes';
5
5
  declare function getRepresentationRenderingConfig(): {
6
6
  ofun: vtkPiecewiseFunction;
7
7
  cfun: vtkColorTransferFunction;
8
8
  };
9
- declare function removeSegmentationRepresentation(toolGroupId: string, segmentationRepresentationUID: string, renderImmediate?: boolean): void;
10
- declare function render(viewport: Types.IVolumeViewport | Types.IStackViewport, representation: ToolGroupSpecificRepresentation, toolGroupConfig: SegmentationRepresentationConfig): Promise<void>;
9
+ declare function removeRepresentation(viewportId: string, segmentationRepresentationUID: string, renderImmediate?: boolean): void;
10
+ declare function render(viewport: Types.IStackViewport | Types.IVolumeViewport, representation: LabelmapRepresentation): Promise<void>;
11
11
  declare const _default: {
12
12
  getRepresentationRenderingConfig: typeof getRepresentationRenderingConfig;
13
13
  render: typeof render;
14
- removeSegmentationRepresentation: typeof removeSegmentationRepresentation;
14
+ removeRepresentation: typeof removeRepresentation;
15
15
  };
16
16
  export default _default;
17
- export { getRepresentationRenderingConfig, render, removeSegmentationRepresentation, };
17
+ export { getRepresentationRenderingConfig, render, removeRepresentation };
@@ -1,13 +1,13 @@
1
1
  import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
2
2
  import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
3
- import { cache, getEnabledElementByIds, StackViewport, VolumeViewport, } from '@cornerstonejs/core';
3
+ import { cache, getEnabledElementByViewportId, StackViewport, VolumeViewport, } from '@cornerstonejs/core';
4
4
  import Representations from '../../../enums/SegmentationRepresentations';
5
5
  import * as SegmentationState from '../../../stateManagement/segmentation/segmentationState';
6
- import { getToolGroup } from '../../../store/ToolGroupManager';
7
6
  import addLabelmapToElement from './addLabelmapToElement';
8
7
  import removeLabelmapFromElement from './removeLabelmapFromElement';
9
8
  import { isVolumeSegmentation } from '../../segmentation/strategies/utils/stackVolumeCheck';
10
9
  import { polySeg } from '../../../stateManagement/segmentation';
10
+ import { getSegmentsHidden } from '../../../stateManagement/segmentation/config/segmentationVisibility';
11
11
  const MAX_NUMBER_COLORS = 255;
12
12
  const labelMapConfigCache = new Map();
13
13
  function getRepresentationRenderingConfig() {
@@ -20,16 +20,18 @@ function getRepresentationRenderingConfig() {
20
20
  };
21
21
  }
22
22
  let polySegConversionInProgress = false;
23
- function removeSegmentationRepresentation(toolGroupId, segmentationRepresentationUID, renderImmediate = false) {
24
- _removeLabelmapFromToolGroupViewports(toolGroupId, segmentationRepresentationUID);
25
- SegmentationState.removeSegmentationRepresentation(toolGroupId, segmentationRepresentationUID);
26
- if (renderImmediate) {
27
- const viewportsInfo = getToolGroup(toolGroupId).getViewportsInfo();
28
- viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
29
- const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
30
- enabledElement.viewport.render();
31
- });
23
+ function removeRepresentation(viewportId, segmentationRepresentationUID, renderImmediate = false) {
24
+ const enabledElement = getEnabledElementByViewportId(viewportId);
25
+ if (!enabledElement) {
26
+ return;
32
27
  }
28
+ const { viewport } = enabledElement;
29
+ removeLabelmapFromElement(viewport.element, segmentationRepresentationUID);
30
+ SegmentationState.removeRepresentation(segmentationRepresentationUID);
31
+ if (!renderImmediate) {
32
+ return;
33
+ }
34
+ viewport.render();
33
35
  }
34
36
  function isSameFrameOfReference(viewport, referencedVolumeId) {
35
37
  if (!referencedVolumeId) {
@@ -51,8 +53,8 @@ function isSameFrameOfReference(viewport, referencedVolumeId) {
51
53
  }
52
54
  return false;
53
55
  }
54
- async function render(viewport, representation, toolGroupConfig) {
55
- const { colorLUTIndex, active, segmentationId, segmentationRepresentationUID, segmentsHidden, config: renderingConfig, } = representation;
56
+ async function render(viewport, representation) {
57
+ const { segmentationId, segmentationRepresentationUID } = representation;
56
58
  const segmentation = SegmentationState.getSegmentation(segmentationId);
57
59
  if (!segmentation) {
58
60
  console.warn('No segmentation found for segmentationId: ', segmentationId);
@@ -110,29 +112,38 @@ async function render(viewport, representation, toolGroupConfig) {
110
112
  if (!actorEntry) {
111
113
  return;
112
114
  }
113
- const { cfun, ofun } = renderingConfig;
114
- const renderInactiveSegmentations = toolGroupConfig.renderInactiveSegmentations;
115
- _setLabelmapColorAndOpacity(viewport.id, actorEntry, cfun, ofun, colorLUTIndex, toolGroupConfig.representations[Representations.Labelmap], representation, active, renderInactiveSegmentations, segmentsHidden);
115
+ _setLabelmapColorAndOpacity(viewport.id, actorEntry, representation);
116
116
  }
117
- function _setLabelmapColorAndOpacity(viewportId, actorEntry, cfun, ofun, colorLUTIndex, toolGroupLabelmapConfig, segmentationRepresentation, isActiveLabelmap, renderInactiveSegmentations, segmentsHidden) {
118
- const { segmentSpecificConfig, segmentationRepresentationSpecificConfig } = segmentationRepresentation;
119
- const segmentationRepresentationLabelmapConfig = segmentationRepresentationSpecificConfig[Representations.Labelmap];
117
+ function _setLabelmapColorAndOpacity(viewportId, actorEntry, segmentationRepresentation) {
118
+ const { rendering, config, colorLUTIndex } = segmentationRepresentation;
119
+ const activeSegRep = SegmentationState.getActiveRepresentation(viewportId);
120
+ const isActiveLabelmap = activeSegRep === segmentationRepresentation;
121
+ const { cfun, ofun } = rendering;
122
+ const { allSegments, perSegment } = config;
123
+ const globalLabelmapConfig = SegmentationState.getGlobalConfig().representations[Representations.Labelmap];
124
+ const globalConfig = SegmentationState.getGlobalConfig();
125
+ const renderInactiveRepresentations = globalConfig.renderInactiveRepresentations;
126
+ const configToUse = {
127
+ ...globalLabelmapConfig,
128
+ ...allSegments[Representations.Labelmap],
129
+ };
130
+ const labelmapConfig = configToUse;
120
131
  const colorLUT = SegmentationState.getColorLUT(colorLUTIndex);
121
132
  const numColors = Math.min(256, colorLUT.length);
122
133
  const { uid: actorUID } = actorEntry;
123
- const { outlineWidth, renderOutline, outlineOpacity } = _getLabelmapConfig(toolGroupLabelmapConfig, segmentationRepresentationLabelmapConfig, isActiveLabelmap);
134
+ const { outlineWidth, renderOutline, outlineOpacity, activeSegmentOutlineWidthDelta, } = _getLabelmapConfig(labelmapConfig, isActiveLabelmap);
135
+ const segmentsHidden = getSegmentsHidden(viewportId, segmentationRepresentation.segmentationRepresentationUID);
124
136
  for (let i = 0; i < numColors; i++) {
125
137
  const segmentIndex = i;
126
138
  const segmentColor = colorLUT[segmentIndex];
127
- const segmentSpecificLabelmapConfig = segmentSpecificConfig[segmentIndex]?.[Representations.Labelmap];
128
- const { fillAlpha, outlineWidth, renderFill, renderOutline } = _getLabelmapConfig(toolGroupLabelmapConfig, segmentationRepresentationLabelmapConfig, isActiveLabelmap, segmentSpecificLabelmapConfig);
139
+ const segmentSpecificLabelmapConfig = perSegment?.[segmentIndex]?.[Representations.Labelmap];
140
+ const { fillAlpha, outlineWidth, renderFill, renderOutline } = _getLabelmapConfig(labelmapConfig, isActiveLabelmap, segmentSpecificLabelmapConfig);
129
141
  const { forceOpacityUpdate, forceColorUpdate } = _needsTransferFunctionUpdate(viewportId, actorUID, segmentIndex, {
130
142
  fillAlpha,
131
143
  renderFill,
132
144
  renderOutline,
133
145
  segmentColor,
134
146
  outlineWidth,
135
- segmentsHidden,
136
147
  });
137
148
  if (forceColorUpdate) {
138
149
  cfun.addRGBPoint(segmentIndex, segmentColor[0] / MAX_NUMBER_COLORS, segmentColor[1] / MAX_NUMBER_COLORS, segmentColor[2] / MAX_NUMBER_COLORS);
@@ -167,18 +178,17 @@ function _setLabelmapColorAndOpacity(viewportId, actorEntry, cfun, ofun, colorLU
167
178
  }
168
179
  outlineWidths[i - 1] =
169
180
  i === activeSegmentIndex
170
- ? outlineWidth + toolGroupLabelmapConfig.activeSegmentOutlineWidthDelta
181
+ ? outlineWidth + activeSegmentOutlineWidthDelta
171
182
  : outlineWidth;
172
183
  }
173
184
  actor.getProperty().setLabelOutlineThickness(outlineWidths);
174
- const visible = isActiveLabelmap || renderInactiveSegmentations;
185
+ const visible = isActiveLabelmap || renderInactiveRepresentations;
175
186
  actor.setVisibility(visible);
176
187
  }
177
- function _getLabelmapConfig(toolGroupLabelmapConfig, segmentationRepresentationLabelmapConfig, isActiveLabelmap, segmentsLabelmapConfig) {
188
+ function _getLabelmapConfig(labelmapConfig, isActiveLabelmap, segmentsLabelmapConfig) {
178
189
  const segmentLabelmapConfig = segmentsLabelmapConfig || {};
179
190
  const configToUse = {
180
- ...toolGroupLabelmapConfig,
181
- ...segmentationRepresentationLabelmapConfig,
191
+ ...labelmapConfig,
182
192
  ...segmentLabelmapConfig,
183
193
  };
184
194
  const fillAlpha = isActiveLabelmap
@@ -194,15 +204,17 @@ function _getLabelmapConfig(toolGroupLabelmapConfig, segmentationRepresentationL
194
204
  const outlineOpacity = isActiveLabelmap
195
205
  ? configToUse.outlineOpacity
196
206
  : configToUse.outlineOpacityInactive;
207
+ const activeSegmentOutlineWidthDelta = configToUse.activeSegmentOutlineWidthDelta;
197
208
  return {
198
209
  fillAlpha,
199
210
  outlineWidth,
200
211
  renderFill,
201
212
  renderOutline,
202
213
  outlineOpacity,
214
+ activeSegmentOutlineWidthDelta,
203
215
  };
204
216
  }
205
- function _needsTransferFunctionUpdate(viewportId, actorUID, segmentIndex, { fillAlpha, renderFill, renderOutline, segmentColor, outlineWidth, segmentsHidden, }) {
217
+ function _needsTransferFunctionUpdate(viewportId, actorUID, segmentIndex, { fillAlpha, renderFill, renderOutline, segmentColor, outlineWidth, }) {
206
218
  const cacheUID = `${viewportId}-${actorUID}-${segmentIndex}`;
207
219
  const oldConfig = labelMapConfigCache.get(cacheUID);
208
220
  if (!oldConfig) {
@@ -212,14 +224,13 @@ function _needsTransferFunctionUpdate(viewportId, actorUID, segmentIndex, { fill
212
224
  renderOutline,
213
225
  outlineWidth,
214
226
  segmentColor: segmentColor.slice(),
215
- segmentsHidden: new Set(segmentsHidden),
216
227
  });
217
228
  return {
218
229
  forceOpacityUpdate: true,
219
230
  forceColorUpdate: true,
220
231
  };
221
232
  }
222
- const { fillAlpha: oldFillAlpha, renderFill: oldRenderFill, renderOutline: oldRenderOutline, outlineWidth: oldOutlineWidth, segmentColor: oldSegmentColor, segmentsHidden: oldSegmentsHidden, } = oldConfig;
233
+ const { fillAlpha: oldFillAlpha, renderFill: oldRenderFill, renderOutline: oldRenderOutline, outlineWidth: oldOutlineWidth, segmentColor: oldSegmentColor, } = oldConfig;
223
234
  const forceColorUpdate = oldSegmentColor[0] !== segmentColor[0] ||
224
235
  oldSegmentColor[1] !== segmentColor[1] ||
225
236
  oldSegmentColor[2] !== segmentColor[2];
@@ -228,38 +239,24 @@ function _needsTransferFunctionUpdate(viewportId, actorUID, segmentIndex, { fill
228
239
  oldRenderFill !== renderFill ||
229
240
  oldRenderOutline !== renderOutline ||
230
241
  oldOutlineWidth !== outlineWidth ||
231
- oldSegmentsHidden.has(segmentIndex) !== segmentsHidden.has(segmentIndex);
232
- labelMapConfigCache.set(cacheUID, {
233
- fillAlpha,
234
- renderFill,
235
- renderOutline,
236
- outlineWidth,
237
- segmentColor: segmentColor.slice(),
238
- segmentsHidden: new Set(segmentsHidden),
239
- });
242
+ labelMapConfigCache.set(cacheUID, {
243
+ fillAlpha,
244
+ renderFill,
245
+ renderOutline,
246
+ outlineWidth,
247
+ segmentColor: segmentColor.slice(),
248
+ });
240
249
  return {
241
250
  forceOpacityUpdate,
242
251
  forceColorUpdate,
243
252
  };
244
253
  }
245
- function _removeLabelmapFromToolGroupViewports(toolGroupId, segmentationRepresentationUID) {
246
- const toolGroup = getToolGroup(toolGroupId);
247
- if (toolGroup === undefined) {
248
- throw new Error(`ToolGroup with ToolGroupId ${toolGroupId} does not exist`);
249
- }
250
- const { viewportsInfo } = toolGroup;
251
- for (const viewportInfo of viewportsInfo) {
252
- const { viewportId, renderingEngineId } = viewportInfo;
253
- const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
254
- removeLabelmapFromElement(enabledElement.viewport.element, segmentationRepresentationUID);
255
- }
256
- }
257
254
  async function _addLabelmapToViewport(viewport, labelmapData, segmentationRepresentationUID) {
258
255
  await addLabelmapToElement(viewport.element, labelmapData, segmentationRepresentationUID);
259
256
  }
260
257
  export default {
261
258
  getRepresentationRenderingConfig,
262
259
  render,
263
- removeSegmentationRepresentation,
260
+ removeRepresentation,
264
261
  };
265
- export { getRepresentationRenderingConfig, render, removeSegmentationRepresentation, };
262
+ export { getRepresentationRenderingConfig, render, removeRepresentation };
@@ -0,0 +1,19 @@
1
+ import { Types } from '@cornerstonejs/core';
2
+ declare class SegmentationRenderingEngine {
3
+ private _needsRender;
4
+ private _animationFrameSet;
5
+ private _animationFrameHandle;
6
+ hasBeenDestroyed: boolean;
7
+ renderSegmentations(segmentationId?: string): void;
8
+ renderSegmentationsForViewports(viewportIds?: string[]): void;
9
+ _getAllViewports: () => Types.IViewport[];
10
+ _getViewportIdsForSegmentation(segmentationId?: string): string[];
11
+ private _throwIfDestroyed;
12
+ private _setViewportsToBeRenderedNextFrame;
13
+ private _render;
14
+ private _renderFlaggedSegmentations;
15
+ _triggerRender(viewportId?: string): void;
16
+ _addPlanarFreeHandToolIfAbsent(viewport: any): void;
17
+ }
18
+ declare const segmentationRenderingEngine: SegmentationRenderingEngine;
19
+ export { segmentationRenderingEngine };
@@ -0,0 +1,136 @@
1
+ import { triggerEvent, eventTarget, Enums, getRenderingEngines, getEnabledElementByViewportId, } from '@cornerstonejs/core';
2
+ import { SegmentationRepresentations, Events as csToolsEvents, } from '../../enums';
3
+ import Representations from '../../enums/SegmentationRepresentations';
4
+ import { getRepresentationsForViewport } from '../../stateManagement/segmentation/segmentationState';
5
+ import { surfaceDisplay } from './Surface';
6
+ import { contourDisplay } from './Contour';
7
+ import { labelmapDisplay } from './Labelmap';
8
+ import { addTool, state } from '../../store';
9
+ import PlanarFreehandContourSegmentationTool from '../annotation/PlanarFreehandContourSegmentationTool';
10
+ import { getToolGroupForViewport } from '../../store/ToolGroupManager';
11
+ const renderers = {
12
+ [Representations.Labelmap]: labelmapDisplay,
13
+ [Representations.Contour]: contourDisplay,
14
+ [Representations.Surface]: surfaceDisplay,
15
+ };
16
+ const planarContourToolName = PlanarFreehandContourSegmentationTool.toolName;
17
+ class SegmentationRenderingEngine {
18
+ constructor() {
19
+ this._needsRender = new Set();
20
+ this._animationFrameSet = false;
21
+ this._animationFrameHandle = null;
22
+ this._getAllViewports = () => {
23
+ const renderingEngine = getRenderingEngines();
24
+ return renderingEngine.flatMap((renderingEngine) => renderingEngine.getViewports());
25
+ };
26
+ this._renderFlaggedSegmentations = () => {
27
+ this._throwIfDestroyed();
28
+ const viewportIds = Array.from(this._needsRender);
29
+ viewportIds.forEach((viewportId) => {
30
+ this._triggerRender(viewportId);
31
+ });
32
+ this._needsRender.clear();
33
+ this._animationFrameSet = false;
34
+ this._animationFrameHandle = null;
35
+ };
36
+ }
37
+ renderSegmentations(segmentationId) {
38
+ const viewportIds = this._getViewportIdsForSegmentation(segmentationId);
39
+ this._setViewportsToBeRenderedNextFrame(viewportIds);
40
+ }
41
+ renderSegmentationsForViewports(viewportIds) {
42
+ if (!viewportIds?.length) {
43
+ const allViewports = this._getAllViewports();
44
+ this._setViewportsToBeRenderedNextFrame(allViewports.map((viewport) => viewport.id));
45
+ }
46
+ else {
47
+ this._setViewportsToBeRenderedNextFrame(viewportIds);
48
+ }
49
+ }
50
+ _getViewportIdsForSegmentation(segmentationId) {
51
+ const viewports = this._getAllViewports();
52
+ const viewportIds = [];
53
+ for (const viewport of viewports) {
54
+ const viewportId = viewport.id;
55
+ const segmentationRepresentations = getRepresentationsForViewport(viewportId);
56
+ if (segmentationId) {
57
+ const hasSegmentationRepresentation = segmentationRepresentations.some((representation) => representation.segmentationId === segmentationId);
58
+ if (hasSegmentationRepresentation) {
59
+ viewportIds.push(viewportId);
60
+ }
61
+ }
62
+ else {
63
+ if (segmentationRepresentations.length > 0) {
64
+ viewportIds.push(viewportId);
65
+ }
66
+ }
67
+ }
68
+ return viewportIds;
69
+ }
70
+ _throwIfDestroyed() {
71
+ if (this.hasBeenDestroyed) {
72
+ throw new Error('this.destroy() has been manually called to free up memory, can not longer use this instance. Instead make a new one.');
73
+ }
74
+ }
75
+ _setViewportsToBeRenderedNextFrame(viewportIds) {
76
+ viewportIds.forEach((viewportId) => {
77
+ this._needsRender.add(viewportId);
78
+ });
79
+ this._render();
80
+ }
81
+ _render() {
82
+ if (this._needsRender.size > 0 && this._animationFrameSet === false) {
83
+ this._animationFrameHandle = window.requestAnimationFrame(this._renderFlaggedSegmentations);
84
+ this._animationFrameSet = true;
85
+ }
86
+ }
87
+ _triggerRender(viewportId) {
88
+ const segmentationRepresentations = getRepresentationsForViewport(viewportId);
89
+ if (!segmentationRepresentations?.length) {
90
+ return;
91
+ }
92
+ const { viewport } = getEnabledElementByViewportId(viewportId);
93
+ const viewportRenderList = [];
94
+ const segmentationRenderList = segmentationRepresentations.map((representation) => {
95
+ if (representation.type === SegmentationRepresentations.Contour) {
96
+ this._addPlanarFreeHandToolIfAbsent(viewport);
97
+ }
98
+ const display = renderers[representation.type];
99
+ try {
100
+ const viewportId = display.render(viewport, representation);
101
+ viewportRenderList.push(viewportId);
102
+ }
103
+ catch (error) {
104
+ console.error(error);
105
+ }
106
+ return Promise.resolve();
107
+ });
108
+ function onSegmentationRender(evt) {
109
+ const { element, viewportId } = evt.detail;
110
+ element.removeEventListener(Enums.Events.IMAGE_RENDERED, onSegmentationRender);
111
+ const eventDetail = {
112
+ viewportId,
113
+ };
114
+ triggerEvent(eventTarget, csToolsEvents.SEGMENTATION_RENDERED, {
115
+ ...eventDetail,
116
+ });
117
+ }
118
+ Promise.allSettled(segmentationRenderList).then(() => {
119
+ const element = viewport.element;
120
+ element.addEventListener(Enums.Events.IMAGE_RENDERED, onSegmentationRender);
121
+ viewport.render();
122
+ });
123
+ }
124
+ _addPlanarFreeHandToolIfAbsent(viewport) {
125
+ if (!(planarContourToolName in state.tools)) {
126
+ addTool(PlanarFreehandContourSegmentationTool);
127
+ }
128
+ const toolGroup = getToolGroupForViewport(viewport.id);
129
+ if (!toolGroup.hasTool(planarContourToolName)) {
130
+ toolGroup.addTool(planarContourToolName);
131
+ toolGroup.setToolPassive(planarContourToolName);
132
+ }
133
+ }
134
+ }
135
+ const segmentationRenderingEngine = new SegmentationRenderingEngine();
136
+ export { segmentationRenderingEngine };
@@ -1,10 +1,10 @@
1
1
  import { Types } from '@cornerstonejs/core';
2
- import { ToolGroupSpecificRepresentation } from '../../../types/SegmentationStateTypes';
3
- declare function removeSegmentationRepresentation(toolGroupId: string, segmentationRepresentationUID: string, renderImmediate?: boolean): void;
4
- declare function render(viewport: Types.IVolumeViewport, representation: ToolGroupSpecificRepresentation): Promise<void>;
2
+ import { SegmentationRepresentation } from '../../../types/SegmentationStateTypes';
3
+ declare function removeRepresentation(viewportId: string, segmentationRepresentationUID: string, renderImmediate?: boolean): void;
4
+ declare function render(viewport: Types.IVolumeViewport | Types.IStackViewport, representation: SegmentationRepresentation): Promise<void>;
5
5
  declare const _default: {
6
6
  render: typeof render;
7
- removeSegmentationRepresentation: typeof removeSegmentationRepresentation;
7
+ removeRepresentation: typeof removeRepresentation;
8
8
  };
9
9
  export default _default;
10
- export { render, removeSegmentationRepresentation };
10
+ export { render, removeRepresentation };