Hello Forest,
Sorry for the late reply.
I also checked whether I am creating another canvas somewhere but I don’t see any wrong in the code.
However, here’s the code:
function tri_planar(tri_imageData){
var container = document.getElementById('viewContainer');
const openglRenderWindow = vtk.Rendering.OpenGL.vtkRenderWindow.newInstance();
const renderer = vtk.Rendering.Core.vtkRenderer.newInstance();
const renderWindow = vtk.Rendering.Core.vtkRenderWindow.newInstance();
const vtkInteractorStyleTrackballCamera = vtk.Interaction.Style.vtkInteractorStyleTrackballCamera;
const vtkRenderWindowInteractor = vtk.Rendering.Core.vtkRenderWindowInteractor;
const vtkAnnotatedCubeActor = vtk.Rendering.Core.vtkAnnotatedCubeActor;
const vtkOrientationMarkerWidget = vtk.Interaction.Widgets.vtkOrientationMarkerWidget;
const interactor = vtk.Rendering.Core.vtkRenderWindowInteractor.newInstance();
const vtkInteractorStyleManipulator = vtk.Interaction.Style.vtkInteractorStyleManipulator;
const vtkImageSlice = vtk.Rendering.Core.vtkImageSlice;
const vtkImageMapper = vtk.Rendering.Core.vtkImageMapper;
const PiecewiseFun = vtk.Common.DataModel.vtkPiecewiseFunction.newInstance();
const ColorTransFun = vtk.Rendering.Core.vtkColorTransferFunction.newInstance();
container.style.display = 'flex';
container.style.position = 'static';
openglRenderWindow.setContainer(container);
const { width, height } = container.getBoundingClientRect();
openglRenderWindow.setSize(width, height);
renderWindow.addView(openglRenderWindow);
const imageActorI = vtkImageSlice.newInstance(); // 2D YZ images.
const imageActorJ = vtkImageSlice.newInstance(); // 2D XZ images.
const imageActorK = vtkImageSlice.newInstance(); // 2D XY images.
const imageMapperK = vtkImageMapper.newInstance();
const imageMapperJ = vtkImageMapper.newInstance();
const imageMapperI = vtkImageMapper.newInstance();
function getCenterOfScene (renderer) {
const bounds = renderer.computeVisiblePropBounds();
const center = [0, 0, 0];
center[0] = (bounds[0] + bounds[1]) / 2.0;
center[1] = (bounds[2] + bounds[3]) / 2.0;
center[2] = (bounds[4] + bounds[5]) / 2.0;
return center;
}
function updateColorLevel(e) {
const colorLevel = Number((e ? e.target : document.querySelector('.colorLevel')).value);
imageActorI.getProperty().setColorLevel(colorLevel);
imageActorJ.getProperty().setColorLevel(colorLevel);
imageActorK.getProperty().setColorLevel(colorLevel);
renderWindow.render();
};
function updateColorWindow(e) {
const colorLevel = Number((e ? e.target : document.querySelector('.colorWindow')).value);
imageActorI.getProperty().setColorWindow(colorLevel);
imageActorJ.getProperty().setColorWindow(colorLevel);
imageActorK.getProperty().setColorWindow(colorLevel);
renderWindow.render();
};
const viewColors = [
[0.0, 0.0, 0.0], // sagittal
[0.0, 0.0, 0.0], // coronal
[0.0, 0.0, 0.0], // axial
];
function createRGBStringFromRGBValues(rgb) {
if (rgb.length !== 3) {
return 'rgb(0, 0, 0)';
}
return `rgb(${(rgb[0] * 255).toString()}, ${(rgb[1] * 255).toString()}, ${(rgb[2] * 255).toString()})`;
}
imageI = []
imageJ = []
imageK = []
for (y = 0; y < tri_imageData.length; y++){
const dataRange = tri_imageData[y].getPointData().getScalars().getRange();
const extent = tri_imageData[y].getExtent();
tri_imageData[y].setOrigin(0.0, 0.0, 0.0)
image_origin = tri_imageData[y].getOrigin();
console.log(image_origin)
imageMapperK.setInputData(tri_imageData[y]);
imageMapperK.setKSlice(0);
imageActorK.setMapper(imageMapperK);
imageMapperJ.setInputData(tri_imageData[y]);
imageMapperJ.setJSlice(0);
imageActorJ.setMapper(imageMapperJ);
imageMapperI.setInputData(tri_imageData[y]);
imageMapperI.setISlice(0);
imageActorI.setMapper(imageMapperI);
renderer.addActor(imageActorK);
renderer.addActor(imageActorJ);
renderer.addActor(imageActorI);
['.YZ', '.XZ', '.XY'].forEach((selector, idx) => {
const el = document.querySelector(selector);
el.setAttribute('min', extent[idx * 2 + 0]);
el.setAttribute('max', extent[idx * 2 + 1]);
el.setAttribute('value', 0);
});
['.colorLevel', '.colorWindow'].forEach((selector) => {
document.querySelector(selector).setAttribute('max', dataRange[1]);
document.querySelector(selector).setAttribute('value', dataRange[1]);
});
document.querySelector('.colorLevel').setAttribute('value', (dataRange[0] + dataRange[1]) / 2);
updateColorLevel();
updateColorWindow();
const axes = vtkAnnotatedCubeActor.newInstance();
axes.setDefaultStyle({text: '+X', fontStyle: 'bold', fontFamily: 'Arial', fontColor: 'white',
faceColor: createRGBStringFromRGBValues(viewColors[0]), edgeThickness: 0.1, edgeColor: 'white',
resolution: 1600,
});
axes.setXMinusFaceProperty({text: '-X', faceColor: createRGBStringFromRGBValues(viewColors[0]),
});
axes.setYPlusFaceProperty({text: '+Y', faceColor: createRGBStringFromRGBValues(viewColors[1]),
});
axes.setYMinusFaceProperty({text: '-Y', faceColor: createRGBStringFromRGBValues(viewColors[1]),
});
axes.setZPlusFaceProperty({text: '+Z', faceColor: createRGBStringFromRGBValues(viewColors[2]),
});
axes.setZMinusFaceProperty({text: '-Z', faceColor: createRGBStringFromRGBValues(viewColors[2]),
});
// create orientation widget
orientationWidget = vtkOrientationMarkerWidget.newInstance({actor: axes, interactor: interactor});
setTimeout(() => {
orientationWidget.setEnabled(true);
orientationWidget.setViewportCorner(vtkOrientationMarkerWidget.Corners.BOTTOM_RIGHT);
orientationWidget.setViewportSize(0.15);
orientationWidget.setMinPixelSize(20);
orientationWidget.setMaxPixelSize(80);
}, 1);
window.onresize = () => {orientationWidget.updateViewport();}
imageI = imageActorI // 2D YZ images.
imageJ = imageActorJ// 2D XZ images.
imageK = imageActorK // 2D XY images.
}
document.querySelector('.YZ').addEventListener('input', (e) => {
imageActorI.getMapper().setISlice(Number(e.target.value));
renderWindow.render();
});
document.querySelector('.XZ').addEventListener('input', (e) => {
imageActorJ.getMapper().setJSlice(Number(e.target.value));
renderWindow.render();
});
document.querySelector('.XY').addEventListener('input', (e) => {
imageActorK.getMapper().setKSlice(Number(e.target.value));
renderWindow.render();
});
document.querySelector('.colorLevel').addEventListener('input', updateColorLevel);
document.querySelector('.colorWindow').addEventListener('input', updateColorWindow);
var edge_K = edge_J = edge_I = true;
$("#XY_button").on('click', function() {
imageK.setVisibility(edge_K);
renderWindow.render();
edge_K = !(edge_K);
});
$("#XZ_button").on('click', function() {
imageJ.setVisibility(edge_J);
renderWindow.render();
edge_J = !(edge_J);
});
$("#YZ_button").on('click', function() {
imageI.setVisibility(edge_I);
renderWindow.render();
edge_I = !(edge_I);
});
// const interactor = vtkRenderWindowInteractor.newInstance();
renderWindow.addRenderer(renderer);
interactor.setView(openglRenderWindow);
interactor.initialize();
interactor.bindEvents(container);
const center = getCenterOfScene(renderer);
const iStyle = vtkInteractorStyleManipulator.newInstance();
iStyle.setCenterOfRotation(center);
renderWindow.getInteractor().setInteractorStyle(iStyle);
renderer.resetCamera();
renderer.resetCameraClippingRange();
renderWindow.render()
}
I am too wondering why it’s creating two canvases.
Any suggestion regarding it?
And another question about .tif image.
C1-sample1_single.zip (3.0 MB)
Above I have uploaded a .tif image. When I open it in a glance-vtk viewer, the viewer can’t seem to render this file. The 3D viewer is blank at a glance.
I think it’s because of the alpha channel. And when I render it in my viewer it shows a black screen in composite mode and solid color in MaxIP like below.
Is it possible to ignore that channel while rendering it in 3D volume?
Thank you!