@cornerstonejs/tools 1.9.3 → 1.10.1
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/enums/Events.d.ts +1 -0
- package/dist/cjs/enums/Events.js +1 -0
- package/dist/cjs/enums/Events.js.map +1 -1
- package/dist/cjs/eventDispatchers/shared/getMouseModifier.js +10 -5
- package/dist/cjs/eventDispatchers/shared/getMouseModifier.js.map +1 -1
- package/dist/cjs/eventListeners/mouse/mouseDownListener.js +2 -1
- package/dist/cjs/eventListeners/mouse/mouseDownListener.js.map +1 -1
- package/dist/cjs/eventListeners/touch/touchStartListener.js +10 -5
- package/dist/cjs/eventListeners/touch/touchStartListener.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/config/getState.js +6 -3
- package/dist/cjs/stateManagement/annotation/config/getState.js.map +1 -1
- package/dist/cjs/stateManagement/annotation/config/helpers.js +4 -2
- package/dist/cjs/stateManagement/annotation/config/helpers.js.map +1 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js +8 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/cjs/store/ToolGroupManager/getToolGroupsWithToolName.js +2 -1
- package/dist/cjs/store/ToolGroupManager/getToolGroupsWithToolName.js.map +1 -1
- package/dist/cjs/tools/MIPJumpToClickTool.js +4 -2
- package/dist/cjs/tools/MIPJumpToClickTool.js.map +1 -1
- package/dist/cjs/tools/PlanarRotateTool.js +2 -1
- package/dist/cjs/tools/PlanarRotateTool.js.map +1 -1
- package/dist/cjs/tools/ReferenceCursors.js +58 -29
- package/dist/cjs/tools/ReferenceCursors.js.map +1 -1
- package/dist/cjs/tools/ScaleOverlayTool.js +2 -1
- package/dist/cjs/tools/ScaleOverlayTool.js.map +1 -1
- package/dist/cjs/tools/annotation/AngleTool.js +4 -2
- package/dist/cjs/tools/annotation/AngleTool.js.map +1 -1
- package/dist/cjs/tools/annotation/CircleROITool.js +2 -1
- package/dist/cjs/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js +6 -3
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/cjs/tools/segmentation/PaintFillTool.js +4 -2
- package/dist/cjs/tools/segmentation/PaintFillTool.js.map +1 -1
- package/dist/cjs/types/EventTypes.d.ts +8 -1
- package/dist/cjs/types/ISetToolModeOptions.d.ts +2 -2
- package/dist/cjs/utilities/cine/playClip.js +2 -1
- package/dist/cjs/utilities/cine/playClip.js.map +1 -1
- package/dist/cjs/utilities/getCalibratedUnits.js +10 -5
- package/dist/cjs/utilities/getCalibratedUnits.js.map +1 -1
- package/dist/cjs/utilities/math/midPoint.js +2 -1
- package/dist/cjs/utilities/math/midPoint.js.map +1 -1
- package/dist/cjs/utilities/math/polyline/pointInPolyline.js +2 -1
- package/dist/cjs/utilities/math/polyline/pointInPolyline.js.map +1 -1
- package/dist/cjs/utilities/math/vec2/liangBarksyClip.js +10 -5
- package/dist/cjs/utilities/math/vec2/liangBarksyClip.js.map +1 -1
- package/dist/cjs/utilities/roundNumber.js +4 -2
- package/dist/cjs/utilities/roundNumber.js.map +1 -1
- package/dist/cjs/utilities/segmentation/thresholdVolumeByRange.js +2 -1
- package/dist/cjs/utilities/segmentation/thresholdVolumeByRange.js.map +1 -1
- package/dist/esm/enums/Events.d.ts +1 -0
- package/dist/esm/enums/Events.js +1 -0
- package/dist/esm/enums/Events.js.map +1 -1
- package/dist/esm/eventDispatchers/shared/getMouseModifier.js +10 -5
- package/dist/esm/eventDispatchers/shared/getMouseModifier.js.map +1 -1
- package/dist/esm/eventListeners/mouse/mouseDownListener.js +2 -1
- package/dist/esm/eventListeners/mouse/mouseDownListener.js.map +1 -1
- package/dist/esm/eventListeners/touch/touchStartListener.js +10 -5
- package/dist/esm/eventListeners/touch/touchStartListener.js.map +1 -1
- package/dist/esm/stateManagement/annotation/config/getState.js +6 -3
- package/dist/esm/stateManagement/annotation/config/getState.js.map +1 -1
- package/dist/esm/stateManagement/annotation/config/helpers.js +4 -2
- package/dist/esm/stateManagement/annotation/config/helpers.js.map +1 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.js +9 -2
- package/dist/esm/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/esm/store/ToolGroupManager/getToolGroupsWithToolName.js +2 -1
- package/dist/esm/store/ToolGroupManager/getToolGroupsWithToolName.js.map +1 -1
- package/dist/esm/tools/MIPJumpToClickTool.js +4 -2
- package/dist/esm/tools/MIPJumpToClickTool.js.map +1 -1
- package/dist/esm/tools/PlanarRotateTool.js +2 -1
- package/dist/esm/tools/PlanarRotateTool.js.map +1 -1
- package/dist/esm/tools/ReferenceCursors.js +58 -29
- package/dist/esm/tools/ReferenceCursors.js.map +1 -1
- package/dist/esm/tools/ScaleOverlayTool.js +2 -1
- package/dist/esm/tools/ScaleOverlayTool.js.map +1 -1
- package/dist/esm/tools/annotation/AngleTool.js +4 -2
- package/dist/esm/tools/annotation/AngleTool.js.map +1 -1
- package/dist/esm/tools/annotation/CircleROITool.js +2 -1
- package/dist/esm/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +6 -3
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/esm/tools/segmentation/PaintFillTool.js +4 -2
- package/dist/esm/tools/segmentation/PaintFillTool.js.map +1 -1
- package/dist/esm/types/EventTypes.d.ts +8 -1
- package/dist/esm/types/ISetToolModeOptions.d.ts +2 -2
- package/dist/esm/utilities/cine/playClip.js +2 -1
- package/dist/esm/utilities/cine/playClip.js.map +1 -1
- package/dist/esm/utilities/getCalibratedUnits.js +10 -5
- package/dist/esm/utilities/getCalibratedUnits.js.map +1 -1
- package/dist/esm/utilities/math/midPoint.js +2 -1
- package/dist/esm/utilities/math/midPoint.js.map +1 -1
- package/dist/esm/utilities/math/polyline/pointInPolyline.js +2 -1
- package/dist/esm/utilities/math/polyline/pointInPolyline.js.map +1 -1
- package/dist/esm/utilities/math/vec2/liangBarksyClip.js +10 -5
- package/dist/esm/utilities/math/vec2/liangBarksyClip.js.map +1 -1
- package/dist/esm/utilities/roundNumber.js +4 -2
- package/dist/esm/utilities/roundNumber.js.map +1 -1
- package/dist/esm/utilities/segmentation/thresholdVolumeByRange.js +2 -1
- package/dist/esm/utilities/segmentation/thresholdVolumeByRange.js.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/enums/Events.ts +13 -0
- package/src/eventDispatchers/shared/getMouseModifier.ts +15 -5
- package/src/eventListeners/mouse/mouseDownListener.ts +3 -1
- package/src/eventListeners/touch/touchStartListener.ts +15 -5
- package/src/stateManagement/annotation/config/getState.ts +7 -3
- package/src/stateManagement/annotation/config/helpers.ts +6 -2
- package/src/store/ToolGroupManager/ToolGroup.ts +13 -1
- package/src/store/ToolGroupManager/getToolGroupsWithToolName.ts +3 -1
- package/src/tools/MIPJumpToClickTool.ts +6 -2
- package/src/tools/PlanarRotateTool.ts +3 -1
- package/src/tools/ReferenceCursors.ts +85 -29
- package/src/tools/ScaleOverlayTool.ts +3 -1
- package/src/tools/annotation/AngleTool.ts +6 -2
- package/src/tools/annotation/CircleROITool.ts +3 -1
- package/src/tools/annotation/PlanarFreehandROITool.ts +8 -3
- package/src/tools/segmentation/PaintFillTool.ts +6 -2
- package/src/types/EventTypes.ts +20 -0
- package/src/types/ISetToolModeOptions.ts +2 -2
- package/src/utilities/cine/playClip.ts +3 -1
- package/src/utilities/getCalibratedUnits.ts +15 -5
- package/src/utilities/math/midPoint.ts +3 -1
- package/src/utilities/math/polyline/pointInPolyline.ts +3 -1
- package/src/utilities/math/vec2/liangBarksyClip.ts +15 -5
- package/src/utilities/roundNumber.ts +6 -2
- package/src/utilities/segmentation/thresholdVolumeByRange.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/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.
|
|
32
|
+
"@cornerstonejs/core": "^1.10.1",
|
|
33
33
|
"lodash.clonedeep": "4.5.0",
|
|
34
34
|
"lodash.get": "^4.4.2"
|
|
35
35
|
},
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"type": "individual",
|
|
53
53
|
"url": "https://ohif.org/donate"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "d5dfd002158723322adb328e32bc8637b8035dea"
|
|
56
56
|
}
|
package/src/enums/Events.ts
CHANGED
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
enum Events {
|
|
8
|
+
///////////////////////////////////////
|
|
9
|
+
// Tools
|
|
10
|
+
///////////////////////////////////////
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Triggers on the eventTarget when a new tools is activated.
|
|
14
|
+
*
|
|
15
|
+
* Make use of {@link EventTypes.ToolActivatedEventType | Tool Activated Event Type }
|
|
16
|
+
* for typing your event listeners for this tool activated event, and see what event
|
|
17
|
+
* detail is included in {@link EventTypes.ToolActivatedEventDetail | Tool Activated Event Detail}.
|
|
18
|
+
*/
|
|
19
|
+
TOOL_ACTIVATED = 'CORNERSTONE_TOOLS_TOOL_ACTIVATED',
|
|
20
|
+
|
|
8
21
|
///////////////////////////////////////
|
|
9
22
|
// Annotations
|
|
10
23
|
///////////////////////////////////////
|
|
@@ -8,14 +8,24 @@ import { KeyboardBindings as kb } from '../../enums';
|
|
|
8
8
|
const getMouseModifierKey = (evt) => {
|
|
9
9
|
// The logic is a hard coded key mapping
|
|
10
10
|
if (evt.shiftKey) {
|
|
11
|
-
if (evt.ctrlKey)
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (evt.ctrlKey) {
|
|
12
|
+
return kb.ShiftCtrl;
|
|
13
|
+
}
|
|
14
|
+
if (evt.altKey) {
|
|
15
|
+
return kb.ShiftAlt;
|
|
16
|
+
}
|
|
17
|
+
if (evt.metaKey) {
|
|
18
|
+
return kb.ShiftMeta;
|
|
19
|
+
}
|
|
14
20
|
return kb.Shift;
|
|
15
21
|
}
|
|
16
22
|
if (evt.ctrlKey) {
|
|
17
|
-
if (evt.altKey)
|
|
18
|
-
|
|
23
|
+
if (evt.altKey) {
|
|
24
|
+
return kb.CtrlAlt;
|
|
25
|
+
}
|
|
26
|
+
if (evt.metaKey) {
|
|
27
|
+
return kb.CtrlMeta;
|
|
28
|
+
}
|
|
19
29
|
return kb.Ctrl;
|
|
20
30
|
}
|
|
21
31
|
if (evt.altKey) {
|
|
@@ -129,7 +129,9 @@ const doubleClickState: IDoubleClickState = {
|
|
|
129
129
|
function mouseDownListener(evt: MouseEvent) {
|
|
130
130
|
if (doubleClickState.doubleClickTimeout) {
|
|
131
131
|
// A second identical click will be a double click event, so ignore it
|
|
132
|
-
if (evt.buttons === doubleClickState.mouseDownEvent.buttons)
|
|
132
|
+
if (evt.buttons === doubleClickState.mouseDownEvent.buttons) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
133
135
|
|
|
134
136
|
// Record the second button or the changed button event as the initial
|
|
135
137
|
// button down state so that the multi-button event can be detected
|
|
@@ -168,7 +168,9 @@ function touchStartListener(evt: TouchEvent) {
|
|
|
168
168
|
state.renderingEngineId = renderingEngineId;
|
|
169
169
|
state.viewportId = viewportId;
|
|
170
170
|
// this prevents multiple start firing
|
|
171
|
-
if (state.isTouchStart)
|
|
171
|
+
if (state.isTouchStart) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
172
174
|
// this will clear on touchstart and touchend
|
|
173
175
|
clearTimeout(state.pressTimeout);
|
|
174
176
|
state.pressTimeout = setTimeout(() => _onTouchPress(evt), state.pressDelay);
|
|
@@ -187,7 +189,9 @@ function touchStartListener(evt: TouchEvent) {
|
|
|
187
189
|
*/
|
|
188
190
|
function _onTouchPress(evt: TouchEvent) {
|
|
189
191
|
const totalDistance = state.accumulatedDistance.canvas;
|
|
190
|
-
if (totalDistance > state.pressMaxDistance)
|
|
192
|
+
if (totalDistance > state.pressMaxDistance) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
191
195
|
const eventDetail: EventTypes.TouchPressEventDetail = {
|
|
192
196
|
event: evt, // touchstart native event
|
|
193
197
|
eventName: TOUCH_PRESS,
|
|
@@ -384,7 +388,9 @@ function _onTouchEnd(evt: TouchEvent): void {
|
|
|
384
388
|
function _checkTouchTap(evt: TouchEvent): void {
|
|
385
389
|
const currentTime = new Date().getTime();
|
|
386
390
|
const startTime = state.startTime.getTime();
|
|
387
|
-
if (currentTime - startTime > tapState.tapToleranceMs)
|
|
391
|
+
if (currentTime - startTime > tapState.tapToleranceMs) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
388
394
|
|
|
389
395
|
// first tap, initialize the state
|
|
390
396
|
if (tapState.taps === 0) {
|
|
@@ -422,7 +428,9 @@ function _checkTouchTap(evt: TouchEvent): void {
|
|
|
422
428
|
// region where the user has the option to perform unlimited multitaps as long
|
|
423
429
|
// as they are < the tapToleranceMs value. So a tap somewhere else on the screen
|
|
424
430
|
// that is > the tapMaxDistance will start a separate and new "TapChain".
|
|
425
|
-
if (distanceFromStart > tapState.tapMaxDistance)
|
|
431
|
+
if (distanceFromStart > tapState.tapMaxDistance) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
426
434
|
|
|
427
435
|
clearTimeout(tapState.tapTimeout);
|
|
428
436
|
tapState.taps += 1;
|
|
@@ -447,7 +455,9 @@ function _checkTouchTap(evt: TouchEvent): void {
|
|
|
447
455
|
function _checkTouchSwipe(evt: TouchEvent, deltaPoints: IPoints) {
|
|
448
456
|
const currentTime = new Date().getTime();
|
|
449
457
|
const startTime = state.startTime.getTime();
|
|
450
|
-
if (state.swiped || currentTime - startTime > state.swipeToleranceMs)
|
|
458
|
+
if (state.swiped || currentTime - startTime > state.swipeToleranceMs) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
451
461
|
const [x, y] = deltaPoints.canvas;
|
|
452
462
|
const eventDetail: EventTypes.TouchSwipeEventDetail = {
|
|
453
463
|
event: evt,
|
|
@@ -11,13 +11,17 @@ import { AnnotationStyleStates } from '../../../enums';
|
|
|
11
11
|
*/
|
|
12
12
|
function getState(annotation?: Annotation): AnnotationStyleStates {
|
|
13
13
|
if (annotation) {
|
|
14
|
-
if (annotation.data && annotation.highlighted)
|
|
14
|
+
if (annotation.data && annotation.highlighted) {
|
|
15
15
|
return AnnotationStyleStates.Highlighted;
|
|
16
|
-
|
|
16
|
+
}
|
|
17
|
+
if (isAnnotationSelected(annotation.annotationUID)) {
|
|
17
18
|
return AnnotationStyleStates.Selected;
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
// Todo: make annotation lock api not to rely on the annotation itself
|
|
20
|
-
if (isAnnotationLocked(annotation))
|
|
22
|
+
if (isAnnotationLocked(annotation)) {
|
|
23
|
+
return AnnotationStyleStates.Locked;
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
return AnnotationStyleStates.Default;
|
|
@@ -15,8 +15,12 @@ function getHierarchalPropertyStyles(
|
|
|
15
15
|
mode?: ToolModes
|
|
16
16
|
): string[] {
|
|
17
17
|
const list = [`${property}`];
|
|
18
|
-
if (state)
|
|
19
|
-
|
|
18
|
+
if (state) {
|
|
19
|
+
list.push(`${list[0]}${state}`);
|
|
20
|
+
}
|
|
21
|
+
if (mode) {
|
|
22
|
+
list.push(`${list[list.length - 1]}${mode}`);
|
|
23
|
+
}
|
|
20
24
|
return list;
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -2,6 +2,8 @@ import { MouseBindings, ToolModes } from '../../enums';
|
|
|
2
2
|
import cloneDeep from 'lodash.clonedeep';
|
|
3
3
|
import get from 'lodash.get';
|
|
4
4
|
import {
|
|
5
|
+
triggerEvent,
|
|
6
|
+
eventTarget,
|
|
5
7
|
getRenderingEngine,
|
|
6
8
|
getRenderingEngines,
|
|
7
9
|
getEnabledElementByIds,
|
|
@@ -9,6 +11,8 @@ import {
|
|
|
9
11
|
utilities as csUtils,
|
|
10
12
|
} from '@cornerstonejs/core';
|
|
11
13
|
import type { Types } from '@cornerstonejs/core';
|
|
14
|
+
import { Events } from '../../enums';
|
|
15
|
+
import { ToolActivatedEventDetail } from '../../types/EventTypes';
|
|
12
16
|
import { state } from '../index';
|
|
13
17
|
import {
|
|
14
18
|
IToolBinding,
|
|
@@ -69,7 +73,7 @@ export default class ToolGroup implements IToolGroup {
|
|
|
69
73
|
const toolInstance = this._toolInstances[toolInstanceName];
|
|
70
74
|
if (!toolInstance) {
|
|
71
75
|
console.warn(
|
|
72
|
-
`'${toolInstanceName}' is not registered with this toolGroup.`
|
|
76
|
+
`'${toolInstanceName}' is not registered with this toolGroup (${this.id}).`
|
|
73
77
|
);
|
|
74
78
|
return;
|
|
75
79
|
}
|
|
@@ -372,6 +376,14 @@ export default class ToolGroup implements IToolGroup {
|
|
|
372
376
|
toolInstance.onSetToolActive();
|
|
373
377
|
}
|
|
374
378
|
this._renderViewports();
|
|
379
|
+
|
|
380
|
+
const eventDetail: ToolActivatedEventDetail = {
|
|
381
|
+
toolGroupId: this.id,
|
|
382
|
+
toolName,
|
|
383
|
+
toolBindingsOptions,
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
triggerEvent(eventTarget, Events.TOOL_ACTIVATED, eventDetail);
|
|
375
387
|
}
|
|
376
388
|
|
|
377
389
|
/**
|
|
@@ -15,7 +15,9 @@ function getToolGroupsWithToolName(toolName: string): IToolGroup[] | [] {
|
|
|
15
15
|
const toolGroupToolNames = Object.keys(toolOptions);
|
|
16
16
|
|
|
17
17
|
for (let i = 0; i < toolGroupToolNames.length; i++) {
|
|
18
|
-
if (toolName !== toolGroupToolNames[i])
|
|
18
|
+
if (toolName !== toolGroupToolNames[i]) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
19
21
|
|
|
20
22
|
/* filter out tools that don't have options */
|
|
21
23
|
if (!toolOptions[toolName]) {
|
|
@@ -80,9 +80,13 @@ class MIPJumpToClickTool extends BaseTool {
|
|
|
80
80
|
const { targetViewportIds, toolGroupId } = this.configuration;
|
|
81
81
|
// TODO - consider making this a utility
|
|
82
82
|
const viewports = renderingEngine.getViewports().filter((vp) => {
|
|
83
|
-
if (targetViewportIds?.indexOf(vp.id) >= 0)
|
|
83
|
+
if (targetViewportIds?.indexOf(vp.id) >= 0) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
84
86
|
const foundToolGroup = getToolGroupForViewport(vp.id, renderingEngine.id);
|
|
85
|
-
if (toolGroupId && toolGroupId === foundToolGroup?.id)
|
|
87
|
+
if (toolGroupId && toolGroupId === foundToolGroup?.id) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
86
90
|
return false;
|
|
87
91
|
});
|
|
88
92
|
|
|
@@ -104,26 +104,38 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
104
104
|
|
|
105
105
|
onSetToolActive(): void {
|
|
106
106
|
this._disableCursorEnabled = this.configuration.disableCursor;
|
|
107
|
-
if (!this._disableCursorEnabled)
|
|
107
|
+
if (!this._disableCursorEnabled) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
108
110
|
const viewportIds = getToolGroup(this.toolGroupId).viewportsInfo;
|
|
109
|
-
if (!viewportIds)
|
|
111
|
+
if (!viewportIds) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
110
114
|
const enabledElements = viewportIds.map((e) =>
|
|
111
115
|
getEnabledElementByIds(e.viewportId, e.renderingEngineId)
|
|
112
116
|
);
|
|
113
117
|
|
|
114
118
|
enabledElements.forEach((element) => {
|
|
115
|
-
if (element)
|
|
119
|
+
if (element) {
|
|
120
|
+
hideElementCursor(element.viewport.element);
|
|
121
|
+
}
|
|
116
122
|
});
|
|
117
123
|
}
|
|
118
124
|
onSetToolDisabled(): void {
|
|
119
|
-
if (!this._disableCursorEnabled)
|
|
125
|
+
if (!this._disableCursorEnabled) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
120
128
|
const viewportIds = getToolGroup(this.toolGroupId).viewportsInfo;
|
|
121
|
-
if (!viewportIds)
|
|
129
|
+
if (!viewportIds) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
122
132
|
const enabledElements = viewportIds.map((e) =>
|
|
123
133
|
getEnabledElementByIds(e.viewportId, e.renderingEngineId)
|
|
124
134
|
);
|
|
125
135
|
enabledElements.forEach((element) => {
|
|
126
|
-
if (element)
|
|
136
|
+
if (element) {
|
|
137
|
+
resetElementCursor(element.viewport.element);
|
|
138
|
+
}
|
|
127
139
|
});
|
|
128
140
|
}
|
|
129
141
|
|
|
@@ -132,14 +144,18 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
132
144
|
element: HTMLDivElement
|
|
133
145
|
): void => {
|
|
134
146
|
const enabledElement = getEnabledElement(element);
|
|
135
|
-
if (!enabledElement)
|
|
147
|
+
if (!enabledElement) {
|
|
148
|
+
throw new Error('No enabled element found');
|
|
149
|
+
}
|
|
136
150
|
const { viewport, renderingEngine } = enabledElement;
|
|
137
151
|
|
|
138
152
|
this.isDrawing = true;
|
|
139
153
|
|
|
140
154
|
const camera = viewport.getCamera();
|
|
141
155
|
const { viewPlaneNormal, viewUp } = camera;
|
|
142
|
-
if (!viewPlaneNormal || !viewUp)
|
|
156
|
+
if (!viewPlaneNormal || !viewUp) {
|
|
157
|
+
throw new Error('Camera not found');
|
|
158
|
+
}
|
|
143
159
|
|
|
144
160
|
const referencedImageId = this.getReferencedImageId(
|
|
145
161
|
viewport,
|
|
@@ -181,10 +197,14 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
181
197
|
|
|
182
198
|
const annotations = getAnnotations(this.getToolName(), element);
|
|
183
199
|
|
|
184
|
-
if (annotations.length > 0)
|
|
200
|
+
if (annotations.length > 0) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
185
203
|
const annotationId = addAnnotation(annotation, element);
|
|
186
204
|
|
|
187
|
-
if (annotationId === null)
|
|
205
|
+
if (annotationId === null) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
188
208
|
|
|
189
209
|
const viewportIdsToRender = getViewportIdsWithToolToRender(
|
|
190
210
|
element,
|
|
@@ -212,8 +232,12 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
212
232
|
annotation: Annotation
|
|
213
233
|
): void {
|
|
214
234
|
const worldPos = this._currentCursorWorldPosition;
|
|
215
|
-
if (!worldPos)
|
|
216
|
-
|
|
235
|
+
if (!worldPos) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (!annotation.data?.handles?.points) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
217
241
|
annotation.data.handles.points = [[...worldPos]];
|
|
218
242
|
annotation.invalidated = true;
|
|
219
243
|
|
|
@@ -223,7 +247,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
223
247
|
false
|
|
224
248
|
);
|
|
225
249
|
const enabledElement = getEnabledElement(element);
|
|
226
|
-
if (!enabledElement)
|
|
250
|
+
if (!enabledElement) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
227
253
|
const { renderingEngine } = enabledElement;
|
|
228
254
|
triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
|
|
229
255
|
}
|
|
@@ -238,7 +264,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
238
264
|
| Types.IStackViewport;
|
|
239
265
|
|
|
240
266
|
//only react to changes for element with cursor, otherwise would cause infinite loop
|
|
241
|
-
if (element !== this._elementWithCursor)
|
|
267
|
+
if (element !== this._elementWithCursor) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
242
270
|
//check if camera moved along its normal
|
|
243
271
|
const oldFocalPoint = previousCamera.focalPoint;
|
|
244
272
|
const cameraNormal = camera.viewPlaneNormal;
|
|
@@ -247,14 +275,20 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
247
275
|
const deltaCameraFocalPoint: Types.Point3 = [0, 0, 0];
|
|
248
276
|
vtkMath.subtract(newFocalPoint, oldFocalPoint, deltaCameraFocalPoint);
|
|
249
277
|
//check if focal point changed
|
|
250
|
-
if (deltaCameraFocalPoint.reduce((a, b) => a + b, 0) === 0)
|
|
278
|
+
if (deltaCameraFocalPoint.reduce((a, b) => a + b, 0) === 0) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
251
281
|
//if nomrmal is perpendicular to focal point change, then we are not moving along the normal
|
|
252
282
|
const dotProduct = vtkMath.dot(deltaCameraFocalPoint, cameraNormal);
|
|
253
283
|
//dot product is 0 -> perpendicular
|
|
254
|
-
if (Math.abs(dotProduct) < 1e-2)
|
|
284
|
+
if (Math.abs(dotProduct) < 1e-2) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
255
287
|
|
|
256
288
|
//need to update the position of the annotation since camera changed
|
|
257
|
-
if (!this._currentCanvasPosition)
|
|
289
|
+
if (!this._currentCanvasPosition) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
258
292
|
|
|
259
293
|
const newWorldPos = viewport.canvasToWorld(this._currentCanvasPosition);
|
|
260
294
|
this._currentCursorWorldPosition = newWorldPos;
|
|
@@ -267,15 +301,23 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
267
301
|
annotations: Annotations
|
|
268
302
|
): Annotations {
|
|
269
303
|
//calculate distance of current viewport to annotation
|
|
270
|
-
if (!(annotations instanceof Array) || annotations.length === 0)
|
|
304
|
+
if (!(annotations instanceof Array) || annotations.length === 0) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
271
307
|
const annotation = annotations[0];
|
|
272
308
|
const viewport = getEnabledElement(element)?.viewport;
|
|
273
|
-
if (!viewport)
|
|
309
|
+
if (!viewport) {
|
|
310
|
+
return [];
|
|
311
|
+
}
|
|
274
312
|
const camera = viewport.getCamera();
|
|
275
313
|
const { viewPlaneNormal, focalPoint } = camera;
|
|
276
|
-
if (!viewPlaneNormal || !focalPoint)
|
|
314
|
+
if (!viewPlaneNormal || !focalPoint) {
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
277
317
|
const points = annotation.data?.handles?.points;
|
|
278
|
-
if (!(points instanceof Array) || points.length !== 1)
|
|
318
|
+
if (!(points instanceof Array) || points.length !== 1) {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
279
321
|
const worldPos = points[0];
|
|
280
322
|
const plane = utilities.planar.planeEquation(viewPlaneNormal, focalPoint);
|
|
281
323
|
const distance = utilities.planar.planeDistanceToPoint(plane, worldPos);
|
|
@@ -333,7 +375,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
333
375
|
const { handles } = data;
|
|
334
376
|
const { points } = handles;
|
|
335
377
|
|
|
336
|
-
if (!annotationUID)
|
|
378
|
+
if (!annotationUID) {
|
|
379
|
+
return renderStatus;
|
|
380
|
+
}
|
|
337
381
|
styleSpecifier.annotationUID = annotationUID;
|
|
338
382
|
|
|
339
383
|
const lineWidthBase = parseFloat(
|
|
@@ -347,7 +391,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
347
391
|
const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
|
|
348
392
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
349
393
|
|
|
350
|
-
if (points[0].some((e) => isNaN(e)))
|
|
394
|
+
if (points[0].some((e) => isNaN(e))) {
|
|
395
|
+
return renderStatus;
|
|
396
|
+
}
|
|
351
397
|
const canvasCoordinates = points.map((p) =>
|
|
352
398
|
viewport.worldToCanvas(p)
|
|
353
399
|
) as [Types.Point2];
|
|
@@ -414,8 +460,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
414
460
|
): void {
|
|
415
461
|
const currentMousePosition = this._currentCursorWorldPosition;
|
|
416
462
|
|
|
417
|
-
if (!currentMousePosition || currentMousePosition.some((e) => isNaN(e)))
|
|
463
|
+
if (!currentMousePosition || currentMousePosition.some((e) => isNaN(e))) {
|
|
418
464
|
return;
|
|
465
|
+
}
|
|
419
466
|
|
|
420
467
|
if (viewport instanceof StackViewport) {
|
|
421
468
|
const closestIndex = utilities.getClosestStackImageIndexForPoint(
|
|
@@ -423,12 +470,17 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
423
470
|
viewport
|
|
424
471
|
);
|
|
425
472
|
|
|
426
|
-
if (closestIndex === null)
|
|
427
|
-
|
|
473
|
+
if (closestIndex === null) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
if (closestIndex !== viewport.getCurrentImageIdIndex()) {
|
|
428
477
|
viewport.setImageIdIndex(closestIndex);
|
|
478
|
+
}
|
|
429
479
|
} else if (viewport instanceof VolumeViewport) {
|
|
430
480
|
const { focalPoint, viewPlaneNormal } = viewport.getCamera();
|
|
431
|
-
if (!focalPoint || !viewPlaneNormal)
|
|
481
|
+
if (!focalPoint || !viewPlaneNormal) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
432
484
|
const plane = utilities.planar.planeEquation(viewPlaneNormal, focalPoint);
|
|
433
485
|
const currentDistance = utilities.planar.planeDistanceToPoint(
|
|
434
486
|
plane,
|
|
@@ -436,7 +488,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
436
488
|
true
|
|
437
489
|
);
|
|
438
490
|
|
|
439
|
-
if (Math.abs(currentDistance) < 0.5)
|
|
491
|
+
if (Math.abs(currentDistance) < 0.5) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
440
494
|
const normalizedViewPlane = vec3.normalize(
|
|
441
495
|
vec3.create(),
|
|
442
496
|
vec3.fromValues(...viewPlaneNormal)
|
|
@@ -456,7 +510,9 @@ class ReferenceCursors extends AnnotationDisplayTool {
|
|
|
456
510
|
if (isInBounds) {
|
|
457
511
|
viewport.setCamera({ focalPoint: newFocalPoint });
|
|
458
512
|
const renderingEngine = viewport.getRenderingEngine();
|
|
459
|
-
if (renderingEngine)
|
|
513
|
+
if (renderingEngine) {
|
|
514
|
+
renderingEngine.renderViewport(viewport.id);
|
|
515
|
+
}
|
|
460
516
|
}
|
|
461
517
|
}
|
|
462
518
|
}
|
|
@@ -72,7 +72,9 @@ class ScaleOverlayTool extends AnnotationDisplayTool {
|
|
|
72
72
|
// get viewports with tool enabled
|
|
73
73
|
const viewportIds = getToolGroup(this.toolGroupId).viewportsInfo;
|
|
74
74
|
|
|
75
|
-
if (!viewportIds)
|
|
75
|
+
if (!viewportIds) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
76
78
|
|
|
77
79
|
// get enabled elements
|
|
78
80
|
const enabledElements = viewportIds.map((e) =>
|
|
@@ -219,8 +219,12 @@ class AngleTool extends AnnotationTool {
|
|
|
219
219
|
[canvasCoords[0], canvasCoords[1]]
|
|
220
220
|
);
|
|
221
221
|
|
|
222
|
-
if (distanceToPoint <= proximity)
|
|
223
|
-
|
|
222
|
+
if (distanceToPoint <= proximity) {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
if (!point3) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
224
228
|
|
|
225
229
|
const canvasPoint3 = viewport.worldToCanvas(point3);
|
|
226
230
|
|
|
@@ -281,7 +281,9 @@ class CircleROITool extends AnnotationTool {
|
|
|
281
281
|
canvasCoords,
|
|
282
282
|
]);
|
|
283
283
|
|
|
284
|
-
if (Math.abs(radiusPoint - radius) < proximity / 2)
|
|
284
|
+
if (Math.abs(radiusPoint - radius) < proximity / 2) {
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
285
287
|
|
|
286
288
|
return false;
|
|
287
289
|
};
|
|
@@ -662,15 +662,18 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
662
662
|
renderStatus = true;
|
|
663
663
|
}
|
|
664
664
|
|
|
665
|
-
if (!this.configuration.calculateStats)
|
|
665
|
+
if (!this.configuration.calculateStats) {
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
666
668
|
|
|
667
669
|
annotations.forEach((annotation) => {
|
|
668
670
|
const activeAnnotationUID = this.commonData?.annotation.annotationUID;
|
|
669
671
|
if (
|
|
670
672
|
annotation.annotationUID === activeAnnotationUID &&
|
|
671
673
|
!this.commonData?.movingTextBox
|
|
672
|
-
)
|
|
674
|
+
) {
|
|
673
675
|
return;
|
|
676
|
+
}
|
|
674
677
|
|
|
675
678
|
const modalityUnitOptions = {
|
|
676
679
|
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
@@ -893,7 +896,9 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
893
896
|
const targetId = this.getTargetId(viewport);
|
|
894
897
|
|
|
895
898
|
const textLines = this._getTextLines(data, targetId);
|
|
896
|
-
if (!textLines || textLines.length === 0)
|
|
899
|
+
if (!textLines || textLines.length === 0) {
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
897
902
|
|
|
898
903
|
const canvasCoordinates = data.polyline.map((p) =>
|
|
899
904
|
viewport.worldToCanvas(p)
|
|
@@ -169,8 +169,12 @@ class PaintFillTool extends BaseTool {
|
|
|
169
169
|
for (let b = 0; b < boundaries.length; b++) {
|
|
170
170
|
const j = boundaries[b][1];
|
|
171
171
|
|
|
172
|
-
if (j < minJ)
|
|
173
|
-
|
|
172
|
+
if (j < minJ) {
|
|
173
|
+
minJ = j;
|
|
174
|
+
}
|
|
175
|
+
if (j > maxJ) {
|
|
176
|
+
maxJ = j;
|
|
177
|
+
}
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
const framesModified = [];
|
package/src/types/EventTypes.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Annotation } from './AnnotationTypes';
|
|
|
3
3
|
import IPoints from './IPoints';
|
|
4
4
|
import ITouchPoints from './ITouchPoints';
|
|
5
5
|
import IDistance from './IDistance';
|
|
6
|
+
import { SetToolBindingsType } from './ISetToolModeOptions';
|
|
6
7
|
import { Swipe } from '../enums/Touch';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -70,6 +71,18 @@ type InteractionStartEventDetail = InteractionEventDetail;
|
|
|
70
71
|
|
|
71
72
|
type InteractionEndEventDetail = InteractionEventDetail;
|
|
72
73
|
|
|
74
|
+
/**
|
|
75
|
+
* The data that is passed to the event handler when a tool is activated.
|
|
76
|
+
*/
|
|
77
|
+
type ToolActivatedEventDetail = {
|
|
78
|
+
/** unique id of the toolGroup */
|
|
79
|
+
toolGroupId: string;
|
|
80
|
+
/** Tool name */
|
|
81
|
+
toolName: string;
|
|
82
|
+
/** Tool binding options */
|
|
83
|
+
toolBindingsOptions: SetToolBindingsType;
|
|
84
|
+
};
|
|
85
|
+
|
|
73
86
|
/**
|
|
74
87
|
* The data that is passed to the event handler when a new annotation is added
|
|
75
88
|
* to the annotations.
|
|
@@ -411,6 +424,11 @@ type NormalizedMouseEventType = Types.CustomEventType<MouseCustomEventDetail>;
|
|
|
411
424
|
*/
|
|
412
425
|
type NormalizedTouchEventType = Types.CustomEventType<TouchCustomEventDetail>;
|
|
413
426
|
|
|
427
|
+
/**
|
|
428
|
+
* The ToolActivated event type
|
|
429
|
+
*/
|
|
430
|
+
type ToolActivatedEventType = Types.CustomEventType<ToolActivatedEventDetail>;
|
|
431
|
+
|
|
414
432
|
/**
|
|
415
433
|
* The AnnotationAdded event type
|
|
416
434
|
*/
|
|
@@ -611,6 +629,8 @@ export {
|
|
|
611
629
|
NormalizedInteractionEventDetail,
|
|
612
630
|
NormalizedMouseEventType,
|
|
613
631
|
NormalizedTouchEventType,
|
|
632
|
+
ToolActivatedEventDetail,
|
|
633
|
+
ToolActivatedEventType,
|
|
614
634
|
AnnotationAddedEventDetail,
|
|
615
635
|
AnnotationAddedEventType,
|
|
616
636
|
AnnotationCompletedEventDetail,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ToolModes, MouseBindings, KeyboardBindings } from '../enums';
|
|
2
2
|
|
|
3
|
-
type ToolBindingMouseType = typeof MouseBindings[keyof typeof MouseBindings];
|
|
3
|
+
type ToolBindingMouseType = (typeof MouseBindings)[keyof typeof MouseBindings];
|
|
4
4
|
|
|
5
5
|
type ToolBindingKeyboardType =
|
|
6
|
-
typeof KeyboardBindings[keyof typeof KeyboardBindings];
|
|
6
|
+
(typeof KeyboardBindings)[keyof typeof KeyboardBindings];
|
|
7
7
|
|
|
8
8
|
type IToolBinding = {
|
|
9
9
|
/** Mouse button bindings e.g., MouseBindings.Primary/Secondary etc. */
|
|
@@ -193,7 +193,9 @@ function stopClip(element: HTMLDivElement): void {
|
|
|
193
193
|
|
|
194
194
|
function _stopClip(element: HTMLDivElement, stopDynamicCine: boolean): void {
|
|
195
195
|
const enabledElement = getEnabledElement(element);
|
|
196
|
-
if (!enabledElement)
|
|
196
|
+
if (!enabledElement) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
197
199
|
const { viewport } = enabledElement;
|
|
198
200
|
const cineToolData = getToolState(viewport.element);
|
|
199
201
|
|