import '@kitware/vtk.js/favicon';
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'; import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager'; import WidgetManagerConstants from '@kitware/vtk.js/Widgets/Core/WidgetManager/Constants';
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'; import vtkConeSource from '@kitware/vtk.js/Filters/Sources/ConeSource'; import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
import vtkBoxWidget from 'vtk.js/Examples/Widgets/Box/BoxWidget'; import vtkImplicitPlaneWidget from '@kitware/vtk.js/Widgets/Widgets3D/ImplicitPlaneWidget'; import vtkPolyLineWidget from '@kitware/vtk.js/Widgets/Widgets3D/PolyLineWidget';
import controlPanel from './controlPanel.html';
const { CaptureOn } = WidgetManagerConstants;
const WIDGET_BUILDERS = { Box(widgetManager) { return widgetManager.addWidget(vtkBoxWidget.newInstance({ label: 'Box' })); }, PlaneWidget(widgetManager) { return widgetManager.addWidget( vtkImplicitPlaneWidget.newInstance({ label: 'Plane' }) ); }, PolyLine(widgetManager) { const instance = widgetManager.addWidget( vtkPolyLineWidget.newInstance({ label: 'Polyline', }) ); instance.setCoincidentTopologyParameters({ Point: { factor: -1.0, offset: -1.0, }, Line: { factor: -1.5, offset: -1.5, }, Polygon: { factor: -2.0, offset: -2.0, }, }); instance.setActiveScaleFactor(0.9); instance.setGlyphResolution(60); return instance; }, ClosedPolyLine(widgetManager) { const instance = widgetManager.addWidget( vtkPolyLineWidget.newInstance({ label: 'Closed Polyline', }), null, { coincidentTopologyParameters: { Point: { factor: -1.0, offset: -1.0, }, Line: { factor: -1.5, offset: -1.5, }, Polygon: { factor: -2.0, offset: -2.0, }, }, } ); instance.setActiveScaleFactor(1.1); instance.setGlyphResolution(30); instance.setClosePolyLine(true); return instance; }, };
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background: [0, 0, 0], }); const renderer = fullScreenRenderer.getRenderer(); const renderWindow = fullScreenRenderer.getRenderWindow();
const cone = vtkConeSource.newInstance(); const mapper = vtkMapper.newInstance(); const actor = vtkActor.newInstance({ pickable: false });
actor.setMapper(mapper); mapper.setInputConnection(cone.getOutputPort()); actor.getProperty().setOpacity(0.5); renderer.addActor(actor);
renderer.resetCamera(); renderWindow.render();
const widgetManager = vtkWidgetManager.newInstance(); widgetManager.setCaptureOn(CaptureOn.MOUSE_RELEASE); widgetManager.setRenderer(renderer);
fullScreenRenderer.addController(controlPanel);
const widgetListElem = document.querySelector('.widgetList'); const selectElem = document.querySelector('select'); const buttonCreate = document.querySelector('button.create');
buttonCreate.addEventListener('click', () => { const w = WIDGET_BUILDERS[selectElem.value](widgetManager); w.placeWidget(cone.getOutputData().getBounds()); w.setPlaceFactor(2);
widgetManager.enablePicking(); renderWindow.render(); updateUI(); });
function toggle(e) { const value = !!e.target.checked; const name = e.currentTarget.dataset.name; const index = Number( e.currentTarget.parentElement.parentElement.dataset.index ); if (name === 'focus') { if (value) { widgetManager.grabFocus(widgetManager.getWidgets()[index]); } else { widgetManager.releaseFocus(); } } else { const w = widgetManager.getWidgets()[index]; w.set({ [name]: value }); } widgetManager.enablePicking(); renderWindow.render(); }
function grabFocus(e) { const index = Number( e.currentTarget.parentElement.parentElement.dataset.index ); const w = widgetManager.getWidgets()[index];
if (!w.hasFocus()) { widgetManager.grabFocus(w); } else { widgetManager.releaseFocus(); } widgetManager.enablePicking(); renderWindow.render(); updateUI(); }
function deleteWidget(e) { const index = Number( e.currentTarget.parentElement.parentElement.dataset.index ); const w = widgetManager.getWidgets()[index]; widgetManager.removeWidget(w); updateUI(); widgetManager.enablePicking(); renderWindow.render(); }
function toHTML(w, index) { return `<tr data-index="${index}"> <td> <button class="focus">${!w.focus ? 'Grab' : 'Release'}</button> </td> <td>${w.name}</td> <td> <input type="checkbox" data-name="pickable" ${w.pickable ? 'checked' : ''} /> </td> <td> <input type="checkbox" data-name="visibility" ${w.visibility ? 'checked' : ''} /> </td> <td> <input type="checkbox" data-name="contextVisibility" ${w.contextVisibility ? 'checked' : ''} /> </td> <td> <input type="checkbox" data-name="handleVisibility" ${w.handleVisibility ? 'checked' : ''} /> </td> <td> <button class='delete'>x</button> </td> </tr>`; }
function updateUI() { const widgets = widgetManager.getWidgets(); widgetListElem.innerHTML = widgets .map((w) => ({ name: w.getReferenceByName('label'), focus: w.hasFocus(), pickable: w.getPickable(), visibility: w.getVisibility(), contextVisibility: w.getContextVisibility(), handleVisibility: w.getHandleVisibility(), })) .map(toHTML) .join('\n'); const toggleElems = document.querySelectorAll('input[type="checkbox"]'); for (let i = 0; i < toggleElems.length; i++) { toggleElems[i].addEventListener('change', toggle); } const deleteElems = document.querySelectorAll('button.delete'); for (let i = 0; i < deleteElems.length; i++) { deleteElems[i].addEventListener('click', deleteWidget); } const grabElems = document.querySelectorAll('button.focus'); for (let i = 0; i < grabElems.length; i++) { grabElems[i].addEventListener('click', grabFocus); } }
|