@cornerstonejs/tools 4.16.4 → 4.17.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.
@@ -7,7 +7,7 @@ import { shouldSmooth, getInterpolatedPoints, } from '../../../utilities/planarF
7
7
  import getMouseModifierKey from '../../../eventDispatchers/shared/getMouseModifier';
8
8
  import triggerAnnotationRenderForViewportIds from '../../../utilities/triggerAnnotationRenderForViewportIds';
9
9
  import { triggerAnnotationModified, triggerContourAnnotationCompleted, } from '../../../stateManagement/annotation/helpers/state';
10
- import findOpenUShapedContourVectorToPeak from './findOpenUShapedContourVectorToPeak';
10
+ import { resolveVectorToPeak } from './findOpenUShapedContourVectorToPeak';
11
11
  import { polyline } from '../../../utilities/math';
12
12
  import { removeAnnotation } from '../../../stateManagement/annotation/annotationState';
13
13
  import { ContourWindingDirection } from '../../../types/ContourAnnotation';
@@ -193,10 +193,12 @@ function completeDrawOpenContour(element, options) {
193
193
  worldPoints[0],
194
194
  worldPoints[worldPoints.length - 1],
195
195
  ];
196
- if (annotation.data.isOpenUShapeContour === true ||
197
- annotation.data.isOpenUShapeContour === 'farthestT') {
198
- annotation.data.openUShapeContourVectorToPeak =
199
- findOpenUShapedContourVectorToPeak(canvasPoints, viewport);
196
+ if (!annotation.data.isOpenUShapeContour &&
197
+ this.configuration?.openUShapeContour) {
198
+ annotation.data.isOpenUShapeContour = this.configuration.openUShapeContour;
199
+ }
200
+ if (annotation.data.isOpenUShapeContour) {
201
+ annotation.data.openUShapeContourVectorToPeak = resolveVectorToPeak(canvasPoints, viewport, annotation.data.isOpenUShapeContour);
200
202
  }
201
203
  if (!textBox.hasMoved) {
202
204
  triggerContourAnnotationCompleted(annotation, contourHoleProcessingEnabled);
@@ -1,4 +1,5 @@
1
1
  import type { Types } from '@cornerstonejs/core';
2
2
  import type { PlanarFreehandROIAnnotation } from '../../../types/ToolSpecificAnnotationTypes';
3
3
  export default function findOpenUShapedContourVectorToPeak(canvasPoints: Types.Point2[], viewport: Types.IStackViewport | Types.IVolumeViewport): Types.Point3[];
4
- export declare function findOpenUShapedContourVectorToPeakOnRender(enabledElement: Types.IEnabledElement, annotation: PlanarFreehandROIAnnotation): Types.Point3[];
4
+ export declare function resolveVectorToPeak(canvasPoints: Types.Point2[], viewport: Types.IStackViewport | Types.IVolumeViewport, variant: PlanarFreehandROIAnnotation['data']['isOpenUShapeContour']): Types.Point3[] | null;
5
+ export declare function resolveVectorToPeakOnRender(enabledElement: Types.IEnabledElement, annotation: PlanarFreehandROIAnnotation): Types.Point3[] | null;
@@ -32,8 +32,66 @@ export default function findOpenUShapedContourVectorToPeak(canvasPoints, viewpor
32
32
  const toFurthestWorld = toFurthest.map(viewport.canvasToWorld);
33
33
  return toFurthestWorld;
34
34
  }
35
- export function findOpenUShapedContourVectorToPeakOnRender(enabledElement, annotation) {
35
+ export function resolveVectorToPeak(canvasPoints, viewport, variant) {
36
+ if (variant === 'orthogonalT') {
37
+ return findOpenUShapedContourVectorToPeakOrthogonal(canvasPoints, viewport);
38
+ }
39
+ if (variant === 'lineSegment') {
40
+ return null;
41
+ }
42
+ if (variant) {
43
+ return findOpenUShapedContourVectorToPeak(canvasPoints, viewport);
44
+ }
45
+ return null;
46
+ }
47
+ export function resolveVectorToPeakOnRender(enabledElement, annotation) {
36
48
  const { viewport } = enabledElement;
37
49
  const canvasPoints = annotation.data.contour.polyline.map(viewport.worldToCanvas);
38
- return findOpenUShapedContourVectorToPeak(canvasPoints, viewport);
50
+ return resolveVectorToPeak(canvasPoints, viewport, annotation.data.isOpenUShapeContour);
51
+ }
52
+ function findOpenUShapedContourVectorToPeakOrthogonal(canvasPoints, viewport) {
53
+ const first = canvasPoints[0];
54
+ const last = canvasPoints[canvasPoints.length - 1];
55
+ const firstToLastUnitVector = vec2.sub(vec2.create(), last, first);
56
+ vec2.normalize(firstToLastUnitVector, firstToLastUnitVector);
57
+ const chordDir = [
58
+ firstToLastUnitVector[0],
59
+ firstToLastUnitVector[1],
60
+ ];
61
+ const centerOfFirstToLast = [
62
+ (first[0] + last[0]) / 2,
63
+ (first[1] + last[1]) / 2,
64
+ ];
65
+ const delta = vec2.create();
66
+ let prevDp = null;
67
+ let prevPoint = null;
68
+ let orthogonalPoint = null;
69
+ for (const p of canvasPoints) {
70
+ vec2.sub(delta, p, centerOfFirstToLast);
71
+ const dp = vec2.dot(chordDir, delta);
72
+ if (prevDp !== null && prevDp * dp < 0) {
73
+ const t = Math.abs(prevDp) / (Math.abs(prevDp) + Math.abs(dp));
74
+ orthogonalPoint = [
75
+ prevPoint[0] + t * (p[0] - prevPoint[0]),
76
+ prevPoint[1] + t * (p[1] - prevPoint[1]),
77
+ ];
78
+ break;
79
+ }
80
+ if (Math.abs(dp) < 1e-10) {
81
+ orthogonalPoint = p;
82
+ break;
83
+ }
84
+ prevDp = dp;
85
+ prevPoint = p;
86
+ }
87
+ if (!orthogonalPoint) {
88
+ console.warn('No orthogonal intersection found for open U-shaped contour');
89
+ return null;
90
+ }
91
+ const toOrthogonal = [
92
+ orthogonalPoint,
93
+ centerOfFirstToLast,
94
+ ];
95
+ const toOrthogonalWorld = toOrthogonal.map(viewport.canvasToWorld);
96
+ return toOrthogonalWorld;
39
97
  }
@@ -7,7 +7,7 @@ import { polyline } from '../../../utilities/math';
7
7
  import { shouldSmooth, getInterpolatedPoints, } from '../../../utilities/planarFreehandROITool/smoothPoints';
8
8
  import triggerAnnotationRenderForViewportIds from '../../../utilities/triggerAnnotationRenderForViewportIds';
9
9
  import updateContourPolyline from '../../../utilities/contours/updateContourPolyline';
10
- import findOpenUShapedContourVectorToPeak from './findOpenUShapedContourVectorToPeak';
10
+ import { resolveVectorToPeak } from './findOpenUShapedContourVectorToPeak';
11
11
  import { triggerAnnotationModified } from '../../../stateManagement/annotation/helpers/state';
12
12
  const { addCanvasPointsToArray, getSubPixelSpacingAndXYDirections } = polyline;
13
13
  function activateOpenContourEdit(evt, annotation, viewportIdsToRender) {
@@ -289,8 +289,7 @@ function completeOpenContourEdit(element) {
289
289
  worldPoints[worldPoints.length - 1],
290
290
  ];
291
291
  if (annotation.data.isOpenUShapeContour) {
292
- annotation.data.openUShapeContourVectorToPeak =
293
- findOpenUShapedContourVectorToPeak(fusedCanvasPoints, viewport);
292
+ annotation.data.openUShapeContourVectorToPeak = resolveVectorToPeak(fusedCanvasPoints, viewport, annotation.data.isOpenUShapeContour);
294
293
  }
295
294
  triggerAnnotationModified(annotation, element);
296
295
  }
@@ -1,6 +1,6 @@
1
1
  import { drawHandles as drawHandlesSvg, drawPolyline as drawPolylineSvg, drawPath as drawPathSvg, } from '../../../drawingSvg';
2
2
  import { polyline } from '../../../utilities/math';
3
- import { findOpenUShapedContourVectorToPeakOnRender } from './findOpenUShapedContourVectorToPeak';
3
+ import { resolveVectorToPeakOnRender } from './findOpenUShapedContourVectorToPeak';
4
4
  import getContourHolesDataCanvas from '../../../utilities/contours/getContourHolesDataCanvas';
5
5
  const { pointsAreWithinCloseContourProximity } = polyline;
6
6
  function _getRenderingOptions(enabledElement, annotation) {
@@ -20,7 +20,9 @@ function _getRenderingOptions(enabledElement, annotation) {
20
20
  width: lineWidth,
21
21
  lineDash,
22
22
  fillColor,
23
- fillOpacity,
23
+ fillOpacity: this.configuration?.fillOpacity !== undefined
24
+ ? this.configuration.fillOpacity
25
+ : fillOpacity,
24
26
  closePath: isClosedContour,
25
27
  };
26
28
  return options;
@@ -34,7 +36,9 @@ function renderContour(enabledElement, svgDrawingHelper, annotation) {
34
36
  }
35
37
  else {
36
38
  if (annotation.data.isOpenUShapeContour) {
37
- calculateUShapeContourVectorToPeakIfNotPresent(enabledElement, annotation);
39
+ if (annotation.data.isOpenUShapeContour !== 'lineSegment') {
40
+ calculateUShapeContourVectorToPeakIfNotPresent(enabledElement, annotation);
41
+ }
38
42
  this.renderOpenUShapedContour(enabledElement, svgDrawingHelper, annotation);
39
43
  }
40
44
  else {
@@ -44,8 +48,7 @@ function renderContour(enabledElement, svgDrawingHelper, annotation) {
44
48
  }
45
49
  function calculateUShapeContourVectorToPeakIfNotPresent(enabledElement, annotation) {
46
50
  if (!annotation.data.openUShapeContourVectorToPeak) {
47
- annotation.data.openUShapeContourVectorToPeak =
48
- findOpenUShapedContourVectorToPeakOnRender(enabledElement, annotation);
51
+ annotation.data.openUShapeContourVectorToPeak = resolveVectorToPeakOnRender(enabledElement, annotation);
49
52
  }
50
53
  }
51
54
  function renderClosedContour(enabledElement, svgDrawingHelper, annotation) {
@@ -97,15 +100,12 @@ function renderOpenUShapedContour(enabledElement, svgDrawingHelper, annotation)
97
100
  const { openUShapeContourVectorToPeak } = annotation.data;
98
101
  const { polyline } = annotation.data.contour;
99
102
  this.renderOpenContour(enabledElement, svgDrawingHelper, annotation);
100
- if (!openUShapeContourVectorToPeak) {
103
+ const isLineSegmentOnly = annotation.data.isOpenUShapeContour === 'lineSegment';
104
+ if (!isLineSegmentOnly && !openUShapeContourVectorToPeak) {
101
105
  return;
102
106
  }
103
107
  const firstCanvasPoint = viewport.worldToCanvas(polyline[0]);
104
108
  const lastCanvasPoint = viewport.worldToCanvas(polyline[polyline.length - 1]);
105
- const openUShapeContourVectorToPeakCanvas = [
106
- viewport.worldToCanvas(openUShapeContourVectorToPeak[0]),
107
- viewport.worldToCanvas(openUShapeContourVectorToPeak[1]),
108
- ];
109
109
  const options = this._getRenderingOptions(enabledElement, annotation);
110
110
  drawPolylineSvg(svgDrawingHelper, annotation.annotationUID, 'first-to-last', [firstCanvasPoint, lastCanvasPoint], {
111
111
  color: options.color,
@@ -113,15 +113,31 @@ function renderOpenUShapedContour(enabledElement, svgDrawingHelper, annotation)
113
113
  closePath: false,
114
114
  lineDash: '2,2',
115
115
  });
116
- drawPolylineSvg(svgDrawingHelper, annotation.annotationUID, 'midpoint-to-open-contour', [
117
- openUShapeContourVectorToPeakCanvas[0],
118
- openUShapeContourVectorToPeakCanvas[1],
119
- ], {
120
- color: options.color,
121
- width: options.width,
122
- closePath: false,
123
- lineDash: '2,2',
124
- });
116
+ if (!isLineSegmentOnly) {
117
+ const openUShapeContourVectorToPeakCanvas = [
118
+ viewport.worldToCanvas(openUShapeContourVectorToPeak[0]),
119
+ viewport.worldToCanvas(openUShapeContourVectorToPeak[1]),
120
+ ];
121
+ drawPolylineSvg(svgDrawingHelper, annotation.annotationUID, 'midpoint-to-open-contour', [
122
+ openUShapeContourVectorToPeakCanvas[0],
123
+ openUShapeContourVectorToPeakCanvas[1],
124
+ ], {
125
+ color: options.color,
126
+ width: options.width,
127
+ closePath: false,
128
+ lineDash: '2,2',
129
+ });
130
+ }
131
+ if (options.fillOpacity > 0) {
132
+ const canvasPolyline = polyline.map((worldPos) => viewport.worldToCanvas(worldPos));
133
+ drawPathSvg(svgDrawingHelper, annotation.annotationUID, 'u-shape-fill', [[...canvasPolyline, firstCanvasPoint]], {
134
+ color: options.fillColor || options.color,
135
+ fillColor: options.fillColor || options.color,
136
+ fillOpacity: options.fillOpacity,
137
+ closePath: true,
138
+ width: 0,
139
+ });
140
+ }
125
141
  }
126
142
  function renderContourBeingDrawn(enabledElement, svgDrawingHelper, annotation) {
127
143
  const options = this._getRenderingOptions(enabledElement, annotation);
@@ -1 +1 @@
1
- export declare const version = "4.16.4";
1
+ export declare const version = "4.17.0";
@@ -1 +1 @@
1
- export const version = '4.16.4';
1
+ export const version = '4.17.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "4.16.4",
3
+ "version": "4.17.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.16.4",
111
+ "@cornerstonejs/core": "4.17.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": "8f2403461fd69c52ba70d54f5a84b436782f5d56"
130
+ "gitHead": "f5a86e32f08c55617ab0c6213607ce341bb7b02c"
131
131
  }