UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

379 lines (327 loc) 15.2 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import macro from '../../macro.js'; import vtkActor from '../../Rendering/Core/Actor.js'; import vtkArrow2DSource from '../../Filters/Sources/Arrow2DSource.js'; import vtkDataArray from '../../Common/Core/DataArray.js'; import vtkGlyph3DMapper from '../../Rendering/Core/Glyph3DMapper.js'; import vtkHandleRepresentation from './HandleRepresentation.js'; import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js'; import vtkPixelSpaceCallbackMapper from '../../Rendering/Core/PixelSpaceCallbackMapper.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; import vtkConeSource from '../../Filters/Sources/ConeSource.js'; import vtkSphereSource from '../../Filters/Sources/SphereSource.js'; import vtkCircleSource from '../../Filters/Sources/CircleSource.js'; import vtkCubeSource from '../../Filters/Sources/CubeSource.js'; import vtkViewFinderSource from '../../Filters/Sources/ViewFinderSource.js'; import Constants from '../Widgets3D/LineWidget/Constants.js'; import { ScalarMode } from '../../Rendering/Core/Mapper/Constants.js'; import { RenderingTypes } from '../Core/WidgetManager/Constants.js'; import { i as identity } from '../../vendor/gl-matrix/esm/mat4.js'; import { f as fromMat4, i as identity$1, a as invert, m as multiply } from '../../vendor/gl-matrix/esm/mat3.js'; import { p as transformMat3 } from '../../vendor/gl-matrix/esm/vec3.js'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var ShapeType = Constants.ShapeType, Shapes2D = Constants.Shapes2D, ShapesOrientable = Constants.ShapesOrientable; // ---------------------------------------------------------------------------- // vtkArrowHandleRepresentation methods // ---------------------------------------------------------------------------- function vtkArrowHandleRepresentation(publicAPI, model) { // Set our className model.classHierarchy.push('vtkArrowHandleRepresentation'); var superClass = _objectSpread({}, publicAPI); // -------------------------------------------------------------------------- // Internal polydata dataset // -------------------------------------------------------------------------- model.internalPolyData = vtkPolyData.newInstance({ mtime: 0 }); model.internalArrays = { points: model.internalPolyData.getPoints(), scale: vtkDataArray.newInstance({ name: 'scale', numberOfComponents: 1, empty: true }), color: vtkDataArray.newInstance({ name: 'color', numberOfComponents: 1, empty: true }), direction: vtkDataArray.newInstance({ name: 'direction', numberOfComponents: 9, empty: true }) }; model.internalPolyData.getPointData().addArray(model.internalArrays.scale); model.internalPolyData.getPointData().addArray(model.internalArrays.color); model.internalPolyData.getPointData().addArray(model.internalArrays.direction); /** * Set the shape for the glyph according to lineWidget state inputs */ function createGlyph(shape) { var _representationToSour; var representationToSource = (_representationToSour = {}, _defineProperty(_representationToSour, ShapeType.STAR, { builder: vtkArrow2DSource, initialValues: { shape: 'star', height: 0.6 } }), _defineProperty(_representationToSour, ShapeType.ARROWHEAD3, { builder: vtkArrow2DSource, initialValues: { shape: 'triangle' } }), _defineProperty(_representationToSour, ShapeType.ARROWHEAD4, { builder: vtkArrow2DSource, initialValues: { shape: 'arrow4points' } }), _defineProperty(_representationToSour, ShapeType.ARROWHEAD6, { builder: vtkArrow2DSource, initialValues: { shape: 'arrow6points' } }), _defineProperty(_representationToSour, ShapeType.CONE, { builder: vtkConeSource, initialValues: { direction: [0, 1, 0] } }), _defineProperty(_representationToSour, ShapeType.SPHERE, { builder: vtkSphereSource }), _defineProperty(_representationToSour, ShapeType.CUBE, { builder: vtkCubeSource, initialValues: { xLength: 0.8, yLength: 0.8, zLength: 0.8 } }), _defineProperty(_representationToSour, ShapeType.DISK, { builder: vtkCircleSource, initialValues: { resolution: 30, radius: 0.5, direction: [0, 0, 1], lines: false, face: true } }), _defineProperty(_representationToSour, ShapeType.CIRCLE, { builder: vtkCircleSource, initialValues: { resolution: 30, radius: 0.5, direction: [0, 0, 1], lines: true, face: false } }), _defineProperty(_representationToSour, ShapeType.VIEWFINDER, { builder: vtkViewFinderSource, initialValues: { radius: 0.1, spacing: 0.3, width: 1.4 } }), _defineProperty(_representationToSour, ShapeType.NONE, { builder: vtkSphereSource }), _representationToSour); var rep = representationToSource[shape]; return rep.builder.newInstance(rep.initialValues); } // -------------------------------------------------------------------------- // Generic rendering pipeline // -------------------------------------------------------------------------- // displayActors and displayMappers are used to render objects in HTML, // allowing objects to be 'rendered' internally in a VTK scene without // being visible on the final output. model.displayMapper = vtkPixelSpaceCallbackMapper.newInstance(); model.displayActor = vtkActor.newInstance(); // model.displayActor.getProperty().setOpacity(0); // don't show in 3D model.displayActor.setMapper(model.displayMapper); model.displayMapper.setInputConnection(publicAPI.getOutputPort()); publicAPI.addActor(model.displayActor); model.alwaysVisibleActors = [model.displayActor]; model.mapper = vtkGlyph3DMapper.newInstance({ orientationArray: 'direction', scaleArray: 'scale', colorByArrayName: 'color', scalarMode: ScalarMode.USE_POINT_FIELD_DATA }); model.mapper.setOrientationModeToMatrix(); model.mapper.setInputConnection(publicAPI.getOutputPort()); model.actor = vtkActor.newInstance(); model.actor.setMapper(model.mapper); publicAPI.addActor(model.actor); // -------------------------------------------------------------------------- publicAPI.setGlyphResolution = macro.chain(publicAPI.setGlyphResolution, function (r) { return model.glyph.setPhiResolution(r) && model.glyph.setThetaResolution(r); }); // -------------------------------------------------------------------------- function callbackProxy(coords) { if (model.displayCallback) { var filteredList = []; var states = publicAPI.getRepresentationStates(); for (var i = 0; i < states.length; i++) { if (states[i].getActive()) { filteredList.push(coords[i]); } } if (filteredList.length) { model.displayCallback(filteredList); return; } } model.displayCallback(); } publicAPI.setDisplayCallback = function (callback) { model.displayCallback = callback; model.displayMapper.setCallback(callback ? callbackProxy : null); }; // -------------------------------------------------------------------------- publicAPI.is2DShape = function () { return Shapes2D.includes(model.shape); }; publicAPI.isOrientableShape = function () { return ShapesOrientable.includes(model.shape); }; /** * Returns the orientation matrix to align glyph on model.orientation. * */ function getOrientationRotation(viewMatrixInv) { var displayOrientation = new Float64Array(3); var baseDir = [0, 1, 0]; transformMat3(displayOrientation, model.orientation, viewMatrixInv); displayOrientation[2] = 0; var displayMatrix = vtkMatrixBuilder.buildFromDegree().rotateFromDirections(baseDir, displayOrientation).getMatrix(); var displayRotation = new Float64Array(9); fromMat4(displayRotation, displayMatrix); return displayRotation; } function getCameraFacingRotation(scale3, displayRotation, viewMatrix) { var rotation = new Float64Array(9); multiply(rotation, viewMatrix, displayRotation); transformMat3(scale3, scale3, rotation); return rotation; } /** * Computes the rotation matrix of the glyph. There are 2 rotations: * - a first rotation to be oriented along model.rotation * - an optional second rotation to face the camera * @param {vec3} scale3 Scale of the glyph, rotated when glyph is rotated. */ function getGlyphRotation(scale3) { var shouldFaceCamera = model.faceCamera === true || model.faceCamera == null && publicAPI.is2DShape(); var viewMatrix = new Float64Array(9); fromMat4(viewMatrix, model.viewMatrix); var viewMatrixInv = identity$1(new Float64Array(9)); if (shouldFaceCamera) { invert(viewMatrixInv, viewMatrix); } var orientationRotation = null; if (publicAPI.isOrientableShape()) { orientationRotation = getOrientationRotation(viewMatrixInv); } else { orientationRotation = identity$1(new Float64Array(9)); } if (shouldFaceCamera) { orientationRotation = getCameraFacingRotation(scale3, orientationRotation, viewMatrix); } return orientationRotation; } publicAPI.requestDataInternal = function (inData, outData) { var _model$internalArrays = model.internalArrays, points = _model$internalArrays.points, scale = _model$internalArrays.scale, color = _model$internalArrays.color, direction = _model$internalArrays.direction; var list = publicAPI.getRepresentationStates(inData[0]); var totalCount = list.length; if (color.getNumberOfValues() !== totalCount) { // Need to resize dataset points.setData(new Float32Array(3 * totalCount), 3); scale.setData(new Float32Array(totalCount)); color.setData(new Float32Array(totalCount)); direction.setData(new Float32Array(9 * totalCount)); } var typedArray = { points: points.getData(), scale: scale.getData(), color: color.getData(), direction: direction.getData() }; for (var i = 0; i < list.length; i++) { var state = list[i]; var isActive = state.getActive(); var scaleFactor = isActive ? model.activeScaleFactor : 1; var coord = state.getOrigin(); typedArray.points[i * 3 + 0] = coord[0]; typedArray.points[i * 3 + 1] = coord[1]; typedArray.points[i * 3 + 2] = coord[2]; var scale3 = state.getScale3 ? state.getScale3() : [1, 1, 1]; scale3 = scale3.map(function (x) { return x === 0 ? 2 * model.defaultScale : 2 * x; }); var rotation = getGlyphRotation(scale3); typedArray.direction.set(rotation, 9 * i); typedArray.scale[i] = scaleFactor * (state.getScale1 ? state.getScale1() : model.defaultScale); if (publicAPI.getScaleInPixels()) { typedArray.scale[i] *= publicAPI.getPixelWorldHeightAtCoord(coord); } typedArray.color[i] = model.useActiveColor && isActive ? model.activeColor : state.getColor(); } model.internalPolyData.modified(); outData[0] = model.internalPolyData; }; publicAPI.requestData = function (inData, outData) { var shape = publicAPI.getRepresentationStates(inData[0])[0].getShape(); var shouldCreateGlyph = model.glyph == null; if (model.shape !== shape && Object.values(ShapeType).includes(shape)) { model.shape = shape; shouldCreateGlyph = true; } if (shouldCreateGlyph) { model.glyph = createGlyph(model.shape); model.mapper.setInputConnection(model.glyph.getOutputPort(), 1); } publicAPI.requestDataInternal(inData, outData); }; publicAPI.updateActorVisibility = function () { var renderingType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : RenderingTypes.FRONT_BUFFER; var widgetVisible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var ctxVisible = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var handleVisible = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var state = publicAPI.getRepresentationStates()[0]; superClass.updateActorVisibility(renderingType, widgetVisible, ctxVisible, handleVisible && state.isVisible()); }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- /** * 'shape' default value is used first time 'shape' mixin is invalid. * 'faceCamera' controls wether the glyph should face camera or not: * - null or undefined to leave it to shape type (i.e. 2D are facing camera, * 3D are not) * - true to face camera * - false to not face camera */ function defaultValues(initialValues) { return _objectSpread({ defaultScale: 1, faceCamera: null, orientation: [1, 0, 0], shape: ShapeType.SPHERE, viewMatrix: identity(new Float64Array(16)) }, initialValues); } // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, defaultValues(initialValues)); vtkHandleRepresentation.extend(publicAPI, model, initialValues); macro.get(publicAPI, model, ['glyph', 'mapper', 'actor']); macro.setGetArray(publicAPI, model, ['visibilityFlagArray'], 2); macro.setGetArray(publicAPI, model, ['orientation'], 3); macro.setGetArray(publicAPI, model, ['viewMatrix'], 16); macro.setGet(publicAPI, model, ['faceCamera']); // Object specific methods vtkArrowHandleRepresentation(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkArrowHandleRepresentation'); // ---------------------------------------------------------------------------- var vtkArrowHandleRepresentation$1 = { newInstance: newInstance, extend: extend }; export default vtkArrowHandleRepresentation$1; export { extend, newInstance };