Good morning,
I am trying to create a web application for a Hospital Lab who has asked for some help. The basic requirement is to render an STL file and then create a pressure map from a series of 144 pressure values for which I have the coordinates.
I have been able to create what I need in Python using @ Kenichiro Yoshimi’s code from this thread however, I’m now struggling to port this to VTK.js. For example, the interpolation looks to be using
gaussian_kernel = vtk.vtkGaussianKernel() gaussian_kernel.SetSharpness(2) gaussian_kernel.SetRadius(12)
which I can’t find in the VTK.js API.
I have written the JS to the point where I am rendering my STL file
Would someone be willing to help me port this code across? Unfortunately, I am not allowed to upload the STL file or pressure file. I have uploaded my code so far below
PYTHON - DOES WHAT I NEED:
import vtk
import numpy as np
points_reader = vtk.vtkDelimitedTextReader()
points_reader.SetFileName('points.txt')
points_reader.DetectNumericColumnsOn()
points_reader.SetFieldDelimiterCharacters(',')
points_reader.SetHaveHeaders(True)
table_points = vtk.vtkTableToPolyData()
table_points.SetInputConnection(points_reader.GetOutputPort())
table_points.SetXColumn('x')
table_points.SetYColumn('y')
table_points.SetZColumn('z')
table_points.Update()
points = table_points.GetOutput()
points.GetPointData().SetActiveScalars('val')
range = points.GetPointData().GetScalars().GetRange()
# Read a probe surface
stl_reader = vtk.vtkSTLReader()
stl_reader.SetFileName('InterpolatingOnSTL_final.stl')
stl_reader.Update()
surface = stl_reader.GetOutput()
bounds = np.array(surface.GetBounds())
dims = np.array([101, 101, 101])
box = vtk.vtkImageData()
box.SetDimensions(dims)
box.SetSpacing((bounds[1::2] - bounds[:-1:2])/(dims - 1))
box.SetOrigin(bounds[::2])
# Gaussian kernel
gaussian_kernel = vtk.vtkGaussianKernel()
gaussian_kernel.SetSharpness(2)
gaussian_kernel.SetRadius(12)
interpolator = vtk.vtkPointInterpolator()
interpolator.SetInputData(box)
interpolator.SetSourceData(points)
interpolator.SetKernel(gaussian_kernel)
resample = vtk.vtkResampleWithDataSet()
resample.SetInputData(surface)
resample.SetSourceConnection(interpolator.GetOutputPort())
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(resample.GetOutputPort())
mapper.SetScalarRange(range)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
point_mapper = vtk.vtkPointGaussianMapper()
point_mapper.SetInputData(points)
point_mapper.SetScalarRange(range)
point_mapper.SetScaleFactor(0.6)
point_mapper.EmissiveOff()
point_mapper.SetSplatShaderCode(
"//VTK::Color::Impl\n"
"float dist = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
"if (dist > 1.0) {\n"
" discard;\n"
"} else {\n"
" float scale = (1.0 - dist);\n"
" ambientColor *= scale;\n"
" diffuseColor *= scale;\n"
"}\n"
)
point_actor = vtk.vtkActor()
point_actor.SetMapper(point_mapper)
renderer = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
renderer.AddActor(actor)
renderer.AddActor(point_actor)
iren.Initialize()
renWin.Render()
iren.Start()
JAVASCRIPT:
import 'vtk.js/Sources/favicon';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkSTLReader from 'vtk.js/Sources/IO/Geometry/STLReader';
const stlFile = './newpivot.stl'
reader.setUrl(stlFile, { binary: true }).then(update)
// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------
const reader = vtkSTLReader.newInstance();
const mapper = vtkMapper.newInstance({ scalarVisibility: false });
const actor = vtkActor.newInstance();
actor.setMapper(mapper);
mapper.setInputConnection(reader.getOutputPort());
// ----------------------------------------------------------------------------
function update() {
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();
const resetCamera = renderer.resetCamera;
const render = renderWindow.render;
renderer.addActor(actor);
resetCamera();
render();
}
// ----------------------------------------------------------------------------
// Use a file reader to load a local file
// ----------------------------------------------------------------------------
// const fileContainer = document.getElementById('container');
// fileContainer.innerHTML = '<input type="file" class="file"/>';
// myContainer.appendChild(fileContainer);
// const fileInput = fileContainer.querySelector('input');
// function handleFile(event) {
// event.preventDefault();
// const dataTransfer = event.dataTransfer;
// const files = event.target.files || dataTransfer.files;
// if (files.length === 1) {
// myContainer.removeChild(fileContainer);
// const fileReader = new FileReader();
// fileReader.onload = function onLoad(e) {
// reader.parseAsArrayBuffer(fileReader.result);
// update();
// };
// fileReader.readAsArrayBuffer(files[0]);
// }
// }
// fileInput.addEventListener('change', handleFile);
// ----------------------------------------------------------------------------
// Use the reader to download a file
// ----------------------------------------------------------------------------
// reader.setUrl(`./socket.stl`, { binary: true }).then(update);
Thank you,
Adam