import 'vtk.js/Sources/Rendering/OpenGL/Profiles/All';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor'; import vtkColorTransferFunction from 'vtk.js/Sources/Rendering/Core/ColorTransferFunction'; import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray'; import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper'; import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow'; import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData'; import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer'; import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow'; import vtkRenderWindowInteractor from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
const EMPTY_CELL_ARRAY = new Uint32Array(0);
export default class VTKGeometryBuilder { constructor(lutMgr, geometryDataModel, pipelineModel, queryDataModel) { this.meshMap = {}; this.initActions = [];
this.firstSceneLoad = true; this.lookupTableManager = lutMgr; this.geometryDataModel = geometryDataModel; this.pipelineModel = pipelineModel; this.queryDataModel = queryDataModel; this.layerMap = this.queryDataModel.originalData.Geometry.layer_map; this.fieldMap = this.queryDataModel.originalData.CompositePipeline.fields;
const updatePipeline = (pipelineQuery, envelope) => { var size = pipelineQuery.length;
for (let i = 0; i < size; i += 2) { const objectName = this.layerMap[pipelineQuery[i]], fieldName = this.fieldMap[pipelineQuery[i + 1]]; if (fieldName) { this.geometryDataModel.loadField(objectName, fieldName); this.updateObjectVisibility(objectName, true); } else { this.updateObjectVisibility(objectName, false); } }
this.queryDataModel.fetchData(); }; this.pipelineModel.onChange(updatePipeline);
this.queryDataModel.onDataChange((data, envelope) => { if (data.scene) { this.geometryDataModel.loadScene(data.scene.data);
if (this.firstSceneLoad) { this.firstSceneLoad = false; updatePipeline(this.pipelineModel.getPipelineQuery()); } } });
this.lookupTableManager.addFields( this.queryDataModel.originalData.Geometry.ranges, this.queryDataModel.originalData.LookupTables ); this.lookupTableManager.onChange((data, envelope) => { this.updateColoring(data.change, data.lut); });
this.renderWindow = vtkRenderWindow.newInstance(); this.renderer = vtkRenderer.newInstance(); this.renderWindow.addRenderer(this.renderer);
this.geometryBuilderSubscription = this.geometryDataModel.onGeometryReady( (data, envelope) => { this.updateGeometry(data); } ); }
destroy() { if (this.geometryBuilderSubscription) { this.geometryBuilderSubscription.unsubscribe(); this.geometryBuilderSubscription = null; } }
configureRenderer(canvas) { this.openGlRenderWindow = vtkOpenGLRenderWindow.newInstance(); this.openGlRenderWindow.setCanvas(canvas); this.renderWindow.addView(this.openGlRenderWindow);
this.interactor = vtkRenderWindowInteractor.newInstance(); this.interactor.setView(this.openGlRenderWindow); this.interactor.initialize(); this.interactor.bindEvents(canvas);
this.render = this.renderWindow.render;
this.queryDataModel.fetchData(); }
updateColoring(whatChanged, lookupTable) { Object.keys(this.meshMap).forEach((name) => { const renderInfo = this.meshMap[name]; if (renderInfo.colorArrayName === lookupTable.name) { renderInfo.mapper.setScalarRange(...lookupTable.getScalarRange()); if (renderInfo.fieldValue !== undefined) { const c = lookupTable.getColor(renderInfo.fieldValue); renderInfo.actor.getProperty().setDiffuseColor(c[0], c[1], c[2]); } if (renderInfo.mapper.getLookupTable().removeAllPoints) { renderInfo.mapper.getLookupTable().removeAllPoints(); lookupTable.controlPoints.forEach(({ x, r, g, b }) => { renderInfo.mapper.getLookupTable().addRGBPoint(x, r, g, b); }); } this.renderWindow.render(); } }); }
updateGeometry(geo) { let firstTime = false; const lut = this.lookupTableManager.getLookupTable(geo.fieldName); if (!(geo.name in this.meshMap)) { firstTime = true; const sha = geo.sha; const source = vtkPolyData.newInstance(); const mapper = vtkMapper.newInstance({ interpolateScalarsBeforeMapping: true, }); const actor = vtkActor.newInstance(); const lookupTable = vtkColorTransferFunction.newInstance(); mapper.setLookupTable(lookupTable);
mapper.setInputData(source); actor.setMapper(mapper);
if (lut) { mapper.setScalarRange(...lut.getScalarRange()); if (lookupTable.removeAllPoints) { lookupTable.removeAllPoints(); lut.controlPoints.forEach(({ x, r, g, b }) => { lookupTable.addRGBPoint(x, r, g, b); }); } }
this.meshMap[geo.name] = { source, mapper, actor, lookupTable, sha, };
source.getPoints().setData(geo.points, 3); ['verts', 'lines', 'polys', 'strips'].forEach((cellType) => { if (geo.cells.indexOf(cellType) === -1) { source.get(cellType)[cellType].setData(EMPTY_CELL_ARRAY); } else { source.get(cellType)[cellType].setData(geo[cellType]); } }); this.renderer.addActor(actor); this.renderer.resetCamera();
this.initActions.forEach((cb) => cb()); } else { let changeDetected = false; const { source, sha } = this.meshMap[geo.name]; if (geo.sha.points !== sha.points) { source.getPoints().setData(geo.points, 3); sha.points = geo.sha.points; changeDetected = true; }
['verts', 'lines', 'polys', 'strips'].forEach((cellType) => { if (geo.cells.indexOf(cellType) === -1) { if (source.get(cellType)[cellType].getData() !== EMPTY_CELL_ARRAY) { source.get(cellType)[cellType].setData(EMPTY_CELL_ARRAY); changeDetected = true; } } else if (geo.sha[cellType] !== sha[cellType]) { source.get(cellType)[cellType].setData(geo[cellType]); sha[cellType] = geo.sha[cellType]; changeDetected = true; } }); if (changeDetected) { source.modified(); } }
this.meshMap[geo.name].colorArrayName = geo.fieldName; const { actor, source, sha } = this.meshMap[geo.name]; if ( sha.field !== geo.sha.field || firstTime || Number.isFinite(geo.field) ) { const fields = { POINT_DATA: source.getPointData(), CELL_DATA: source.getCellData(), }; Object.keys(fields).forEach((key) => fields[key].removeAllArrays());
if (geo.field !== undefined) { const { fieldLocation, fieldName, field } = geo; if (Number.isFinite(field)) { if (lut) { this.meshMap[geo.name].fieldValue = field; const c = lut.getColor(field); actor.getProperty().setDiffuseColor(c[0], c[1], c[2]); } } else { const array = vtkDataArray.newInstance({ name: fieldName, values: field, }); fields[fieldLocation].setScalars(array); } } }
this.renderer.resetCameraClippingRange(); this.renderWindow.render(); }
addInitializationAction(initCallback) { this.initActions.push(initCallback); }
clearInitializationActions() { this.initActions = []; }
getActiveCamera() { return this.renderer.getActiveCamera(); }
getRenderer() { return this.renderer; }
getRenderWindow() { return this.renderWindow; }
render() { this.renderer.resetCameraClippingRange(); this.renderWindow.render(); }
updateObjectVisibility(name, visibility) { if (this.meshMap[name]) { this.meshMap[name].actor.setVisibility(!!visibility); } }
resetCamera() { this.renderer.resetCamera(); this.renderWindow.render(); }
updateSize(width, height) { this.openGlRenderWindow.setSize(width, height); this.renderWindow.render(); } }
|