import '@kitware/vtk.js/favicon';
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'; import vtkCalculator from '@kitware/vtk.js/Filters/General/Calculator'; import vtkConeSource from '@kitware/vtk.js/Filters/Sources/ConeSource'; import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'; import vtkOpenGLHardwareSelector from '@kitware/vtk.js/Rendering/OpenGL/HardwareSelector'; import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper'; import { AttributeTypes } from '@kitware/vtk.js/Common/DataModel/DataSetAttributes/Constants'; import { FieldDataTypes, FieldAssociations, } from '@kitware/vtk.js/Common/DataModel/DataSet/Constants'; import vtkSphereSource from '@kitware/vtk.js/Filters/Sources/SphereSource';
import vtkFPSMonitor from '@kitware/vtk.js/Interaction/UI/FPSMonitor';
import controlPanel from './controller.html';
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background: [0, 0, 0], }); const renderer = fullScreenRenderer.getRenderer(); const renderWindow = fullScreenRenderer.getRenderWindow(); const openGLRenderWindow = fullScreenRenderer.getApiSpecificRenderWindow();
const fpsMonitor = vtkFPSMonitor.newInstance(); const fpsElm = fpsMonitor.getFpsMonitorContainer(); fpsElm.style.position = 'absolute'; fpsElm.style.left = '10px'; fpsElm.style.bottom = '10px'; fpsElm.style.background = 'rgba(255,255,255,0.5)'; fpsElm.style.borderRadius = '5px';
const container = document.querySelector('body'); fpsMonitor.setContainer(container); fpsMonitor.setRenderWindow(renderWindow);
fullScreenRenderer.setResizeCallback(fpsMonitor.update);
const selector = vtkOpenGLHardwareSelector.newInstance({ captureZValues: true, }); selector.setFieldAssociation(FieldAssociations.FIELD_ASSOCIATION_POINTS); selector.attach(openGLRenderWindow, renderer);
const coneSource = vtkConeSource.newInstance({ center: [0, 1, 1000], height: 1.0, });
const filter = vtkCalculator.newInstance();
filter.setInputConnection(coneSource.getOutputPort());
filter.setFormula({ getArrays: (inputDataSets) => ({ input: [], output: [ { location: FieldDataTypes.CELL, name: 'Random', dataType: 'Float32Array', attribute: AttributeTypes.SCALARS, }, ], }), evaluate: (arraysIn, arraysOut) => { const [scalars] = arraysOut.map((d) => d.getData()); for (let i = 0; i < scalars.length; i++) { scalars[i] = Math.random(); } }, });
const mapper = vtkMapper.newInstance(); mapper.setInputConnection(filter.getOutputPort());
const actor = vtkActor.newInstance(); actor.setMapper(mapper);
const sphereSource = vtkSphereSource.newInstance({ center: [0, 1, 1000], radius: 0.02, }); const mapper1 = vtkMapper.newInstance(); mapper1.setInputConnection(sphereSource.getOutputPort()); const actor1 = vtkActor.newInstance(); actor1.setMapper(mapper1); actor1.getProperty().setColor([0.95, 0.45, 0.95]); renderer.addActor(actor1);
renderer.addActor(actor); renderer.resetCamera(); renderWindow.render(); fpsMonitor.update();
fullScreenRenderer.addController(controlPanel); const representationSelector = document.querySelector('.representations'); const resolutionChange = document.querySelector('.resolution'); const pickInfo = document.getElementById('pickInfo');
representationSelector.addEventListener('change', (e) => { const newRepValue = Number(e.target.value); actor.getProperty().setRepresentation(newRepValue); renderWindow.render(); fpsMonitor.update(); });
resolutionChange.addEventListener('input', (e) => { const resolution = Number(e.target.value); coneSource.setResolution(resolution); renderWindow.render(); fpsMonitor.update(); });
function handlePicking(xp, yp, tolerance) { const x1 = Math.floor(xp - tolerance); const y1 = Math.floor(yp - tolerance); const x2 = Math.ceil(xp + tolerance); const y2 = Math.ceil(yp + tolerance);
selector.setArea(x1, y1, x2, y2);
if (selector.captureBuffers()) { const pos = [xp, yp]; const outSelectedPosition = [0, 0]; const info = selector.getPixelInformation( pos, tolerance, outSelectedPosition );
if (info == null || info.prop == null) return [];
const startPoint = openGLRenderWindow.displayToWorld( Math.round((x1 + x2) / 2), Math.round((y1 + y2) / 2), 0, renderer );
const endPoint = openGLRenderWindow.displayToWorld( Math.round((x1 + x2) / 2), Math.round((y1 + y2) / 2), 1, renderer );
const ray = [Array.from(startPoint), Array.from(endPoint)];
const worldPosition = Array.from( openGLRenderWindow.displayToWorld( info.displayPosition[0], info.displayPosition[1], info.zValue, renderer ) );
const displayPosition = [ info.displayPosition[0], info.displayPosition[1], info.zValue, ];
const selection = []; selection[0] = { worldPosition, displayPosition, compositeID: info.compositeID, ...info.prop.get('representationId'), ray, }; return selection; } return []; }
function getScreenEventPositionFor(source) { const bounds = container.getBoundingClientRect(); const [canvasWidth, canvasHeight] = openGLRenderWindow.getSize(); const scaleX = canvasWidth / bounds.width; const scaleY = canvasHeight / bounds.height; const position = { x: scaleX * (source.clientX - bounds.left), y: scaleY * (bounds.height - source.clientY + bounds.top), z: 0, }; return position; }
function onMouseDown(e) { if (e !== undefined) { const sc = getScreenEventPositionFor(e); const e1 = handlePicking(sc.x, sc.y, 10); if (e1.length === 0) { console.warn('e1 null', e1); return; } let pickInfoText = `Screen Position: ${sc.x}, ${sc.y} \nPick Info:\n`; pickInfoText += `${JSON.stringify(e1[0], null, 10)}`; pickInfo.innerHTML = pickInfoText; console.log(pickInfoText);
sphereSource.setCenter(e1[0].worldPosition); renderWindow.render(); fpsMonitor.update(); } }
container.addEventListener('mousedown', onMouseDown);
global.source = coneSource; global.mapper = mapper; global.actor = actor; global.renderer = renderer; global.renderWindow = renderWindow;
|