Skip to content

Commit 1463664

Browse files
authored
fix: 🐛 Fix Parallel Projection with new vtk.js version (#68)
Closes: #66 #65
1 parent c801b5a commit 1463664

File tree

3 files changed

+114
-32
lines changed

3 files changed

+114
-32
lines changed

examples/VTKCrosshairsExample.js

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,99 @@ import React from 'react';
22
import { Component } from 'react';
33
import {
44
View2D,
5+
getImageData,
6+
loadImageData,
57
vtkInteractorStyleMPRCrosshairs,
68
vtkSVGCrosshairsWidget,
79
} from '@vtk-viewport';
8-
import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
10+
import { api as dicomwebClientApi } from 'dicomweb-client';
911
import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
1012
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';
1113

14+
const url = 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs';
15+
const studyInstanceUID =
16+
'1.3.6.1.4.1.14519.5.2.1.2744.7002.373729467545468642229382466905';
17+
const ctSeriesInstanceUID =
18+
'1.3.6.1.4.1.14519.5.2.1.2744.7002.182837959725425690842769990419';
19+
const searchInstanceOptions = {
20+
studyInstanceUID,
21+
};
22+
23+
function loadDataset(imageIds, displaySetInstanceUid) {
24+
const imageDataObject = getImageData(imageIds, displaySetInstanceUid);
25+
26+
loadImageData(imageDataObject);
27+
return imageDataObject;
28+
}
29+
30+
function createStudyImageIds(baseUrl, studySearchOptions) {
31+
const SOP_INSTANCE_UID = '00080018';
32+
const SERIES_INSTANCE_UID = '0020000E';
33+
34+
const client = new dicomwebClientApi.DICOMwebClient({ url });
35+
36+
return new Promise((resolve, reject) => {
37+
client.retrieveStudyMetadata(studySearchOptions).then(instances => {
38+
const imageIds = instances.map(metaData => {
39+
const imageId =
40+
`wadors:` +
41+
baseUrl +
42+
'/studies/' +
43+
studyInstanceUID +
44+
'/series/' +
45+
metaData[SERIES_INSTANCE_UID].Value[0] +
46+
'/instances/' +
47+
metaData[SOP_INSTANCE_UID].Value[0] +
48+
'/frames/1';
49+
50+
cornerstoneWADOImageLoader.wadors.metaDataManager.add(
51+
imageId,
52+
metaData
53+
);
54+
55+
return imageId;
56+
});
57+
58+
resolve(imageIds);
59+
}, reject);
60+
});
61+
}
62+
1263
class VTKCrosshairsExample extends Component {
1364
state = {
1465
volumes: [],
1566
};
1667

17-
componentDidMount() {
68+
async componentDidMount() {
1869
this.apis = [];
1970

20-
const reader = vtkHttpDataSetReader.newInstance({
21-
fetchGzip: true,
22-
});
23-
const volumeActor = vtkVolume.newInstance();
24-
const volumeMapper = vtkVolumeMapper.newInstance();
71+
const imageIds = await createStudyImageIds(url, searchInstanceOptions);
72+
73+
let ctImageIds = imageIds.filter(imageId =>
74+
imageId.includes(ctSeriesInstanceUID)
75+
);
76+
77+
const ctImageDataObject = loadDataset(ctImageIds, 'ctDisplaySet');
2578

26-
volumeActor.setMapper(volumeMapper);
79+
Promise.all(ctImageDataObject.insertPixelDataPromises).then(() => {
80+
const ctImageData = ctImageDataObject.vtkImageData;
2781

28-
reader.setUrl('/vmhead2-large.vti', { loadData: true }).then(() => {
29-
const data = reader.getOutputData();
30-
const range = data
82+
const range = ctImageData
3183
.getPointData()
3284
.getScalars()
3385
.getRange();
3486

35-
const rgbTransferFunction = volumeActor
36-
.getProperty()
37-
.getRGBTransferFunction(0);
87+
const mapper = vtkVolumeMapper.newInstance();
88+
const ctVol = vtkVolume.newInstance();
89+
const rgbTransferFunction = ctVol.getProperty().getRGBTransferFunction(0);
3890

91+
mapper.setInputData(ctImageData);
92+
mapper.setMaximumSamplesPerRay(2000);
3993
rgbTransferFunction.setRange(range[0], range[1]);
40-
41-
volumeMapper.setInputData(data);
94+
ctVol.setMapper(mapper);
4295

4396
this.setState({
44-
volumes: [volumeActor],
97+
volumes: [ctVol],
4598
});
4699
});
47100
}
@@ -53,22 +106,45 @@ class VTKCrosshairsExample extends Component {
53106
const apis = this.apis;
54107
const renderWindow = api.genericRenderWindow.getRenderWindow();
55108

109+
// Add svg widget
56110
api.addSVGWidget(
57111
vtkSVGCrosshairsWidget.newInstance(),
58112
'crosshairsWidget'
59113
);
60114

61115
const istyle = vtkInteractorStyleMPRCrosshairs.newInstance();
62116

117+
// add istyle
63118
api.setInteractorStyle({
64119
istyle,
65120
configuration: { apis, apiIndex: viewportIndex },
66121
});
67122

123+
// set blend mode to MIP.
124+
const mapper = api.volumes[0].getMapper();
125+
if (mapper.setBlendModeToMaximumIntensity) {
126+
mapper.setBlendModeToMaximumIntensity();
127+
}
128+
129+
api.setSlabThickness(0.1);
130+
68131
renderWindow.render();
69132
};
70133
};
71134

135+
handleSlabThicknessChange(evt) {
136+
const value = evt.target.value;
137+
const valueInMM = value / 10;
138+
const apis = this.apis;
139+
140+
apis.forEach(api => {
141+
const renderWindow = api.genericRenderWindow.getRenderWindow();
142+
143+
api.setSlabThickness(valueInMM);
144+
renderWindow.render();
145+
});
146+
}
147+
72148
render() {
73149
if (!this.state.volumes || !this.state.volumes.length) {
74150
return <h4>Loading...</h4>;
@@ -77,34 +153,40 @@ class VTKCrosshairsExample extends Component {
77153
return (
78154
<>
79155
<div className="row">
80-
<div className="col-xs-6">
156+
<div className="col-xs-4">
81157
<p>
82158
This example demonstrates how to use the Crosshairs manipulator.
83159
</p>
160+
<label htmlFor="set-slab-thickness">SlabThickness: </label>
161+
<input
162+
id="set-slab-thickness"
163+
type="range"
164+
name="points"
165+
min="1"
166+
max="5000"
167+
onChange={this.handleSlabThicknessChange.bind(this)}
168+
/>
84169
</div>
85170
</div>
86171
<div className="row">
87-
<div className="col-xs-6 col-xs-6">
172+
<div className="col-sm-4">
88173
<View2D
89174
volumes={this.state.volumes}
90-
onCreated={this.storeApi(2)}
175+
onCreated={this.storeApi(0)}
91176
orientation={{ sliceNormal: [0, 1, 0], viewUp: [0, 0, 1] }}
92177
/>
93178
</div>
94-
<div className="col-xs-6 col-xs-6">
179+
<div className="col-sm-4">
95180
<View2D
96181
volumes={this.state.volumes}
97182
onCreated={this.storeApi(1)}
98183
orientation={{ sliceNormal: [1, 0, 0], viewUp: [0, 0, 1] }}
99184
/>
100185
</div>
101-
</div>
102-
103-
<div className="row">
104-
<div className="col-xs-6 col-xs-6">
186+
<div className="col-sm-4">
105187
<View2D
106188
volumes={this.state.volumes}
107-
onCreated={this.storeApi(0)}
189+
onCreated={this.storeApi(2)}
108190
orientation={{ sliceNormal: [0, 0, 1], viewUp: [0, -1, 0] }}
109191
/>
110192
</div>

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"peerDependencies": {
2424
"react": "^16.8.6",
2525
"react-dom": "^16.8.6",
26-
"vtk.js": "^11.7.1"
26+
"vtk.js": "^11.7.2"
2727
},
2828
"dependencies": {
2929
"date-fns": "^2.2.1",
@@ -81,7 +81,7 @@
8181
"style-loader": "^0.23.1",
8282
"stylelint": "^10.1.0",
8383
"stylelint-config-recommended": "^2.2.0",
84-
"vtk.js": "^11.7.1",
84+
"vtk.js": "^11.7.2",
8585
"webpack": "4.34.0",
8686
"webpack-cli": "^3.3.4",
8787
"webpack-dev-server": "^3.8.0",

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13602,10 +13602,10 @@ vm-browserify@^1.0.1:
1360213602
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
1360313603
integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
1360413604

13605-
vtk.js@^11.7.1:
13606-
version "11.7.1"
13607-
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-11.7.1.tgz#e9527c75d84e292c5d25fc4cacf62d42c777930e"
13608-
integrity sha512-r6KTDYRF+XBq8gvoi27HJs+1DN4E39FX1k9i15el6JXRuZQebnBjWZ0W8XlfM8Nc6AAAax6DdauBFZdhyG0s/Q==
13605+
vtk.js@^11.7.2:
13606+
version "11.7.2"
13607+
resolved "https://registry.yarnpkg.com/vtk.js/-/vtk.js-11.7.2.tgz#451031a4a03756cfdf44c05490c8c28dee80dd3f"
13608+
integrity sha512-ALAJP0gj5kSTOsf/YSicp2wy2YrbCns4vuUQVVKh/vGdlO3npRPt8gxmJLc7QLB2Gwcwl2DKkngu1/q1OC001g==
1360913609
dependencies:
1361013610
blueimp-md5 "2.10.0"
1361113611
commander "2.11.0"

0 commit comments

Comments
 (0)