@cornerstonejs/tools 1.77.3 → 1.77.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.
- package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +6 -4
- package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
- package/dist/cjs/tools/annotation/LivewireContourSegmentationTool.js +1 -1
- package/dist/cjs/tools/annotation/LivewireContourSegmentationTool.js.map +1 -1
- package/dist/cjs/tools/annotation/LivewireContourTool.d.ts +4 -4
- package/dist/cjs/tools/annotation/LivewireContourTool.js +19 -20
- package/dist/cjs/tools/annotation/LivewireContourTool.js.map +1 -1
- package/dist/cjs/tools/base/ContourBaseTool.d.ts +1 -0
- package/dist/cjs/tools/base/ContourBaseTool.js.map +1 -1
- package/dist/cjs/utilities/contours/updateContourPolyline.d.ts +1 -0
- package/dist/cjs/utilities/contours/updateContourPolyline.js +11 -4
- package/dist/cjs/utilities/contours/updateContourPolyline.js.map +1 -1
- package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +6 -4
- package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
- package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js +1 -1
- package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js.map +1 -1
- package/dist/esm/tools/annotation/LivewireContourTool.js +19 -20
- package/dist/esm/tools/annotation/LivewireContourTool.js.map +1 -1
- package/dist/esm/tools/base/ContourBaseTool.js.map +1 -1
- package/dist/esm/utilities/contours/updateContourPolyline.js +11 -4
- package/dist/esm/utilities/contours/updateContourPolyline.js.map +1 -1
- package/dist/types/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.d.ts.map +1 -1
- package/dist/types/tools/annotation/LivewireContourTool.d.ts +4 -4
- package/dist/types/tools/annotation/LivewireContourTool.d.ts.map +1 -1
- package/dist/types/tools/base/ContourBaseTool.d.ts +1 -0
- package/dist/types/tools/base/ContourBaseTool.d.ts.map +1 -1
- package/dist/types/utilities/contours/updateContourPolyline.d.ts +1 -0
- package/dist/types/utilities/contours/updateContourPolyline.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.ts +18 -9
- package/src/tools/annotation/LivewireContourSegmentationTool.ts +1 -1
- package/src/tools/annotation/LivewireContourTool.ts +28 -25
- package/src/tools/base/ContourBaseTool.ts +1 -0
- package/src/utilities/contours/updateContourPolyline.ts +19 -4
- package/src/utilities/math/polyline/getSignedArea.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.77.
|
|
3
|
+
"version": "1.77.5",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@cornerstonejs/core": "^1.77.
|
|
32
|
+
"@cornerstonejs/core": "^1.77.5",
|
|
33
33
|
"@icr/polyseg-wasm": "0.4.0",
|
|
34
34
|
"@types/offscreencanvas": "2019.7.3",
|
|
35
35
|
"comlink": "^4.4.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"type": "individual",
|
|
60
60
|
"url": "https://ohif.org/donate"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "8f841470fce4dfe7f865ab4f3a9d657f5629f6f6"
|
|
63
63
|
}
|
|
@@ -216,17 +216,26 @@ export function createPolylineHole(
|
|
|
216
216
|
const { windingDirection: holeWindingDirection } =
|
|
217
217
|
holeAnnotation.data.contour;
|
|
218
218
|
|
|
219
|
-
// Check if both normals are pointing to the same direction because the
|
|
220
|
-
// polyline for the hole needs to be in a different direction
|
|
221
|
-
// if (glMatrix.equals(1, dotNormals)) {
|
|
222
|
-
if (targetWindingDirection === holeWindingDirection) {
|
|
223
|
-
holeAnnotation.data.contour.polyline.reverse();
|
|
224
|
-
holeAnnotation.data.contour.windingDirection = targetWindingDirection * -1;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
219
|
addChildAnnotation(targetAnnotation, holeAnnotation);
|
|
228
220
|
contourSegUtils.removeContourSegmentationAnnotation(holeAnnotation);
|
|
229
221
|
|
|
222
|
+
const { contour: holeContour } = holeAnnotation.data;
|
|
223
|
+
const holePolyline = convertContourPolylineToCanvasSpace(
|
|
224
|
+
holeContour.polyline,
|
|
225
|
+
viewport
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
// Calling `updateContourPolyline` method instead of reversing the polyline
|
|
229
|
+
// locally because it is also responsible for checking/fixing the winding direction.
|
|
230
|
+
contourUtils.updateContourPolyline(
|
|
231
|
+
holeAnnotation,
|
|
232
|
+
{
|
|
233
|
+
points: holePolyline,
|
|
234
|
+
closed: holeContour.closed,
|
|
235
|
+
},
|
|
236
|
+
viewport
|
|
237
|
+
);
|
|
238
|
+
|
|
230
239
|
const { element } = viewport;
|
|
231
240
|
const enabledElement = getEnabledElement(element);
|
|
232
241
|
const { renderingEngine } = enabledElement;
|
|
@@ -393,7 +402,7 @@ function combinePolylines(
|
|
|
393
402
|
};
|
|
394
403
|
|
|
395
404
|
// Calling `updateContourPolyline` method instead of setting it locally
|
|
396
|
-
// because it is also responsible for checking/
|
|
405
|
+
// because it is also responsible for checking/fixing the winding direction.
|
|
397
406
|
contourUtils.updateContourPolyline(
|
|
398
407
|
newAnnotation,
|
|
399
408
|
{
|
|
@@ -96,7 +96,7 @@ class LivewireContourSegmentationTool extends LivewireContourTool {
|
|
|
96
96
|
// Now, update the rendering
|
|
97
97
|
this.updateAnnotation(acceptedPath);
|
|
98
98
|
this.scissors = null;
|
|
99
|
-
this.
|
|
99
|
+
this.scissorsNext = null;
|
|
100
100
|
this.editData = null;
|
|
101
101
|
annotation.data.handles.interpolationSources = null;
|
|
102
102
|
|
|
@@ -38,8 +38,8 @@ const CLICK_CLOSE_CURVE_SQR_DIST = 10 ** 2; // px
|
|
|
38
38
|
class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
39
39
|
public static toolName: string;
|
|
40
40
|
protected scissors: LivewireScissors;
|
|
41
|
-
/** The scissors from the
|
|
42
|
-
protected
|
|
41
|
+
/** The scissors from the next handle, used for editing */
|
|
42
|
+
protected scissorsNext: LivewireScissors;
|
|
43
43
|
|
|
44
44
|
touchDragCallback: any;
|
|
45
45
|
mouseDragCallback: any;
|
|
@@ -53,7 +53,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
53
53
|
confirmedPath?: LivewirePath;
|
|
54
54
|
currentPath?: LivewirePath;
|
|
55
55
|
/** The next path segment, on the other side of the handle */
|
|
56
|
-
|
|
56
|
+
confirmedPathNext?: LivewirePath;
|
|
57
57
|
closed?: boolean;
|
|
58
58
|
worldToSlice?: (point: Types.Point3) => Types.Point2;
|
|
59
59
|
sliceToWorld?: (point: Types.Point2) => Types.Point3;
|
|
@@ -141,7 +141,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
141
141
|
worldPos,
|
|
142
142
|
element,
|
|
143
143
|
annotation,
|
|
144
|
-
|
|
144
|
+
nextPos?,
|
|
145
145
|
contourHoleProcessingEnabled?
|
|
146
146
|
) {
|
|
147
147
|
const enabledElement = getEnabledElement(element);
|
|
@@ -217,21 +217,21 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
217
217
|
height,
|
|
218
218
|
voiRange
|
|
219
219
|
);
|
|
220
|
-
if (
|
|
221
|
-
this.
|
|
220
|
+
if (nextPos) {
|
|
221
|
+
this.scissorsNext = LivewireScissors.createInstanceFromRawPixelData(
|
|
222
222
|
scalarData as Float32Array,
|
|
223
223
|
width,
|
|
224
224
|
height,
|
|
225
225
|
voiRange
|
|
226
226
|
);
|
|
227
|
-
this.
|
|
227
|
+
this.scissorsNext.startSearch(worldToSlice(nextPos));
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
// Scissors always start at the startPos for both editing handles and
|
|
231
231
|
// for initial rendering
|
|
232
232
|
this.scissors.startSearch(startPos);
|
|
233
233
|
|
|
234
|
-
const newAnnotation = !
|
|
234
|
+
const newAnnotation = !nextPos;
|
|
235
235
|
|
|
236
236
|
const confirmedPath = new LivewirePath();
|
|
237
237
|
const currentPath = new LivewirePath();
|
|
@@ -255,7 +255,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
255
255
|
lastCanvasPoint,
|
|
256
256
|
confirmedPath,
|
|
257
257
|
currentPath,
|
|
258
|
-
|
|
258
|
+
confirmedPathNext: currentPathNext,
|
|
259
259
|
closed: false,
|
|
260
260
|
handleIndex:
|
|
261
261
|
this.editData?.handleIndex ?? annotation.handles?.activeHandleIndex,
|
|
@@ -467,7 +467,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
467
467
|
protected clearEditData() {
|
|
468
468
|
this.editData = null;
|
|
469
469
|
this.scissors = null;
|
|
470
|
-
this.
|
|
470
|
+
this.scissorsNext = null;
|
|
471
471
|
this.isDrawing = false;
|
|
472
472
|
}
|
|
473
473
|
|
|
@@ -628,7 +628,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
628
628
|
public editHandle(
|
|
629
629
|
worldPos: Types.Point3,
|
|
630
630
|
element,
|
|
631
|
-
annotation,
|
|
631
|
+
annotation: LivewireContourAnnotation,
|
|
632
632
|
handleIndex: number
|
|
633
633
|
) {
|
|
634
634
|
const { data } = annotation;
|
|
@@ -638,11 +638,11 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
638
638
|
handlePoints[(handleIndex - 1 + numHandles) % numHandles];
|
|
639
639
|
const nextHandle = handlePoints[(handleIndex + 1) % numHandles];
|
|
640
640
|
|
|
641
|
-
if (!this.editData?.
|
|
641
|
+
if (!this.editData?.confirmedPathNext) {
|
|
642
642
|
this.setupBaseEditData(previousHandle, element, annotation, nextHandle);
|
|
643
643
|
const { polyline } = data.contour;
|
|
644
644
|
const confirmedPath = new LivewirePath();
|
|
645
|
-
const
|
|
645
|
+
const confirmedPathNext = new LivewirePath();
|
|
646
646
|
const { worldToSlice } = this.editData;
|
|
647
647
|
const previousIndex = findHandlePolylineIndex(
|
|
648
648
|
annotation,
|
|
@@ -660,23 +660,19 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
660
660
|
// For this case, the next/previous indices are swapped, and the
|
|
661
661
|
// path data gets inserted in between the newly generated data, so
|
|
662
662
|
// handle this case specially
|
|
663
|
-
|
|
663
|
+
confirmedPathNext.addPoints(
|
|
664
664
|
polyline.slice(nextIndex + 1, previousIndex).map(worldToSlice)
|
|
665
665
|
);
|
|
666
|
-
} else if (nextIndex < previousIndex) {
|
|
667
|
-
throw new Error(
|
|
668
|
-
`Expected right index after left index, but were: ${previousIndex} ${nextIndex}`
|
|
669
|
-
);
|
|
670
666
|
} else {
|
|
671
667
|
confirmedPath.addPoints(
|
|
672
668
|
polyline.slice(0, previousIndex + 1).map(worldToSlice)
|
|
673
669
|
);
|
|
674
|
-
|
|
670
|
+
confirmedPathNext.addPoints(
|
|
675
671
|
polyline.slice(nextIndex, polyline.length).map(worldToSlice)
|
|
676
672
|
);
|
|
677
673
|
}
|
|
678
674
|
this.editData.confirmedPath = confirmedPath;
|
|
679
|
-
this.editData.
|
|
675
|
+
this.editData.confirmedPathNext = confirmedPathNext;
|
|
680
676
|
}
|
|
681
677
|
const { editData, scissors } = this;
|
|
682
678
|
const { worldToSlice, sliceToWorld } = editData;
|
|
@@ -702,7 +698,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
702
698
|
handlePoints[handleIndex] = sliceToWorld(slicePos);
|
|
703
699
|
|
|
704
700
|
const pathPointsLeft = scissors.findPathToPoint(slicePos);
|
|
705
|
-
const pathPointsRight = this.
|
|
701
|
+
const pathPointsRight = this.scissorsNext.findPathToPoint(slicePos);
|
|
706
702
|
const currentPath = new LivewirePath();
|
|
707
703
|
|
|
708
704
|
// Merge the "confirmed" path that goes from the first control point to the
|
|
@@ -713,7 +709,7 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
713
709
|
currentPath.addPoints(pathPointsLeft);
|
|
714
710
|
}
|
|
715
711
|
currentPath.addPoints(pathPointsRight.reverse());
|
|
716
|
-
currentPath.appendPath(editData.
|
|
712
|
+
currentPath.appendPath(editData.confirmedPathNext);
|
|
717
713
|
if (handleIndex === 0) {
|
|
718
714
|
currentPath.addPoints(pathPointsLeft);
|
|
719
715
|
}
|
|
@@ -928,22 +924,29 @@ class LivewireContourTool extends ContourSegmentationBaseTool {
|
|
|
928
924
|
return;
|
|
929
925
|
}
|
|
930
926
|
|
|
931
|
-
const { annotation, sliceToWorld } =
|
|
927
|
+
const { annotation, sliceToWorld, worldToSlice, closed, newAnnotation } =
|
|
928
|
+
this.editData;
|
|
932
929
|
let { pointArray: imagePoints } = livewirePath;
|
|
933
930
|
|
|
934
931
|
if (imagePoints.length > 1) {
|
|
935
932
|
imagePoints = [...imagePoints, imagePoints[0]];
|
|
936
933
|
}
|
|
937
934
|
|
|
935
|
+
// Save the annotation in clockwise winding direction only after closing it
|
|
936
|
+
// because reversing the handle points may cause some weird issues
|
|
937
|
+
const targetWindingDirection =
|
|
938
|
+
newAnnotation && closed ? ContourWindingDirection.Clockwise : undefined;
|
|
939
|
+
|
|
938
940
|
this.updateContourPolyline(
|
|
939
941
|
annotation,
|
|
940
942
|
{
|
|
941
943
|
points: imagePoints,
|
|
942
|
-
closed
|
|
943
|
-
targetWindingDirection
|
|
944
|
+
closed,
|
|
945
|
+
targetWindingDirection,
|
|
944
946
|
},
|
|
945
947
|
{
|
|
946
948
|
canvasToWorld: sliceToWorld,
|
|
949
|
+
worldToCanvas: worldToSlice,
|
|
947
950
|
}
|
|
948
951
|
);
|
|
949
952
|
}
|
|
@@ -219,6 +219,7 @@ abstract class ContourBaseTool extends AnnotationTool {
|
|
|
219
219
|
},
|
|
220
220
|
transforms: {
|
|
221
221
|
canvasToWorld: (point: Types.Point2) => Types.Point3;
|
|
222
|
+
worldToCanvas: (point: Types.Point3) => Types.Point2;
|
|
222
223
|
}
|
|
223
224
|
) {
|
|
224
225
|
const decimateConfig = this.configuration?.decimate || {};
|
|
@@ -30,6 +30,7 @@ export default function updateContourPolyline(
|
|
|
30
30
|
},
|
|
31
31
|
transforms: {
|
|
32
32
|
canvasToWorld: (point: Types.Point2) => Types.Point3;
|
|
33
|
+
worldToCanvas: (point: Types.Point3) => Types.Point2;
|
|
33
34
|
},
|
|
34
35
|
options?: {
|
|
35
36
|
decimate?: {
|
|
@@ -38,7 +39,7 @@ export default function updateContourPolyline(
|
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
) {
|
|
41
|
-
const { canvasToWorld } = transforms;
|
|
42
|
+
const { canvasToWorld, worldToCanvas } = transforms;
|
|
42
43
|
const { data } = annotation;
|
|
43
44
|
const { targetWindingDirection } = polylineData;
|
|
44
45
|
let { points: polyline } = polylineData;
|
|
@@ -54,7 +55,8 @@ export default function updateContourPolyline(
|
|
|
54
55
|
let { closed } = polylineData;
|
|
55
56
|
const numPoints = polyline.length;
|
|
56
57
|
const polylineWorldPoints = new Array(numPoints);
|
|
57
|
-
const
|
|
58
|
+
const currentPolylineWindingDirection =
|
|
59
|
+
math.polyline.getWindingDirection(polyline);
|
|
58
60
|
const parentAnnotation = getParentAnnotation(annotation) as ContourAnnotation;
|
|
59
61
|
|
|
60
62
|
if (closed === undefined) {
|
|
@@ -79,11 +81,24 @@ export default function updateContourPolyline(
|
|
|
79
81
|
: targetWindingDirection;
|
|
80
82
|
|
|
81
83
|
if (windingDirection === undefined) {
|
|
82
|
-
windingDirection =
|
|
83
|
-
}
|
|
84
|
+
windingDirection = currentPolylineWindingDirection;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (windingDirection !== currentPolylineWindingDirection) {
|
|
84
88
|
polyline.reverse();
|
|
85
89
|
}
|
|
86
90
|
|
|
91
|
+
const handlePoints = data.handles.points.map((p) => worldToCanvas(p));
|
|
92
|
+
|
|
93
|
+
if (handlePoints.length > 2) {
|
|
94
|
+
const currentHandlesWindingDirection =
|
|
95
|
+
math.polyline.getWindingDirection(handlePoints);
|
|
96
|
+
|
|
97
|
+
if (currentHandlesWindingDirection !== windingDirection) {
|
|
98
|
+
data.handles.points.reverse();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
87
102
|
for (let i = 0; i < numPoints; i++) {
|
|
88
103
|
polylineWorldPoints[i] = canvasToWorld(polyline[i]);
|
|
89
104
|
}
|
|
@@ -5,9 +5,9 @@ import type { Types } from '@cornerstonejs/core';
|
|
|
5
5
|
* https://www.youtube.com/watch?v=GpsKrAipXm8&t=1900s
|
|
6
6
|
*
|
|
7
7
|
* This functions has a runtime very close to `getArea` and it is recommended to
|
|
8
|
-
* be called only if you need the area signal (eg: calculate polygon normal
|
|
9
|
-
* you do not need the area signal you should always call
|
|
10
|
-
*
|
|
8
|
+
* be called only if you need the area signal (eg: calculate polygon normal or
|
|
9
|
+
* winding direction). If you do not need the area signal you should always call
|
|
10
|
+
* `getArea`.
|
|
11
11
|
*
|
|
12
12
|
* @param polyline - Polyline points (2D)
|
|
13
13
|
* @returns Area of the polyline (with signal)
|