@cornerstonejs/tools 1.77.7 → 1.77.9
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/tools/TrackballRotateTool.d.ts +1 -0
- package/dist/cjs/tools/TrackballRotateTool.js +13 -8
- package/dist/cjs/tools/TrackballRotateTool.js.map +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js +49 -57
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/planarFreehandROITool/closedContourEditLoop.js +8 -1
- package/dist/cjs/tools/annotation/planarFreehandROITool/closedContourEditLoop.js.map +1 -1
- package/dist/cjs/tools/annotation/planarFreehandROITool/openContourEditLoop.js +8 -1
- package/dist/cjs/tools/annotation/planarFreehandROITool/openContourEditLoop.js.map +1 -1
- package/dist/esm/tools/TrackballRotateTool.js +13 -8
- package/dist/esm/tools/TrackballRotateTool.js.map +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +49 -57
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/annotation/planarFreehandROITool/closedContourEditLoop.js +7 -1
- package/dist/esm/tools/annotation/planarFreehandROITool/closedContourEditLoop.js.map +1 -1
- package/dist/esm/tools/annotation/planarFreehandROITool/openContourEditLoop.js +7 -1
- package/dist/esm/tools/annotation/planarFreehandROITool/openContourEditLoop.js.map +1 -1
- package/dist/types/tools/TrackballRotateTool.d.ts +1 -0
- package/dist/types/tools/TrackballRotateTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/EllipticalROITool.d.ts.map +1 -1
- package/dist/types/tools/annotation/planarFreehandROITool/closedContourEditLoop.d.ts.map +1 -1
- package/dist/types/tools/annotation/planarFreehandROITool/openContourEditLoop.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/tools/TrackballRotateTool.ts +15 -19
- package/src/tools/annotation/EllipticalROITool.ts +75 -80
- package/src/tools/annotation/planarFreehandROITool/closedContourEditLoop.ts +9 -1
- package/src/tools/annotation/planarFreehandROITool/openContourEditLoop.ts +9 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.77.
|
|
3
|
+
"version": "1.77.9",
|
|
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.9",
|
|
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": "5e851b48111469c3669a0240a44f6980ec2860e8"
|
|
63
63
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import vtkMath from '@kitware/vtk.js/Common/Core/Math';
|
|
2
2
|
import { Events } from '../enums';
|
|
3
|
-
|
|
4
3
|
import {
|
|
5
4
|
eventTarget,
|
|
6
5
|
getEnabledElement,
|
|
@@ -12,9 +11,6 @@ import { EventTypes, PublicToolProps, ToolProps } from '../types';
|
|
|
12
11
|
import { BaseTool } from './base';
|
|
13
12
|
import { getToolGroup } from '../store/ToolGroupManager';
|
|
14
13
|
|
|
15
|
-
/**
|
|
16
|
-
* Tool that rotates the camera in the plane defined by the viewPlaneNormal and the viewUp.
|
|
17
|
-
*/
|
|
18
14
|
class TrackballRotateTool extends BaseTool {
|
|
19
15
|
static toolName;
|
|
20
16
|
touchDragCallback: (evt: EventTypes.InteractionEventType) => void;
|
|
@@ -22,6 +18,7 @@ class TrackballRotateTool extends BaseTool {
|
|
|
22
18
|
cleanUp: () => void;
|
|
23
19
|
_resizeObservers = new Map();
|
|
24
20
|
_viewportAddedListener: (evt: any) => void;
|
|
21
|
+
_hasResolutionChanged = false;
|
|
25
22
|
|
|
26
23
|
constructor(
|
|
27
24
|
toolProps: PublicToolProps = {},
|
|
@@ -33,7 +30,6 @@ class TrackballRotateTool extends BaseTool {
|
|
|
33
30
|
}
|
|
34
31
|
) {
|
|
35
32
|
super(toolProps, defaultToolProps);
|
|
36
|
-
|
|
37
33
|
this.touchDragCallback = this._dragCallback.bind(this);
|
|
38
34
|
this.mouseDragCallback = this._dragCallback.bind(this);
|
|
39
35
|
}
|
|
@@ -43,31 +39,33 @@ class TrackballRotateTool extends BaseTool {
|
|
|
43
39
|
const { element } = eventDetail;
|
|
44
40
|
const enabledElement = getEnabledElement(element);
|
|
45
41
|
const { viewport } = enabledElement;
|
|
46
|
-
|
|
47
42
|
const actorEntry = viewport.getDefaultActor();
|
|
48
43
|
const actor = actorEntry.actor as Types.VolumeActor;
|
|
49
44
|
const mapper = actor.getMapper();
|
|
50
45
|
const originalSampleDistance = mapper.getSampleDistance();
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
if (!this._hasResolutionChanged) {
|
|
48
|
+
mapper.setSampleDistance(originalSampleDistance * 2);
|
|
49
|
+
this._hasResolutionChanged = true;
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
if (this.cleanUp !== null) {
|
|
52
|
+
// Clean up previous event listener
|
|
53
|
+
document.removeEventListener('mouseup', this.cleanUp);
|
|
54
|
+
}
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
this.cleanUp = () => {
|
|
57
|
+
mapper.setSampleDistance(originalSampleDistance);
|
|
58
|
+
viewport.render();
|
|
59
|
+
this._hasResolutionChanged = false;
|
|
60
|
+
};
|
|
63
61
|
|
|
64
|
-
|
|
62
|
+
document.addEventListener('mouseup', this.cleanUp, { once: true });
|
|
63
|
+
}
|
|
65
64
|
return true;
|
|
66
65
|
};
|
|
67
66
|
|
|
68
67
|
_getViewportsInfo = () => {
|
|
69
68
|
const viewports = getToolGroup(this.toolGroupId).viewportsInfo;
|
|
70
|
-
|
|
71
69
|
return viewports;
|
|
72
70
|
};
|
|
73
71
|
|
|
@@ -168,8 +166,6 @@ class TrackballRotateTool extends BaseTool {
|
|
|
168
166
|
});
|
|
169
167
|
};
|
|
170
168
|
|
|
171
|
-
// pseudocode inspired from
|
|
172
|
-
// https://github.com/kitware/vtk-js/blob/HEAD/Sources/Interaction/Manipulators/MouseCameraUnicamRotateManipulator/index.js
|
|
173
169
|
_dragCallback(evt: EventTypes.InteractionEventType): void {
|
|
174
170
|
const { element, currentPoints, lastPoints } = evt.detail;
|
|
175
171
|
const currentPointsCanvas = currentPoints.canvas;
|
|
@@ -770,7 +770,6 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
770
770
|
);
|
|
771
771
|
|
|
772
772
|
const { centerPointRadius } = this.configuration;
|
|
773
|
-
|
|
774
773
|
// If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
|
|
775
774
|
// force to recalculate the stats from the points
|
|
776
775
|
if (
|
|
@@ -1012,99 +1011,95 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
1012
1011
|
// Check if one of the indexes are inside the volume, this then gives us
|
|
1013
1012
|
// Some area to do stats over.
|
|
1014
1013
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1014
|
+
this.isHandleOutsideImage = !this._isInsideVolume(
|
|
1015
|
+
pos1Index,
|
|
1016
|
+
post2Index,
|
|
1017
|
+
dimensions
|
|
1018
|
+
);
|
|
1017
1019
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
+
const iMin = Math.min(pos1Index[0], post2Index[0]);
|
|
1021
|
+
const iMax = Math.max(pos1Index[0], post2Index[0]);
|
|
1020
1022
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
+
const jMin = Math.min(pos1Index[1], post2Index[1]);
|
|
1024
|
+
const jMax = Math.max(pos1Index[1], post2Index[1]);
|
|
1023
1025
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
+
const kMin = Math.min(pos1Index[2], post2Index[2]);
|
|
1027
|
+
const kMax = Math.max(pos1Index[2], post2Index[2]);
|
|
1026
1028
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1029
|
+
const boundsIJK = [
|
|
1030
|
+
[iMin, iMax],
|
|
1031
|
+
[jMin, jMax],
|
|
1032
|
+
[kMin, kMax],
|
|
1033
|
+
] as [Types.Point2, Types.Point2, Types.Point2];
|
|
1032
1034
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1035
|
+
const center = [
|
|
1036
|
+
(topLeftWorld[0] + bottomRightWorld[0]) / 2,
|
|
1037
|
+
(topLeftWorld[1] + bottomRightWorld[1]) / 2,
|
|
1038
|
+
(topLeftWorld[2] + bottomRightWorld[2]) / 2,
|
|
1039
|
+
] as Types.Point3;
|
|
1038
1040
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints(
|
|
1047
|
-
viewPlaneNormal,
|
|
1048
|
-
viewUp,
|
|
1049
|
-
worldPos1,
|
|
1050
|
-
worldPos2
|
|
1051
|
-
);
|
|
1052
|
-
const isEmptyArea = worldWidth === 0 && worldHeight === 0;
|
|
1041
|
+
const ellipseObj = {
|
|
1042
|
+
center,
|
|
1043
|
+
xRadius: Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2,
|
|
1044
|
+
yRadius: Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2,
|
|
1045
|
+
zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2,
|
|
1046
|
+
};
|
|
1053
1047
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1048
|
+
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints(
|
|
1049
|
+
viewPlaneNormal,
|
|
1050
|
+
viewUp,
|
|
1051
|
+
worldPos1,
|
|
1052
|
+
worldPos2
|
|
1053
|
+
);
|
|
1054
|
+
const isEmptyArea = worldWidth === 0 && worldHeight === 0;
|
|
1059
1055
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1056
|
+
const handles = [pos1Index, post2Index];
|
|
1057
|
+
const { scale, areaUnits } = getCalibratedLengthUnitsAndScale(
|
|
1058
|
+
image,
|
|
1059
|
+
handles
|
|
1060
|
+
);
|
|
1064
1061
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1062
|
+
const area =
|
|
1063
|
+
Math.abs(Math.PI * (worldWidth / 2) * (worldHeight / 2)) /
|
|
1064
|
+
scale /
|
|
1065
|
+
scale;
|
|
1067
1066
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
targetId,
|
|
1071
|
-
annotation.metadata.referencedImageId
|
|
1072
|
-
),
|
|
1073
|
-
};
|
|
1067
|
+
const modalityUnitOptions = {
|
|
1068
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
1074
1069
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
)
|
|
1070
|
+
isSuvScaled: this.isSuvScaled(
|
|
1071
|
+
viewport,
|
|
1072
|
+
targetId,
|
|
1073
|
+
annotation.metadata.referencedImageId
|
|
1074
|
+
),
|
|
1075
|
+
};
|
|
1080
1076
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
);
|
|
1077
|
+
const modalityUnit = getModalityUnit(
|
|
1078
|
+
metadata.Modality,
|
|
1079
|
+
annotation.metadata.referencedImageId,
|
|
1080
|
+
modalityUnitOptions
|
|
1081
|
+
);
|
|
1087
1082
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
stdDev: stats.stdDev?.value,
|
|
1095
|
-
statsArray: stats.array,
|
|
1096
|
-
pointsInShape,
|
|
1097
|
-
isEmptyArea,
|
|
1098
|
-
areaUnit: areaUnits,
|
|
1099
|
-
modalityUnit,
|
|
1100
|
-
};
|
|
1101
|
-
} else {
|
|
1102
|
-
this.isHandleOutsideImage = true;
|
|
1083
|
+
const pointsInShape = pointInShapeCallback(
|
|
1084
|
+
imageData,
|
|
1085
|
+
(pointLPS) => pointInEllipse(ellipseObj, pointLPS, { fast: true }),
|
|
1086
|
+
this.configuration.statsCalculator.statsCallback,
|
|
1087
|
+
boundsIJK
|
|
1088
|
+
);
|
|
1103
1089
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1090
|
+
const stats = this.configuration.statsCalculator.getStatistics();
|
|
1091
|
+
cachedStats[targetId] = {
|
|
1092
|
+
Modality: metadata.Modality,
|
|
1093
|
+
area,
|
|
1094
|
+
mean: stats.mean?.value,
|
|
1095
|
+
max: stats.max?.value,
|
|
1096
|
+
stdDev: stats.stdDev?.value,
|
|
1097
|
+
statsArray: stats.array,
|
|
1098
|
+
pointsInShape,
|
|
1099
|
+
isEmptyArea,
|
|
1100
|
+
areaUnit: areaUnits,
|
|
1101
|
+
modalityUnit,
|
|
1102
|
+
};
|
|
1108
1103
|
}
|
|
1109
1104
|
|
|
1110
1105
|
annotation.invalidated = false;
|
|
@@ -452,6 +452,8 @@ function completeClosedContourEdit(element: HTMLDivElement) {
|
|
|
452
452
|
)
|
|
453
453
|
: fusedCanvasPoints;
|
|
454
454
|
|
|
455
|
+
const decimateConfig = this.configuration?.decimate || {};
|
|
456
|
+
|
|
455
457
|
updateContourPolyline(
|
|
456
458
|
annotation,
|
|
457
459
|
{
|
|
@@ -459,7 +461,13 @@ function completeClosedContourEdit(element: HTMLDivElement) {
|
|
|
459
461
|
closed: true,
|
|
460
462
|
targetWindingDirection: ContourWindingDirection.Clockwise,
|
|
461
463
|
},
|
|
462
|
-
viewport
|
|
464
|
+
viewport,
|
|
465
|
+
{
|
|
466
|
+
decimate: {
|
|
467
|
+
enabled: !!decimateConfig.enabled,
|
|
468
|
+
epsilon: decimateConfig.epsilon,
|
|
469
|
+
},
|
|
470
|
+
}
|
|
463
471
|
);
|
|
464
472
|
|
|
465
473
|
// If any manual update, triggered on an annotation, then it will be treated as non-autogenerated.
|
|
@@ -562,13 +562,21 @@ function completeOpenContourEdit(element: HTMLDivElement) {
|
|
|
562
562
|
)
|
|
563
563
|
: fusedCanvasPoints;
|
|
564
564
|
|
|
565
|
+
const decimateConfig = this.configuration?.decimate || {};
|
|
566
|
+
|
|
565
567
|
updateContourPolyline(
|
|
566
568
|
annotation,
|
|
567
569
|
{
|
|
568
570
|
points: updatedPoints,
|
|
569
571
|
closed: false,
|
|
570
572
|
},
|
|
571
|
-
viewport
|
|
573
|
+
viewport,
|
|
574
|
+
{
|
|
575
|
+
decimate: {
|
|
576
|
+
enabled: !!decimateConfig.enabled,
|
|
577
|
+
epsilon: decimateConfig.epsilon,
|
|
578
|
+
},
|
|
579
|
+
}
|
|
572
580
|
);
|
|
573
581
|
|
|
574
582
|
const worldPoints = annotation.data.contour.polyline;
|