@cornerstonejs/tools 1.20.2 → 1.21.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/cjs/drawingSvg/getSvgDrawingHelper.js +1 -1
- package/dist/cjs/drawingSvg/getSvgDrawingHelper.js.map +1 -1
- 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/mouseEventHandlers/mouseDown.js +5 -0
- package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
- package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.d.ts +2 -0
- package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js +41 -0
- package/dist/cjs/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js.map +1 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts +3 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +39 -0
- package/dist/cjs/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -0
- package/dist/cjs/eventListeners/mouse/mouseDownListener.js +5 -1
- package/dist/cjs/eventListeners/mouse/mouseDownListener.js.map +1 -1
- package/dist/cjs/eventListeners/mouse/mouseMoveListener.js +5 -1
- package/dist/cjs/eventListeners/mouse/mouseMoveListener.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/store/ToolGroupManager/ToolGroup.d.ts +2 -0
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js +35 -0
- package/dist/cjs/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/cjs/tools/AdvancedMagnifyTool.d.ts +36 -0
- package/dist/cjs/tools/AdvancedMagnifyTool.js +448 -0
- package/dist/cjs/tools/AdvancedMagnifyTool.js.map +1 -0
- package/dist/cjs/tools/AdvancedMagnifyViewport.d.ts +76 -0
- package/dist/cjs/tools/AdvancedMagnifyViewport.js +352 -0
- package/dist/cjs/tools/AdvancedMagnifyViewport.js.map +1 -0
- package/dist/cjs/tools/AdvancedMagnifyViewportManager.d.ts +36 -0
- package/dist/cjs/tools/AdvancedMagnifyViewportManager.js +133 -0
- package/dist/cjs/tools/AdvancedMagnifyViewportManager.js.map +1 -0
- package/dist/cjs/tools/annotation/EllipticalROITool.d.ts +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.js +12 -8
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/index.d.ts +2 -1
- package/dist/cjs/tools/index.js +3 -1
- package/dist/cjs/tools/index.js.map +1 -1
- package/dist/cjs/types/EventTypes.d.ts +9 -1
- package/dist/cjs/types/IToolGroup.d.ts +3 -0
- package/dist/cjs/types/ToolAction.d.ts +8 -0
- package/dist/cjs/types/ToolAction.js +3 -0
- package/dist/cjs/types/ToolAction.js.map +1 -0
- package/dist/cjs/types/ToolSpecificAnnotationTypes.d.ts +11 -0
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/esm/drawingSvg/getSvgDrawingHelper.js +1 -1
- package/dist/esm/drawingSvg/getSvgDrawingHelper.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/mouseEventHandlers/mouseDown.js +5 -0
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDown.js.map +1 -1
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.d.ts +2 -0
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js +35 -0
- package/dist/esm/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.js.map +1 -0
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.d.ts +3 -0
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +32 -0
- package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js.map +1 -0
- package/dist/esm/eventListeners/mouse/mouseDownListener.js +5 -1
- package/dist/esm/eventListeners/mouse/mouseDownListener.js.map +1 -1
- package/dist/esm/eventListeners/mouse/mouseMoveListener.js +5 -1
- package/dist/esm/eventListeners/mouse/mouseMoveListener.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.d.ts +2 -0
- package/dist/esm/store/ToolGroupManager/ToolGroup.js +35 -1
- package/dist/esm/store/ToolGroupManager/ToolGroup.js.map +1 -1
- package/dist/esm/tools/AdvancedMagnifyTool.d.ts +36 -0
- package/dist/esm/tools/AdvancedMagnifyTool.js +440 -0
- package/dist/esm/tools/AdvancedMagnifyTool.js.map +1 -0
- package/dist/esm/tools/AdvancedMagnifyViewport.d.ts +76 -0
- package/dist/esm/tools/AdvancedMagnifyViewport.js +346 -0
- package/dist/esm/tools/AdvancedMagnifyViewport.js.map +1 -0
- package/dist/esm/tools/AdvancedMagnifyViewportManager.d.ts +36 -0
- package/dist/esm/tools/AdvancedMagnifyViewportManager.js +128 -0
- package/dist/esm/tools/AdvancedMagnifyViewportManager.js.map +1 -0
- package/dist/esm/tools/annotation/EllipticalROITool.d.ts +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.js +12 -8
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/index.d.ts +2 -1
- package/dist/esm/tools/index.js +2 -1
- package/dist/esm/tools/index.js.map +1 -1
- package/dist/esm/types/EventTypes.d.ts +9 -1
- package/dist/esm/types/IToolGroup.d.ts +3 -0
- package/dist/esm/types/ToolAction.d.ts +8 -0
- package/dist/esm/types/ToolAction.js +2 -0
- package/dist/esm/types/ToolAction.js.map +1 -0
- package/dist/esm/types/ToolSpecificAnnotationTypes.d.ts +11 -0
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/drawingSvg/getSvgDrawingHelper.ts +4 -1
- package/src/enums/Events.ts +9 -0
- package/src/eventDispatchers/mouseEventHandlers/mouseDown.ts +10 -1
- package/src/eventDispatchers/mouseEventHandlers/mouseDownAnnotationAction.ts +72 -0
- package/src/eventDispatchers/shared/getToolsWithActionsForMouseEvent.ts +66 -0
- package/src/eventListeners/mouse/mouseDownListener.ts +7 -1
- package/src/eventListeners/mouse/mouseMoveListener.ts +7 -1
- package/src/index.ts +2 -0
- package/src/store/ToolGroupManager/ToolGroup.ts +79 -2
- package/src/tools/AdvancedMagnifyTool.ts +725 -0
- package/src/tools/AdvancedMagnifyViewport.ts +624 -0
- package/src/tools/AdvancedMagnifyViewportManager.ts +291 -0
- package/src/tools/annotation/EllipticalROITool.ts +14 -9
- package/src/tools/index.ts +2 -0
- package/src/types/EventTypes.ts +23 -0
- package/src/types/IToolGroup.ts +7 -0
- package/src/types/ToolAction.ts +54 -0
- package/src/types/ToolSpecificAnnotationTypes.ts +12 -0
- package/src/types/index.ts +2 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
2
|
+
import {
|
|
3
|
+
eventTarget,
|
|
4
|
+
Enums,
|
|
5
|
+
getRenderingEngine,
|
|
6
|
+
CONSTANTS,
|
|
7
|
+
} from '@cornerstonejs/core';
|
|
8
|
+
import type { Types } from '@cornerstonejs/core';
|
|
9
|
+
import { AnnotationRemovedEventType } from '../types/EventTypes';
|
|
10
|
+
import { Events as cstEvents } from '../enums';
|
|
11
|
+
import {
|
|
12
|
+
AdvancedMagnifyViewport,
|
|
13
|
+
AutoPanCallback,
|
|
14
|
+
} from './AdvancedMagnifyViewport';
|
|
15
|
+
import { AdvancedMagnifyAnnotation } from '../types/ToolSpecificAnnotationTypes';
|
|
16
|
+
|
|
17
|
+
// Defined the tool name internally instead of importing
|
|
18
|
+
// AdvangedMagnifyTool due to cyclic dependency
|
|
19
|
+
const ADVANCED_MAGNIFY_TOOL_NAME = 'AdvancedMagnify';
|
|
20
|
+
|
|
21
|
+
const PARALLEL_THRESHOLD = 1 - CONSTANTS.EPSILON;
|
|
22
|
+
const { Events } = Enums;
|
|
23
|
+
|
|
24
|
+
export type MagnifyViewportInfo = {
|
|
25
|
+
// Viewport id to be used or new v4 compliant GUID is used instead
|
|
26
|
+
magnifyViewportId?: string;
|
|
27
|
+
// Enabled element where the magnifying glass shall be added to
|
|
28
|
+
sourceEnabledElement: Types.IEnabledElement;
|
|
29
|
+
// Magnifying glass position (center)
|
|
30
|
+
position: Types.Point2;
|
|
31
|
+
// Magnifying glass radius (pixels)
|
|
32
|
+
radius: number;
|
|
33
|
+
// Amount of magnification applied to the magnifying glass image compared to the source viewport.
|
|
34
|
+
zoomFactor: number;
|
|
35
|
+
// Allow panning the viewport when moving an annotation point close to the border of the magnifying glass
|
|
36
|
+
autoPan: {
|
|
37
|
+
// Enable or disable auto pan
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
// Minimum distance to the border before start auto panning
|
|
40
|
+
padding: number;
|
|
41
|
+
// Callback function responsible for updating the annotation (circle)
|
|
42
|
+
// that contains the magnifying viewport
|
|
43
|
+
callback: AutoPanCallback;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type MagnifyViewportsMapEntry = {
|
|
48
|
+
annotation: AdvancedMagnifyAnnotation;
|
|
49
|
+
magnifyViewport: AdvancedMagnifyViewport;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Manager responsible for creating, storing and destroying magnifying glass
|
|
54
|
+
* viewports. There are no restrictions to create a new instance of it but it
|
|
55
|
+
* should be accessed through getInstance() method.
|
|
56
|
+
*/
|
|
57
|
+
class AdvancedMagnifyViewportManager {
|
|
58
|
+
private static _singleton: AdvancedMagnifyViewportManager;
|
|
59
|
+
private _magnifyViewportsMap: Map<string, MagnifyViewportsMapEntry>;
|
|
60
|
+
|
|
61
|
+
constructor() {
|
|
62
|
+
this._magnifyViewportsMap = new Map();
|
|
63
|
+
this._initialize();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates a new magnifying glass viewport manager instance when this method is
|
|
68
|
+
* called for the first time or return the instance previously created for
|
|
69
|
+
* any subsequent call (singleton pattern).
|
|
70
|
+
* @returns A magnifying viewport manager instance
|
|
71
|
+
*/
|
|
72
|
+
public static getInstance(): AdvancedMagnifyViewportManager {
|
|
73
|
+
AdvancedMagnifyViewportManager._singleton =
|
|
74
|
+
AdvancedMagnifyViewportManager._singleton ??
|
|
75
|
+
new AdvancedMagnifyViewportManager();
|
|
76
|
+
|
|
77
|
+
return AdvancedMagnifyViewportManager._singleton;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Creates a new magnifying glass viewport instance
|
|
82
|
+
* @param viewportInfo - Viewport data used when creating a new magnifying glass viewport
|
|
83
|
+
* @returns A magnifying glass viewport instance
|
|
84
|
+
*/
|
|
85
|
+
public createViewport = (
|
|
86
|
+
annotation: AdvancedMagnifyAnnotation,
|
|
87
|
+
viewportInfo: MagnifyViewportInfo
|
|
88
|
+
): AdvancedMagnifyViewport => {
|
|
89
|
+
const {
|
|
90
|
+
magnifyViewportId,
|
|
91
|
+
sourceEnabledElement,
|
|
92
|
+
position,
|
|
93
|
+
radius,
|
|
94
|
+
zoomFactor,
|
|
95
|
+
autoPan,
|
|
96
|
+
} = viewportInfo;
|
|
97
|
+
const { viewport: sourceViewport } = sourceEnabledElement;
|
|
98
|
+
const { element: sourceElement } = sourceViewport;
|
|
99
|
+
|
|
100
|
+
const magnifyViewport = new AdvancedMagnifyViewport({
|
|
101
|
+
magnifyViewportId,
|
|
102
|
+
sourceEnabledElement,
|
|
103
|
+
radius,
|
|
104
|
+
position,
|
|
105
|
+
zoomFactor,
|
|
106
|
+
autoPan,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
this._addSourceElementEventListener(sourceElement);
|
|
110
|
+
this._magnifyViewportsMap.set(magnifyViewport.viewportId, {
|
|
111
|
+
annotation,
|
|
112
|
+
magnifyViewport,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return magnifyViewport;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Find and return a magnifying glass viewport based on its id
|
|
120
|
+
* @param magnifyViewportId - Magnifying glass viewport id
|
|
121
|
+
* @returns A magnifying glass viewport instance
|
|
122
|
+
*/
|
|
123
|
+
public getViewport(magnifyViewportId: string): AdvancedMagnifyViewport {
|
|
124
|
+
return this._magnifyViewportsMap.get(magnifyViewportId)?.magnifyViewport;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Release all magnifying glass viewport instances and remove all event
|
|
129
|
+
* listeners making all objects available to be garbage collected.
|
|
130
|
+
*/
|
|
131
|
+
public dispose() {
|
|
132
|
+
this._removeEventListeners();
|
|
133
|
+
this._destroyViewports();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private _destroyViewport(magnifyViewportId: string) {
|
|
137
|
+
const magnifyViewportMapEntry =
|
|
138
|
+
this._magnifyViewportsMap.get(magnifyViewportId);
|
|
139
|
+
|
|
140
|
+
if (magnifyViewportMapEntry) {
|
|
141
|
+
const { magnifyViewport } = magnifyViewportMapEntry;
|
|
142
|
+
const { viewport: sourceViewport } = magnifyViewport.sourceEnabledElement;
|
|
143
|
+
const { element: sourceElement } = sourceViewport;
|
|
144
|
+
|
|
145
|
+
this._removeSourceElementEventListener(sourceElement);
|
|
146
|
+
|
|
147
|
+
magnifyViewport.dispose();
|
|
148
|
+
this._magnifyViewportsMap.delete(magnifyViewportId);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private _destroyViewports() {
|
|
153
|
+
const magnifyViewportIds = Array.from(this._magnifyViewportsMap.keys());
|
|
154
|
+
|
|
155
|
+
magnifyViewportIds.forEach((magnifyViewportId) =>
|
|
156
|
+
this._destroyViewport(magnifyViewportId)
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private _annotationRemovedCallback = (evt: AnnotationRemovedEventType) => {
|
|
161
|
+
const { annotation } = evt.detail;
|
|
162
|
+
|
|
163
|
+
if (annotation.metadata.toolName !== ADVANCED_MAGNIFY_TOOL_NAME) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this._destroyViewport(annotation.data.magnifyViewportId);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
private _getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId) {
|
|
171
|
+
const magnifyViewportsMapEntries = Array.from(
|
|
172
|
+
this._magnifyViewportsMap.values()
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
return magnifyViewportsMapEntries.filter(({ magnifyViewport }) => {
|
|
176
|
+
const { viewport } = magnifyViewport.sourceEnabledElement;
|
|
177
|
+
return viewport.id === sourceViewportId;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private _newStackImageCallback = (
|
|
182
|
+
evt: Types.EventTypes.StackNewImageEvent
|
|
183
|
+
) => {
|
|
184
|
+
const { viewportId: sourceViewportId, imageId } = evt.detail;
|
|
185
|
+
const magnifyViewportsMapEntries =
|
|
186
|
+
this._getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId);
|
|
187
|
+
|
|
188
|
+
magnifyViewportsMapEntries.forEach(({ annotation }) => {
|
|
189
|
+
annotation.metadata.referencedImageId = imageId;
|
|
190
|
+
annotation.invalidated = true;
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
private _newVolumeImageCallback = (
|
|
195
|
+
evt: Types.EventTypes.VolumeNewImageEvent
|
|
196
|
+
) => {
|
|
197
|
+
const { renderingEngineId, viewportId: sourceViewportId } = evt.detail;
|
|
198
|
+
const renderingEngine = getRenderingEngine(renderingEngineId);
|
|
199
|
+
const sourceViewport = renderingEngine.getViewport(sourceViewportId);
|
|
200
|
+
const { viewPlaneNormal: currentViewPlaneNormal } =
|
|
201
|
+
sourceViewport.getCamera();
|
|
202
|
+
|
|
203
|
+
const magnifyViewportsMapEntries =
|
|
204
|
+
this._getMagnifyViewportsMapEntriesBySourceViewportId(sourceViewportId);
|
|
205
|
+
|
|
206
|
+
magnifyViewportsMapEntries.forEach(({ annotation }) => {
|
|
207
|
+
const { viewPlaneNormal } = annotation.metadata;
|
|
208
|
+
|
|
209
|
+
// Compare the normal to make sure the volume is not rotate in 3D space
|
|
210
|
+
const isParallel =
|
|
211
|
+
Math.abs(vec3.dot(viewPlaneNormal, currentViewPlaneNormal)) >
|
|
212
|
+
PARALLEL_THRESHOLD;
|
|
213
|
+
|
|
214
|
+
if (!isParallel) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const { handles } = annotation.data;
|
|
219
|
+
const worldImagePlanePoint = sourceViewport.canvasToWorld([0, 0]);
|
|
220
|
+
const vecHandleToImagePlane = vec3.sub(
|
|
221
|
+
vec3.create(),
|
|
222
|
+
worldImagePlanePoint,
|
|
223
|
+
handles.points[0]
|
|
224
|
+
);
|
|
225
|
+
const worldDist = vec3.dot(vecHandleToImagePlane, currentViewPlaneNormal);
|
|
226
|
+
const worldDelta = vec3.scale(
|
|
227
|
+
vec3.create(),
|
|
228
|
+
currentViewPlaneNormal,
|
|
229
|
+
worldDist
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
// Move all handle points to the image plane to make the annotation visible
|
|
233
|
+
for (let i = 0, len = handles.points.length; i < len; i++) {
|
|
234
|
+
const point = handles.points[i];
|
|
235
|
+
|
|
236
|
+
point[0] += worldDelta[0];
|
|
237
|
+
point[1] += worldDelta[1];
|
|
238
|
+
point[2] += worldDelta[2];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
annotation.invalidated = true;
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
private _addEventListeners() {
|
|
246
|
+
eventTarget.addEventListener(
|
|
247
|
+
cstEvents.ANNOTATION_REMOVED,
|
|
248
|
+
this._annotationRemovedCallback
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private _removeEventListeners() {
|
|
253
|
+
eventTarget.removeEventListener(
|
|
254
|
+
cstEvents.ANNOTATION_REMOVED,
|
|
255
|
+
this._annotationRemovedCallback
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private _addSourceElementEventListener(element) {
|
|
260
|
+
element.addEventListener(
|
|
261
|
+
Events.STACK_NEW_IMAGE,
|
|
262
|
+
this._newStackImageCallback
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
element.addEventListener(
|
|
266
|
+
Events.VOLUME_NEW_IMAGE,
|
|
267
|
+
this._newVolumeImageCallback
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private _removeSourceElementEventListener(element) {
|
|
272
|
+
element.removeEventListener(
|
|
273
|
+
Events.STACK_NEW_IMAGE,
|
|
274
|
+
this._newStackImageCallback
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
element.removeEventListener(
|
|
278
|
+
Events.VOLUME_NEW_IMAGE,
|
|
279
|
+
this._newVolumeImageCallback
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private _initialize() {
|
|
284
|
+
this._addEventListeners();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export {
|
|
289
|
+
AdvancedMagnifyViewportManager as default,
|
|
290
|
+
AdvancedMagnifyViewportManager,
|
|
291
|
+
};
|
|
@@ -125,7 +125,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
125
125
|
viewportIdsToRender: Array<string>;
|
|
126
126
|
handleIndex?: number;
|
|
127
127
|
movingTextBox?: boolean;
|
|
128
|
-
|
|
128
|
+
centerWorld?: Array<number>;
|
|
129
129
|
canvasWidth?: number;
|
|
130
130
|
canvasHeight?: number;
|
|
131
131
|
originalHandleCanvas?: Array<number>;
|
|
@@ -238,7 +238,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
238
238
|
this.editData = {
|
|
239
239
|
annotation,
|
|
240
240
|
viewportIdsToRender,
|
|
241
|
-
|
|
241
|
+
centerWorld: worldPos,
|
|
242
242
|
newAnnotation: true,
|
|
243
243
|
hasMoved: false,
|
|
244
244
|
};
|
|
@@ -365,6 +365,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
365
365
|
let handleIndex;
|
|
366
366
|
|
|
367
367
|
let centerCanvas;
|
|
368
|
+
let centerWorld;
|
|
368
369
|
let canvasWidth;
|
|
369
370
|
let canvasHeight;
|
|
370
371
|
let originalHandleCanvas;
|
|
@@ -373,8 +374,8 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
373
374
|
movingTextBox = true;
|
|
374
375
|
} else {
|
|
375
376
|
const { points } = data.handles;
|
|
376
|
-
const
|
|
377
|
-
const { worldToCanvas } =
|
|
377
|
+
const { viewport } = getEnabledElement(element);
|
|
378
|
+
const { worldToCanvas, canvasToWorld } = viewport;
|
|
378
379
|
|
|
379
380
|
handleIndex = points.findIndex((p) => p === handle);
|
|
380
381
|
|
|
@@ -389,6 +390,8 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
389
390
|
(pointsCanvas[2][0] + pointsCanvas[3][0]) / 2,
|
|
390
391
|
(pointsCanvas[0][1] + pointsCanvas[1][1]) / 2,
|
|
391
392
|
];
|
|
393
|
+
|
|
394
|
+
centerWorld = canvasToWorld(centerCanvas);
|
|
392
395
|
}
|
|
393
396
|
|
|
394
397
|
// Find viewports to render on drag.
|
|
@@ -403,7 +406,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
403
406
|
handleIndex,
|
|
404
407
|
canvasWidth,
|
|
405
408
|
canvasHeight,
|
|
406
|
-
|
|
409
|
+
centerWorld,
|
|
407
410
|
originalHandleCanvas,
|
|
408
411
|
movingTextBox,
|
|
409
412
|
};
|
|
@@ -480,7 +483,8 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
480
483
|
const { canvasToWorld } = viewport;
|
|
481
484
|
|
|
482
485
|
//////
|
|
483
|
-
const { annotation, viewportIdsToRender,
|
|
486
|
+
const { annotation, viewportIdsToRender, centerWorld } = this.editData;
|
|
487
|
+
const centerCanvas = viewport.worldToCanvas(centerWorld as Types.Point3);
|
|
484
488
|
const { data } = annotation;
|
|
485
489
|
|
|
486
490
|
const dX = Math.abs(currentCanvasPoints[0] - centerCanvas[0]);
|
|
@@ -554,17 +558,18 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
554
558
|
_dragHandle = (evt: EventTypes.InteractionEventType): void => {
|
|
555
559
|
const eventDetail = evt.detail;
|
|
556
560
|
const { element } = eventDetail;
|
|
557
|
-
const
|
|
558
|
-
const { canvasToWorld } =
|
|
561
|
+
const { viewport } = getEnabledElement(element);
|
|
562
|
+
const { canvasToWorld, worldToCanvas } = viewport;
|
|
559
563
|
|
|
560
564
|
const {
|
|
561
565
|
annotation,
|
|
562
566
|
canvasWidth,
|
|
563
567
|
canvasHeight,
|
|
564
568
|
handleIndex,
|
|
565
|
-
|
|
569
|
+
centerWorld,
|
|
566
570
|
originalHandleCanvas,
|
|
567
571
|
} = this.editData;
|
|
572
|
+
const centerCanvas = viewport.worldToCanvas(centerWorld as Types.Point3);
|
|
568
573
|
const { data } = annotation;
|
|
569
574
|
const { points } = data.handles;
|
|
570
575
|
|
package/src/tools/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import VolumeRotateMouseWheelTool from './VolumeRotateMouseWheelTool';
|
|
|
10
10
|
import MIPJumpToClickTool from './MIPJumpToClickTool';
|
|
11
11
|
import CrosshairsTool from './CrosshairsTool';
|
|
12
12
|
import MagnifyTool from './MagnifyTool';
|
|
13
|
+
import AdvancedMagnifyTool from './AdvancedMagnifyTool';
|
|
13
14
|
import ReferenceLinesTool from './ReferenceLinesTool';
|
|
14
15
|
import OverlayGridTool from './OverlayGridTool';
|
|
15
16
|
//
|
|
@@ -82,6 +83,7 @@ export {
|
|
|
82
83
|
RectangleROIStartEndThresholdTool,
|
|
83
84
|
BrushTool,
|
|
84
85
|
MagnifyTool,
|
|
86
|
+
AdvancedMagnifyTool,
|
|
85
87
|
ReferenceLines,
|
|
86
88
|
PaintFillTool,
|
|
87
89
|
ScaleOverlayTool,
|
package/src/types/EventTypes.ts
CHANGED
|
@@ -5,6 +5,7 @@ import ITouchPoints from './ITouchPoints';
|
|
|
5
5
|
import IDistance from './IDistance';
|
|
6
6
|
import { SetToolBindingsType } from './ISetToolModeOptions';
|
|
7
7
|
import { Swipe } from '../enums/Touch';
|
|
8
|
+
import { ToolModes } from '../enums';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* The normalized interaction event detail
|
|
@@ -71,6 +72,20 @@ type InteractionStartEventDetail = InteractionEventDetail;
|
|
|
71
72
|
|
|
72
73
|
type InteractionEndEventDetail = InteractionEventDetail;
|
|
73
74
|
|
|
75
|
+
/**
|
|
76
|
+
* The data that is passed to the event handler when tool mode changes
|
|
77
|
+
*/
|
|
78
|
+
type ToolModeChangedEventDetail = {
|
|
79
|
+
/** unique id of the toolGroup */
|
|
80
|
+
toolGroupId: string;
|
|
81
|
+
/** Tool name */
|
|
82
|
+
toolName: string;
|
|
83
|
+
/** Tool mode */
|
|
84
|
+
mode: ToolModes;
|
|
85
|
+
/** Tool binding options */
|
|
86
|
+
toolBindingsOptions?: SetToolBindingsType;
|
|
87
|
+
};
|
|
88
|
+
|
|
74
89
|
/**
|
|
75
90
|
* The data that is passed to the event handler when a tool is activated.
|
|
76
91
|
*/
|
|
@@ -424,6 +439,12 @@ type NormalizedMouseEventType = Types.CustomEventType<MouseCustomEventDetail>;
|
|
|
424
439
|
*/
|
|
425
440
|
type NormalizedTouchEventType = Types.CustomEventType<TouchCustomEventDetail>;
|
|
426
441
|
|
|
442
|
+
/**
|
|
443
|
+
* The ToolModeChanged event type
|
|
444
|
+
*/
|
|
445
|
+
type ToolModeChangedEventType =
|
|
446
|
+
Types.CustomEventType<ToolModeChangedEventDetail>;
|
|
447
|
+
|
|
427
448
|
/**
|
|
428
449
|
* The ToolActivated event type
|
|
429
450
|
*/
|
|
@@ -629,6 +650,8 @@ export {
|
|
|
629
650
|
NormalizedInteractionEventDetail,
|
|
630
651
|
NormalizedMouseEventType,
|
|
631
652
|
NormalizedTouchEventType,
|
|
653
|
+
ToolModeChangedEventDetail,
|
|
654
|
+
ToolModeChangedEventType,
|
|
632
655
|
ToolActivatedEventDetail,
|
|
633
656
|
ToolActivatedEventType,
|
|
634
657
|
AnnotationAddedEventDetail,
|
package/src/types/IToolGroup.ts
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Annotation } from './AnnotationTypes';
|
|
2
|
+
import type { InteractionEventType } from './EventTypes';
|
|
3
|
+
import type { SetToolBindingsType } from './ISetToolModeOptions';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* An action that may be defined at the tool configuration level
|
|
7
|
+
*
|
|
8
|
+
* Annotations can have actions that run a specific task (ex: showing a dropdown
|
|
9
|
+
* containing a list of all predefined zoom levels - advanced magnifier glass).
|
|
10
|
+
* Each action must have at least one binding option (mouse button + [modifier(s)])
|
|
11
|
+
* and a action runs if and only if no other tool is using that same binding options
|
|
12
|
+
* to draw an annotation because action has lower priority.
|
|
13
|
+
*
|
|
14
|
+
* Actions are defined in the following way in a annotation tool constructor:
|
|
15
|
+
*
|
|
16
|
+
* class MyAnnotationTool extends AnnotationTool {
|
|
17
|
+
* constructor(
|
|
18
|
+
* toolProps: PublicToolProps = {},
|
|
19
|
+
* defaultToolProps: ToolProps = {
|
|
20
|
+
* configuration: {
|
|
21
|
+
* actions: [
|
|
22
|
+
* {
|
|
23
|
+
* method: 'myAction',
|
|
24
|
+
* bindings: [
|
|
25
|
+
* {
|
|
26
|
+
* mouseButton: MouseBindings.Secondary,
|
|
27
|
+
* modifierKey: KeyboardBindings.Shift,
|
|
28
|
+
* }
|
|
29
|
+
* ]
|
|
30
|
+
* }
|
|
31
|
+
* ]
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ) {
|
|
35
|
+
* super(toolProps, defaultToolProps);
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* public myAction(evt: EventTypes.InteractionEventType, annotation: MyAnnotation) {
|
|
39
|
+
* // action code
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* The "method" property may be a string or a javascript function. In case it is
|
|
44
|
+
* a string a function with same name must exists in the tool class. In both ways
|
|
45
|
+
* (string or function) the function is called in the tool's context (`this`)
|
|
46
|
+
*/
|
|
47
|
+
type ToolAction = {
|
|
48
|
+
method:
|
|
49
|
+
| string
|
|
50
|
+
| ((evt: InteractionEventType, annotation: Annotation) => void);
|
|
51
|
+
bindings: SetToolBindingsType[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default ToolAction;
|
|
@@ -78,6 +78,18 @@ export interface LengthAnnotation extends Annotation {
|
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
export interface AdvancedMagnifyAnnotation extends Annotation {
|
|
82
|
+
data: {
|
|
83
|
+
zoomFactor: number;
|
|
84
|
+
sourceViewportId: string;
|
|
85
|
+
magnifyViewportId: string;
|
|
86
|
+
handles: {
|
|
87
|
+
points: Types.Point3[]; // [top, right, bottom, left]
|
|
88
|
+
activeHandleIndex: number | null;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
81
93
|
export interface CircleROIAnnotation extends Annotation {
|
|
82
94
|
data: {
|
|
83
95
|
handles: {
|
package/src/types/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type * as AnnotationStyle from './AnnotationStyle';
|
|
|
21
21
|
import type ToolHandle from './ToolHandle';
|
|
22
22
|
import type { AnnotationHandle, TextBoxHandle } from './ToolHandle';
|
|
23
23
|
import type InteractionTypes from './InteractionTypes';
|
|
24
|
+
import type ToolAction from './ToolAction';
|
|
24
25
|
import type {
|
|
25
26
|
ToolProps,
|
|
26
27
|
PublicToolProps,
|
|
@@ -84,6 +85,7 @@ export type {
|
|
|
84
85
|
SetToolBindingsType,
|
|
85
86
|
ToolOptionsType,
|
|
86
87
|
InteractionTypes,
|
|
88
|
+
ToolAction,
|
|
87
89
|
//
|
|
88
90
|
IToolGroup,
|
|
89
91
|
IToolClassReference,
|