@cornerstonejs/tools 2.0.0-beta.28 → 2.0.0-beta.29

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 (63) hide show
  1. package/dist/esm/constants/COLOR_LUT.d.ts +2 -1
  2. package/dist/esm/eventListeners/segmentation/imageChangeEventListener.js +1 -1
  3. package/dist/esm/eventListeners/segmentation/segmentationModifiedEventListener.js +0 -1
  4. package/dist/esm/eventListeners/segmentation/segmentationRepresentationModifiedListener.d.ts +3 -0
  5. package/dist/esm/eventListeners/segmentation/segmentationRepresentationModifiedListener.js +6 -0
  6. package/dist/esm/init.js +4 -0
  7. package/dist/esm/stateManagement/segmentation/SegmentationRenderingEngine.js +22 -12
  8. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.d.ts +1 -0
  9. package/dist/esm/stateManagement/segmentation/SegmentationStateManager.js +63 -25
  10. package/dist/esm/stateManagement/segmentation/SegmentationStyle.d.ts +22 -25
  11. package/dist/esm/stateManagement/segmentation/SegmentationStyle.js +138 -77
  12. package/dist/esm/stateManagement/segmentation/activeSegmentation.js +0 -4
  13. package/dist/esm/stateManagement/segmentation/config/segmentationColor.js +5 -5
  14. package/dist/esm/stateManagement/segmentation/config/segmentationVisibility.js +12 -8
  15. package/dist/esm/stateManagement/segmentation/config/styleHelpers.d.ts +17 -31
  16. package/dist/esm/stateManagement/segmentation/config/styleHelpers.js +14 -37
  17. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationModified.d.ts +1 -1
  18. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationModified.js +4 -14
  19. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationRepresentationModified.d.ts +2 -0
  20. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationRepresentationModified.js +10 -0
  21. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationRepresentationRemoved.d.ts +2 -0
  22. package/dist/esm/stateManagement/segmentation/events/triggerSegmentationRepresentationRemoved.js +10 -0
  23. package/dist/esm/stateManagement/segmentation/getActiveSegmentIndex.js +3 -1
  24. package/dist/esm/stateManagement/segmentation/getGlobalStyle.js +1 -1
  25. package/dist/esm/stateManagement/segmentation/helpers/clearSegmentValue.js +0 -1
  26. package/dist/esm/stateManagement/segmentation/helpers/internalGetHiddenSegmentIndices.d.ts +5 -0
  27. package/dist/esm/stateManagement/segmentation/helpers/internalGetHiddenSegmentIndices.js +14 -0
  28. package/dist/esm/stateManagement/segmentation/helpers/normalizeSegmentationInput.js +13 -6
  29. package/dist/esm/stateManagement/segmentation/index.d.ts +3 -1
  30. package/dist/esm/stateManagement/segmentation/index.js +3 -1
  31. package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +9 -8
  32. package/dist/esm/stateManagement/segmentation/polySeg/Contour/contourComputationStrategies.js +1 -1
  33. package/dist/esm/stateManagement/segmentation/polySeg/computeAndAddRepresentation.js +0 -1
  34. package/dist/esm/stateManagement/segmentation/removeSegment.d.ts +3 -0
  35. package/dist/esm/stateManagement/segmentation/removeSegment.js +50 -0
  36. package/dist/esm/stateManagement/segmentation/removeSegmentationRepresentations.d.ts +1 -1
  37. package/dist/esm/stateManagement/segmentation/removeSegmentationRepresentations.js +10 -12
  38. package/dist/esm/stateManagement/segmentation/segmentIndex.js +18 -2
  39. package/dist/esm/stateManagement/segmentation/segmentLocking.js +7 -11
  40. package/dist/esm/stateManagement/segmentation/setGlobalStyle.js +3 -3
  41. package/dist/esm/stateManagement/segmentation/triggerSegmentationEvents.d.ts +3 -1
  42. package/dist/esm/stateManagement/segmentation/triggerSegmentationEvents.js +3 -1
  43. package/dist/esm/stateManagement/segmentation/updateSegmentations.d.ts +5 -0
  44. package/dist/esm/stateManagement/segmentation/updateSegmentations.js +11 -0
  45. package/dist/esm/tools/base/ContourSegmentationBaseTool.js +11 -10
  46. package/dist/esm/tools/displayTools/Contour/contourConfig.js +2 -2
  47. package/dist/esm/tools/displayTools/Contour/contourHandler/handleContourSegmentation.js +1 -5
  48. package/dist/esm/tools/displayTools/Labelmap/labelmapConfig.js +3 -3
  49. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +38 -29
  50. package/dist/esm/tools/displayTools/Surface/surfaceDisplay.js +2 -2
  51. package/dist/esm/tools/segmentation/BrushTool.js +4 -1
  52. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +1 -1
  53. package/dist/esm/types/ContourTypes.d.ts +15 -8
  54. package/dist/esm/types/EventTypes.d.ts +6 -0
  55. package/dist/esm/types/LabelmapTypes.d.ts +9 -6
  56. package/dist/esm/types/SegmentationStateTypes.d.ts +31 -21
  57. package/dist/esm/types/SurfaceTypes.d.ts +1 -0
  58. package/dist/esm/types/index.d.ts +6 -4
  59. package/dist/esm/utilities/dynamicVolume/generateImageFromTimeData.d.ts +8 -2
  60. package/dist/esm/utilities/dynamicVolume/generateImageFromTimeData.js +51 -24
  61. package/dist/esm/utilities/dynamicVolume/index.d.ts +2 -2
  62. package/dist/esm/utilities/dynamicVolume/index.js +2 -2
  63. package/package.json +3 -3
@@ -1,2 +1,3 @@
1
- declare const CORNERSTONE_COLOR_LUT: number[][];
1
+ import type { Types } from '@cornerstonejs/core';
2
+ declare const CORNERSTONE_COLOR_LUT: Types.Color[];
2
3
  export default CORNERSTONE_COLOR_LUT;
@@ -94,7 +94,7 @@ function _imageChangeEventListener(evt) {
94
94
  },
95
95
  },
96
96
  ]);
97
- triggerSegmentationRender();
97
+ triggerSegmentationRender(viewportId);
98
98
  return;
99
99
  }
100
100
  else {
@@ -1,4 +1,3 @@
1
- import {} from '../../stateManagement/segmentation/triggerSegmentationEvents';
2
1
  import { triggerSegmentationRenderBySegmentationId } from '../../stateManagement/segmentation/SegmentationRenderingEngine';
3
2
  const segmentationModifiedListener = function (evt) {
4
3
  const { segmentationId } = evt.detail;
@@ -0,0 +1,3 @@
1
+ import type { SegmentationRepresentationModifiedEventType } from '../../types/EventTypes';
2
+ declare const segmentationRepresentationModifiedListener: (evt: SegmentationRepresentationModifiedEventType) => void;
3
+ export default segmentationRepresentationModifiedListener;
@@ -0,0 +1,6 @@
1
+ import { triggerSegmentationRender } from '../../stateManagement/segmentation/SegmentationRenderingEngine';
2
+ const segmentationRepresentationModifiedListener = function (evt) {
3
+ const { viewportId } = evt.detail;
4
+ triggerSegmentationRender(viewportId);
5
+ };
6
+ export default segmentationRepresentationModifiedListener;
package/dist/esm/init.js CHANGED
@@ -1,3 +1,4 @@
1
+ console.debug("tools: link: init: 3DA675F2-86A1-41A1-9E15-A7019E085C0F");
1
2
  import { eventTarget, Enums } from '@cornerstonejs/core';
2
3
  import { getAnnotationManager } from './stateManagement/annotation/annotationState';
3
4
  import { Events as TOOLS_EVENTS } from './enums';
@@ -7,6 +8,7 @@ import { annotationCompletedListener, annotationRemovedListener, annotationSelec
7
8
  import { annotationInterpolationEventDispatcher } from './eventDispatchers';
8
9
  import * as ToolGroupManager from './store/ToolGroupManager';
9
10
  import { defaultSegmentationStateManager } from './stateManagement/segmentation/SegmentationStateManager';
11
+ import segmentationRepresentationModifiedListener from './eventListeners/segmentation/segmentationRepresentationModifiedListener';
10
12
  let csToolsInitialized = false;
11
13
  export function init(defaultConfiguration = {}) {
12
14
  if (csToolsInitialized) {
@@ -51,6 +53,7 @@ function _addCornerstoneToolsEventListeners() {
51
53
  eventTarget.addEventListener(TOOLS_EVENTS.ANNOTATION_REMOVED, annotationRemovedListener);
52
54
  eventTarget.addEventListener(TOOLS_EVENTS.SEGMENTATION_MODIFIED, segmentationModifiedListener);
53
55
  eventTarget.addEventListener(TOOLS_EVENTS.SEGMENTATION_DATA_MODIFIED, segmentationDataModifiedEventListener);
56
+ eventTarget.addEventListener(TOOLS_EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED, segmentationRepresentationModifiedListener);
54
57
  }
55
58
  function _removeCornerstoneToolsEventListeners() {
56
59
  eventTarget.removeEventListener(TOOLS_EVENTS.ANNOTATION_COMPLETED, annotationCompletedListener);
@@ -59,5 +62,6 @@ function _removeCornerstoneToolsEventListeners() {
59
62
  eventTarget.removeEventListener(TOOLS_EVENTS.ANNOTATION_SELECTION_CHANGE, annotationSelectionListener);
60
63
  eventTarget.removeEventListener(TOOLS_EVENTS.SEGMENTATION_MODIFIED, segmentationModifiedListener);
61
64
  eventTarget.removeEventListener(TOOLS_EVENTS.SEGMENTATION_DATA_MODIFIED, segmentationDataModifiedEventListener);
65
+ eventTarget.removeEventListener(TOOLS_EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED, segmentationRepresentationModifiedListener);
62
66
  }
63
67
  export default init;
@@ -104,19 +104,29 @@ class SegmentationRenderingEngine {
104
104
  catch (error) {
105
105
  console.error(error);
106
106
  }
107
- return Promise.resolve();
108
- });
109
- function onSegmentationRender(evt) {
110
- const { element, viewportId } = evt.detail;
111
- element.removeEventListener(Enums.Events.IMAGE_RENDERED, onSegmentationRender);
112
- const eventDetail = {
113
- viewportId,
114
- };
115
- triggerEvent(eventTarget, csToolsEvents.SEGMENTATION_RENDERED, {
116
- ...eventDetail,
107
+ return Promise.resolve({
108
+ segmentationId: representation.segmentationId,
109
+ type: representation.type,
117
110
  });
118
- }
119
- Promise.allSettled(segmentationRenderList).then(() => {
111
+ });
112
+ Promise.allSettled(segmentationRenderList).then((results) => {
113
+ const segmentationDetails = results
114
+ .filter((r) => r.status === 'fulfilled')
115
+ .map((r) => r.value);
116
+ function onSegmentationRender(evt) {
117
+ const { element, viewportId } = evt.detail;
118
+ element.removeEventListener(Enums.Events.IMAGE_RENDERED, onSegmentationRender);
119
+ segmentationDetails.forEach((detail) => {
120
+ const eventDetail = {
121
+ viewportId,
122
+ segmentationId: detail.segmentationId,
123
+ type: detail.type,
124
+ };
125
+ triggerEvent(eventTarget, csToolsEvents.SEGMENTATION_RENDERED, {
126
+ ...eventDetail,
127
+ });
128
+ });
129
+ }
120
130
  const element = viewport.element;
121
131
  element.addEventListener(Enums.Events.IMAGE_RENDERED, onSegmentationRender);
122
132
  viewport.render();
@@ -12,6 +12,7 @@ export default class SegmentationStateManager {
12
12
  getNextColorLUTIndex(): number;
13
13
  resetState(): void;
14
14
  getSegmentation(segmentationId: string): Segmentation | undefined;
15
+ updateSegmentation(segmentationId: string, payload: Partial<Segmentation>): void;
15
16
  addSegmentation(segmentation: Segmentation): void;
16
17
  removeSegmentation(segmentationId: string): void;
17
18
  addSegmentationRepresentation(viewportId: string, segmentationId: string, type: SegmentationRepresentations, renderingConfig: RenderingConfig): void;
@@ -2,6 +2,7 @@ import { BaseVolumeViewport, cache, utilities as csUtils, getEnabledElementByVie
2
2
  import { SegmentationRepresentations } from '../../enums';
3
3
  import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
4
4
  import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunction';
5
+ import { triggerSegmentationModified, triggerSegmentationRemoved, triggerSegmentationRepresentationModified, triggerSegmentationRepresentationRemoved, } from './triggerSegmentationEvents';
5
6
  import { segmentationStyle } from './SegmentationStyle';
6
7
  const initialDefaultState = {
7
8
  colorLUT: [],
@@ -35,6 +36,17 @@ export default class SegmentationStateManager {
35
36
  getSegmentation(segmentationId) {
36
37
  return this.state.segmentations.find((segmentation) => segmentation.segmentationId === segmentationId);
37
38
  }
39
+ updateSegmentation(segmentationId, payload) {
40
+ this.updateState((draftState) => {
41
+ const segmentation = draftState.segmentations.find((segmentation) => segmentation.segmentationId === segmentationId);
42
+ if (!segmentation) {
43
+ console.warn(`Segmentation with id ${segmentationId} not found. Update aborted.`);
44
+ return;
45
+ }
46
+ Object.assign(segmentation, payload);
47
+ });
48
+ triggerSegmentationModified(segmentationId);
49
+ }
38
50
  addSegmentation(segmentation) {
39
51
  if (this.getSegmentation(segmentation.segmentationId)) {
40
52
  throw new Error(`Segmentation with id ${segmentation.segmentationId} already exists`);
@@ -50,6 +62,7 @@ export default class SegmentationStateManager {
50
62
  }
51
63
  state.segmentations.push(newSegmentation);
52
64
  });
65
+ triggerSegmentationModified(segmentation.segmentationId);
53
66
  }
54
67
  removeSegmentation(segmentationId) {
55
68
  this.updateState((state) => {
@@ -58,6 +71,7 @@ export default class SegmentationStateManager {
58
71
  representations = representations.filter((representation) => representation.segmentationId !== segmentationId);
59
72
  });
60
73
  });
74
+ triggerSegmentationRemoved(segmentationId);
61
75
  }
62
76
  addSegmentationRepresentation(viewportId, segmentationId, type, renderingConfig) {
63
77
  const enabledElement = getEnabledElementByViewportId(viewportId);
@@ -67,7 +81,7 @@ export default class SegmentationStateManager {
67
81
  this.updateState((state) => {
68
82
  if (!state.viewportSegRepresentations[viewportId]) {
69
83
  state.viewportSegRepresentations[viewportId] = [];
70
- segmentationStyle.setViewportRenderInactiveSegmentations(viewportId, true);
84
+ segmentationStyle.setRenderInactiveSegmentations(viewportId, true);
71
85
  }
72
86
  if (type !== SegmentationRepresentations.Labelmap) {
73
87
  this.addDefaultSegmentationRepresentation(state, viewportId, segmentationId, type, renderingConfig);
@@ -76,14 +90,26 @@ export default class SegmentationStateManager {
76
90
  this.addLabelmapRepresentation(state, viewportId, segmentationId, renderingConfig);
77
91
  }
78
92
  });
93
+ triggerSegmentationRepresentationModified(viewportId, segmentationId, type);
79
94
  }
80
95
  addDefaultSegmentationRepresentation(state, viewportId, segmentationId, type, renderingConfig) {
96
+ const segmentation = state.segmentations.find((segmentation) => segmentation.segmentationId === segmentationId);
97
+ if (!segmentation) {
98
+ return;
99
+ }
100
+ const segmentReps = {};
101
+ Object.keys(segmentation.segments).forEach((segmentIndex) => {
102
+ segmentReps[Number(segmentIndex)] = {
103
+ visible: true,
104
+ };
105
+ });
81
106
  state.viewportSegRepresentations[viewportId].push({
82
107
  segmentationId,
83
108
  type,
84
109
  active: true,
85
110
  visible: true,
86
- segmentsHidden: new Set(),
111
+ colorLUTIndex: 0,
112
+ segments: segmentReps,
87
113
  config: {
88
114
  ...getDefaultRenderingConfig(type),
89
115
  ...renderingConfig,
@@ -246,33 +272,42 @@ export default class SegmentationStateManager {
246
272
  });
247
273
  }
248
274
  removeSegmentationRepresentations(viewportId, specifier) {
275
+ const removedRepresentations = [];
249
276
  this.updateState((state) => {
250
277
  if (!state.viewportSegRepresentations[viewportId]) {
251
278
  return;
252
279
  }
253
- if (!specifier) {
280
+ const currentRepresentations = state.viewportSegRepresentations[viewportId];
281
+ if (!specifier ||
282
+ Object.values(specifier).every((value) => value === undefined)) {
283
+ removedRepresentations.push(...currentRepresentations);
254
284
  delete state.viewportSegRepresentations[viewportId];
255
- return;
256
285
  }
257
- const { segmentationId, type } = specifier;
258
- state.viewportSegRepresentations[viewportId] =
259
- state.viewportSegRepresentations[viewportId].filter((representation) => {
260
- if (segmentationId && type) {
261
- return !(representation.segmentationId === segmentationId &&
262
- representation.type === type);
263
- }
264
- else if (segmentationId) {
265
- return representation.segmentationId !== segmentationId;
266
- }
267
- else if (type) {
268
- return representation.type !== type;
269
- }
270
- return true;
271
- });
272
- if (state.viewportSegRepresentations[viewportId].length === 0) {
273
- delete state.viewportSegRepresentations[viewportId];
286
+ else {
287
+ const { segmentationId, type } = specifier;
288
+ state.viewportSegRepresentations[viewportId] =
289
+ currentRepresentations.filter((representation) => {
290
+ const shouldRemove = (segmentationId &&
291
+ type &&
292
+ representation.segmentationId === segmentationId &&
293
+ representation.type === type) ||
294
+ (segmentationId &&
295
+ !type &&
296
+ representation.segmentationId === segmentationId) ||
297
+ (!segmentationId && type && representation.type === type);
298
+ if (shouldRemove) {
299
+ removedRepresentations.push(representation);
300
+ }
301
+ return !shouldRemove;
302
+ });
303
+ if (state.viewportSegRepresentations[viewportId].length === 0) {
304
+ delete state.viewportSegRepresentations[viewportId];
305
+ }
274
306
  }
275
307
  });
308
+ removedRepresentations.forEach((representation) => {
309
+ triggerSegmentationRepresentationRemoved(viewportId, representation.segmentationId, representation.type);
310
+ });
276
311
  }
277
312
  removeSegmentationRepresentation(viewportId, specifier) {
278
313
  this.updateState((state) => {
@@ -287,6 +322,7 @@ export default class SegmentationStateManager {
287
322
  }
288
323
  viewport.splice(viewport.indexOf(viewportRendering), 1);
289
324
  });
325
+ triggerSegmentationRepresentationRemoved(viewportId, specifier.segmentationId, specifier.type);
290
326
  }
291
327
  _setActiveSegmentation(state, viewportId, segmentationId) {
292
328
  const viewport = state.viewportSegRepresentations[viewportId];
@@ -307,6 +343,7 @@ export default class SegmentationStateManager {
307
343
  value.active = value.segmentationId === segmentationId;
308
344
  });
309
345
  });
346
+ triggerSegmentationRepresentationModified(viewportId, segmentationId);
310
347
  }
311
348
  getActiveSegmentation(viewportId) {
312
349
  if (!this.state.viewportSegRepresentations[viewportId]) {
@@ -351,8 +388,12 @@ export default class SegmentationStateManager {
351
388
  }
352
389
  viewportRepresentations.forEach((representation) => {
353
390
  representation.visible = visible;
391
+ Object.entries(representation.segments).forEach(([segmentIndex, segment]) => {
392
+ segment.visible = visible;
393
+ });
354
394
  });
355
395
  });
396
+ triggerSegmentationRepresentationModified(viewportId, specifier.segmentationId, specifier.type);
356
397
  }
357
398
  addColorLUT(colorLUT, lutIndex) {
358
399
  this.updateState((state) => {
@@ -403,13 +444,10 @@ function getDefaultRenderingConfig(type) {
403
444
  return {
404
445
  cfun,
405
446
  ofun,
406
- colorLUTIndex: 0,
407
447
  };
408
448
  }
409
449
  else {
410
- return {
411
- colorLUTIndex: 0,
412
- };
450
+ return {};
413
451
  }
414
452
  }
415
453
  const defaultSegmentationStateManager = new SegmentationStateManager('DEFAULT');
@@ -1,42 +1,39 @@
1
- import { SegmentationRepresentations } from '../../enums';
2
- import type { ContourStyle } from '../../types/ContourTypes';
3
- import type { LabelmapStyle } from '../../types/LabelmapTypes';
1
+ import type { SegmentationRepresentations } from '../../enums';
2
+ import type { BaseContourStyle, ContourStyle } from '../../types/ContourTypes';
3
+ import type { BaseLabelmapStyle, LabelmapStyle } from '../../types/LabelmapTypes';
4
4
  import type { SurfaceStyle } from '../../types/SurfaceTypes';
5
5
  export type RepresentationStyle = LabelmapStyle | ContourStyle | SurfaceStyle;
6
+ export type BaseRepresentationStyle = BaseLabelmapStyle | BaseContourStyle;
6
7
  declare class SegmentationStyle {
7
8
  private config;
8
9
  constructor();
9
- setGlobalStyle(type: SegmentationRepresentations, styles: RepresentationStyle): void;
10
- getGlobalStyle(type: SegmentationRepresentations): RepresentationStyle;
11
- setGlobalLabelmapStyle(styles: LabelmapStyle): void;
12
- setGlobalContourStyle(styles: ContourStyle): void;
13
- setGlobalSurfaceStyle(styles: SurfaceStyle): void;
14
- setSegmentationSpecificStyle(specifier: {
15
- segmentationId: string;
16
- type: SegmentationRepresentations;
17
- segmentIndex?: number;
18
- }, styles: RepresentationStyle): void;
19
- setViewportSpecificStyleForType(specifier: {
20
- viewportId: string;
21
- type: SegmentationRepresentations;
22
- }, styles: RepresentationStyle): void;
23
- setViewportSpecificStyleForSegmentation(specifier: {
24
- viewportId: string;
25
- segmentationId: string;
10
+ setStyle(specifier: {
26
11
  type: SegmentationRepresentations;
12
+ viewportId?: string;
13
+ segmentationId?: string;
27
14
  segmentIndex?: number;
28
15
  }, styles: RepresentationStyle): void;
29
- setViewportRenderInactiveSegmentations(viewportId: string, renderInactiveSegmentations: boolean): void;
16
+ private copyActiveToInactiveIfNotProvided;
30
17
  getStyle(specifier: {
31
18
  viewportId?: string;
32
19
  segmentationId?: string;
33
20
  type?: SegmentationRepresentations;
34
21
  segmentIndex?: number;
35
- }): {
36
- style: RepresentationStyle;
37
- renderInactiveSegmentations: boolean;
38
- };
22
+ }): RepresentationStyle;
23
+ getRenderInactiveSegmentations(viewportId: string): boolean;
24
+ setRenderInactiveSegmentations(viewportId: string, renderInactiveSegmentations: boolean): void;
39
25
  private getDefaultStyle;
26
+ clearSegmentationStyle(segmentationId: string): void;
27
+ clearAllSegmentationStyles(): void;
28
+ clearViewportStyle(viewportId: string): void;
29
+ clearAllViewportStyles(): void;
30
+ resetToGlobalStyle(): void;
31
+ hasCustomStyle(specifier: {
32
+ viewportId?: string;
33
+ segmentationId?: string;
34
+ type?: SegmentationRepresentations;
35
+ segmentIndex?: number;
36
+ }): boolean;
40
37
  }
41
38
  declare const segmentationStyle: SegmentationStyle;
42
39
  export { segmentationStyle };
@@ -1,7 +1,7 @@
1
- import { SegmentationRepresentations } from '../../enums';
2
1
  import getDefaultContourConfig from '../../tools/displayTools/Contour/contourConfig';
3
2
  import getDefaultLabelmapConfig from '../../tools/displayTools/Labelmap/labelmapConfig';
4
3
  import * as Enums from '../../enums';
4
+ import { utilities } from '@cornerstonejs/core';
5
5
  class SegmentationStyle {
6
6
  constructor() {
7
7
  this.config = {
@@ -10,90 +10,105 @@ class SegmentationStyle {
10
10
  viewportsStyle: {},
11
11
  };
12
12
  }
13
- setGlobalStyle(type, styles) {
14
- this.config.global[type] = styles;
15
- }
16
- getGlobalStyle(type) {
17
- return this.config.global[type];
18
- }
19
- setGlobalLabelmapStyle(styles) {
20
- this.setGlobalStyle(SegmentationRepresentations.Labelmap, styles);
21
- }
22
- setGlobalContourStyle(styles) {
23
- this.setGlobalStyle(SegmentationRepresentations.Contour, styles);
24
- }
25
- setGlobalSurfaceStyle(styles) {
26
- this.setGlobalStyle(SegmentationRepresentations.Surface, styles);
27
- }
28
- setSegmentationSpecificStyle(specifier, styles) {
29
- const { segmentationId, type, segmentIndex } = specifier;
30
- if (!this.config.segmentations[segmentationId]) {
31
- this.config.segmentations[segmentationId] = {};
32
- }
33
- if (!this.config.segmentations[segmentationId][type]) {
34
- this.config.segmentations[segmentationId][type] = {};
35
- }
36
- if (segmentIndex !== undefined) {
37
- if (!this.config.segmentations[segmentationId][type].perSegment) {
38
- this.config.segmentations[segmentationId][type].perSegment = {};
39
- }
40
- this.config.segmentations[segmentationId][type].perSegment[segmentIndex] =
41
- styles;
42
- }
43
- else {
44
- this.config.segmentations[segmentationId][type].allSegments = styles;
45
- }
46
- }
47
- setViewportSpecificStyleForType(specifier, styles) {
48
- const { viewportId, type } = specifier;
49
- if (!this.config.viewportsStyle[viewportId]) {
50
- this.config.viewportsStyle[viewportId] = {
51
- renderInactiveSegmentations: false,
52
- representations: {},
53
- };
54
- }
55
- const allSegmentationsKey = '__allSegmentations__';
56
- if (!this.config.viewportsStyle[viewportId].representations[allSegmentationsKey]) {
57
- this.config.viewportsStyle[viewportId].representations[allSegmentationsKey] = {};
58
- }
59
- this.config.viewportsStyle[viewportId].representations[allSegmentationsKey][type] = {
60
- allSegments: styles,
61
- };
62
- }
63
- setViewportSpecificStyleForSegmentation(specifier, styles) {
13
+ setStyle(specifier, styles) {
64
14
  const { viewportId, segmentationId, type, segmentIndex } = specifier;
65
- if (!this.config.viewportsStyle[viewportId]) {
66
- this.config.viewportsStyle[viewportId] = {
67
- renderInactiveSegmentations: false,
68
- representations: {},
15
+ const currentStyles = this.getStyle(specifier);
16
+ let updatedStyles;
17
+ if (!viewportId && !segmentationId) {
18
+ updatedStyles = {
19
+ ...currentStyles,
20
+ ...styles,
69
21
  };
70
22
  }
71
- if (!this.config.viewportsStyle[viewportId].representations[segmentationId]) {
72
- this.config.viewportsStyle[viewportId].representations[segmentationId] =
73
- {};
74
- }
75
- if (!this.config.viewportsStyle[viewportId].representations[segmentationId][type]) {
76
- this.config.viewportsStyle[viewportId].representations[segmentationId][type] = {};
23
+ else {
24
+ updatedStyles = this.copyActiveToInactiveIfNotProvided({
25
+ ...currentStyles,
26
+ ...styles,
27
+ }, type);
28
+ }
29
+ if (!type) {
30
+ throw new Error('Type is required to set a style');
31
+ }
32
+ if (viewportId) {
33
+ if (!this.config.viewportsStyle[viewportId]) {
34
+ this.config.viewportsStyle[viewportId] = {
35
+ renderInactiveSegmentations: false,
36
+ representations: {},
37
+ };
38
+ }
39
+ const representations = this.config.viewportsStyle[viewportId].representations;
40
+ if (segmentationId) {
41
+ if (!representations[segmentationId]) {
42
+ representations[segmentationId] = {};
43
+ }
44
+ if (!representations[segmentationId][type]) {
45
+ representations[segmentationId][type] = {};
46
+ }
47
+ const repConfig = representations[segmentationId][type];
48
+ if (segmentIndex !== undefined) {
49
+ if (!repConfig.perSegment) {
50
+ repConfig.perSegment = {};
51
+ }
52
+ repConfig.perSegment[segmentIndex] = updatedStyles;
53
+ }
54
+ else {
55
+ repConfig.allSegments = updatedStyles;
56
+ }
57
+ }
58
+ else {
59
+ const ALL_SEGMENTATIONS_KEY = '__allSegmentations__';
60
+ if (!representations[ALL_SEGMENTATIONS_KEY]) {
61
+ representations[ALL_SEGMENTATIONS_KEY] = {};
62
+ }
63
+ if (!representations[ALL_SEGMENTATIONS_KEY][type]) {
64
+ representations[ALL_SEGMENTATIONS_KEY][type] = {};
65
+ }
66
+ representations[ALL_SEGMENTATIONS_KEY][type].allSegments =
67
+ updatedStyles;
68
+ }
77
69
  }
78
- if (segmentIndex !== undefined) {
79
- if (!this.config.viewportsStyle[viewportId].representations[segmentationId][type].perSegment) {
80
- this.config.viewportsStyle[viewportId].representations[segmentationId][type].perSegment = {};
70
+ else if (segmentationId) {
71
+ if (!this.config.segmentations[segmentationId]) {
72
+ this.config.segmentations[segmentationId] = {};
73
+ }
74
+ if (!this.config.segmentations[segmentationId][type]) {
75
+ this.config.segmentations[segmentationId][type] = {};
76
+ }
77
+ const segConfig = this.config.segmentations[segmentationId][type];
78
+ if (segmentIndex !== undefined) {
79
+ if (!segConfig.perSegment) {
80
+ segConfig.perSegment = {};
81
+ }
82
+ segConfig.perSegment[segmentIndex] = updatedStyles;
83
+ }
84
+ else {
85
+ segConfig.allSegments = updatedStyles;
81
86
  }
82
- this.config.viewportsStyle[viewportId].representations[segmentationId][type].perSegment[segmentIndex] = styles;
83
87
  }
84
88
  else {
85
- this.config.viewportsStyle[viewportId].representations[segmentationId][type].allSegments = styles;
89
+ this.config.global[type] = updatedStyles;
86
90
  }
87
91
  }
88
- setViewportRenderInactiveSegmentations(viewportId, renderInactiveSegmentations) {
89
- if (!this.config.viewportsStyle[viewportId]) {
90
- this.config.viewportsStyle[viewportId] = {
91
- renderInactiveSegmentations: false,
92
- representations: {},
93
- };
94
- }
95
- this.config.viewportsStyle[viewportId].renderInactiveSegmentations =
96
- renderInactiveSegmentations;
92
+ copyActiveToInactiveIfNotProvided(styles, type) {
93
+ const processedStyles = { ...styles };
94
+ if (type === Enums.SegmentationRepresentations.Labelmap) {
95
+ const labelmapStyles = processedStyles;
96
+ labelmapStyles.renderOutlineInactive = labelmapStyles.renderOutline;
97
+ labelmapStyles.outlineWidthInactive = labelmapStyles.outlineWidth;
98
+ labelmapStyles.renderFillInactive = labelmapStyles.renderFill;
99
+ labelmapStyles.fillAlphaInactive = labelmapStyles.fillAlpha;
100
+ labelmapStyles.outlineOpacityInactive = labelmapStyles.outlineOpacity;
101
+ }
102
+ else if (type === Enums.SegmentationRepresentations.Contour) {
103
+ const contourStyles = processedStyles;
104
+ contourStyles.outlineWidthInactive = contourStyles.outlineWidth;
105
+ contourStyles.outlineOpacityInactive = contourStyles.outlineOpacity;
106
+ contourStyles.outlineDashInactive = contourStyles.outlineDash;
107
+ contourStyles.renderOutlineInactive = contourStyles.renderOutline;
108
+ contourStyles.renderFillInactive = contourStyles.renderFill;
109
+ contourStyles.fillAlphaInactive = contourStyles.fillAlpha;
110
+ }
111
+ return processedStyles;
97
112
  }
98
113
  getStyle(specifier) {
99
114
  const { viewportId, segmentationId, type, segmentIndex } = specifier;
@@ -143,7 +158,20 @@ class SegmentationStyle {
143
158
  }
144
159
  }
145
160
  }
146
- return { style: combinedStyle, renderInactiveSegmentations };
161
+ return combinedStyle;
162
+ }
163
+ getRenderInactiveSegmentations(viewportId) {
164
+ return this.config.viewportsStyle[viewportId]?.renderInactiveSegmentations;
165
+ }
166
+ setRenderInactiveSegmentations(viewportId, renderInactiveSegmentations) {
167
+ if (!this.config.viewportsStyle[viewportId]) {
168
+ this.config.viewportsStyle[viewportId] = {
169
+ renderInactiveSegmentations: false,
170
+ representations: {},
171
+ };
172
+ }
173
+ this.config.viewportsStyle[viewportId].renderInactiveSegmentations =
174
+ renderInactiveSegmentations;
147
175
  }
148
176
  getDefaultStyle(type) {
149
177
  switch (type) {
@@ -157,6 +185,39 @@ class SegmentationStyle {
157
185
  throw new Error(`Unknown representation type: ${type}`);
158
186
  }
159
187
  }
188
+ clearSegmentationStyle(segmentationId) {
189
+ if (this.config.segmentations[segmentationId]) {
190
+ delete this.config.segmentations[segmentationId];
191
+ }
192
+ }
193
+ clearAllSegmentationStyles() {
194
+ this.config.segmentations = {};
195
+ }
196
+ clearViewportStyle(viewportId) {
197
+ if (this.config.viewportsStyle[viewportId]) {
198
+ delete this.config.viewportsStyle[viewportId];
199
+ }
200
+ }
201
+ clearAllViewportStyles() {
202
+ for (const viewportId in this.config.viewportsStyle) {
203
+ const viewportStyle = this.config.viewportsStyle[viewportId];
204
+ const renderInactiveSegmentations = viewportStyle.renderInactiveSegmentations;
205
+ this.config.viewportsStyle[viewportId] = {
206
+ renderInactiveSegmentations,
207
+ representations: {},
208
+ };
209
+ }
210
+ }
211
+ resetToGlobalStyle() {
212
+ this.clearAllSegmentationStyles();
213
+ this.clearAllViewportStyles();
214
+ }
215
+ hasCustomStyle(specifier) {
216
+ const { type } = specifier;
217
+ const style = this.getStyle(specifier);
218
+ const defaultStyle = this.getDefaultStyle(type);
219
+ return !utilities.deepEqual(style, defaultStyle);
220
+ }
160
221
  }
161
222
  const segmentationStyle = new SegmentationStyle();
162
223
  export { segmentationStyle };
@@ -1,13 +1,9 @@
1
1
  import { getActiveSegmentation as _getActiveSegmentation } from './getActiveSegmentation';
2
- import { triggerSegmentationRender } from './SegmentationRenderingEngine';
3
2
  import { setActiveSegmentation as _setActiveSegmentation } from './setActiveSegmentation';
4
3
  function getActiveSegmentation(viewportId) {
5
4
  return _getActiveSegmentation(viewportId);
6
5
  }
7
6
  function setActiveSegmentation(viewportId, segmentationId, suppressEvent = false) {
8
7
  _setActiveSegmentation(viewportId, segmentationId);
9
- if (!suppressEvent) {
10
- triggerSegmentationRender(viewportId);
11
- }
12
8
  }
13
9
  export { getActiveSegmentation, setActiveSegmentation, };