Skip to content

Commit fef6f39

Browse files
feat(sliceHelper): add helper for slicing imageMapper with clip planes
To deprecate vtkInteractorStyleMPRSlice I add a helper using two clip planes instead. The included example is similar to vtkInteractorStyleMPRSlice example. re #1872
1 parent 129f4bf commit fef6f39

File tree

4 files changed

+145
-1
lines changed

4 files changed

+145
-1
lines changed

Examples/Volume/MPRSlice/index.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import 'vtk.js/Sources/favicon';
2+
/* eslint-disable */
3+
4+
import 'vtk.js/Sources/Rendering/Profiles/Volume';
5+
6+
// Force DataAccessHelper to have access to various data source
7+
import 'vtk.js/Sources/IO/Core/DataAccessHelper/HtmlDataAccessHelper';
8+
import 'vtk.js/Sources/IO/Core/DataAccessHelper/HttpDataAccessHelper';
9+
import 'vtk.js/Sources/IO/Core/DataAccessHelper/JSZipDataAccessHelper';
10+
11+
import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
12+
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
13+
import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
14+
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';
15+
16+
// ----------------------------------------------------------------------------
17+
// Standard rendering code setup
18+
// ----------------------------------------------------------------------------
19+
20+
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
21+
background: [0, 0, 0],
22+
});
23+
const renderer = fullScreenRenderer.getRenderer();
24+
const renderWindow = fullScreenRenderer.getRenderWindow();
25+
26+
global.fullScreen = fullScreenRenderer;
27+
global.renderWindow = renderWindow;
28+
29+
// ----------------------------------------------------------------------------
30+
// Example code
31+
// ----------------------------------------------------------------------------
32+
33+
const reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
34+
const actor = vtkVolume.newInstance();
35+
const mapper = vtkVolumeMapper.newInstance();
36+
mapper.setSampleDistance(1.1);
37+
actor.setMapper(mapper);
38+
mapper.setInputConnection(reader.getOutputPort());
39+
40+
const mprSlice = vtkVolumeMapper.vtkSliceHelper.newInstance();
41+
mprSlice.setMapper(mapper);
42+
43+
reader.setUrl(`${__BASE_PATH__}/data/volume/headsq.vti`).then(() => {
44+
reader.loadData().then(() => {
45+
const data = reader.getOutputData();
46+
renderer.addVolume(actor);
47+
const [xMin, xMax, yMin, yMax, zMin, zMax] = data.getBounds();
48+
mprSlice.setOrigin((xMin + xMax) / 2, (yMin + yMax) / 2, (zMin + zMax) / 2);
49+
50+
renderer.resetCamera();
51+
renderWindow.render();
52+
});
53+
});
54+
55+
// Set MPR slice to follow camera orientation
56+
const camera = renderer.getActiveCamera();
57+
camera.onModified(() => {
58+
const direction = camera.getDirectionOfProjection();
59+
mprSlice.setNormal(direction);
60+
});
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import macro from 'vtk.js/Sources/macros';
2+
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
3+
import vtkPlane from 'vtk.js/Sources/Common/DataModel/Plane';
4+
5+
function vtkSliceHelper(publicAPI, model) {
6+
model.classHierarchy.push('vtkSliceHelper');
7+
8+
model.clipPlane1 = vtkPlane.newInstance();
9+
model.clipPlane2 = vtkPlane.newInstance();
10+
11+
const superClass = { ...publicAPI };
12+
13+
function update() {
14+
const n1 = model.clipPlane1.getNormalByReference();
15+
n1[0] = model.normal[0];
16+
n1[1] = model.normal[1];
17+
n1[2] = model.normal[2];
18+
19+
const n2 = model.clipPlane2.getNormalByReference();
20+
n2[0] = -model.normal[0];
21+
n2[1] = -model.normal[1];
22+
n2[2] = -model.normal[2];
23+
24+
vtkMath.multiplyAccumulate(
25+
model.origin,
26+
model.normal,
27+
-model.thickness / 2,
28+
model.clipPlane1.getOriginByReference()
29+
);
30+
31+
vtkMath.multiplyAccumulate(
32+
model.origin,
33+
model.normal,
34+
model.thickness / 2,
35+
model.clipPlane2.getOriginByReference()
36+
);
37+
38+
model.clipPlane1.modified();
39+
model.clipPlane2.modified();
40+
}
41+
42+
const subscription = publicAPI.onModified(update);
43+
publicAPI.delete = () => {
44+
superClass.delete();
45+
subscription.unsubscribe();
46+
};
47+
48+
publicAPI.setMapper = (mapper) => {
49+
mapper.addClippingPlane(model.clipPlane1);
50+
mapper.addClippingPlane(model.clipPlane2);
51+
};
52+
}
53+
54+
// ----------------------------------------------------------------------------
55+
// Object factory
56+
// ----------------------------------------------------------------------------
57+
58+
const DEFAULT_VALUES = {
59+
thickness: 3,
60+
origin: [0, 0, 0],
61+
normal: [1, 0, 0],
62+
};
63+
64+
export function extend(publicAPI, model, initialValues = {}) {
65+
Object.assign(model, DEFAULT_VALUES, initialValues);
66+
67+
// Build VTK API
68+
macro.obj(publicAPI, model);
69+
macro.setGet(publicAPI, model, ['thickness']);
70+
macro.setGetArray(publicAPI, model, ['origin', 'normal'], 3);
71+
72+
// Object methods
73+
vtkSliceHelper(publicAPI, model);
74+
}
75+
76+
// ----------------------------------------------------------------------------
77+
78+
export const newInstance = macro.newInstance(extend, 'vtkSliceHelper');
79+
80+
// ----------------------------------------------------------------------------
81+
82+
export default { newInstance, extend };

Sources/Rendering/Core/VolumeMapper/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import macro from 'vtk.js/Sources/macros';
22
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
33
import Constants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants';
44
import vtkAbstractMapper from 'vtk.js/Sources/Rendering/Core/AbstractMapper';
5+
import vtkSliceHelper from 'vtk.js/Sources/Rendering/Core/VolumeMapper/SliceHelper';
56

67
const { BlendMode, FilterMode } = Constants;
78

@@ -126,4 +127,4 @@ export const newInstance = macro.newInstance(extend, 'vtkVolumeMapper');
126127

127128
// ----------------------------------------------------------------------------
128129

129-
export default { newInstance, extend };
130+
export default { newInstance, extend, vtkSliceHelper };

Sources/Rendering/Core/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export default {
7979
vtkRenderWindowInteractor,
8080
vtkScalarBarActor,
8181
vtkSkybox,
82+
vtkSliceHelper: vtkVolumeMapper.vtkSliceHelper,
8283
vtkSphereMapper,
8384
vtkStickMapper,
8485
vtkTexture,

0 commit comments

Comments
 (0)