@cornerstonejs/tools 4.12.6 → 4.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  declare enum StrategyCallbacks {
2
+ CalculateCursorGeometry = "calculateCursorGeometry",
3
+ RenderCursor = "renderCursor",
2
4
  OnInteractionStart = "onInteractionStart",
3
5
  OnInteractionEnd = "onInteractionEnd",
4
6
  Preview = "preview",
@@ -1,5 +1,7 @@
1
1
  var StrategyCallbacks;
2
2
  (function (StrategyCallbacks) {
3
+ StrategyCallbacks["CalculateCursorGeometry"] = "calculateCursorGeometry";
4
+ StrategyCallbacks["RenderCursor"] = "renderCursor";
3
5
  StrategyCallbacks["OnInteractionStart"] = "onInteractionStart";
4
6
  StrategyCallbacks["OnInteractionEnd"] = "onInteractionEnd";
5
7
  StrategyCallbacks["Preview"] = "preview";
@@ -1,3 +1,3 @@
1
- export declare function getCurrentLabelmapImageIdForViewport(viewportId: string, segmentationId: string): string;
1
+ export declare function getCurrentLabelmapImageIdForViewport(viewportId: string, segmentationId: string): string | undefined;
2
2
  export declare function getCurrentLabelmapImageIdsForViewport(viewportId: string, segmentationId: string): string[];
3
3
  export declare function getLabelmapImageIdsForImageId(imageId: string, segmentationId: string): string[];
@@ -1,6 +1,9 @@
1
1
  import { defaultSegmentationStateManager } from './SegmentationStateManager';
2
2
  export function getCurrentLabelmapImageIdForViewport(viewportId, segmentationId) {
3
3
  const imageIds = getCurrentLabelmapImageIdsForViewport(viewportId, segmentationId);
4
+ if (!imageIds?.length) {
5
+ return;
6
+ }
4
7
  return imageIds[0];
5
8
  }
6
9
  export function getCurrentLabelmapImageIdsForViewport(viewportId, segmentationId) {
@@ -290,51 +290,7 @@ class BrushTool extends LabelmapBaseTool {
290
290
  }
291
291
  _calculateCursor(element, centerCanvas) {
292
292
  const enabledElement = getEnabledElement(element);
293
- const { viewport } = enabledElement;
294
- const { canvasToWorld } = viewport;
295
- const camera = viewport.getCamera();
296
- const { brushSize } = this.configuration;
297
- const viewUp = vec3.fromValues(camera.viewUp[0], camera.viewUp[1], camera.viewUp[2]);
298
- const viewPlaneNormal = vec3.fromValues(camera.viewPlaneNormal[0], camera.viewPlaneNormal[1], camera.viewPlaneNormal[2]);
299
- const viewRight = vec3.create();
300
- vec3.cross(viewRight, viewUp, viewPlaneNormal);
301
- const centerCursorInWorld = canvasToWorld([
302
- centerCanvas[0],
303
- centerCanvas[1],
304
- ]);
305
- const bottomCursorInWorld = vec3.create();
306
- const topCursorInWorld = vec3.create();
307
- const leftCursorInWorld = vec3.create();
308
- const rightCursorInWorld = vec3.create();
309
- for (let i = 0; i <= 2; i++) {
310
- bottomCursorInWorld[i] = centerCursorInWorld[i] - viewUp[i] * brushSize;
311
- topCursorInWorld[i] = centerCursorInWorld[i] + viewUp[i] * brushSize;
312
- leftCursorInWorld[i] = centerCursorInWorld[i] - viewRight[i] * brushSize;
313
- rightCursorInWorld[i] = centerCursorInWorld[i] + viewRight[i] * brushSize;
314
- }
315
- if (!this._hoverData) {
316
- return;
317
- }
318
- const { brushCursor } = this._hoverData;
319
- const { data } = brushCursor;
320
- if (data.handles === undefined) {
321
- data.handles = {};
322
- }
323
- data.handles.points = [
324
- bottomCursorInWorld,
325
- topCursorInWorld,
326
- leftCursorInWorld,
327
- rightCursorInWorld,
328
- ];
329
- const activeStrategy = this.configuration.activeStrategy;
330
- const strategy = this.configuration.strategies[activeStrategy];
331
- if (typeof strategy?.computeInnerCircleRadius === 'function') {
332
- strategy.computeInnerCircleRadius({
333
- configuration: this.configuration,
334
- viewport,
335
- });
336
- }
337
- data.invalidated = false;
293
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.CalculateCursorGeometry);
338
294
  }
339
295
  getStatistics(element, segmentIndices) {
340
296
  if (!element) {
@@ -396,40 +352,7 @@ class BrushTool extends LabelmapBaseTool {
396
352
  const { element } = viewport;
397
353
  this._calculateCursor(element, centerCanvas);
398
354
  }
399
- const toolMetadata = brushCursor.metadata;
400
- if (!toolMetadata) {
401
- return;
402
- }
403
- const annotationUID = toolMetadata.brushCursorUID;
404
- const data = brushCursor.data;
405
- const { points } = data.handles;
406
- const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
407
- const bottom = canvasCoordinates[0];
408
- const top = canvasCoordinates[1];
409
- const center = [
410
- Math.floor((bottom[0] + top[0]) / 2),
411
- Math.floor((bottom[1] + top[1]) / 2),
412
- ];
413
- const radius = Math.abs(bottom[1] - Math.floor((bottom[1] + top[1]) / 2));
414
- const color = `rgb(${toolMetadata.segmentColor?.slice(0, 3) || [0, 0, 0]})`;
415
- if (!viewport.getRenderingEngine()) {
416
- console.warn('Rendering Engine has been destroyed');
417
- return;
418
- }
419
- const circleUID = '0';
420
- drawCircleSvg(svgDrawingHelper, annotationUID, circleUID, center, radius, {
421
- color,
422
- lineDash: this.centerSegmentIndexInfo.segmentIndex === 0 ? [1, 2] : null,
423
- });
424
- const { dynamicRadiusInCanvas } = this.configuration?.threshold || {
425
- dynamicRadiusInCanvas: 0,
426
- };
427
- if (dynamicRadiusInCanvas) {
428
- const circleUID1 = '1';
429
- drawCircleSvg(svgDrawingHelper, annotationUID, circleUID1, center, dynamicRadiusInCanvas, {
430
- color,
431
- });
432
- }
355
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(viewport.element), StrategyCallbacks.RenderCursor, svgDrawingHelper);
433
356
  }
434
357
  }
435
358
  BrushTool.toolName = 'Brush';
@@ -221,6 +221,7 @@ export default class LabelmapBaseTool extends BaseTool {
221
221
  previewColor,
222
222
  previewSegmentIndex,
223
223
  createMemo: this.createMemo.bind(this),
224
+ hoverData: this._hoverData,
224
225
  };
225
226
  return operationData;
226
227
  }
@@ -26,6 +26,7 @@ export type InitializedOperationData = LabelmapToolOperationDataAny & {
26
26
  activeStrategy: string;
27
27
  configuration?: {
28
28
  [key: string]: unknown;
29
+ brushSize: number;
29
30
  centerSegmentIndex?: {
30
31
  segmentIndex: number;
31
32
  };
@@ -36,6 +37,15 @@ export type InitializedOperationData = LabelmapToolOperationDataAny & {
36
37
  dynamicRadiusInCanvas?: number;
37
38
  };
38
39
  };
40
+ hoverData?: {
41
+ brushCursor: any;
42
+ segmentationId: string;
43
+ segmentIndex: number;
44
+ segmentColor: [number, number, number, number];
45
+ viewportIdsToRender: string[];
46
+ centerCanvas?: Array<number>;
47
+ viewport: Types.IViewport;
48
+ };
39
49
  memo?: LabelmapMemo;
40
50
  modified?: boolean;
41
51
  };
@@ -90,6 +100,10 @@ export default class BrushStrategy {
90
100
  ensureImageVolumeFor3DManipulation: {
91
101
  ensureImageVolumeFor3DManipulation: (data: any) => void;
92
102
  };
103
+ circularCursor: {
104
+ calculateCursorGeometry: (enabledElement: any, operationData: InitializedOperationData) => void;
105
+ renderCursor: (enabledElement: any, operationData: InitializedOperationData, svgDrawingHelper: import("../../../types").SVGDrawingHelper) => void;
106
+ };
93
107
  };
94
108
  protected static childFunctions: {
95
109
  onInteractionStart: (brushStrategy: any, func: any) => void;
@@ -107,6 +121,8 @@ export default class BrushStrategy {
107
121
  ensureImageVolumeFor3DManipulation: (brushStrategy: any, func: any) => void;
108
122
  addPreview: (brushStrategy: any, func: any) => void;
109
123
  getStatistics: (brushStrategy: any, func: any) => void;
124
+ calculateCursorGeometry: (brushStrategy: any, func: any) => void;
125
+ renderCursor: (brushStrategy: any, func: any) => void;
110
126
  compositions: any;
111
127
  };
112
128
  compositions: Composition[];
@@ -128,4 +144,5 @@ export default class BrushStrategy {
128
144
  interpolate: (enabledElement: Types.IEnabledElement, operationData: LabelmapToolOperationDataAny) => unknown;
129
145
  setValue: (operationData: InitializedOperationData, data: any) => void;
130
146
  createIsInThreshold: (operationData: InitializedOperationData) => any;
147
+ calculateCursorGeometry: (enabledElement: Types.IEnabledElement, operationData: InitializedOperationData) => void;
131
148
  }
@@ -21,6 +21,8 @@ export default class BrushStrategy {
21
21
  [StrategyCallbacks.EnsureImageVolumeFor3DManipulation]: addListMethod(StrategyCallbacks.EnsureImageVolumeFor3DManipulation),
22
22
  [StrategyCallbacks.AddPreview]: addListMethod(StrategyCallbacks.AddPreview),
23
23
  [StrategyCallbacks.GetStatistics]: addSingletonMethod(StrategyCallbacks.GetStatistics),
24
+ [StrategyCallbacks.CalculateCursorGeometry]: addSingletonMethod(StrategyCallbacks.CalculateCursorGeometry, true),
25
+ [StrategyCallbacks.RenderCursor]: addSingletonMethod(StrategyCallbacks.RenderCursor, true),
24
26
  compositions: null,
25
27
  }; }
26
28
  constructor(name, ...initializers) {
@@ -52,6 +54,18 @@ export default class BrushStrategy {
52
54
  return initializedData;
53
55
  };
54
56
  this.configurationName = name;
57
+ const cursorGeometryInitializer = initializers.find(init => init.hasOwnProperty(StrategyCallbacks.CalculateCursorGeometry));
58
+ const renderCursorInitializer = initializers.find(init => init.hasOwnProperty(StrategyCallbacks.RenderCursor));
59
+ if (!cursorGeometryInitializer) {
60
+ initializers.push({
61
+ [StrategyCallbacks.CalculateCursorGeometry]: compositions.circularCursor.calculateCursorGeometry
62
+ });
63
+ }
64
+ if (!renderCursorInitializer) {
65
+ initializers.push({
66
+ [StrategyCallbacks.RenderCursor]: compositions.circularCursor.renderCursor
67
+ });
68
+ }
55
69
  this.compositions = initializers;
56
70
  initializers.forEach((initializer) => {
57
71
  const result = typeof initializer === 'function' ? initializer() : initializer;
@@ -0,0 +1,7 @@
1
+ import type { InitializedOperationData } from '../BrushStrategy';
2
+ import type { SVGDrawingHelper } from '../../../../types';
3
+ declare const _default: {
4
+ calculateCursorGeometry: (enabledElement: any, operationData: InitializedOperationData) => void;
5
+ renderCursor: (enabledElement: any, operationData: InitializedOperationData, svgDrawingHelper: SVGDrawingHelper) => void;
6
+ };
7
+ export default _default;
@@ -0,0 +1,98 @@
1
+ import { vec3 } from 'gl-matrix';
2
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
+ import { drawCircle as drawCircleSvg } from '../../../../drawingSvg';
4
+ export default {
5
+ [StrategyCallbacks.CalculateCursorGeometry]: function (enabledElement, operationData) {
6
+ if (!operationData) {
7
+ return;
8
+ }
9
+ const { configuration, activeStrategy, hoverData } = operationData;
10
+ const { viewport } = enabledElement;
11
+ const camera = viewport.getCamera();
12
+ const { brushSize } = configuration;
13
+ const viewUp = vec3.fromValues(camera.viewUp[0], camera.viewUp[1], camera.viewUp[2]);
14
+ const viewPlaneNormal = vec3.fromValues(camera.viewPlaneNormal[0], camera.viewPlaneNormal[1], camera.viewPlaneNormal[2]);
15
+ const viewRight = vec3.create();
16
+ vec3.cross(viewRight, viewUp, viewPlaneNormal);
17
+ const { canvasToWorld } = viewport;
18
+ const { centerCanvas } = hoverData;
19
+ const centerCursorInWorld = canvasToWorld([
20
+ centerCanvas[0],
21
+ centerCanvas[1],
22
+ ]);
23
+ const bottomCursorInWorld = vec3.create();
24
+ const topCursorInWorld = vec3.create();
25
+ const leftCursorInWorld = vec3.create();
26
+ const rightCursorInWorld = vec3.create();
27
+ for (let i = 0; i <= 2; i++) {
28
+ bottomCursorInWorld[i] = centerCursorInWorld[i] - viewUp[i] * brushSize;
29
+ topCursorInWorld[i] = centerCursorInWorld[i] + viewUp[i] * brushSize;
30
+ leftCursorInWorld[i] = centerCursorInWorld[i] - viewRight[i] * brushSize;
31
+ rightCursorInWorld[i] = centerCursorInWorld[i] + viewRight[i] * brushSize;
32
+ }
33
+ if (!hoverData) {
34
+ return;
35
+ }
36
+ const { brushCursor } = hoverData;
37
+ const { data } = brushCursor;
38
+ if (data.handles === undefined) {
39
+ data.handles = {};
40
+ }
41
+ data.handles.points = [
42
+ bottomCursorInWorld,
43
+ topCursorInWorld,
44
+ leftCursorInWorld,
45
+ rightCursorInWorld,
46
+ ];
47
+ const strategy = configuration.strategies[activeStrategy];
48
+ if (typeof strategy?.computeInnerCircleRadius === 'function') {
49
+ strategy.computeInnerCircleRadius({
50
+ configuration,
51
+ viewport,
52
+ });
53
+ }
54
+ data.invalidated = false;
55
+ },
56
+ [StrategyCallbacks.RenderCursor]: function (enabledElement, operationData, svgDrawingHelper) {
57
+ if (!operationData) {
58
+ return;
59
+ }
60
+ const { configuration, hoverData } = operationData;
61
+ const { viewport } = enabledElement;
62
+ const { brushCursor } = hoverData;
63
+ const toolMetadata = brushCursor.metadata;
64
+ if (!toolMetadata) {
65
+ return;
66
+ }
67
+ const annotationUID = toolMetadata.brushCursorUID;
68
+ const data = brushCursor.data;
69
+ const { points } = data.handles;
70
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
71
+ const bottom = canvasCoordinates[0];
72
+ const top = canvasCoordinates[1];
73
+ const center = [
74
+ Math.floor((bottom[0] + top[0]) / 2),
75
+ Math.floor((bottom[1] + top[1]) / 2),
76
+ ];
77
+ const radius = Math.abs(bottom[1] - Math.floor((bottom[1] + top[1]) / 2));
78
+ const color = `rgb(${toolMetadata.segmentColor?.slice(0, 3) || [0, 0, 0]})`;
79
+ if (!viewport.getRenderingEngine()) {
80
+ console.warn('Rendering Engine has been destroyed');
81
+ return;
82
+ }
83
+ const circleUID = '0';
84
+ drawCircleSvg(svgDrawingHelper, annotationUID, circleUID, center, radius, {
85
+ color,
86
+ lineDash: this.centerSegmentIndexInfo.segmentIndex === 0 ? [1, 2] : null,
87
+ });
88
+ const { dynamicRadiusInCanvas } = configuration?.threshold || {
89
+ dynamicRadiusInCanvas: 0,
90
+ };
91
+ if (dynamicRadiusInCanvas) {
92
+ const circleUID1 = '1';
93
+ drawCircleSvg(svgDrawingHelper, annotationUID, circleUID1, center, dynamicRadiusInCanvas, {
94
+ color,
95
+ });
96
+ }
97
+ },
98
+ };
@@ -53,9 +53,13 @@ export default {
53
53
  },
54
54
  [StrategyCallbacks.ComputeInnerCircleRadius]: (operationData) => {
55
55
  const { configuration, viewport } = operationData;
56
- const { dynamicRadius = 0, isDynamic } = configuration.threshold;
56
+ const thresholdConfig = configuration?.threshold;
57
+ if (!thresholdConfig) {
58
+ return;
59
+ }
60
+ const { dynamicRadius = 0, isDynamic } = thresholdConfig;
57
61
  if (!isDynamic) {
58
- configuration.threshold.dynamicRadiusInCanvas = 0;
62
+ thresholdConfig.dynamicRadiusInCanvas = 0;
59
63
  return;
60
64
  }
61
65
  if (dynamicRadius === 0) {
@@ -75,9 +79,9 @@ export default {
75
79
  const offSetCenterInWorld = centerCursorInWorld.map((coord) => coord + radiusInWorld);
76
80
  const offSetCenterCanvas = viewport.worldToCanvas(offSetCenterInWorld);
77
81
  const dynamicRadiusInCanvas = Math.abs(centerCanvas[0] - offSetCenterCanvas[0]);
78
- if (!configuration.threshold.dynamicRadiusInCanvas) {
79
- configuration.threshold.dynamicRadiusInCanvas = 0;
82
+ if (!thresholdConfig.dynamicRadiusInCanvas) {
83
+ thresholdConfig.dynamicRadiusInCanvas = 0;
80
84
  }
81
- configuration.threshold.dynamicRadiusInCanvas = 3 + dynamicRadiusInCanvas;
85
+ thresholdConfig.dynamicRadiusInCanvas = 3 + dynamicRadiusInCanvas;
82
86
  },
83
87
  };
@@ -42,5 +42,9 @@ declare const _default: {
42
42
  ensureImageVolumeFor3DManipulation: {
43
43
  ensureImageVolumeFor3DManipulation: (data: any) => void;
44
44
  };
45
+ circularCursor: {
46
+ calculateCursorGeometry: (enabledElement: any, operationData: import("../BrushStrategy").InitializedOperationData) => void;
47
+ renderCursor: (enabledElement: any, operationData: import("../BrushStrategy").InitializedOperationData, svgDrawingHelper: import("../../../../types").SVGDrawingHelper) => void;
48
+ };
45
49
  };
46
50
  export default _default;
@@ -9,6 +9,7 @@ import threshold from './threshold';
9
9
  import labelmapStatistics from './labelmapStatistics';
10
10
  import ensureSegmentationVolumeFor3DManipulation from './ensureSegmentationVolume';
11
11
  import ensureImageVolumeFor3DManipulation from './ensureImageVolume';
12
+ import circularCursor from './circularCursor';
12
13
  export default {
13
14
  determineSegmentIndex,
14
15
  dynamicThreshold,
@@ -21,4 +22,5 @@ export default {
21
22
  labelmapStatistics,
22
23
  ensureSegmentationVolumeFor3DManipulation,
23
24
  ensureImageVolumeFor3DManipulation,
25
+ circularCursor
24
26
  };
@@ -1 +1 @@
1
- export declare const version = "4.12.6";
1
+ export declare const version = "4.13.0";
@@ -1 +1 @@
1
- export const version = '4.12.6';
1
+ export const version = '4.13.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "4.12.6",
3
+ "version": "4.13.0",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "types": "./dist/esm/index.d.ts",
6
6
  "module": "./dist/esm/index.js",
@@ -108,7 +108,7 @@
108
108
  "canvas": "3.2.0"
109
109
  },
110
110
  "peerDependencies": {
111
- "@cornerstonejs/core": "4.12.6",
111
+ "@cornerstonejs/core": "4.13.0",
112
112
  "@kitware/vtk.js": "34.15.1",
113
113
  "@types/d3-array": "3.2.1",
114
114
  "@types/d3-interpolate": "3.0.4",
@@ -127,5 +127,5 @@
127
127
  "type": "individual",
128
128
  "url": "https://ohif.org/donate"
129
129
  },
130
- "gitHead": "67da5ec35cb711e4310f0f1971bd8ed090377338"
130
+ "gitHead": "782d0a3cb60f0c174d5f5445f7c7092c544bb9d1"
131
131
  }