UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

315 lines (267 loc) 11.3 kB
import macro from '../../macro.js'; import { g as subtract, Q as multiplyAccumulate, l as normalize } from '../../Common/Core/Math/index.js'; import vtkActor from '../../Rendering/Core/Actor.js'; import vtkCylinderSource from '../../Filters/Sources/CylinderSource.js'; import vtkMapper from '../../Rendering/Core/Mapper.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; import vtkSphereSource from '../../Filters/Sources/SphereSource.js'; import vtkWidgetRepresentation from './WidgetRepresentation.js'; import { RenderingTypes } from '../Core/WidgetManager/Constants.js'; import { InteractionMethodsName } from '../Widgets3D/ResliceCursorWidget/Constants.js'; // vtkResliceCursorContextRepresentation methods // ---------------------------------------------------------------------------- function vtkResliceCursorContextRepresentation(publicAPI, model) { // Set our className model.classHierarchy.push('vtkResliceCursorContextRepresentation'); // -------------------------------------------------------------------------- // Generic rendering pipeline // -------------------------------------------------------------------------- model.mapper = vtkMapper.newInstance(); model.actor = vtkActor.newInstance(); model.mapper.setInputConnection(publicAPI.getOutputPort()); model.actor.setMapper(model.mapper); publicAPI.addActor(model.actor); model.pipelines = {}; model.pipelines.center = { source: vtkSphereSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance() }; model.pipelines.axes = []; // Create axis 1 var axis1 = {}; axis1.line = { source: vtkCylinderSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; axis1.rotation1 = { source: vtkSphereSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; axis1.rotation2 = { source: vtkSphereSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; // Create axis 2 var axis2 = {}; axis2.line = { source: vtkCylinderSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; axis2.rotation1 = { source: vtkSphereSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; axis2.rotation2 = { source: vtkSphereSource.newInstance(), mapper: vtkMapper.newInstance(), actor: vtkActor.newInstance({ pickable: true }) }; model.pipelines.axes.push(axis1); model.pipelines.axes.push(axis2); // Improve actors rendering model.pipelines.center.actor.getProperty().setAmbient(1, 1, 1); model.pipelines.center.actor.getProperty().setDiffuse(0, 0, 0); // Render it squarish model.pipelines.axes[0].line.source.setResolution(4); model.pipelines.axes[1].line.source.setResolution(4); model.pipelines.axes.forEach(function (axis) { Object.values(axis).forEach(function (lineOrRotationHandle) { vtkWidgetRepresentation.connectPipeline(lineOrRotationHandle); var actor = lineOrRotationHandle.actor; actor.getProperty().setAmbient(1, 1, 1); actor.getProperty().setDiffuse(0, 0, 0); publicAPI.addActor(actor); }); }); vtkWidgetRepresentation.connectPipeline(model.pipelines.center); publicAPI.addActor(model.pipelines.center.actor); publicAPI.setLineThickness = function (lineThickness) { var scaledLineThickness = lineThickness; if (publicAPI.getScaleInPixels()) { var centerCoords = model.pipelines.center.source.getCenter(); scaledLineThickness *= publicAPI.getPixelWorldHeightAtCoord(centerCoords); } model.pipelines.axes[0].line.source.setRadius(scaledLineThickness); model.pipelines.axes[1].line.source.setRadius(scaledLineThickness); }; publicAPI.setSphereRadius = function (radius) { publicAPI.setSphereRadiusOnSphere(radius, model.pipelines.center.source); publicAPI.setSphereRadiusOnSphere(radius, model.pipelines.axes[0].rotation1.source); publicAPI.setSphereRadiusOnSphere(radius, model.pipelines.axes[0].rotation2.source); publicAPI.setSphereRadiusOnSphere(radius, model.pipelines.axes[1].rotation1.source); publicAPI.setSphereRadiusOnSphere(radius, model.pipelines.axes[1].rotation2.source); }; publicAPI.setSphereRadiusOnSphere = function (radius, source) { var scaledRadius = radius; if (publicAPI.getScaleInPixels()) { var centerCoords = source.getCenter(); scaledRadius *= publicAPI.getPixelWorldHeightAtCoord(centerCoords); } source.setRadius(scaledRadius); }; publicAPI.setSphereRadius(7); function updateRender(state, axis) { var color = state.getColor(); axis.line.actor.getProperty().setColor(color); axis.rotation1.actor.getProperty().setColor(color); axis.rotation2.actor.getProperty().setColor(color); var vector = [0, 0, 0]; subtract(state.getPoint2(), state.getPoint1(), vector); var center = [0, 0, 0]; multiplyAccumulate(state.getPoint1(), vector, 0.5, center); axis.line.source.setCenter(center); var length = normalize(vector); axis.line.source.setDirection(vector); axis.line.source.setHeight(length); axis.rotation1.source.setCenter(state.getRotationPoint1()); axis.rotation2.source.setCenter(state.getRotationPoint2()); } /** * Returns the line actors in charge of translating the views. */ publicAPI.getTranslationActors = function () { return [model.pipelines.axes[0].line.actor, model.pipelines.axes[1].line.actor]; }; publicAPI.getRotationActors = function () { return [model.pipelines.axes[0].rotation1.actor, model.pipelines.axes[0].rotation2.actor, model.pipelines.axes[1].rotation1.actor, model.pipelines.axes[1].rotation2.actor]; }; publicAPI.requestData = function (inData, outData) { var state = inData[0]; var origin = state.getCenter(); model.pipelines.center.source.setCenter(origin); var getAxis1 = "get".concat(model.axis1Name); var getAxis2 = "get".concat(model.axis2Name); var axis1State = state[getAxis1](); var axis2State = state[getAxis2](); updateRender(axis1State, model.pipelines.axes[0]); updateRender(axis2State, model.pipelines.axes[1]); publicAPI.setLineThickness(state.getLineThickness()); publicAPI.setSphereRadius(state.getSphereRadius()); // TODO: return meaningful polydata (e.g. appended lines) outData[0] = vtkPolyData.newInstance(); }; publicAPI.updateActorVisibility = function (renderingType, wVisible, ctxVisible, hVisible) { var state = model.inputData[0]; var visibility = renderingType === RenderingTypes.PICKING_BUFFER ? wVisible : wVisible && hVisible; publicAPI.getActors().forEach(function (actor) { actor.getProperty().setOpacity(state.getOpacity()); var actorVisibility = visibility; // Conditionally display rotation handles if (publicAPI.getRotationActors().includes(actor)) { actorVisibility = actorVisibility && state.getEnableRotation(); } // Conditionally display center handle but always show it for picking if (!state.getShowCenter() && actor === model.pipelines.center.actor) { actorVisibility = actorVisibility && renderingType === RenderingTypes.PICKING_BUFFER; } actor.setVisibility(actorVisibility); // Conditionally pick lines if (publicAPI.getTranslationActors().includes(actor)) { actor.setPickable(state.getEnableTranslation()); } }); var lineThickness = state.getLineThickness(); if (renderingType === RenderingTypes.PICKING_BUFFER) { lineThickness = Math.max(3, lineThickness); } publicAPI.setLineThickness(lineThickness); var radius = state.getSphereRadius(); if (renderingType === RenderingTypes.PICKING_BUFFER) { radius += 1; } publicAPI.setSphereRadius(radius); }; publicAPI.getSelectedState = function (prop, compositeID) { var state = model.inputData[0]; state.setActiveViewType(model.viewType); var getAxis1 = "get".concat(model.axis1Name); var getAxis2 = "get".concat(model.axis2Name); var axis1State = state[getAxis1](); var axis2State = state[getAxis2](); var activeLineState = null; var activeRotationPointName = ''; var methodName = ''; switch (prop) { case model.pipelines.axes[0].line.actor: activeLineState = axis1State; methodName = InteractionMethodsName.TranslateAxis; break; case model.pipelines.axes[1].line.actor: activeLineState = axis2State; methodName = InteractionMethodsName.TranslateAxis; break; case model.pipelines.axes[0].rotation1.actor: activeLineState = axis1State; activeRotationPointName = 'RotationPoint1'; methodName = InteractionMethodsName.RotateLine; break; case model.pipelines.axes[0].rotation2.actor: activeLineState = axis1State; activeRotationPointName = 'RotationPoint2'; methodName = InteractionMethodsName.RotateLine; break; case model.pipelines.axes[1].rotation1.actor: activeLineState = axis2State; activeRotationPointName = 'RotationPoint1'; methodName = InteractionMethodsName.RotateLine; break; case model.pipelines.axes[1].rotation2.actor: activeLineState = axis2State; activeRotationPointName = 'RotationPoint2'; methodName = InteractionMethodsName.RotateLine; break; default: methodName = InteractionMethodsName.TranslateCenter; break; } state.setActiveLineState(activeLineState); state.setActiveRotationPointName(activeRotationPointName); state.setUpdateMethodName(methodName); return state; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { axis1Name: '', axis2Name: '', coincidentTopologyParameters: { Point: { factor: -1.0, offset: -1.0 }, Line: { factor: -1.5, offset: -1.5 }, Polygon: { factor: -2.0, offset: -2.0 } }, rotationEnabled: true, scaleInPixels: true, viewType: null }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; vtkWidgetRepresentation.extend(publicAPI, model, initialValues); Object.assign(model, DEFAULT_VALUES, initialValues); // Object specific methods vtkResliceCursorContextRepresentation(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkResliceCursorContextRepresentation'); // ---------------------------------------------------------------------------- var vtkResliceCursorContextRepresentation$1 = { newInstance: newInstance, extend: extend }; export default vtkResliceCursorContextRepresentation$1; export { extend, newInstance };