Я изучаю vtk. js и пытаюсь манипулировать файлом vti с помощью объектной архитектуры, но у меня есть некоторые проблемы с камерой. Когда я пытаюсь визуализировать трехмерный вид моего файла vti, он работает отлично, но когда я пробую вид срезов, он работает, но каждый раз, когда я изменяю прозрачность или срезы с помощью мыши, это вызывает у меня массу ошибок в консоли: «Неверный или отсутствует input 'and' No input 'в myfilename. js: отформатирован: 207.
Я знаю, что это как-то связано с тем, что я не объявляю свой рендерер и окно рендеринга в одном блоке как мои операции нарезки, но это работает для моего трехмерного изображения, поэтому я не понимаю.
Спасибо за ваше время.
import vtkFullScreenWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkHttpDataSetReader from 'vtk.js/Sources/IO/Core/HttpDataSetReader';
import vtkColorTransferFunction from 'vtk.js/Sources/Rendering/Core/ColorTransferFunction';
import vtkColorMaps from 'vtk.js/Sources/Rendering/Core/ColorTransferFunction/ColorMaps';
import vtkPiecewiseFunction from 'vtk.js/Sources/Common/DataModel/PiecewiseFunction';
import vtkVolume from 'vtk.js/Sources/Rendering/Core/Volume';
import vtkVolumeMapper from 'vtk.js/Sources/Rendering/Core/VolumeMapper';
import vtkOutlineFilter from 'vtk.js/Sources/Filters/General/OutlineFilter'
import vtkImageSlice from 'vtk.js/Sources/Rendering/Core/ImageSlice'
import vtkImageMapper from 'vtk.js/Sources/Rendering/Core/ImageMapper'
import vtkInteractorStyleImage from 'vtk.js/Sources/Interaction/Style/InteractorStyleImage'
import ImageConstants from 'vtk.js/Sources/Rendering/Core/ImageMapper/Constants'
import { AttributeTypes } from 'vtk.js/Sources/Common/DataModel/DataSetAttributes/Constants';
import { FieldDataTypes } from 'vtk.js/Sources/Common/DataModel/DataSet/Constants';
const { SlicingMode } = ImageConstants;
import controlPanel from './controller.html';
import {render} from "vtk.js/Sources/Widgets/Core/WidgetManager/vdom";
var mapPreset = require('../node_modules/vtk.js/Sources/Rendering/Core/ColorTransferFunction/ColorMaps.json')
class ThreeDViewer{
constructor() {
this.actor = vtkVolume.newInstance();
this.mapper = vtkVolumeMapper.newInstance();
this.actor.setMapper(this.mapper);
console.log('3dViewer initialised.');
}
}
class SliceViewer{
constructor() {
this.actor = vtkImageSlice.newInstance();
this.mapper = vtkImageMapper.newInstance();
this.istyle = vtkInteractorStyleImage.newInstance();
this.mapper.setSliceAtFocalPoint(true);
this.mapper.setSlicingMode(SlicingMode.Z);
this.actor.setMapper(this.mapper);
this.actor.getProperty().setColorWindow(255);
this.actor.getProperty().setColorLevel(127);
this.istyle.setInteractionMode('IMAGE_SLICING');
console.log('SliceViewer initialised.');
}
}
class filterManager{
constructor() {
this.filter = vtkOutlineFilter.newInstance();
this.actor = vtkActor.newInstance();
this.mapper = vtkMapper.newInstance();
console.log('FilterManager initialised.');
this.actor.setMapper(this.mapper);
this.mapper.setInputConnection(this.filter.getOutputPort());
console.log('FilterManager set up. Ready to use.');
}
}
class ReaderManager{
constructor(dataUrl) {
this.url = url;
this.reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true });
}
loadData() {
return new Promise((resolve) => {
this.reader.setUrl(this.url)
.then(() => this.reader.loadData())
.then(() => resolve("DATA LOADED"));
})
}
}
class Visualizer{
constructor(mode, showfilter, mapColorPreset, opacity, dataURL){
this.mode = mode;
this.showFilter = showfilter;
this.mapColorPreset = mapColorPreset;
this.opacity = opacity;
this.threeDViewer = new ThreeDViewer();
this.sliceViewer = new SliceViewer();
this.filterManager = new filterManager();
this.readerManager = new ReaderManager(dataURL);
this.fullScreenRenderer = vtkFullScreenWindow.newInstance();
this.renderer = this.fullScreenRenderer.getRenderer();
this.renderWindow = this.fullScreenRenderer.getRenderWindow();
console.log('Visualizer initialised.');
this.updateMode(this.mode);
console.log('Visualizer mode set up.');
this.updateOpacity();
console.log('Visualizer opacity set up.');
console.log(this.showProperties());
this.updateFilter();
console.log('Visualizer filter set up.');
this.updateMapColorPreset();
console.log('Visualizer map preset set up.');
}
showProperties(){
return 'Visualizer for: ' + this.readerManager.url
+ ' in mode ' + this.mode
+ '. Color preset: ' + this.mapColorPreset
+ '. Opacity: ' + this.opacity
+ '. Filter: ' + this.showFilter;
}
updateMode(mode) {
switch(mode){
case '3d':
this.threeDViewer.mapper.setInputConnection(this.readerManager.reader.getOutputPort());
this.filterManager.filter.setInputConnection(this.readerManager.reader.getOutputPort());
this.readerManager.loadData()
.then(() => {
this.renderer.addVolume(this.threeDViewer.actor);
this.showRenderer();
});
break;
case 'Slicing':
this.sliceViewer.mapper.setInputConnection(this.readerManager.reader.getOutputPort());
this.readerManager.loadData()
.then(() => {
this.renderer.addActor(this.sliceViewer.actor);
this.showRenderer();
});
break;
default:
console.log('This mode doesn`\'t exist');
}
}
showRenderer(){
console.log('try render');
this.renderer.resetCamera();
console.log('Reset camera. Done.');
this.renderWindow.render();
console.log('Rendering Data. Done.');
}
updateOpacity(){
const piecewisefun = vtkPiecewiseFunction.newInstance();
for (let i = 0; i <= 8; i++){
piecewisefun.addPoint(i * 32, i / 8 + this.opacity);
}
this.threeDViewer.actor.getProperty().setScalarOpacity(0, piecewisefun);
}
updateFilter(){
if (this.showFilter){
this.renderer.addActor(this.filterManager.actor);
}else{
this.renderer.removeActor(this.filterManager.actor);
}
}
updateMapColorPreset(){
if (this.mapColorPreset == '') {
const lookupTable = vtkColorTransferFunction.newInstance();
lookupTable.removeAllPoints();
this.threeDViewer.actor.getProperty().setRGBTransferFunction(0, lookupTable);
} else {
const lookupTable = vtkColorTransferFunction.newInstance();
lookupTable.applyColorMap(vtkColorMaps.getPresetByName(this.mapColorPreset));
lookupTable.setMappingRange(0, 256);
lookupTable.updateRange()
this.threeDViewer.actor.getProperty().setRGBTransferFunction(0, lookupTable);
}
}
}
//Main
const url = 'https://kitware.github.io/vtk-js/data/volume/LIDC2.vti';
let visualizationManager = new Visualizer('Slicing', 'true', '', '0', url);
visualizationManager.fullScreenRenderer.addController(controlPanel);
const opacitySelector = document.querySelector('#opacity');
const filterSelector = document.querySelector('#filter');
const colorSelector = document.querySelector('#colorTransfers');
//Adding all mapPreset for vtkColorTransferFunction to HTML selector
mapPreset = JSON.parse(JSON.stringify(mapPreset));
for (let i=0; i<mapPreset.length; i++){
if (mapPreset[i].RGBPoints != null){
const opt = document.createElement('option');
opt.appendChild(document.createTextNode(mapPreset[i].Name));
opt.value = mapPreset[i].Name;
console.log('Adding: ' + opt.value);
colorSelector.appendChild(opt);
}else{
console.log('Removing: ' + mapPreset[i].Name);
}
}
opacitySelector.addEventListener('change', (e) => {
const newOpacityValue = Number(e.target.value) / 1000;
console.log('newOpacityValue :' + newOpacityValue);
visualizationManager.opacity = newOpacityValue;
visualizationManager.updateOpacity();
visualizationManager.showRenderer();
});
filterSelector.addEventListener('change', (e) => {
const newFilterValue = Boolean(e.target.checked);
console.log(Boolean(e.target.checked));
visualizationManager.showFilter = newFilterValue;
visualizationManager.updateFilter();
visualizationManager.showRenderer();
});
colorSelector.addEventListener('change', (e) => {
const newColorValue = String(e.target.value);
console.log('newColorValue :', newColorValue);
visualizationManager.mapColorPreset = newColorValue;
visualizationManager.updateMapColorPreset();
visualizationManager.showRenderer();
});