@cornerstonejs/tools 1.17.1 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "1.17.1",
3
+ "version": "1.18.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.17.1",
32
+ "@cornerstonejs/core": "^1.18.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": "ad1027f35619023f6b549bf254fcf4638eb3abf1"
55
+ "gitHead": "a3a41620de2a91c64588493e6a332c3808145e91"
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;
@@ -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
  };