@cornerstonejs/tools 4.12.3 → 4.12.5

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 (32) hide show
  1. package/dist/esm/enums/MeasurementType.d.ts +6 -0
  2. package/dist/esm/enums/MeasurementType.js +7 -0
  3. package/dist/esm/enums/index.d.ts +1 -0
  4. package/dist/esm/enums/index.js +1 -0
  5. package/dist/esm/tools/SculptorTool/CircleSculptCursor.d.ts +8 -10
  6. package/dist/esm/tools/SculptorTool/CircleSculptCursor.js +33 -133
  7. package/dist/esm/tools/SculptorTool.d.ts +20 -5
  8. package/dist/esm/tools/SculptorTool.js +243 -52
  9. package/dist/esm/tools/annotation/BidirectionalTool.d.ts +0 -2
  10. package/dist/esm/tools/annotation/BidirectionalTool.js +24 -28
  11. package/dist/esm/tools/annotation/CircleROITool.d.ts +1 -2
  12. package/dist/esm/tools/annotation/CircleROITool.js +51 -44
  13. package/dist/esm/tools/annotation/EllipticalROITool.js +1 -1
  14. package/dist/esm/tools/annotation/LengthTool.d.ts +0 -2
  15. package/dist/esm/tools/annotation/LengthTool.js +13 -25
  16. package/dist/esm/tools/annotation/PlanarFreehandROITool.d.ts +2 -1
  17. package/dist/esm/tools/annotation/PlanarFreehandROITool.js +70 -68
  18. package/dist/esm/tools/base/BaseTool.d.ts +4 -2
  19. package/dist/esm/tools/base/BaseTool.js +38 -11
  20. package/dist/esm/tools/segmentation/BrushTool.js +9 -0
  21. package/dist/esm/tools/segmentation/CircleROIStartEndThresholdTool.js +4 -1
  22. package/dist/esm/types/CalculatorTypes.d.ts +4 -3
  23. package/dist/esm/types/ISculptToolShape.d.ts +6 -4
  24. package/dist/esm/utilities/contours/index.d.ts +1 -2
  25. package/dist/esm/utilities/contours/index.js +1 -2
  26. package/dist/esm/utilities/getCalibratedUnits.d.ts +2 -0
  27. package/dist/esm/utilities/getCalibratedUnits.js +32 -63
  28. package/dist/esm/version.d.ts +1 -1
  29. package/dist/esm/version.js +1 -1
  30. package/package.json +3 -3
  31. package/dist/esm/utilities/contours/calculatePerimeter.d.ts +0 -2
  32. package/dist/esm/utilities/contours/calculatePerimeter.js +0 -16
@@ -0,0 +1,6 @@
1
+ export declare enum MeasurementType {
2
+ Linear = "Linear",
3
+ Area = "Area",
4
+ Volume = "Volume",
5
+ Pixel = "Pixel"
6
+ }
@@ -0,0 +1,7 @@
1
+ export var MeasurementType;
2
+ (function (MeasurementType) {
3
+ MeasurementType["Linear"] = "Linear";
4
+ MeasurementType["Area"] = "Area";
5
+ MeasurementType["Volume"] = "Volume";
6
+ MeasurementType["Pixel"] = "Pixel";
7
+ })(MeasurementType || (MeasurementType = {}));
@@ -1,3 +1,4 @@
1
+ export * from "./MeasurementType";
1
2
  import { MouseBindings } from './ToolBindings';
2
3
  import { KeyboardBindings } from './ToolBindings';
3
4
  import ToolModes from './ToolModes';
@@ -7,4 +7,5 @@ import { Swipe } from './Touch';
7
7
  import StrategyCallbacks from './StrategyCallbacks';
8
8
  import ChangeTypes from './ChangeTypes';
9
9
  import WorkerTypes from './WorkerTypes';
10
+ export * from './MeasurementType';
10
11
  export { MouseBindings, KeyboardBindings, ToolModes, AnnotationStyleStates, Events, SegmentationRepresentations, Swipe, StrategyCallbacks, ChangeTypes, WorkerTypes, };
@@ -1,6 +1,5 @@
1
1
  import type { Types } from '@cornerstonejs/core';
2
2
  import type { ISculptToolShape } from '../../types/ISculptToolShape';
3
- import type { SculptData } from '../SculptorTool';
4
3
  import type { SVGDrawingHelper, EventTypes, ContourAnnotationData } from '../../types';
5
4
  export type PushedHandles = {
6
5
  first?: number;
@@ -8,19 +7,18 @@ export type PushedHandles = {
8
7
  };
9
8
  declare class CircleSculptCursor implements ISculptToolShape {
10
9
  static shapeName: string;
11
- static readonly CHAIN_MAINTENANCE_ITERATIONS = 3;
12
- static readonly CHAIN_PULL_STRENGTH_FACTOR = 0.3;
13
- static readonly MAX_INTER_DISTANCE_FACTOR = 1.2;
14
10
  private toolInfo;
15
11
  renderShape(svgDrawingHelper: SVGDrawingHelper, canvasLocation: Types.Point2, options: unknown): void;
16
- pushHandles(viewport: Types.IViewport, sculptData: SculptData): PushedHandles;
17
12
  configureToolSize(evt: EventTypes.InteractionEventType): void;
18
13
  updateToolSize(canvasCoords: Types.Point2, viewport: Types.IViewport, activeAnnotation: ContourAnnotationData): void;
19
14
  getMaxSpacing(minSpacing: number): number;
20
- getInsertPosition(previousIndex: number, nextIndex: number, sculptData: SculptData): Types.Point3;
21
- private pushOneHandle;
22
- private directionalVector;
23
- private calculateMeanConsecutiveDistance;
24
- private maintainChainStructure;
15
+ computeWorldRadius(viewport: any, clearExisting?: boolean): any;
16
+ getEdge(viewport: any, p1: Types.Point3, p2: Types.Point3, mouseCanvas: Types.Point2): {
17
+ point: any;
18
+ angle: number;
19
+ canvasPoint: any;
20
+ };
21
+ interpolatePoint(viewport: any, angle: any, center: any): any;
22
+ isInCursor(point: any, mousePoint: any): boolean;
25
23
  }
26
24
  export default CircleSculptCursor;
@@ -1,4 +1,4 @@
1
- import { vec3 } from 'gl-matrix';
1
+ import { vec2, vec3 } from 'gl-matrix';
2
2
  import { getEnabledElement } from '@cornerstonejs/core';
3
3
  import { distancePointToContour } from '../distancePointToContour';
4
4
  import { drawCircle as drawCircleSvg } from '../../drawingSvg';
@@ -7,46 +7,15 @@ class CircleSculptCursor {
7
7
  constructor() {
8
8
  this.toolInfo = {
9
9
  toolSize: null,
10
+ radius: null,
10
11
  maxToolSize: null,
11
12
  };
12
13
  }
13
14
  static { this.shapeName = 'Circle'; }
14
- static { this.CHAIN_MAINTENANCE_ITERATIONS = 3; }
15
- static { this.CHAIN_PULL_STRENGTH_FACTOR = 0.3; }
16
- static { this.MAX_INTER_DISTANCE_FACTOR = 1.2; }
17
15
  renderShape(svgDrawingHelper, canvasLocation, options) {
18
16
  const circleUID = '0';
19
17
  drawCircleSvg(svgDrawingHelper, 'SculptorTool', circleUID, canvasLocation, this.toolInfo.toolSize, options);
20
18
  }
21
- pushHandles(viewport, sculptData) {
22
- const { points, mouseCanvasPoint } = sculptData;
23
- const pushedHandles = { first: undefined, last: undefined };
24
- const worldRadius = point.distanceToPoint(viewport.canvasToWorld(mouseCanvasPoint), viewport.canvasToWorld([
25
- mouseCanvasPoint[0] + this.toolInfo.toolSize,
26
- mouseCanvasPoint[1],
27
- ]));
28
- for (let i = 0; i < points.length; i++) {
29
- const handleCanvasPoint = viewport.worldToCanvas(points[i]);
30
- const distanceToHandle = point.distanceToPoint(handleCanvasPoint, mouseCanvasPoint);
31
- if (distanceToHandle > this.toolInfo.toolSize) {
32
- continue;
33
- }
34
- this.pushOneHandle(i, worldRadius, sculptData);
35
- if (pushedHandles.first === undefined) {
36
- pushedHandles.first = i;
37
- pushedHandles.last = i;
38
- }
39
- else {
40
- pushedHandles.last = i;
41
- }
42
- }
43
- if (pushedHandles.first !== undefined && pushedHandles.last !== undefined) {
44
- for (let i = 0; i < CircleSculptCursor.CHAIN_MAINTENANCE_ITERATIONS; i++) {
45
- this.maintainChainStructure(sculptData, pushedHandles);
46
- }
47
- }
48
- return pushedHandles;
49
- }
50
19
  configureToolSize(evt) {
51
20
  const toolInfo = this.toolInfo;
52
21
  if (toolInfo.toolSize && toolInfo.maxToolSize) {
@@ -55,8 +24,9 @@ class CircleSculptCursor {
55
24
  const eventData = evt.detail;
56
25
  const element = eventData.element;
57
26
  const minDim = Math.min(element.clientWidth, element.clientHeight);
58
- const maxRadius = minDim / 12;
27
+ const maxRadius = minDim / 24;
59
28
  toolInfo.toolSize = maxRadius;
29
+ toolInfo.radius = null;
60
30
  toolInfo.maxToolSize = maxRadius;
61
31
  }
62
32
  updateToolSize(canvasCoords, viewport, activeAnnotation) {
@@ -64,114 +34,44 @@ class CircleSculptCursor {
64
34
  const radius = distancePointToContour(viewport, activeAnnotation, canvasCoords);
65
35
  if (radius > 0) {
66
36
  toolInfo.toolSize = Math.min(toolInfo.maxToolSize, radius);
37
+ this.computeWorldRadius(viewport, true);
67
38
  }
68
39
  }
69
40
  getMaxSpacing(minSpacing) {
70
41
  return Math.max(this.toolInfo.toolSize / 4, minSpacing);
71
42
  }
72
- getInsertPosition(previousIndex, nextIndex, sculptData) {
73
- let insertPosition;
74
- const { points, element, mouseCanvasPoint } = sculptData;
75
- const toolSize = this.toolInfo.toolSize;
76
- const enabledElement = getEnabledElement(element);
77
- const { viewport } = enabledElement;
78
- const previousCanvasPoint = viewport.worldToCanvas(points[previousIndex]);
79
- const nextCanvasPoint = viewport.worldToCanvas(points[nextIndex]);
80
- const midPoint = [
81
- (previousCanvasPoint[0] + nextCanvasPoint[0]) / 2.0,
82
- (previousCanvasPoint[1] + nextCanvasPoint[1]) / 2.0,
83
- ];
84
- const distanceToMidPoint = point.distanceToPoint(mouseCanvasPoint, midPoint);
85
- if (distanceToMidPoint < toolSize) {
86
- const directionUnitVector = {
87
- x: (midPoint[0] - mouseCanvasPoint[0]) / distanceToMidPoint,
88
- y: (midPoint[1] - mouseCanvasPoint[1]) / distanceToMidPoint,
89
- };
90
- insertPosition = [
91
- mouseCanvasPoint[0] + toolSize * directionUnitVector.x,
92
- mouseCanvasPoint[1] + toolSize * directionUnitVector.y,
93
- ];
43
+ computeWorldRadius(viewport, clearExisting = false) {
44
+ if (!this.toolInfo.radius || clearExisting) {
45
+ const p0 = viewport.canvasToWorld([0, 0]);
46
+ const p1 = viewport.canvasToWorld([this.toolInfo.toolSize, 0]);
47
+ this.toolInfo.radius = vec3.length(vec3.sub(vec3.create(), p0, p1));
94
48
  }
95
- else {
96
- insertPosition = midPoint;
97
- }
98
- const worldPosition = viewport.canvasToWorld(insertPosition);
99
- return worldPosition;
49
+ return this.toolInfo.radius;
100
50
  }
101
- pushOneHandle(i, worldRadius, sculptData) {
102
- const { points, mousePoint } = sculptData;
103
- const handle = points[i];
104
- const directionUnitVector = this.directionalVector(mousePoint, handle);
105
- const position = vec3.scaleAndAdd(vec3.create(), mousePoint, directionUnitVector, worldRadius);
106
- handle[0] = position[0];
107
- handle[1] = position[1];
108
- handle[2] = position[2];
51
+ getEdge(viewport, p1, p2, mouseCanvas) {
52
+ const midPoint = vec3.add(vec3.create(), p1, p2 || p1);
53
+ vec3.scale(midPoint, midPoint, 0.5);
54
+ const canvasMidPoint = viewport.worldToCanvas(midPoint);
55
+ const canvasDelta = vec2.sub(vec2.create(), canvasMidPoint, mouseCanvas);
56
+ const angle = Math.atan2(canvasDelta[1], canvasDelta[0]);
57
+ const point = this.interpolatePoint(viewport, angle, mouseCanvas);
58
+ const canvasPoint = viewport.worldToCanvas(point);
59
+ return {
60
+ point,
61
+ angle,
62
+ canvasPoint,
63
+ };
109
64
  }
110
- directionalVector(p1, p2) {
111
- return vec3.normalize(vec3.create(), [
112
- p2[0] - p1[0],
113
- p2[1] - p1[1],
114
- p2[2] - p1[2],
115
- ]);
65
+ interpolatePoint(viewport, angle, center) {
66
+ const [cx, cy] = center;
67
+ const r = this.toolInfo.toolSize;
68
+ const dx = Math.cos(angle) * r;
69
+ const dy = Math.sin(angle) * r;
70
+ const newPoint2 = [cx + dx, cy + dy];
71
+ return viewport.canvasToWorld(newPoint2);
116
72
  }
117
- calculateMeanConsecutiveDistance(points) {
118
- if (points.length < 2) {
119
- return 0;
120
- }
121
- let totalDistance = 0;
122
- const numPoints = points.length;
123
- for (let i = 0; i < numPoints; i++) {
124
- const nextIndex = (i + 1) % numPoints;
125
- const distance = point.distanceToPoint(points[i], points[nextIndex]);
126
- totalDistance += distance;
127
- }
128
- return totalDistance / numPoints;
129
- }
130
- maintainChainStructure(sculptData, pushedHandles) {
131
- const { points } = sculptData;
132
- const first = pushedHandles.first;
133
- const last = pushedHandles.last;
134
- const mean = Math.round((first + last) / 2);
135
- const numPoints = points.length;
136
- if (!sculptData.meanDistance) {
137
- sculptData.meanDistance = this.calculateMeanConsecutiveDistance(points);
138
- }
139
- const maxInterDistance = sculptData.meanDistance * CircleSculptCursor.MAX_INTER_DISTANCE_FACTOR;
140
- for (let i = mean; i >= 0; i--) {
141
- if (i >= numPoints - 1 || i < 0) {
142
- continue;
143
- }
144
- const nextIndex = i + 1;
145
- const distanceToNext = point.distanceToPoint(points[i], points[nextIndex]);
146
- if (distanceToNext > maxInterDistance) {
147
- const pullDirection = this.directionalVector(points[i], points[nextIndex]);
148
- const pullStrength = (distanceToNext - sculptData.meanDistance) / sculptData.meanDistance;
149
- const adjustmentMagnitude = pullStrength *
150
- sculptData.meanDistance *
151
- CircleSculptCursor.CHAIN_PULL_STRENGTH_FACTOR;
152
- points[i][0] += pullDirection[0] * adjustmentMagnitude;
153
- points[i][1] += pullDirection[1] * adjustmentMagnitude;
154
- points[i][2] += pullDirection[2] * adjustmentMagnitude;
155
- }
156
- }
157
- for (let i = mean + 1; i < numPoints; i++) {
158
- if (i >= numPoints || i <= 0) {
159
- continue;
160
- }
161
- const previousIndex = i - 1;
162
- const distanceToPrevious = point.distanceToPoint(points[i], points[previousIndex]);
163
- if (distanceToPrevious > maxInterDistance) {
164
- const pullDirection = this.directionalVector(points[i], points[previousIndex]);
165
- const pullStrength = (distanceToPrevious - sculptData.meanDistance) /
166
- sculptData.meanDistance;
167
- const adjustmentMagnitude = pullStrength *
168
- sculptData.meanDistance *
169
- CircleSculptCursor.CHAIN_PULL_STRENGTH_FACTOR;
170
- points[i][0] += pullDirection[0] * adjustmentMagnitude;
171
- points[i][1] += pullDirection[1] * adjustmentMagnitude;
172
- points[i][2] += pullDirection[2] * adjustmentMagnitude;
173
- }
174
- }
73
+ isInCursor(point, mousePoint) {
74
+ return vec3.distance(point, mousePoint) < this.toolInfo.radius;
175
75
  }
176
76
  }
177
77
  export default CircleSculptCursor;
@@ -2,15 +2,27 @@ import type { Types } from '@cornerstonejs/core';
2
2
  import { BaseTool } from './base';
3
3
  import type { EventTypes, PublicToolProps, ToolProps, SVGDrawingHelper } from '../types';
4
4
  import type { ISculptToolShape } from '../types/ISculptToolShape';
5
+ export type Contour = {
6
+ annotationUID: string;
7
+ points: Array<Types.Point3>;
8
+ };
5
9
  export type SculptData = {
6
10
  mousePoint: Types.Point3;
7
- deltaWorld: Types.Point3;
8
11
  mouseCanvasPoint: Types.Point2;
9
12
  points: Array<Types.Point3>;
10
13
  maxSpacing: number;
11
- meanDistance?: number;
12
14
  element: HTMLDivElement;
15
+ contours: Contour[];
16
+ };
17
+ export type SculptIntersect = {
18
+ annotationUID: string;
19
+ isEnter: boolean;
20
+ index: number;
21
+ relIndex?: number;
22
+ point: Types.Point3;
23
+ angle: number;
13
24
  };
25
+ export type ContourSelection = Array<SculptIntersect>;
14
26
  declare class SculptorTool extends BaseTool {
15
27
  static toolName: string;
16
28
  registeredShapes: Map<any, any>;
@@ -23,13 +35,16 @@ declare class SculptorTool extends BaseTool {
23
35
  preMouseDownCallback: (evt: EventTypes.InteractionEventType) => boolean;
24
36
  mouseMoveCallback: (evt: EventTypes.InteractionEventType) => void;
25
37
  protected sculpt(eventData: any, points: Array<Types.Point3>): void;
38
+ intersect(viewport: Types.IViewport, cursorShape: any): SculptIntersect[];
39
+ interpolatePoints(viewport: any, enter: any, exit: any, existing: any, newPoints: any): void;
40
+ getContourSelections(intersections: any, pointLength: any): ContourSelection[];
41
+ findMergeable(contours: any, testIntersection: any, currentIndex: any): any;
42
+ findNext(intersections: any, lastAngle: any, isEnter?: boolean): any;
26
43
  protected interpolatePointsWithinMaxSpacing(i: number, points: Array<Types.Point3>, indicesToInsertAfter: Array<number>, maxSpacing: number): void;
27
44
  private updateCursor;
45
+ protected getToolInstance(element: HTMLDivElement): any;
28
46
  private filterSculptableAnnotationsForElement;
29
47
  private configureToolSize;
30
- private insertNewHandles;
31
- private findNewHandleIndices;
32
- private insertHandleRadially;
33
48
  private selectFreehandTool;
34
49
  private getClosestFreehandToolOnElement;
35
50
  private endCallback;