@cornerstonejs/tools 4.17.4 → 4.18.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.
- package/dist/esm/tools/CrosshairsTool.d.ts +22 -3
- package/dist/esm/tools/CrosshairsTool.js +359 -142
- package/dist/esm/tools/annotation/ProbeTool.js +14 -5
- package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +4 -3
- package/dist/esm/utilities/getCalibratedUnits.js +24 -5
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +3 -3
|
@@ -21,12 +21,20 @@ declare class CrosshairsTool extends AnnotationTool {
|
|
|
21
21
|
_getReferenceLineControllable?: (viewportId: string) => boolean;
|
|
22
22
|
_getReferenceLineDraggableRotatable?: (viewportId: string) => boolean;
|
|
23
23
|
_getReferenceLineSlabThicknessControlsOn?: (viewportId: string) => boolean;
|
|
24
|
+
_volumeViewportNewVolumeListeners: Map<string, {
|
|
25
|
+
element: HTMLDivElement;
|
|
26
|
+
handler: EventListener;
|
|
27
|
+
}>;
|
|
28
|
+
_toolGroupViewportAddedListener: EventListener | null;
|
|
29
|
+
_toolGroupViewportRemovedListener: EventListener | null;
|
|
30
|
+
_ignoreFiredEvents: boolean;
|
|
24
31
|
constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
|
|
25
32
|
initializeViewport: ({ renderingEngineId, viewportId, }: Types.IViewportId) => {
|
|
26
33
|
normal: Types.Point3;
|
|
27
34
|
point: Types.Point3;
|
|
28
35
|
};
|
|
29
36
|
_getViewportsInfo: () => any[];
|
|
37
|
+
_reinitializeListenersAndCenter: () => void;
|
|
30
38
|
onSetToolActive(): void;
|
|
31
39
|
onSetToolPassive(): void;
|
|
32
40
|
onSetToolEnabled(): void;
|
|
@@ -47,9 +55,9 @@ declare class CrosshairsTool extends AnnotationTool {
|
|
|
47
55
|
filterInteractableAnnotationsForElement: (element: any, annotations: any) => any;
|
|
48
56
|
renderAnnotation: (enabledElement: Types.IEnabledElement, svgDrawingHelper: SVGDrawingHelper) => boolean;
|
|
49
57
|
_getAnnotations: (enabledElement: Types.IEnabledElement) => Annotation[];
|
|
50
|
-
_onNewVolume: () => void;
|
|
51
|
-
_unsubscribeToViewportNewVolumeSet(
|
|
52
|
-
_subscribeToViewportNewVolumeSet(
|
|
58
|
+
_onNewVolume: (_evt?: Event) => void;
|
|
59
|
+
_unsubscribeToViewportNewVolumeSet(_viewportsInfo: any): void;
|
|
60
|
+
_subscribeToViewportNewVolumeSet(_viewports: any): void;
|
|
53
61
|
_autoPanViewportIfNecessary(viewportId: string, renderingEngine: Types.IRenderingEngine): void;
|
|
54
62
|
_areViewportIdArraysEqual: (viewportIdArrayOne: any, viewportIdArrayTwo: any) => boolean;
|
|
55
63
|
_getAnnotationsForViewportsWithDifferentCameras: (enabledElement: any, annotations: any) => any;
|
|
@@ -69,5 +77,16 @@ declare class CrosshairsTool extends AnnotationTool {
|
|
|
69
77
|
_getRotationHandleNearImagePoint(viewport: any, annotation: any, canvasCoords: any, proximity: any): any;
|
|
70
78
|
_getSlabThicknessHandleNearImagePoint(viewport: any, annotation: any, canvasCoords: any, proximity: any): any;
|
|
71
79
|
_pointNearTool(element: any, annotation: any, canvasCoords: any, proximity: any): boolean;
|
|
80
|
+
_toViewportKey: (renderingEngineId: string, viewportId: string) => string;
|
|
81
|
+
_isFinitePoint3: (point: Types.Point3) => boolean;
|
|
82
|
+
_bindToolGroupViewportListeners: () => void;
|
|
83
|
+
_unbindToolGroupViewportListeners: () => void;
|
|
84
|
+
_syncVolumeListenersWithToolGroup: () => void;
|
|
85
|
+
_clearAllVolumeListenersAndViewportState: () => void;
|
|
86
|
+
_calculateToolCenterFromAbsoluteCameras: () => Types.Point3 | null;
|
|
87
|
+
_recomputeToolCenterFromAbsoluteCameras: ({ emitEvent, updateViewportCameras, }?: {
|
|
88
|
+
emitEvent?: boolean;
|
|
89
|
+
updateViewportCameras?: boolean;
|
|
90
|
+
}) => Types.Point3 | null;
|
|
72
91
|
}
|
|
73
92
|
export default CrosshairsTool;
|
|
@@ -69,6 +69,10 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
69
69
|
}) {
|
|
70
70
|
super(toolProps, defaultToolProps);
|
|
71
71
|
this.toolCenter = [0, 0, 0];
|
|
72
|
+
this._volumeViewportNewVolumeListeners = new Map();
|
|
73
|
+
this._toolGroupViewportAddedListener = null;
|
|
74
|
+
this._toolGroupViewportRemovedListener = null;
|
|
75
|
+
this._ignoreFiredEvents = false;
|
|
72
76
|
this.initializeViewport = ({ renderingEngineId, viewportId, }) => {
|
|
73
77
|
const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
74
78
|
if (!enabledElement) {
|
|
@@ -114,11 +118,21 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
114
118
|
const viewports = getToolGroup(this.toolGroupId).viewportsInfo;
|
|
115
119
|
return viewports;
|
|
116
120
|
};
|
|
121
|
+
this._reinitializeListenersAndCenter = () => {
|
|
122
|
+
this._unbindToolGroupViewportListeners();
|
|
123
|
+
this._clearAllVolumeListenersAndViewportState();
|
|
124
|
+
this._bindToolGroupViewportListeners();
|
|
125
|
+
this._syncVolumeListenersWithToolGroup();
|
|
126
|
+
this._computeToolCenter(this._getViewportsInfo());
|
|
127
|
+
};
|
|
117
128
|
this.resetCrosshairs = () => {
|
|
118
129
|
const viewportsInfo = this._getViewportsInfo();
|
|
119
130
|
for (const viewportInfo of viewportsInfo) {
|
|
120
131
|
const { viewportId, renderingEngineId } = viewportInfo;
|
|
121
132
|
const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
133
|
+
if (!enabledElement) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
122
136
|
const viewport = enabledElement.viewport;
|
|
123
137
|
const resetPan = true;
|
|
124
138
|
const resetZoom = true;
|
|
@@ -152,31 +166,24 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
152
166
|
console.warn('For crosshairs to operate, at least two viewports must be given.');
|
|
153
167
|
return;
|
|
154
168
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
this.initializeViewport(thirdViewport));
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
vec3.add(point3, point1, point2);
|
|
166
|
-
vec3.scale(point3, point3, 0.5);
|
|
167
|
-
vec3.cross(normal3, normal1, normal2);
|
|
168
|
-
}
|
|
169
|
-
const firstPlane = csUtils.planar.planeEquation(normal1, point1);
|
|
170
|
-
const secondPlane = csUtils.planar.planeEquation(normal2, point2);
|
|
171
|
-
const thirdPlane = csUtils.planar.planeEquation(normal3, point3);
|
|
172
|
-
const toolCenter = csUtils.planar.threePlaneIntersection(firstPlane, secondPlane, thirdPlane);
|
|
173
|
-
this.setToolCenter(toolCenter);
|
|
169
|
+
viewportsInfo.forEach((viewportInfo) => {
|
|
170
|
+
this.initializeViewport(viewportInfo);
|
|
171
|
+
});
|
|
172
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
173
|
+
emitEvent: true,
|
|
174
|
+
updateViewportCameras: true,
|
|
175
|
+
});
|
|
174
176
|
};
|
|
175
177
|
this.addNewAnnotation = (evt) => {
|
|
176
178
|
const eventDetail = evt.detail;
|
|
177
179
|
const { element } = eventDetail;
|
|
178
180
|
const { currentPoints } = eventDetail;
|
|
179
181
|
const jumpWorld = currentPoints.world;
|
|
182
|
+
this._syncVolumeListenersWithToolGroup();
|
|
183
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
184
|
+
emitEvent: false,
|
|
185
|
+
updateViewportCameras: false,
|
|
186
|
+
});
|
|
180
187
|
const enabledElement = getEnabledElement(element);
|
|
181
188
|
const { viewport } = enabledElement;
|
|
182
189
|
this._jump(enabledElement, jumpWorld);
|
|
@@ -231,46 +238,33 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
231
238
|
const eventDetail = evt.detail;
|
|
232
239
|
const { element } = eventDetail;
|
|
233
240
|
const enabledElement = getEnabledElement(element);
|
|
241
|
+
if (!enabledElement) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
234
244
|
const { renderingEngine } = enabledElement;
|
|
235
245
|
const viewport = enabledElement.viewport;
|
|
246
|
+
this._syncVolumeListenersWithToolGroup();
|
|
247
|
+
if (this._ignoreFiredEvents) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const isSourceInToolGroup = this._getViewportsInfo().some(({ viewportId, renderingEngineId }) => viewportId === viewport.id && renderingEngineId === renderingEngine.id);
|
|
251
|
+
if (!isSourceInToolGroup) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
236
254
|
const annotations = this._getAnnotations(enabledElement);
|
|
237
255
|
const filteredToolAnnotations = this.filterInteractableAnnotationsForElement(element, annotations);
|
|
238
256
|
const viewportAnnotation = filteredToolAnnotations[0];
|
|
239
|
-
if (!viewportAnnotation) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
257
|
const currentCamera = viewport.getCamera();
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
vtkMath.subtract(currentCamera.focalPoint, oldCameraFocalPoint, deltaCameraFocalPoint);
|
|
249
|
-
viewportAnnotation.metadata.cameraPosition = [...currentCamera.position];
|
|
250
|
-
viewportAnnotation.metadata.cameraFocalPoint = [
|
|
251
|
-
...currentCamera.focalPoint,
|
|
252
|
-
];
|
|
253
|
-
const viewportControllable = this._getReferenceLineControllable(viewport.id);
|
|
254
|
-
const viewportDraggableRotatable = this._getReferenceLineDraggableRotatable(viewport.id);
|
|
255
|
-
if (!csUtils.isEqual(currentCamera.position, oldCameraPosition, 1e-3) &&
|
|
256
|
-
viewportControllable &&
|
|
257
|
-
viewportDraggableRotatable) {
|
|
258
|
-
let isRotation = false;
|
|
259
|
-
const cameraModifiedSameForPosAndFocalPoint = csUtils.isEqual(deltaCameraPosition, deltaCameraFocalPoint, 1e-3);
|
|
260
|
-
if (!cameraModifiedSameForPosAndFocalPoint) {
|
|
261
|
-
isRotation = true;
|
|
262
|
-
}
|
|
263
|
-
const cameraModifiedInPlane = Math.abs(vtkMath.dot(deltaCameraPosition, currentCamera.viewPlaneNormal)) < 1e-2;
|
|
264
|
-
if (!isRotation && !cameraModifiedInPlane) {
|
|
265
|
-
this.toolCenter[0] += deltaCameraPosition[0];
|
|
266
|
-
this.toolCenter[1] += deltaCameraPosition[1];
|
|
267
|
-
this.toolCenter[2] += deltaCameraPosition[2];
|
|
268
|
-
triggerEvent(eventTarget, Events.CROSSHAIR_TOOL_CENTER_CHANGED, {
|
|
269
|
-
toolGroupId: this.toolGroupId,
|
|
270
|
-
toolCenter: this.toolCenter,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
258
|
+
if (viewportAnnotation) {
|
|
259
|
+
viewportAnnotation.metadata.cameraPosition = [...currentCamera.position];
|
|
260
|
+
viewportAnnotation.metadata.cameraFocalPoint = [
|
|
261
|
+
...currentCamera.focalPoint,
|
|
262
|
+
];
|
|
273
263
|
}
|
|
264
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
265
|
+
emitEvent: true,
|
|
266
|
+
updateViewportCameras: false,
|
|
267
|
+
});
|
|
274
268
|
if (this.configuration.autoPan?.enabled) {
|
|
275
269
|
const toolGroup = getToolGroupForViewport(viewport.id, renderingEngine.id);
|
|
276
270
|
const otherViewportIds = toolGroup
|
|
@@ -708,15 +702,19 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
708
702
|
});
|
|
709
703
|
return toolGroupAnnotations;
|
|
710
704
|
};
|
|
711
|
-
this._onNewVolume = () => {
|
|
712
|
-
|
|
713
|
-
this.
|
|
705
|
+
this._onNewVolume = (_evt) => {
|
|
706
|
+
this._syncVolumeListenersWithToolGroup();
|
|
707
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
708
|
+
emitEvent: true,
|
|
709
|
+
updateViewportCameras: false,
|
|
710
|
+
});
|
|
714
711
|
};
|
|
715
712
|
this._areViewportIdArraysEqual = (viewportIdArrayOne, viewportIdArrayTwo) => {
|
|
716
713
|
if (viewportIdArrayOne.length !== viewportIdArrayTwo.length) {
|
|
717
714
|
return false;
|
|
718
715
|
}
|
|
719
|
-
viewportIdArrayOne.
|
|
716
|
+
for (let index = 0; index < viewportIdArrayOne.length; index++) {
|
|
717
|
+
const id = viewportIdArrayOne[index];
|
|
720
718
|
let itemFound = false;
|
|
721
719
|
for (let i = 0; i < viewportIdArrayTwo.length; ++i) {
|
|
722
720
|
if (id === viewportIdArrayTwo[i]) {
|
|
@@ -727,7 +725,7 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
727
725
|
if (itemFound === false) {
|
|
728
726
|
return false;
|
|
729
727
|
}
|
|
730
|
-
}
|
|
728
|
+
}
|
|
731
729
|
return true;
|
|
732
730
|
};
|
|
733
731
|
this._getAnnotationsForViewportsWithDifferentCameras = (enabledElement, annotations) => {
|
|
@@ -903,10 +901,19 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
903
901
|
return false;
|
|
904
902
|
}
|
|
905
903
|
this._applyDeltaShiftToSelectedViewportCameras(renderingEngine, viewportsAnnotationsToUpdate, delta);
|
|
904
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
905
|
+
emitEvent: true,
|
|
906
|
+
updateViewportCameras: false,
|
|
907
|
+
});
|
|
906
908
|
state.isInteractingWithTool = false;
|
|
907
909
|
return true;
|
|
908
910
|
};
|
|
909
911
|
this._activateModify = (element) => {
|
|
912
|
+
this._syncVolumeListenersWithToolGroup();
|
|
913
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
914
|
+
emitEvent: false,
|
|
915
|
+
updateViewportCameras: false,
|
|
916
|
+
});
|
|
910
917
|
state.isInteractingWithTool = !this.configuration.mobile?.enabled;
|
|
911
918
|
element.addEventListener(Events.MOUSE_UP, this._endCallback);
|
|
912
919
|
element.addEventListener(Events.MOUSE_DRAG, this._dragCallback);
|
|
@@ -927,9 +934,15 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
927
934
|
this._endCallback = (evt) => {
|
|
928
935
|
const eventDetail = evt.detail;
|
|
929
936
|
const { element } = eventDetail;
|
|
930
|
-
this.editData
|
|
931
|
-
|
|
937
|
+
if (this.editData?.annotation?.data) {
|
|
938
|
+
this.editData.annotation.data.handles.activeOperation = null;
|
|
939
|
+
this.editData.annotation.data.activeViewportIds = [];
|
|
940
|
+
}
|
|
932
941
|
this._deactivateModify(element);
|
|
942
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
943
|
+
emitEvent: true,
|
|
944
|
+
updateViewportCameras: false,
|
|
945
|
+
});
|
|
933
946
|
resetElementCursor(element);
|
|
934
947
|
this.editData = null;
|
|
935
948
|
const requireSameOrientation = false;
|
|
@@ -968,6 +981,10 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
968
981
|
viewportAnnotation.data.activeViewportIds.find((id) => id === otherViewport.id));
|
|
969
982
|
});
|
|
970
983
|
this._applyDeltaShiftToSelectedViewportCameras(renderingEngine, viewportsAnnotationsToUpdate, delta);
|
|
984
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
985
|
+
emitEvent: true,
|
|
986
|
+
updateViewportCameras: false,
|
|
987
|
+
});
|
|
971
988
|
}
|
|
972
989
|
else if (handles.activeOperation === OPERATION.ROTATE) {
|
|
973
990
|
const otherViewportAnnotations = this._getAnnotationsForViewportsWithDifferentCameras(enabledElement, annotations);
|
|
@@ -1004,29 +1021,40 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1004
1021
|
.rotate(angle, rotationAxis)
|
|
1005
1022
|
.translate(-center[0], -center[1], -center[2]);
|
|
1006
1023
|
const otherViewportsIds = [];
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
position
|
|
1024
|
-
viewUp
|
|
1025
|
-
|
|
1024
|
+
const previousIgnoreFiredEvents = this._ignoreFiredEvents;
|
|
1025
|
+
this._ignoreFiredEvents = true;
|
|
1026
|
+
try {
|
|
1027
|
+
viewportsAnnotationsToUpdate.forEach((annotation) => {
|
|
1028
|
+
const { data } = annotation;
|
|
1029
|
+
data.handles.toolCenter = center;
|
|
1030
|
+
const otherViewport = renderingEngine.getViewport(data.viewportId);
|
|
1031
|
+
const camera = otherViewport.getCamera();
|
|
1032
|
+
const { viewUp, position, focalPoint } = camera;
|
|
1033
|
+
viewUp[0] += position[0];
|
|
1034
|
+
viewUp[1] += position[1];
|
|
1035
|
+
viewUp[2] += position[2];
|
|
1036
|
+
vec3.transformMat4(focalPoint, focalPoint, matrix);
|
|
1037
|
+
vec3.transformMat4(position, position, matrix);
|
|
1038
|
+
vec3.transformMat4(viewUp, viewUp, matrix);
|
|
1039
|
+
viewUp[0] -= position[0];
|
|
1040
|
+
viewUp[1] -= position[1];
|
|
1041
|
+
viewUp[2] -= position[2];
|
|
1042
|
+
otherViewport.setCamera({
|
|
1043
|
+
position,
|
|
1044
|
+
viewUp,
|
|
1045
|
+
focalPoint,
|
|
1046
|
+
});
|
|
1047
|
+
otherViewportsIds.push(otherViewport.id);
|
|
1026
1048
|
});
|
|
1027
|
-
|
|
1028
|
-
|
|
1049
|
+
}
|
|
1050
|
+
finally {
|
|
1051
|
+
this._ignoreFiredEvents = previousIgnoreFiredEvents;
|
|
1052
|
+
}
|
|
1029
1053
|
renderingEngine.renderViewports(otherViewportsIds);
|
|
1054
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
1055
|
+
emitEvent: true,
|
|
1056
|
+
updateViewportCameras: false,
|
|
1057
|
+
});
|
|
1030
1058
|
}
|
|
1031
1059
|
else if (handles.activeOperation === OPERATION.SLAB) {
|
|
1032
1060
|
const otherViewportAnnotations = this._getAnnotationsForViewportsWithDifferentCameras(enabledElement, annotations);
|
|
@@ -1113,7 +1141,14 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1113
1141
|
}
|
|
1114
1142
|
});
|
|
1115
1143
|
renderingEngine.renderViewports(viewportsIds);
|
|
1144
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
1145
|
+
emitEvent: true,
|
|
1146
|
+
updateViewportCameras: false,
|
|
1147
|
+
});
|
|
1116
1148
|
}
|
|
1149
|
+
const requireSameOrientation = false;
|
|
1150
|
+
const viewportIdsToRender = getViewportIdsWithToolToRender(element, this.getToolName(), requireSameOrientation);
|
|
1151
|
+
triggerAnnotationRenderForViewportIds(viewportIdsToRender);
|
|
1117
1152
|
};
|
|
1118
1153
|
this._pointNearReferenceLine = (annotation, canvasCoords, proximity, lineViewport) => {
|
|
1119
1154
|
const { data } = annotation;
|
|
@@ -1156,6 +1191,170 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1156
1191
|
}
|
|
1157
1192
|
return false;
|
|
1158
1193
|
};
|
|
1194
|
+
this._toViewportKey = (renderingEngineId, viewportId) => {
|
|
1195
|
+
return `${renderingEngineId}::${viewportId}`;
|
|
1196
|
+
};
|
|
1197
|
+
this._isFinitePoint3 = (point) => {
|
|
1198
|
+
if (!point || point.length !== 3) {
|
|
1199
|
+
return false;
|
|
1200
|
+
}
|
|
1201
|
+
return (Number.isFinite(point[0]) &&
|
|
1202
|
+
Number.isFinite(point[1]) &&
|
|
1203
|
+
Number.isFinite(point[2]));
|
|
1204
|
+
};
|
|
1205
|
+
this._bindToolGroupViewportListeners = () => {
|
|
1206
|
+
if (!this._toolGroupViewportAddedListener) {
|
|
1207
|
+
this._toolGroupViewportAddedListener = ((evt) => {
|
|
1208
|
+
if (evt.detail?.toolGroupId !== this.toolGroupId) {
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
this._syncVolumeListenersWithToolGroup();
|
|
1212
|
+
this._computeToolCenter(this._getViewportsInfo());
|
|
1213
|
+
});
|
|
1214
|
+
eventTarget.addEventListener(Events.TOOLGROUP_VIEWPORT_ADDED, this._toolGroupViewportAddedListener);
|
|
1215
|
+
}
|
|
1216
|
+
if (!this._toolGroupViewportRemovedListener) {
|
|
1217
|
+
this._toolGroupViewportRemovedListener = ((evt) => {
|
|
1218
|
+
if (evt.detail?.toolGroupId !== this.toolGroupId) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
this._syncVolumeListenersWithToolGroup();
|
|
1222
|
+
this._recomputeToolCenterFromAbsoluteCameras({
|
|
1223
|
+
emitEvent: true,
|
|
1224
|
+
updateViewportCameras: false,
|
|
1225
|
+
});
|
|
1226
|
+
});
|
|
1227
|
+
eventTarget.addEventListener(Events.TOOLGROUP_VIEWPORT_REMOVED, this._toolGroupViewportRemovedListener);
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
this._unbindToolGroupViewportListeners = () => {
|
|
1231
|
+
if (this._toolGroupViewportAddedListener) {
|
|
1232
|
+
eventTarget.removeEventListener(Events.TOOLGROUP_VIEWPORT_ADDED, this._toolGroupViewportAddedListener);
|
|
1233
|
+
this._toolGroupViewportAddedListener = null;
|
|
1234
|
+
}
|
|
1235
|
+
if (this._toolGroupViewportRemovedListener) {
|
|
1236
|
+
eventTarget.removeEventListener(Events.TOOLGROUP_VIEWPORT_REMOVED, this._toolGroupViewportRemovedListener);
|
|
1237
|
+
this._toolGroupViewportRemovedListener = null;
|
|
1238
|
+
}
|
|
1239
|
+
};
|
|
1240
|
+
this._syncVolumeListenersWithToolGroup = () => {
|
|
1241
|
+
const viewportsInfo = this._getViewportsInfo();
|
|
1242
|
+
const activeViewportKeys = new Set();
|
|
1243
|
+
viewportsInfo.forEach((viewportInfo) => {
|
|
1244
|
+
const { viewportId, renderingEngineId } = viewportInfo;
|
|
1245
|
+
const viewportKey = this._toViewportKey(renderingEngineId, viewportId);
|
|
1246
|
+
activeViewportKeys.add(viewportKey);
|
|
1247
|
+
const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
1248
|
+
const existingListenerInfo = this._volumeViewportNewVolumeListeners.get(viewportKey);
|
|
1249
|
+
if (!enabledElement) {
|
|
1250
|
+
if (existingListenerInfo) {
|
|
1251
|
+
existingListenerInfo.element.removeEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, existingListenerInfo.handler);
|
|
1252
|
+
this._volumeViewportNewVolumeListeners.delete(viewportKey);
|
|
1253
|
+
}
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
const { viewport } = enabledElement;
|
|
1257
|
+
const { element } = viewport;
|
|
1258
|
+
if (existingListenerInfo && existingListenerInfo.element !== element) {
|
|
1259
|
+
existingListenerInfo.element.removeEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, existingListenerInfo.handler);
|
|
1260
|
+
this._volumeViewportNewVolumeListeners.delete(viewportKey);
|
|
1261
|
+
}
|
|
1262
|
+
if (this._volumeViewportNewVolumeListeners.has(viewportKey)) {
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
const handler = ((evt) => this._onNewVolume(evt));
|
|
1266
|
+
element.addEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, handler);
|
|
1267
|
+
this._volumeViewportNewVolumeListeners.set(viewportKey, {
|
|
1268
|
+
element,
|
|
1269
|
+
handler,
|
|
1270
|
+
});
|
|
1271
|
+
});
|
|
1272
|
+
Array.from(this._volumeViewportNewVolumeListeners.entries()).forEach(([viewportKey, listenerInfo]) => {
|
|
1273
|
+
if (activeViewportKeys.has(viewportKey)) {
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
listenerInfo.element.removeEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, listenerInfo.handler);
|
|
1277
|
+
this._volumeViewportNewVolumeListeners.delete(viewportKey);
|
|
1278
|
+
});
|
|
1279
|
+
};
|
|
1280
|
+
this._clearAllVolumeListenersAndViewportState = () => {
|
|
1281
|
+
this._volumeViewportNewVolumeListeners.forEach((listenerInfo) => {
|
|
1282
|
+
listenerInfo.element.removeEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, listenerInfo.handler);
|
|
1283
|
+
});
|
|
1284
|
+
this._volumeViewportNewVolumeListeners.clear();
|
|
1285
|
+
};
|
|
1286
|
+
this._calculateToolCenterFromAbsoluteCameras = () => {
|
|
1287
|
+
const viewportsInfo = this._getViewportsInfo();
|
|
1288
|
+
const uniquePlanes = [];
|
|
1289
|
+
viewportsInfo.forEach((viewportInfo) => {
|
|
1290
|
+
const enabledElement = getEnabledElementByIds(viewportInfo.viewportId, viewportInfo.renderingEngineId);
|
|
1291
|
+
if (!enabledElement) {
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const camera = enabledElement.viewport.getCamera();
|
|
1295
|
+
const normal = [...camera.viewPlaneNormal];
|
|
1296
|
+
const point = [...camera.focalPoint];
|
|
1297
|
+
if (!this._isFinitePoint3(normal) || !this._isFinitePoint3(point)) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
vec3.normalize(normal, normal);
|
|
1301
|
+
const alreadyTracked = uniquePlanes.some((plane) => csUtils.isEqual(plane.normal, normal, 1e-3) ||
|
|
1302
|
+
csUtils.isOpposite(plane.normal, normal, 1e-3));
|
|
1303
|
+
if (!alreadyTracked) {
|
|
1304
|
+
uniquePlanes.push({ normal, point });
|
|
1305
|
+
}
|
|
1306
|
+
});
|
|
1307
|
+
if (uniquePlanes.length < 2) {
|
|
1308
|
+
return null;
|
|
1309
|
+
}
|
|
1310
|
+
const firstPlane = csUtils.planar.planeEquation(uniquePlanes[0].normal, uniquePlanes[0].point);
|
|
1311
|
+
const secondPlane = csUtils.planar.planeEquation(uniquePlanes[1].normal, uniquePlanes[1].point);
|
|
1312
|
+
let thirdPlane;
|
|
1313
|
+
if (uniquePlanes.length >= 3) {
|
|
1314
|
+
thirdPlane = csUtils.planar.planeEquation(uniquePlanes[2].normal, uniquePlanes[2].point);
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
const thirdNormal = vec3.create();
|
|
1318
|
+
vec3.cross(thirdNormal, uniquePlanes[0].normal, uniquePlanes[1].normal);
|
|
1319
|
+
if (vec3.length(thirdNormal) < 1e-6) {
|
|
1320
|
+
return null;
|
|
1321
|
+
}
|
|
1322
|
+
vec3.normalize(thirdNormal, thirdNormal);
|
|
1323
|
+
const thirdPoint = this._isFinitePoint3(this.toolCenter)
|
|
1324
|
+
? [...this.toolCenter]
|
|
1325
|
+
: [
|
|
1326
|
+
(uniquePlanes[0].point[0] + uniquePlanes[1].point[0]) * 0.5,
|
|
1327
|
+
(uniquePlanes[0].point[1] + uniquePlanes[1].point[1]) * 0.5,
|
|
1328
|
+
(uniquePlanes[0].point[2] + uniquePlanes[1].point[2]) * 0.5,
|
|
1329
|
+
];
|
|
1330
|
+
thirdPlane = csUtils.planar.planeEquation(thirdNormal, thirdPoint);
|
|
1331
|
+
}
|
|
1332
|
+
const center = csUtils.planar.threePlaneIntersection(firstPlane, secondPlane, thirdPlane);
|
|
1333
|
+
return this._isFinitePoint3(center) ? center : null;
|
|
1334
|
+
};
|
|
1335
|
+
this._recomputeToolCenterFromAbsoluteCameras = ({ emitEvent = true, updateViewportCameras = false, } = {}) => {
|
|
1336
|
+
const toolCenter = this._calculateToolCenterFromAbsoluteCameras();
|
|
1337
|
+
if (!toolCenter) {
|
|
1338
|
+
return null;
|
|
1339
|
+
}
|
|
1340
|
+
const hasChanged = !csUtils.isEqual(this.toolCenter, toolCenter, 1e-3);
|
|
1341
|
+
if (!hasChanged) {
|
|
1342
|
+
return toolCenter;
|
|
1343
|
+
}
|
|
1344
|
+
if (updateViewportCameras) {
|
|
1345
|
+
this.setToolCenter(toolCenter, !emitEvent);
|
|
1346
|
+
}
|
|
1347
|
+
else {
|
|
1348
|
+
this.toolCenter = toolCenter;
|
|
1349
|
+
if (emitEvent) {
|
|
1350
|
+
triggerEvent(eventTarget, Events.CROSSHAIR_TOOL_CENTER_CHANGED, {
|
|
1351
|
+
toolGroupId: this.toolGroupId,
|
|
1352
|
+
toolCenter: this.toolCenter,
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
return toolCenter;
|
|
1357
|
+
};
|
|
1159
1358
|
this._getReferenceLineColor =
|
|
1160
1359
|
toolProps.configuration?.getReferenceLineColor ||
|
|
1161
1360
|
defaultReferenceLineColor;
|
|
@@ -1170,22 +1369,21 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1170
1369
|
defaultReferenceLineSlabThicknessControlsOn;
|
|
1171
1370
|
}
|
|
1172
1371
|
onSetToolActive() {
|
|
1173
|
-
|
|
1174
|
-
this._unsubscribeToViewportNewVolumeSet(viewportsInfo);
|
|
1175
|
-
this._subscribeToViewportNewVolumeSet(viewportsInfo);
|
|
1176
|
-
this._computeToolCenter(viewportsInfo);
|
|
1372
|
+
this._reinitializeListenersAndCenter();
|
|
1177
1373
|
}
|
|
1178
1374
|
onSetToolPassive() {
|
|
1179
|
-
|
|
1180
|
-
this._computeToolCenter(viewportsInfo);
|
|
1375
|
+
this._reinitializeListenersAndCenter();
|
|
1181
1376
|
}
|
|
1182
1377
|
onSetToolEnabled() {
|
|
1183
|
-
|
|
1184
|
-
this._computeToolCenter(viewportsInfo);
|
|
1378
|
+
this._reinitializeListenersAndCenter();
|
|
1185
1379
|
}
|
|
1186
1380
|
onSetToolDisabled() {
|
|
1187
1381
|
const viewportsInfo = this._getViewportsInfo();
|
|
1188
|
-
this.
|
|
1382
|
+
this._unbindToolGroupViewportListeners();
|
|
1383
|
+
this._clearAllVolumeListenersAndViewportState();
|
|
1384
|
+
this._ignoreFiredEvents = false;
|
|
1385
|
+
this.editData = null;
|
|
1386
|
+
state.isInteractingWithTool = false;
|
|
1189
1387
|
viewportsInfo.forEach(({ renderingEngineId, viewportId }) => {
|
|
1190
1388
|
const enabledElement = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
1191
1389
|
if (!enabledElement) {
|
|
@@ -1201,40 +1399,53 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1201
1399
|
}
|
|
1202
1400
|
setToolCenter(toolCenter, suppressEvents = false) {
|
|
1203
1401
|
const viewportsInfo = this._getViewportsInfo();
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1402
|
+
const previousIgnoreFiredEvents = this._ignoreFiredEvents;
|
|
1403
|
+
this._ignoreFiredEvents = true;
|
|
1404
|
+
try {
|
|
1405
|
+
viewportsInfo.forEach(({ renderingEngineId, viewportId }) => {
|
|
1406
|
+
const renderingEngine = getRenderingEngine(renderingEngineId);
|
|
1407
|
+
if (!renderingEngine) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const viewport = renderingEngine.getViewport(viewportId);
|
|
1411
|
+
if (!viewport) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
const camera = viewport.getCamera();
|
|
1415
|
+
const { focalPoint, position, viewPlaneNormal } = camera;
|
|
1416
|
+
const delta = [
|
|
1417
|
+
toolCenter[0] - focalPoint[0],
|
|
1418
|
+
toolCenter[1] - focalPoint[1],
|
|
1419
|
+
toolCenter[2] - focalPoint[2],
|
|
1420
|
+
];
|
|
1421
|
+
const scroll = delta[0] * viewPlaneNormal[0] +
|
|
1422
|
+
delta[1] * viewPlaneNormal[1] +
|
|
1423
|
+
delta[2] * viewPlaneNormal[2];
|
|
1424
|
+
const scrollDelta = [
|
|
1425
|
+
scroll * viewPlaneNormal[0],
|
|
1426
|
+
scroll * viewPlaneNormal[1],
|
|
1427
|
+
scroll * viewPlaneNormal[2],
|
|
1428
|
+
];
|
|
1429
|
+
const newFocalPoint = [
|
|
1430
|
+
focalPoint[0] + scrollDelta[0],
|
|
1431
|
+
focalPoint[1] + scrollDelta[1],
|
|
1432
|
+
focalPoint[2] + scrollDelta[2],
|
|
1433
|
+
];
|
|
1434
|
+
const newPosition = [
|
|
1435
|
+
position[0] + scrollDelta[0],
|
|
1436
|
+
position[1] + scrollDelta[1],
|
|
1437
|
+
position[2] + scrollDelta[2],
|
|
1438
|
+
];
|
|
1439
|
+
viewport.setCamera({
|
|
1440
|
+
focalPoint: newFocalPoint,
|
|
1441
|
+
position: newPosition,
|
|
1442
|
+
});
|
|
1443
|
+
viewport.render();
|
|
1235
1444
|
});
|
|
1236
|
-
|
|
1237
|
-
|
|
1445
|
+
}
|
|
1446
|
+
finally {
|
|
1447
|
+
this._ignoreFiredEvents = previousIgnoreFiredEvents;
|
|
1448
|
+
}
|
|
1238
1449
|
this.toolCenter = toolCenter;
|
|
1239
1450
|
if (!suppressEvents) {
|
|
1240
1451
|
triggerEvent(eventTarget, Events.CROSSHAIR_TOOL_CENTER_CHANGED, {
|
|
@@ -1255,19 +1466,11 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1255
1466
|
return point;
|
|
1256
1467
|
}
|
|
1257
1468
|
}
|
|
1258
|
-
_unsubscribeToViewportNewVolumeSet(
|
|
1259
|
-
|
|
1260
|
-
const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
1261
|
-
const { element } = viewport;
|
|
1262
|
-
element.removeEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, this._onNewVolume);
|
|
1263
|
-
});
|
|
1469
|
+
_unsubscribeToViewportNewVolumeSet(_viewportsInfo) {
|
|
1470
|
+
this._syncVolumeListenersWithToolGroup();
|
|
1264
1471
|
}
|
|
1265
|
-
_subscribeToViewportNewVolumeSet(
|
|
1266
|
-
|
|
1267
|
-
const { viewport } = getEnabledElementByIds(viewportId, renderingEngineId);
|
|
1268
|
-
const { element } = viewport;
|
|
1269
|
-
element.addEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, this._onNewVolume);
|
|
1270
|
-
});
|
|
1472
|
+
_subscribeToViewportNewVolumeSet(_viewports) {
|
|
1473
|
+
this._syncVolumeListenersWithToolGroup();
|
|
1271
1474
|
}
|
|
1272
1475
|
_autoPanViewportIfNecessary(viewportId, renderingEngine) {
|
|
1273
1476
|
const viewport = renderingEngine.getViewport(viewportId);
|
|
@@ -1312,10 +1515,17 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1312
1515
|
focalPoint[1] - deltaPointsWorld[1],
|
|
1313
1516
|
focalPoint[2] - deltaPointsWorld[2],
|
|
1314
1517
|
];
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1518
|
+
const previousIgnoreFiredEvents = this._ignoreFiredEvents;
|
|
1519
|
+
this._ignoreFiredEvents = true;
|
|
1520
|
+
try {
|
|
1521
|
+
viewport.setCamera({
|
|
1522
|
+
focalPoint: updatedFocalPoint,
|
|
1523
|
+
position: updatedPosition,
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
finally {
|
|
1527
|
+
this._ignoreFiredEvents = previousIgnoreFiredEvents;
|
|
1528
|
+
}
|
|
1319
1529
|
viewport.render();
|
|
1320
1530
|
}
|
|
1321
1531
|
setSlabThickness(viewport, slabThickness) {
|
|
@@ -1356,10 +1566,17 @@ class CrosshairsTool extends AnnotationTool {
|
|
|
1356
1566
|
const newPosition = [0, 0, 0];
|
|
1357
1567
|
vtkMath.add(camera.focalPoint, projectedDelta, newFocalPoint);
|
|
1358
1568
|
vtkMath.add(camera.position, projectedDelta, newPosition);
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1569
|
+
const previousIgnoreFiredEvents = this._ignoreFiredEvents;
|
|
1570
|
+
this._ignoreFiredEvents = true;
|
|
1571
|
+
try {
|
|
1572
|
+
viewport.setCamera({
|
|
1573
|
+
focalPoint: newFocalPoint,
|
|
1574
|
+
position: newPosition,
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
finally {
|
|
1578
|
+
this._ignoreFiredEvents = previousIgnoreFiredEvents;
|
|
1579
|
+
}
|
|
1363
1580
|
viewport.render();
|
|
1364
1581
|
}
|
|
1365
1582
|
}
|
|
@@ -298,31 +298,40 @@ class ProbeTool extends AnnotationTool {
|
|
|
298
298
|
continue;
|
|
299
299
|
}
|
|
300
300
|
const { dimensions, imageData, metadata, voxelManager } = image;
|
|
301
|
-
const modality = metadata
|
|
301
|
+
const modality = metadata?.Modality;
|
|
302
302
|
let ijk = transformWorldToIndex(imageData, worldPos);
|
|
303
303
|
ijk = vec3.round(ijk, ijk);
|
|
304
304
|
if (csUtils.indexWithinDimensions(ijk, dimensions)) {
|
|
305
305
|
this.isHandleOutsideImage = false;
|
|
306
|
-
|
|
307
|
-
if (targetId.startsWith('imageId:')) {
|
|
306
|
+
if (targetId.startsWith('imageId:') && modality !== 'ECG') {
|
|
308
307
|
const imageId = targetId.split('imageId:')[1];
|
|
309
308
|
const imageURI = csUtils.imageIdToURI(imageId);
|
|
310
309
|
const viewports = csUtils.getViewportsWithImageURI(imageURI);
|
|
311
310
|
const viewport = viewports[0];
|
|
312
311
|
ijk[2] = viewport.getCurrentImageIdIndex();
|
|
313
312
|
}
|
|
313
|
+
let value;
|
|
314
314
|
let modalityUnit;
|
|
315
|
-
if (modality === '
|
|
315
|
+
if (modality === 'ECG') {
|
|
316
316
|
const calibratedResults = getCalibratedProbeUnitsAndValue(image, [
|
|
317
317
|
ijk,
|
|
318
318
|
]);
|
|
319
|
-
|
|
319
|
+
value = calibratedResults.values;
|
|
320
|
+
modalityUnit = calibratedResults.units;
|
|
321
|
+
}
|
|
322
|
+
else if (modality === 'US') {
|
|
323
|
+
value = voxelManager?.getAtIJKPoint(ijk);
|
|
324
|
+
const calibratedResults = getCalibratedProbeUnitsAndValue(image, [
|
|
325
|
+
ijk,
|
|
326
|
+
]);
|
|
327
|
+
const hasEnhancedRegionValues = calibratedResults.values.every((v) => v !== null);
|
|
320
328
|
value = (hasEnhancedRegionValues ? calibratedResults.values : value);
|
|
321
329
|
modalityUnit = hasEnhancedRegionValues
|
|
322
330
|
? calibratedResults.units
|
|
323
331
|
: 'raw';
|
|
324
332
|
}
|
|
325
333
|
else {
|
|
334
|
+
value = voxelManager?.getAtIJKPoint(ijk);
|
|
326
335
|
modalityUnit = getPixelValueUnits(modality, annotation.metadata.referencedImageId, pixelUnitsOptions);
|
|
327
336
|
}
|
|
328
337
|
cachedStats[targetId] = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChangeTypes, Events } from '../../enums';
|
|
2
|
-
import { getEnabledElement, utilities as csUtils, StackViewport, } from '@cornerstonejs/core';
|
|
2
|
+
import { getEnabledElement, utilities as csUtils, StackViewport, ECGViewport, } from '@cornerstonejs/core';
|
|
3
3
|
import { AnnotationTool } from '../base';
|
|
4
4
|
import throttle from '../../utilities/throttle';
|
|
5
5
|
import { addAnnotation, getAnnotations, removeAnnotation, } from '../../stateManagement/annotation/annotationState';
|
|
@@ -35,8 +35,9 @@ class UltrasoundDirectionalTool extends AnnotationTool {
|
|
|
35
35
|
const worldPos = currentPoints.world;
|
|
36
36
|
const enabledElement = getEnabledElement(element);
|
|
37
37
|
const { viewport } = enabledElement;
|
|
38
|
-
if (!(viewport instanceof StackViewport)
|
|
39
|
-
|
|
38
|
+
if (!(viewport instanceof StackViewport) &&
|
|
39
|
+
!(viewport instanceof ECGViewport)) {
|
|
40
|
+
throw new Error('UltrasoundDirectionalTool can only be used on a StackViewport or ECGViewport');
|
|
40
41
|
}
|
|
41
42
|
hideElementCursor(element);
|
|
42
43
|
this.isDrawing = true;
|
|
@@ -11,6 +11,7 @@ const SUPPORTED_REGION_DATA_TYPES = [
|
|
|
11
11
|
const SUPPORTED_PROBE_VARIANT = [
|
|
12
12
|
'4,3',
|
|
13
13
|
'4,7',
|
|
14
|
+
'4,-1',
|
|
14
15
|
];
|
|
15
16
|
const UNIT_MAPPING = {
|
|
16
17
|
0: 'px',
|
|
@@ -24,6 +25,7 @@ const UNIT_MAPPING = {
|
|
|
24
25
|
8: 'cm\xb2',
|
|
25
26
|
9: 'cm\xb2/s',
|
|
26
27
|
0xc: 'degrees',
|
|
28
|
+
[-1]: 'mV',
|
|
27
29
|
};
|
|
28
30
|
const EPS = 1e-3;
|
|
29
31
|
const SQUARE = '\xb2';
|
|
@@ -66,7 +68,9 @@ const getCalibratedLengthUnitsAndScale = (image, handles) => {
|
|
|
66
68
|
const region = calibration.sequenceOfUltrasoundRegions.find((region) => handles.every((handle) => handle[0] >= region.regionLocationMinX0 &&
|
|
67
69
|
handle[0] <= region.regionLocationMaxX1 &&
|
|
68
70
|
handle[1] >= region.regionLocationMinY0 &&
|
|
69
|
-
handle[1] <= region.regionLocationMaxY1) &&
|
|
71
|
+
handle[1] <= region.regionLocationMaxY1) &&
|
|
72
|
+
(SUPPORTED_REGION_DATA_TYPES.includes(region.regionDataType) ||
|
|
73
|
+
SUPPORTED_PROBE_VARIANT.includes(`${region.physicalUnitsXDirection},${region.physicalUnitsYDirection}`)));
|
|
70
74
|
if (region &&
|
|
71
75
|
region.physicalUnitsXDirection === region.physicalUnitsYDirection) {
|
|
72
76
|
const physicalDeltaX = Math.abs(region.physicalDeltaX);
|
|
@@ -77,6 +81,19 @@ const getCalibratedLengthUnitsAndScale = (image, handles) => {
|
|
|
77
81
|
unit = UNIT_MAPPING[region.physicalUnitsXDirection] || 'unknown';
|
|
78
82
|
areaUnit = unit + SQUARE;
|
|
79
83
|
}
|
|
84
|
+
else if (region && region.physicalUnitsYDirection === -1) {
|
|
85
|
+
const physicalDeltaX = Math.abs(region.physicalDeltaX);
|
|
86
|
+
const physicalDeltaY = Math.abs(region.physicalDeltaY);
|
|
87
|
+
scale = 1 / physicalDeltaX;
|
|
88
|
+
scaleY = 1 / physicalDeltaY;
|
|
89
|
+
calibrationType = 'ECG Region';
|
|
90
|
+
unit =
|
|
91
|
+
UNIT_MAPPING[region.physicalUnitsXDirection] ||
|
|
92
|
+
UNIT_MAPPING[region.physicalUnitsYDirection] ||
|
|
93
|
+
'unknown';
|
|
94
|
+
areaUnit =
|
|
95
|
+
(UNIT_MAPPING[region.physicalUnitsYDirection] || 'px') + SQUARE;
|
|
96
|
+
}
|
|
80
97
|
}
|
|
81
98
|
else if (calibration.scale) {
|
|
82
99
|
scale = calibration.scale;
|
|
@@ -101,7 +118,8 @@ const getCalibratedProbeUnitsAndValue = (image, handles) => {
|
|
|
101
118
|
return { units, values };
|
|
102
119
|
}
|
|
103
120
|
if (calibration.sequenceOfUltrasoundRegions) {
|
|
104
|
-
const supportedRegionsMetadata = calibration.sequenceOfUltrasoundRegions.filter((region) => SUPPORTED_REGION_DATA_TYPES.includes(region.regionDataType)
|
|
121
|
+
const supportedRegionsMetadata = calibration.sequenceOfUltrasoundRegions.filter((region) => (SUPPORTED_REGION_DATA_TYPES.includes(region.regionDataType) ||
|
|
122
|
+
SUPPORTED_PROBE_VARIANT.includes(`${region.physicalUnitsXDirection},${region.physicalUnitsYDirection}`)) &&
|
|
105
123
|
SUPPORTED_PROBE_VARIANT.includes(`${region.physicalUnitsXDirection},${region.physicalUnitsYDirection}`));
|
|
106
124
|
if (!supportedRegionsMetadata?.length) {
|
|
107
125
|
return { units, values };
|
|
@@ -119,11 +137,12 @@ const getCalibratedProbeUnitsAndValue = (image, handles) => {
|
|
|
119
137
|
physicalDeltaY;
|
|
120
138
|
const xValue = (imageIndex[0] - region.regionLocationMinX0 - referencePixelX0) *
|
|
121
139
|
physicalDeltaX;
|
|
122
|
-
calibrationType =
|
|
140
|
+
calibrationType =
|
|
141
|
+
region.physicalUnitsYDirection === -1 ? 'ECG Region' : 'US Region';
|
|
123
142
|
values = [xValue, yValue];
|
|
124
143
|
units = [
|
|
125
|
-
UNIT_MAPPING[region.physicalUnitsXDirection],
|
|
126
|
-
UNIT_MAPPING[region.physicalUnitsYDirection],
|
|
144
|
+
UNIT_MAPPING[region.physicalUnitsXDirection] ?? 'unknown',
|
|
145
|
+
UNIT_MAPPING[region.physicalUnitsYDirection] ?? 'unknown',
|
|
127
146
|
];
|
|
128
147
|
}
|
|
129
148
|
return {
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "4.
|
|
1
|
+
export declare const version = "4.18.0";
|
package/dist/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '4.
|
|
1
|
+
export const version = '4.18.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.18.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.
|
|
111
|
+
"@cornerstonejs/core": "4.18.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": "
|
|
130
|
+
"gitHead": "7f4a99858ac39083fb1aeab650002ec7d33e3d58"
|
|
131
131
|
}
|