@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.
Files changed (37) hide show
  1. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +6 -4
  2. package/dist/cjs/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
  3. package/dist/cjs/tools/annotation/LivewireContourSegmentationTool.js +1 -1
  4. package/dist/cjs/tools/annotation/LivewireContourSegmentationTool.js.map +1 -1
  5. package/dist/cjs/tools/annotation/LivewireContourTool.d.ts +4 -4
  6. package/dist/cjs/tools/annotation/LivewireContourTool.js +19 -20
  7. package/dist/cjs/tools/annotation/LivewireContourTool.js.map +1 -1
  8. package/dist/cjs/tools/base/ContourBaseTool.d.ts +1 -0
  9. package/dist/cjs/tools/base/ContourBaseTool.js.map +1 -1
  10. package/dist/cjs/utilities/contours/updateContourPolyline.d.ts +1 -0
  11. package/dist/cjs/utilities/contours/updateContourPolyline.js +11 -4
  12. package/dist/cjs/utilities/contours/updateContourPolyline.js.map +1 -1
  13. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js +6 -4
  14. package/dist/esm/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.js.map +1 -1
  15. package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js +1 -1
  16. package/dist/esm/tools/annotation/LivewireContourSegmentationTool.js.map +1 -1
  17. package/dist/esm/tools/annotation/LivewireContourTool.js +19 -20
  18. package/dist/esm/tools/annotation/LivewireContourTool.js.map +1 -1
  19. package/dist/esm/tools/base/ContourBaseTool.js.map +1 -1
  20. package/dist/esm/utilities/contours/updateContourPolyline.js +11 -4
  21. package/dist/esm/utilities/contours/updateContourPolyline.js.map +1 -1
  22. package/dist/types/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.d.ts.map +1 -1
  23. package/dist/types/tools/annotation/LivewireContourTool.d.ts +4 -4
  24. package/dist/types/tools/annotation/LivewireContourTool.d.ts.map +1 -1
  25. package/dist/types/tools/base/ContourBaseTool.d.ts +1 -0
  26. package/dist/types/tools/base/ContourBaseTool.d.ts.map +1 -1
  27. package/dist/types/utilities/contours/updateContourPolyline.d.ts +1 -0
  28. package/dist/types/utilities/contours/updateContourPolyline.d.ts.map +1 -1
  29. package/dist/umd/index.js +1 -1
  30. package/dist/umd/index.js.map +1 -1
  31. package/package.json +3 -3
  32. package/src/eventListeners/annotations/contourSegmentation/contourSegmentationCompleted.ts +18 -9
  33. package/src/tools/annotation/LivewireContourSegmentationTool.ts +1 -1
  34. package/src/tools/annotation/LivewireContourTool.ts +28 -25
  35. package/src/tools/base/ContourBaseTool.ts +1 -0
  36. package/src/utilities/contours/updateContourPolyline.ts +19 -4
  37. 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",
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.3",
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": "a33572ac280ef5d42b56083161c020d04e4d30c2"
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/setting the winding direction.
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.scissorsRight = null;
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 right handle, used for editing */
42
- protected scissorsRight: LivewireScissors;
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
- confirmedPathRight?: LivewirePath;
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
- rightPos?,
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 (rightPos) {
221
- this.scissorsRight = LivewireScissors.createInstanceFromRawPixelData(
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.scissorsRight.startSearch(worldToSlice(rightPos));
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 = !rightPos;
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
- confirmedPathRight: currentPathNext,
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.scissorsRight = null;
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?.confirmedPathRight) {
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 confirmedPathRight = new LivewirePath();
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
- confirmedPathRight.addPoints(
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
- confirmedPathRight.addPoints(
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.confirmedPathRight = confirmedPathRight;
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.scissorsRight.findPathToPoint(slicePos);
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.confirmedPathRight);
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 } = this.editData;
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: annotation.data.contour.closed,
943
- targetWindingDirection: ContourWindingDirection.Clockwise,
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 currentWindingDirection = math.polyline.getWindingDirection(polyline);
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 = currentWindingDirection;
83
- } else if (windingDirection !== currentWindingDirection) {
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). If
9
- * you do not need the area signal you should always call `getArea`.
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)