@cornerstonejs/tools 1.17.1 → 1.19.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/index.d.ts +2 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tools/OrientationMarkerTool.d.ts +88 -0
- package/dist/cjs/tools/OrientationMarkerTool.js +193 -0
- package/dist/cjs/tools/OrientationMarkerTool.js.map +1 -0
- package/dist/cjs/tools/ReferenceLinesTool.d.ts +3 -0
- package/dist/cjs/tools/ReferenceLinesTool.js +71 -2
- package/dist/cjs/tools/ReferenceLinesTool.js.map +1 -1
- package/dist/cjs/tools/base/AnnotationDisplayTool.js +4 -0
- package/dist/cjs/tools/base/AnnotationDisplayTool.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/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tools/OrientationMarkerTool.d.ts +88 -0
- package/dist/esm/tools/OrientationMarkerTool.js +185 -0
- package/dist/esm/tools/OrientationMarkerTool.js.map +1 -0
- package/dist/esm/tools/ReferenceLinesTool.d.ts +3 -0
- package/dist/esm/tools/ReferenceLinesTool.js +71 -2
- package/dist/esm/tools/ReferenceLinesTool.js.map +1 -1
- package/dist/esm/tools/base/AnnotationDisplayTool.js +3 -0
- package/dist/esm/tools/base/AnnotationDisplayTool.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/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +2 -0
- package/src/tools/OrientationMarkerTool.ts +235 -0
- package/src/tools/ReferenceLinesTool.ts +131 -3
- package/src/tools/base/AnnotationDisplayTool.ts +4 -0
- package/src/tools/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
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.19.0",
|
|
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": "4caa1d79544a3076d89de80d02fbb9a18c1ad186"
|
|
56
56
|
}
|
package/src/index.ts
CHANGED
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
ReferenceLines,
|
|
59
59
|
PaintFillTool,
|
|
60
60
|
ScaleOverlayTool,
|
|
61
|
+
OrientationMarkerTool,
|
|
61
62
|
OverlayGridTool,
|
|
62
63
|
} from './tools';
|
|
63
64
|
|
|
@@ -112,6 +113,7 @@ export {
|
|
|
112
113
|
RectangleROIThresholdTool,
|
|
113
114
|
RectangleROIStartEndThresholdTool,
|
|
114
115
|
BrushTool,
|
|
116
|
+
OrientationMarkerTool,
|
|
115
117
|
// Synchronizers
|
|
116
118
|
synchronizers,
|
|
117
119
|
Synchronizer,
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import vtkOrientationMarkerWidget from '@kitware/vtk.js/Interaction/Widgets/OrientationMarkerWidget';
|
|
2
|
+
import vtkAnnotatedCubeActor from '@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor';
|
|
3
|
+
import vtkAxesActor from '@kitware/vtk.js/Rendering/Core/AxesActor';
|
|
4
|
+
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
|
|
5
|
+
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
|
|
6
|
+
import vtkXMLPolyDataReader from '@kitware/vtk.js/IO/XML/XMLPolyDataReader';
|
|
7
|
+
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
|
|
8
|
+
|
|
9
|
+
import { BaseTool } from './base';
|
|
10
|
+
import { getRenderingEngines } from '@cornerstonejs/core';
|
|
11
|
+
import { filterViewportsWithToolEnabled } from '../utilities/viewportFilters';
|
|
12
|
+
|
|
13
|
+
const OverlayMarkerType = {
|
|
14
|
+
ANNOTATED_CUBE: 1,
|
|
15
|
+
AXES: 2,
|
|
16
|
+
CUSTOM: 3,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The OrientationMarker is a tool that includes an orientation marker in viewports
|
|
21
|
+
* when activated
|
|
22
|
+
*/
|
|
23
|
+
class OrientationMarkerTool extends BaseTool {
|
|
24
|
+
static toolName;
|
|
25
|
+
static CUBE = 1;
|
|
26
|
+
static AXIS = 2;
|
|
27
|
+
static VTPFILE = 3;
|
|
28
|
+
orientationMarkers;
|
|
29
|
+
polyDataURL;
|
|
30
|
+
|
|
31
|
+
static OVERLAY_MARKER_TYPES = OverlayMarkerType;
|
|
32
|
+
|
|
33
|
+
configuration_invalidated = true;
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
toolProps = {},
|
|
37
|
+
defaultToolProps = {
|
|
38
|
+
configuration: {
|
|
39
|
+
orientationWidget: {
|
|
40
|
+
enabled: true,
|
|
41
|
+
viewportCorner: vtkOrientationMarkerWidget.Corners.BOTTOM_RIGHT,
|
|
42
|
+
viewportSize: 0.15,
|
|
43
|
+
minPixelSize: 100,
|
|
44
|
+
maxPixelSize: 300,
|
|
45
|
+
},
|
|
46
|
+
overlayMarkerType:
|
|
47
|
+
OrientationMarkerTool.OVERLAY_MARKER_TYPES.ANNOTATED_CUBE,
|
|
48
|
+
overlayConfiguration: {
|
|
49
|
+
[OrientationMarkerTool.OVERLAY_MARKER_TYPES.ANNOTATED_CUBE]: {
|
|
50
|
+
faceProperties: {
|
|
51
|
+
xPlus: { text: 'R', faceColor: '#ffff00', faceRotation: 90 },
|
|
52
|
+
xMinus: { text: 'L', faceColor: '#ffff00', faceRotation: 270 },
|
|
53
|
+
yPlus: {
|
|
54
|
+
text: 'P',
|
|
55
|
+
faceColor: '#00ffff',
|
|
56
|
+
fontColor: 'white',
|
|
57
|
+
faceRotation: 180,
|
|
58
|
+
},
|
|
59
|
+
yMinus: { text: 'A', faceColor: '#00ffff', fontColor: 'white' },
|
|
60
|
+
zPlus: { text: 'S' },
|
|
61
|
+
zMinus: { text: 'I' },
|
|
62
|
+
},
|
|
63
|
+
defaultStyle: {
|
|
64
|
+
fontStyle: 'bold',
|
|
65
|
+
fontFamily: 'Arial',
|
|
66
|
+
fontColor: 'black',
|
|
67
|
+
fontSizeScale: (res) => res / 2,
|
|
68
|
+
faceColor: '#0000ff',
|
|
69
|
+
edgeThickness: 0.1,
|
|
70
|
+
edgeColor: 'black',
|
|
71
|
+
resolution: 400,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
[OrientationMarkerTool.OVERLAY_MARKER_TYPES.AXES]: {},
|
|
75
|
+
[OrientationMarkerTool.OVERLAY_MARKER_TYPES.CUSTOM]: {
|
|
76
|
+
polyDataURL:
|
|
77
|
+
'https://raw.githubusercontent.com/Slicer/Slicer/80ad0a04dacf134754459557bf2638c63f3d1d1b/Base/Logic/Resources/OrientationMarkers/Human.vtp',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
) {
|
|
83
|
+
super(toolProps, defaultToolProps);
|
|
84
|
+
this.orientationMarkers = {};
|
|
85
|
+
this.configuration_invalidated = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
onSetToolEnabled = (): void => {
|
|
89
|
+
this.initViewports();
|
|
90
|
+
this.configuration_invalidated = true;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
onSetToolActive = (): void => {
|
|
94
|
+
this.initViewports();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
private initViewports() {
|
|
98
|
+
const renderingEngines = getRenderingEngines();
|
|
99
|
+
const renderingEngine = renderingEngines[0];
|
|
100
|
+
|
|
101
|
+
if (!renderingEngine) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let viewports = renderingEngine.getViewports();
|
|
106
|
+
viewports = filterViewportsWithToolEnabled(viewports, this.getToolName());
|
|
107
|
+
viewports.forEach((viewport) => this.addAxisActorInViewport(viewport));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async addAxisActorInViewport(viewport) {
|
|
111
|
+
const viewportId = viewport.id;
|
|
112
|
+
const type = this.configuration.overlayMarkerType;
|
|
113
|
+
|
|
114
|
+
const overlayConfiguration = this.configuration.overlayConfiguration[type];
|
|
115
|
+
|
|
116
|
+
if (this.orientationMarkers[viewportId]) {
|
|
117
|
+
const { actor, orientationWidget } = this.orientationMarkers[viewportId];
|
|
118
|
+
// remove the previous one
|
|
119
|
+
viewport.getRenderer().removeActor(actor);
|
|
120
|
+
orientationWidget.setEnabled(false);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let actor;
|
|
124
|
+
if (type === 1) {
|
|
125
|
+
actor = this.createAnnotationCube(overlayConfiguration);
|
|
126
|
+
} else if (type === 2) {
|
|
127
|
+
actor = vtkAxesActor.newInstance();
|
|
128
|
+
} else if (type === 3) {
|
|
129
|
+
actor = await this.createCustomActor();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const renderer = viewport.getRenderer();
|
|
133
|
+
const renderWindow = viewport
|
|
134
|
+
.getRenderingEngine()
|
|
135
|
+
.offscreenMultiRenderWindow.getRenderWindow();
|
|
136
|
+
|
|
137
|
+
const {
|
|
138
|
+
enabled,
|
|
139
|
+
viewportCorner,
|
|
140
|
+
viewportSize,
|
|
141
|
+
minPixelSize,
|
|
142
|
+
maxPixelSize,
|
|
143
|
+
} = this.configuration.orientationWidget;
|
|
144
|
+
|
|
145
|
+
const orientationWidget = vtkOrientationMarkerWidget.newInstance({
|
|
146
|
+
actor,
|
|
147
|
+
interactor: renderWindow.getInteractor(),
|
|
148
|
+
parentRenderer: renderer,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
orientationWidget.setEnabled(enabled);
|
|
152
|
+
orientationWidget.setViewportCorner(viewportCorner);
|
|
153
|
+
orientationWidget.setViewportSize(viewportSize);
|
|
154
|
+
orientationWidget.setMinPixelSize(minPixelSize);
|
|
155
|
+
orientationWidget.setMaxPixelSize(maxPixelSize);
|
|
156
|
+
|
|
157
|
+
orientationWidget.updateMarkerOrientation();
|
|
158
|
+
this.orientationMarkers[viewportId] = {
|
|
159
|
+
orientationWidget,
|
|
160
|
+
actor,
|
|
161
|
+
};
|
|
162
|
+
renderer.resetCamera();
|
|
163
|
+
renderWindow.render();
|
|
164
|
+
viewport.getRenderingEngine().render();
|
|
165
|
+
|
|
166
|
+
this.configuration_invalidated = false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private async createCustomActor() {
|
|
170
|
+
const url =
|
|
171
|
+
this.configuration.overlayConfiguration[OverlayMarkerType.CUSTOM]
|
|
172
|
+
.polyDataURL;
|
|
173
|
+
|
|
174
|
+
const response = await fetch(url);
|
|
175
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
176
|
+
const vtpReader = vtkXMLPolyDataReader.newInstance();
|
|
177
|
+
vtpReader.parseAsArrayBuffer(arrayBuffer);
|
|
178
|
+
vtpReader.update();
|
|
179
|
+
|
|
180
|
+
const polyData = vtkPolyData.newInstance();
|
|
181
|
+
polyData.shallowCopy(vtpReader.getOutputData());
|
|
182
|
+
polyData.getPointData().setActiveScalars('Color');
|
|
183
|
+
const mapper = vtkMapper.newInstance();
|
|
184
|
+
mapper.setInputData(polyData);
|
|
185
|
+
mapper.setColorModeToDirectScalars();
|
|
186
|
+
|
|
187
|
+
const actor = vtkActor.newInstance();
|
|
188
|
+
actor.setMapper(mapper);
|
|
189
|
+
actor.rotateZ(180);
|
|
190
|
+
return actor;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private createAnnotationCube(overlayConfiguration: any) {
|
|
194
|
+
const actor = vtkAnnotatedCubeActor.newInstance();
|
|
195
|
+
actor.setDefaultStyle({ ...overlayConfiguration.defaultStyle });
|
|
196
|
+
actor.setXPlusFaceProperty({
|
|
197
|
+
...overlayConfiguration.faceProperties.xPlus,
|
|
198
|
+
});
|
|
199
|
+
actor.setXMinusFaceProperty({
|
|
200
|
+
...overlayConfiguration.faceProperties.xMinus,
|
|
201
|
+
});
|
|
202
|
+
actor.setYPlusFaceProperty({
|
|
203
|
+
...overlayConfiguration.faceProperties.yPlus,
|
|
204
|
+
});
|
|
205
|
+
actor.setYMinusFaceProperty({
|
|
206
|
+
...overlayConfiguration.faceProperties.yMinus,
|
|
207
|
+
});
|
|
208
|
+
actor.setZPlusFaceProperty({
|
|
209
|
+
...overlayConfiguration.faceProperties.zPlus,
|
|
210
|
+
});
|
|
211
|
+
actor.setZMinusFaceProperty({
|
|
212
|
+
...overlayConfiguration.faceProperties.zMinus,
|
|
213
|
+
});
|
|
214
|
+
return actor;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async createAnnotatedCubeActor() {
|
|
218
|
+
const axes = vtkAnnotatedCubeActor.newInstance();
|
|
219
|
+
const { faceProperties, defaultStyle } = this.configuration.annotatedCube;
|
|
220
|
+
|
|
221
|
+
axes.setDefaultStyle(defaultStyle);
|
|
222
|
+
|
|
223
|
+
Object.keys(faceProperties).forEach((key) => {
|
|
224
|
+
const methodName = `set${
|
|
225
|
+
key.charAt(0).toUpperCase() + key.slice(1)
|
|
226
|
+
}FaceProperty`;
|
|
227
|
+
axes[methodName](faceProperties[key]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return axes;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
OrientationMarkerTool.toolName = 'OrientationMarker';
|
|
235
|
+
export default OrientationMarkerTool;
|
|
@@ -11,7 +11,6 @@ import { addAnnotation } from '../stateManagement/annotation/annotationState';
|
|
|
11
11
|
import { drawLine as drawLineSvg } from '../drawingSvg';
|
|
12
12
|
import { filterViewportsWithToolEnabled } from '../utilities/viewportFilters';
|
|
13
13
|
import triggerAnnotationRenderForViewportIds from '../utilities/triggerAnnotationRenderForViewportIds';
|
|
14
|
-
|
|
15
14
|
import { PublicToolProps, ToolProps, SVGDrawingHelper } from '../types';
|
|
16
15
|
import { ReferenceLineAnnotation } from '../types/ToolSpecificAnnotationTypes';
|
|
17
16
|
import { StyleSpecifier } from '../types/AnnotationStyle';
|
|
@@ -43,6 +42,7 @@ class ReferenceLines extends AnnotationDisplayTool {
|
|
|
43
42
|
supportedInteractionTypes: ['Mouse', 'Touch'],
|
|
44
43
|
configuration: {
|
|
45
44
|
sourceViewportId: '',
|
|
45
|
+
showFullDimension: false,
|
|
46
46
|
},
|
|
47
47
|
}
|
|
48
48
|
) {
|
|
@@ -177,7 +177,7 @@ class ReferenceLines extends AnnotationDisplayTool {
|
|
|
177
177
|
const bottomLeft = annotation.data.handles.points[2];
|
|
178
178
|
const bottomRight = annotation.data.handles.points[3];
|
|
179
179
|
|
|
180
|
-
const { focalPoint, viewPlaneNormal } = targetViewport.getCamera();
|
|
180
|
+
const { focalPoint, viewPlaneNormal, viewUp } = targetViewport.getCamera();
|
|
181
181
|
const { viewPlaneNormal: sourceViewPlaneNormal } =
|
|
182
182
|
sourceViewport.getCamera();
|
|
183
183
|
|
|
@@ -239,10 +239,21 @@ class ReferenceLines extends AnnotationDisplayTool {
|
|
|
239
239
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
240
240
|
const shadow = this.getStyle('shadow', styleSpecifier, annotation);
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
let canvasCoordinates = [lineStartWorld, lineEndWorld].map((world) =>
|
|
243
243
|
targetViewport.worldToCanvas(world)
|
|
244
244
|
);
|
|
245
245
|
|
|
246
|
+
if (this.configuration.showFullDimension) {
|
|
247
|
+
canvasCoordinates = this.handleFullDimension(
|
|
248
|
+
targetViewport,
|
|
249
|
+
lineStartWorld,
|
|
250
|
+
viewPlaneNormal,
|
|
251
|
+
viewUp,
|
|
252
|
+
lineEndWorld,
|
|
253
|
+
canvasCoordinates
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
246
257
|
const dataId = `${annotationUID}-line`;
|
|
247
258
|
const lineUID = '1';
|
|
248
259
|
drawLineSvg(
|
|
@@ -270,9 +281,126 @@ class ReferenceLines extends AnnotationDisplayTool {
|
|
|
270
281
|
return Math.abs(dot) < EPSILON;
|
|
271
282
|
};
|
|
272
283
|
|
|
284
|
+
private handleFullDimension(
|
|
285
|
+
targetViewport: Types.IStackViewport | Types.IVolumeViewport,
|
|
286
|
+
lineStartWorld: Types.Point3,
|
|
287
|
+
viewPlaneNormal: Types.Point3,
|
|
288
|
+
viewUp: Types.Point3,
|
|
289
|
+
lineEndWorld: Types.Point3,
|
|
290
|
+
canvasCoordinates: Types.Point2[]
|
|
291
|
+
) {
|
|
292
|
+
const renderingEngine = targetViewport.getRenderingEngine();
|
|
293
|
+
const targetId = this.getTargetId(targetViewport);
|
|
294
|
+
const targetImage = this.getTargetIdImage(targetId, renderingEngine);
|
|
295
|
+
|
|
296
|
+
const referencedImageId = this.getReferencedImageId(
|
|
297
|
+
targetViewport,
|
|
298
|
+
lineStartWorld,
|
|
299
|
+
viewPlaneNormal,
|
|
300
|
+
viewUp
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
if (referencedImageId && targetImage) {
|
|
304
|
+
try {
|
|
305
|
+
const { imageData, dimensions } = targetImage;
|
|
306
|
+
|
|
307
|
+
// Calculate bound image coordinates
|
|
308
|
+
const [
|
|
309
|
+
topLeftImageCoord,
|
|
310
|
+
topRightImageCoord,
|
|
311
|
+
bottomRightImageCoord,
|
|
312
|
+
bottomLeftImageCoord,
|
|
313
|
+
] = [
|
|
314
|
+
imageData.indexToWorld([0, 0, 0]) as Types.Point3,
|
|
315
|
+
imageData.indexToWorld([dimensions[0] - 1, 0, 0]) as Types.Point3,
|
|
316
|
+
imageData.indexToWorld([
|
|
317
|
+
dimensions[0] - 1,
|
|
318
|
+
dimensions[1] - 1,
|
|
319
|
+
0,
|
|
320
|
+
]) as Types.Point3,
|
|
321
|
+
imageData.indexToWorld([0, dimensions[1] - 1, 0]) as Types.Point3,
|
|
322
|
+
].map((world) => csUtils.worldToImageCoords(referencedImageId, world));
|
|
323
|
+
|
|
324
|
+
// Calculate line start and end image coordinates
|
|
325
|
+
const [lineStartImageCoord, lineEndImageCoord] = [
|
|
326
|
+
lineStartWorld,
|
|
327
|
+
lineEndWorld,
|
|
328
|
+
].map((world) => csUtils.worldToImageCoords(referencedImageId, world));
|
|
329
|
+
|
|
330
|
+
// Calculate intersection points between line and image bounds
|
|
331
|
+
canvasCoordinates = [
|
|
332
|
+
[topLeftImageCoord, topRightImageCoord],
|
|
333
|
+
[topRightImageCoord, bottomRightImageCoord],
|
|
334
|
+
[bottomLeftImageCoord, bottomRightImageCoord],
|
|
335
|
+
[topLeftImageCoord, bottomLeftImageCoord],
|
|
336
|
+
]
|
|
337
|
+
.map(([start, end]) =>
|
|
338
|
+
this.intersectInfiniteLines(
|
|
339
|
+
start,
|
|
340
|
+
end,
|
|
341
|
+
lineStartImageCoord,
|
|
342
|
+
lineEndImageCoord
|
|
343
|
+
)
|
|
344
|
+
)
|
|
345
|
+
.filter((point) => point && this.isInBound(point, dimensions))
|
|
346
|
+
.map((point) => {
|
|
347
|
+
const world = csUtils.imageToWorldCoords(
|
|
348
|
+
referencedImageId,
|
|
349
|
+
point as Types.Point2
|
|
350
|
+
);
|
|
351
|
+
return targetViewport.worldToCanvas(world);
|
|
352
|
+
});
|
|
353
|
+
} catch (err) {
|
|
354
|
+
console.log(err);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return canvasCoordinates;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// get the intersection point between two infinite lines, not line segments
|
|
361
|
+
intersectInfiniteLines(
|
|
362
|
+
line1Start: Types.Point2,
|
|
363
|
+
line1End: Types.Point2,
|
|
364
|
+
line2Start: Types.Point2,
|
|
365
|
+
line2End: Types.Point2
|
|
366
|
+
) {
|
|
367
|
+
const [x1, y1] = line1Start;
|
|
368
|
+
const [x2, y2] = line1End;
|
|
369
|
+
const [x3, y3] = line2Start;
|
|
370
|
+
const [x4, y4] = line2End;
|
|
371
|
+
|
|
372
|
+
// Compute a1, b1, c1, where line joining points 1 and 2 is "a1 x + b1 y + c1 = 0"
|
|
373
|
+
const a1 = y2 - y1;
|
|
374
|
+
const b1 = x1 - x2;
|
|
375
|
+
const c1 = x2 * y1 - x1 * y2;
|
|
376
|
+
|
|
377
|
+
// Compute a2, b2, c2
|
|
378
|
+
const a2 = y4 - y3;
|
|
379
|
+
const b2 = x3 - x4;
|
|
380
|
+
const c2 = x4 * y3 - x3 * y4;
|
|
381
|
+
|
|
382
|
+
if (Math.abs(a1 * b2 - a2 * b1) < EPSILON) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const x = (b1 * c2 - b2 * c1) / (a1 * b2 - a2 * b1);
|
|
387
|
+
const y = (a2 * c1 - a1 * c2) / (a1 * b2 - a2 * b1);
|
|
388
|
+
|
|
389
|
+
return [x, y];
|
|
390
|
+
}
|
|
391
|
+
|
|
273
392
|
isParallel(vec1: Types.Point3, vec2: Types.Point3): boolean {
|
|
274
393
|
return Math.abs(vec3.dot(vec1, vec2)) > 1 - EPSILON;
|
|
275
394
|
}
|
|
395
|
+
|
|
396
|
+
isInBound(point: number[], dimensions: Types.Point3): boolean {
|
|
397
|
+
return (
|
|
398
|
+
point[0] >= 0 &&
|
|
399
|
+
point[0] <= dimensions[0] &&
|
|
400
|
+
point[1] >= 0 &&
|
|
401
|
+
point[1] <= dimensions[1]
|
|
402
|
+
);
|
|
403
|
+
}
|
|
276
404
|
}
|
|
277
405
|
|
|
278
406
|
ReferenceLines.toolName = 'ReferenceLines';
|
|
@@ -102,6 +102,10 @@ abstract class AnnotationDisplayTool extends BaseTool {
|
|
|
102
102
|
|
|
103
103
|
// for this specific tool
|
|
104
104
|
toolSpecificAnnotations.forEach((annotation) => {
|
|
105
|
+
if (!annotation.metadata?.referencedImageId) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
105
109
|
// if the annotation is drawn on the same imageId
|
|
106
110
|
const referencedImageURI = utilities.imageIdToURI(
|
|
107
111
|
annotation.metadata.referencedImageId
|
package/src/tools/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ import RectangleROIThresholdTool from './segmentation/RectangleROIThresholdTool'
|
|
|
39
39
|
import RectangleROIStartEndThresholdTool from './segmentation/RectangleROIStartEndThresholdTool';
|
|
40
40
|
import BrushTool from './segmentation/BrushTool';
|
|
41
41
|
import PaintFillTool from './segmentation/PaintFillTool';
|
|
42
|
+
import OrientationMarkerTool from './OrientationMarkerTool';
|
|
42
43
|
|
|
43
44
|
export {
|
|
44
45
|
// ~~ BASE
|
|
@@ -84,4 +85,5 @@ export {
|
|
|
84
85
|
ReferenceLines,
|
|
85
86
|
PaintFillTool,
|
|
86
87
|
ScaleOverlayTool,
|
|
88
|
+
OrientationMarkerTool,
|
|
87
89
|
};
|