Hi,
I am trying to add multiple orthogonal views of the same image using vtk.js.
I have duplicated the procedure for loading on volume slicing twice to achieve the goal.
For some reason, the 2nd view is not working.
Can anyone help me understand what I might be doing wrong?
Below is my index.js -
import macro, { chain } from ‘vtk.js/Sources/macro’;
console.log('vtk.js imported: ', macro);
// ----------------------------------------------------------------------------
// Standard renderWindow
// ----------------------------------------------------------------------------
//import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkopenglRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow';
import vtkRenderWindowInteractor from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer';
import vtkInteractorStyleTrackballCamera from 'vtk.js/Sources/Interaction/Style/InteractorStyleTrackballCamera';
// ----------------------------------------------------------------------------
// Standard HttpDataReader for loading remote dataset
// Standard XMLImageDataReader for loading images
// ----------------------------------------------------------------------------
//import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
import vtkXMLImageDataReader from 'vtk.js/Sources/IO/XML/XMLImageDataReader';
// ----------------------------------------------------------------------------
// Standard Volume slicing Actor and Mapper import
// ----------------------------------------------------------------------------
import vtkImageMapper from 'vtk.js/Sources/Rendering/Core/ImageMapper';
import vtkImageSlice from 'vtk.js/Sources/Rendering/Core/ImageSlice';
import vtkInteractorStyleImage from 'vtk.js/Sources/Interaction/Style/InteractorStyleImage';
import ImageConstants, { SlicingMode } from 'vtk.js/Sources/Rendering/Core/ImageMapper/Constants';
// ----------------------------------------------------------------------------
// Standard rendering instantiation
// ----------------------------------------------------------------------------
// const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
// const renderer = fullScreenRenderer.getRenderer({ background: [0.2, 0.3, 0.4] });
// const renderWindow = fullScreenRenderer.getRenderWindow();
const renderWindow = vtkRenderWindow.newInstance();
const renderWindow2 = vtkRenderWindow.newInstance();
const renderer = vtkRenderer.newInstance({ background: [0.2, 0.3, 0.4] });
const renderer2 = vtkRenderer.newInstance({ background: [0.2, 0.3, 0.4] });
renderWindow.addRenderer(renderer);
renderWindow2.addRenderer(renderer2);
// ----------------------------------------------------------------------------
// Use OpenGL as the backend to view the all this
// Multiple views can be added
// ----------------------------------------------------------------------------
const openglRenderWindow = vtkopenglRenderWindow.newInstance();
const openglRenderWindow2 = vtkopenglRenderWindow.newInstance();
renderWindow.addView(openglRenderWindow);
renderWindow2.addView(openglRenderWindow2);
// ----------------------------------------------------------------------------
// Create a div section to put this into
// ----------------------------------------------------------------------------
//const container1 = document.createElement('div');
//document.querySelector('body').appendChild(container1);
const container1 = document.getElementById('container1');
openglRenderWindow.setContainer(container1);
const container2 = document.getElementById('container2');
openglRenderWindow2.setContainer(container2);
// ----------------------------------------------------------------------------
// Capture size of the container and set it to the renderWindow
// ----------------------------------------------------------------------------
const { width, height } = container1.getBoundingClientRect();
openglRenderWindow.setSize(width, height);
const { width2, height2 } = container2.getBoundingClientRect();
openglRenderWindow2.setSize(width2, height2);
// ----------------------------------------------------------------------------
// Setup an interactor to handle mouse events
// ----------------------------------------------------------------------------
const interactor = vtkRenderWindowInteractor.newInstance();
interactor.setView(openglRenderWindow);
interactor.initialize();
interactor.bindEvents(container1);
const interactor2 = vtkRenderWindowInteractor.newInstance();
interactor2.setView(openglRenderWindow2);
interactor2.initialize();
interactor2.bindEvents(container2);
// ----------------------------------------------------------------------------
// Setup interactor style to use
// ----------------------------------------------------------------------------
interactor.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance());
interactor2.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance());
// renderer camera to parallel projection
renderer.getActiveCamera(0).setParallelProjection(true);
renderer2.getActiveCamera(0).setParallelProjection(true);
// --- Setting slicing mode ---
const { slicingMode } = ImageConstants;
// --- Set up interactor style for image slicing
const istyle = vtkInteractorStyleImage.newInstance();
istyle.setInteractionMode('IMAGE_SLICING');
renderWindow.getInteractor(0).setInteractorStyle(istyle);
const istyle2 = vtkInteractorStyleImage.newInstance();
istyle2.setInteractionMode('IMAGE_SLICING');
renderWindow2.getInteractor(0).setInteractorStyle(istyle2);
// --- setup the slicing actor ---
const slicingActor = vtkImageSlice.newInstance();
const slicingMapper = vtkImageMapper.newInstance();
const slicingActor2 = vtkImageSlice.newInstance();
const slicingMapper2 = vtkImageMapper.newInstance();
slicingMapper.setSliceAtFocalPoint(true);
slicingMapper.setSlicingMode(SlicingMode.Z);
slicingMapper2.setSliceAtFocalPoint(true);
slicingMapper2.setSlicingMode(SlicingMode.X);
// Tell actor which mapper to use
slicingActor.setMapper(slicingMapper);
slicingActor2.setMapper(slicingMapper2);
// --- load local dataset ---
const input = document.querySelector('input[type="file"]')
input.addEventListener('change', function(e) {
console.log(input.files)
const reader = new FileReader()
reader.onload = function () {
const vtiReader = vtkXMLImageDataReader.newInstance();
vtiReader.parseAsArrayBuffer(reader.result);
slicingMapper.setInputData(vtiReader.getOutputData(0))
slicingMapper2.setInputData(vtiReader.getOutputData(0))
renderer.addActor(slicingActor);
renderer2.addActor(slicingActor2);
renderer.resetCamera();
renderWindow.render();
renderer2.resetCamera();
renderWindow2.render();
}
reader.readAsArrayBuffer(input.files[0])
}, false)
// --- Expose globals so we can play with values in the dev console ---
global.renderWindow = renderWindow;
global.renderer = renderer;
global.slicingActor = slicingActor;
global.slicingMapper = slicingMapper;
===========================================================
My index.html -
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shapework Data Portal</title>
<!--
<style type="text/css">
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
-->
<style type="text/css">
.h1_heading {
text-align: center;
}
.image_container {
width: 25%;
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
padding-bottom: 5px;
border: 2px solid black;
position: relative;
}
.left {
}
.middle {
}
.right {
}
</style>
</head>
<body>
<h1 class="h1_heading">ShapeWorks Data Portal </h1>
<div id="container"></div>
<input type="file">
<p>container1</p>
<div class="image_container left" id = "container1"></div>
<p>container2</p>
<div class="image_container middle" id = "container2"></div>
<p>container3</p>
<div class="image_container right" id = "container3"></div>
<script type="text/javascript" src="./app.js"></script>
</body>
</html>
===========================================================
Thanks in advance.