UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

284 lines (268 loc) 11.4 kB
import { m as macro } from '../../macros2.js'; import vtkActor from '../../Rendering/Core/Actor.js'; import vtkGlyph3DMapper from '../../Rendering/Core/Glyph3DMapper.js'; import vtkHandleRepresentation from './HandleRepresentation.js'; import vtkContextRepresentation from './ContextRepresentation.js'; import vtkSphereSource from '../../Filters/Sources/SphereSource.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; import { ScalarMode } from '../../Rendering/Core/Mapper/Constants.js'; import { getPixelWorldHeightAtCoord } from '../Core/WidgetManager.js'; import vtkWidgetRepresentation, { allocateArray } from './WidgetRepresentation.js'; import { Behavior } from './WidgetRepresentation/Constants.js'; import { OrientationModes } from '../../Rendering/Core/Glyph3DMapper/Constants.js'; // ---------------------------------------------------------------------------- // vtkGlyphRepresentation methods // ---------------------------------------------------------------------------- function origin(publicAPI, model) { return (polyData, states) => { const points = allocateArray(polyData, 'points', states.length).getData(); let j = 0; for (let i = 0; i < states.length; ++i) { const coord = states[i].getOrigin(model.scaleInPixels && model.displayScaleParams); points[j++] = coord[0]; points[j++] = coord[1]; points[j++] = coord[2]; } }; } function noPosition(publicAPI, model) { return (polyData, states) => { allocateArray(polyData, 'points', 0); }; } function color3(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setColorByArrayName('color'); const colorArray = allocateArray(polyData, 'color', states.length, 'Uint8Array', // RGBA 4); const colors = colorArray.getData(); let j = 0; for (let i = 0; i < states.length; ++i) { let c3 = states[i].getColor3(); if (states[i].getActive() && model.useActiveColor) { c3 = model.activeColor; } colors[j++] = c3[0]; colors[j++] = c3[1]; colors[j++] = c3[2]; colors[j++] = states[i].getOpacity(); } colorArray.dataChange(); }; } function color(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setColorByArrayName('color'); const colors = allocateArray(polyData, 'color', states.length).getData(); for (let i = 0; i < states.length; ++i) { let c = states[i].getColor(); if (states[i].getActive() && model.useActiveColor) { c = model.activeColor; } colors[i] = c; } }; } function noColor(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setColorByArrayName(null); }; } function scale3(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setScaleArray('scale'); model._pipeline.mapper.setScaleFactor(1); model._pipeline.mapper.setScaling(true); model._pipeline.mapper.setScaleMode(vtkGlyph3DMapper.ScaleModes.SCALE_BY_COMPONENTS); const scales = allocateArray(polyData, 'scale', states.length, 'Float32Array', 3).getData(); let j = 0; for (let i = 0; i < states.length; ++i) { const state = states[i]; let scaleFactor = state.getActive() ? model.activeScaleFactor : 1; if (publicAPI.getScaleInPixels()) { scaleFactor *= getPixelWorldHeightAtCoord(state.getOrigin(), model.displayScaleParams); } const scale = state.getScale3?.() ?? model.defaultScale; scales[j++] = scaleFactor * scale[0]; scales[j++] = scaleFactor * scale[1]; scales[j++] = scaleFactor * scale[2]; } }; } function scale1(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setScaleArray('scale'); model._pipeline.mapper.setScaleFactor(1); model._pipeline.mapper.setScaling(true); const scales = allocateArray(polyData, 'scale', states.length).getData(); for (let i = 0; i < states.length; ++i) { const state = states[i]; let scaleFactor = state.getActive() ? model.activeScaleFactor : 1; if (publicAPI.getScaleInPixels()) { scaleFactor *= getPixelWorldHeightAtCoord(state.getOrigin(), model.displayScaleParams); } const scale = state.getScale1?.() ?? model.defaultScale; scales[i] = scaleFactor * scale; } }; } function noScale(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setScaleArray(null); model._pipeline.mapper.setScaleFactor(model.defaultScale); model._pipeline.mapper.setScaling(model.defaultScale !== 1); }; } function direction(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setOrientationArray('orientation'); model._pipeline.mapper.setOrientationMode(OrientationModes.MATRIX); const orientation = allocateArray(polyData, 'orientation', states.length, 'Float64Array', 9).getData(); for (let i = 0; i < states.length; ++i) { const state = states[i]; const right = state.getRight ? state.getRight() : [1, 0, 0]; const up = state.getUp ? state.getUp() : [0, 1, 0]; const dir = state.getDirection ? state.getDirection() : [0, 0, 1]; orientation.set(right, 9 * i); orientation.set(up, 9 * i + 3); orientation.set(dir, 9 * i + 6); } }; } function noOrientation(publicAPI, model) { return (polyData, states) => { model._pipeline.mapper.setOrientationArray(null); }; } function vtkGlyphRepresentation(publicAPI, model) { // Set our className model.classHierarchy.push('vtkGlyphRepresentation'); const superClass = { ...publicAPI }; const internalPolyData = vtkPolyData.newInstance({ mtime: 0 }); function hasMixin(states) { for (var _len = arguments.length, requiredMixins = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { requiredMixins[_key - 1] = arguments[_key]; } return requiredMixins.every(requiredMixin => states[0]?.[`get${macro.capitalize(requiredMixin)}`]?.() != null); } // -------------------------------------------------------------------------- // Generic rendering pipeline // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- publicAPI.getRepresentationStates = function () { let input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : model.inputData[0]; return superClass.getRepresentationStates(input).filter(state => state.getOrigin?.() && (state.isVisible?.() ?? true)); }; // -------------------------------------------------------------------------- publicAPI.getMixins = states => { const glyphProperties = {}; if (hasMixin(states, 'origin')) { glyphProperties.position = model.applyMixin.origin; } else { glyphProperties.position = model.applyMixin.noPosition; } if (hasMixin(states, 'color3')) { glyphProperties.color = model.applyMixin.color3; } else if (hasMixin(states, 'color')) { glyphProperties.color = model.applyMixin.color; } else { glyphProperties.color = model.applyMixin.noColor; } if (hasMixin(states, 'scale3')) { glyphProperties.scale = model.applyMixin.scale3; } else if (hasMixin(states, 'scale1')) { glyphProperties.scale = model.applyMixin.scale1; } else { glyphProperties.scale = model.applyMixin.noScale; } if (hasMixin(states, 'direction')) { glyphProperties.orientation = model.applyMixin.direction; } else { glyphProperties.orientation = model.applyMixin.noOrientation; } return glyphProperties; }; publicAPI.requestData = (inData, outData) => { const states = publicAPI.getRepresentationStates(inData[0]); outData[0] = internalPolyData; const glyphProperties = publicAPI.getMixins(states); Object.values(glyphProperties).forEach(property => property(internalPolyData, states)); internalPolyData.getPoints().modified(); internalPolyData.modified(); }; vtkWidgetRepresentation.connectPipeline(model._pipeline); publicAPI.addActor(model._pipeline.actor); } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- function defaultValues(publicAPI, model, initialValues) { return { defaultScale: 1, ...initialValues, _pipeline: { source: initialValues._pipeline?.source ?? publicAPI, glyph: initialValues._pipeline?.glyph ?? // in case glyph was provided vtkSphereSource.newInstance({ phiResolution: 8, thetaResolution: 8 }), mapper: initialValues._pipeline?.mapper ?? // in case mapper was provided vtkGlyph3DMapper.newInstance({ scalarMode: ScalarMode.USE_POINT_FIELD_DATA }), actor: initialValues._pipeline?.actor ?? // in case actor was provided vtkActor.newInstance({ parentProp: publicAPI }), ...initialValues._pipeline // in case there is something else to add to pipeline }, applyMixin: { origin: initialValues.applyMixin?.origin ?? origin(publicAPI, model), noPosition: initialValues.applyMixin?.noPosition ?? noPosition(), color3: initialValues.applyMixin?.color3 ?? color3(publicAPI, model), color: initialValues.applyMixin?.color ?? color(publicAPI, model), noColor: initialValues.applyMixin?.noColor ?? noColor(publicAPI, model), scale3: initialValues.applyMixin?.scale3 ?? scale3(publicAPI, model), scale1: initialValues.applyMixin?.scale1 ?? scale1(publicAPI, model), noScale: initialValues.applyMixin?.noScale ?? noScale(publicAPI, model), direction: initialValues.applyMixin?.direction ?? direction(publicAPI, model), noOrientation: initialValues.applyMixin?.noOrientation ?? noOrientation(publicAPI, model), ...initialValues.applyMixin } }; } // ---------------------------------------------------------------------------- function extend(publicAPI, model) { let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (initialValues.behavior === Behavior.CONTEXT) { vtkContextRepresentation.extend(publicAPI, model, defaultValues(publicAPI, model, initialValues)); } else { vtkHandleRepresentation.extend(publicAPI, model, defaultValues(publicAPI, model, initialValues)); } if ('lighting' in initialValues) { model._pipeline.actor.getProperty().setLighting(initialValues.lighting); } macro.setGet(publicAPI, model._pipeline, ['defaultScale']); macro.get(publicAPI, model._pipeline, ['glyph', 'mapper', 'actor']); // Expose the mixin functions to allow overwriting macro.setGet(publicAPI, model.applyMixin, Object.keys(model.applyMixin)); // Object specific methods vtkGlyphRepresentation(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkGlyphRepresentation'); // ---------------------------------------------------------------------------- var vtkGlyphRepresentation$1 = { newInstance, extend }; export { color, color3, vtkGlyphRepresentation$1 as default, direction, extend, newInstance, noColor, noOrientation, noPosition, noScale, origin, scale1, scale3 };