UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

321 lines (255 loc) 10.8 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import macro from '../../macros.js'; import vtkImageSlice from '../../Rendering/Core/ImageSlice.js'; import vtkImageMapper from '../../Rendering/Core/ImageMapper.js'; import vtkAbstractRepresentationProxy from '../Core/AbstractRepresentationProxy.js'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function sum(a, b) { return a + b; } // ---------------------------------------------------------------------------- function mean() { for (var _len = arguments.length, array = new Array(_len), _key = 0; _key < _len; _key++) { array[_key] = arguments[_key]; } return array.reduce(sum, 0) / array.length; } // ---------------------------------------------------------------------------- function updateDomains(dataset, dataArray, model, updateProp) { var dataRange = dataArray.getRange(); var spacing = dataset.getSpacing(); var bounds = dataset.getBounds(); var extent = dataset.getExtent(); var sliceMin; var sliceMax; var stepVal; var axisIndex; var sliceMode = model.mapper.getSlicingMode(); var sliceModeLabel = 'IJKXYZ'[sliceMode]; switch (sliceMode) { case vtkImageMapper.SlicingMode.I: case vtkImageMapper.SlicingMode.J: case vtkImageMapper.SlicingMode.K: axisIndex = 'IJK'.indexOf(sliceModeLabel); sliceMin = extent[axisIndex * 2]; sliceMax = extent[axisIndex * 2 + 1]; stepVal = 1; break; case vtkImageMapper.SlicingMode.X: case vtkImageMapper.SlicingMode.Y: case vtkImageMapper.SlicingMode.Z: { axisIndex = 'XYZ'.indexOf(sliceModeLabel); sliceMin = bounds[axisIndex * 2]; sliceMax = bounds[axisIndex * 2 + 1]; var _model$mapper$getClos = model.mapper.getClosestIJKAxis(), ijkMode = _model$mapper$getClos.ijkMode; stepVal = spacing[ijkMode]; } break; } var propToUpdate = { slice: { domain: { min: sliceMin, max: sliceMax, step: stepVal } }, windowWidth: { domain: { min: 0, max: dataRange[1] - dataRange[0], step: 'any' } }, windowLevel: { domain: { min: dataRange[0], max: dataRange[1], step: 'any' } } }; updateProp('slice', propToUpdate.slice); updateProp('windowWidth', propToUpdate.windowWidth); updateProp('windowLevel', propToUpdate.windowLevel); return { slice: mean(propToUpdate.slice.domain.min, propToUpdate.slice.domain.max), windowWidth: propToUpdate.windowWidth.domain.max, windowLevel: Math.floor(mean(propToUpdate.windowLevel.domain.min, propToUpdate.windowLevel.domain.max)) }; } // ---------------------------------------------------------------------------- // vtkSliceRepresentationProxy methods // ---------------------------------------------------------------------------- function vtkSliceRepresentationProxy(publicAPI, model) { // Set our className model.classHierarchy.push('vtkSliceRepresentationProxy'); model.mapper = vtkImageMapper.newInstance(); model.actor = vtkImageSlice.newInstance(); model.property = model.actor.getProperty(); // connect rendering pipeline model.actor.setMapper(model.mapper); model.actors.push(model.actor); function setInputData(inputDataset) { var state = updateDomains(inputDataset, publicAPI.getDataArray(), model, publicAPI.updateProxyProperty); publicAPI.set(state); // Init slice location var bounds = inputDataset.getBounds(); var extent = inputDataset.getExtent(); switch (model.mapper.getSlicingMode()) { case vtkImageMapper.SlicingMode.I: publicAPI.setSlice(Math.floor(mean(extent[0], extent[1]))); break; case vtkImageMapper.SlicingMode.J: publicAPI.setSlice(Math.floor(mean(extent[2], extent[3]))); break; case vtkImageMapper.SlicingMode.K: publicAPI.setSlice(Math.floor(mean(extent[4], extent[5]))); break; case vtkImageMapper.SlicingMode.X: publicAPI.setSlice(mean(bounds[0], bounds[1])); break; case vtkImageMapper.SlicingMode.Y: publicAPI.setSlice(mean(bounds[2], bounds[3])); break; case vtkImageMapper.SlicingMode.Z: publicAPI.setSlice(mean(bounds[4], bounds[5])); break; } } // Keep things updated model.sourceDependencies.push(model.mapper); model.sourceDependencies.push({ setInputData: setInputData }); // keeps the slicing mode and domain info updated function updateSlicingMode(mode) { model.mapper.setSlicingMode(vtkImageMapper.SlicingMode[mode]); // Update to previously set position var modelKey = "".concat(mode.toLowerCase(), "Slice"); if (modelKey in model && model[modelKey] !== undefined) { model.mapper.setSlice(model[modelKey]); } if (model.input) { // Update domains for UI... var state = updateDomains(publicAPI.getInputDataSet(), publicAPI.getDataArray(), model, publicAPI.updateProxyProperty); publicAPI.set(state); } publicAPI.modified(); } // API ---------------------------------------------------------------------- publicAPI.setSlicingMode = function (mode) { if (!mode) { return false; } if (model.slicingMode !== mode) { // Update Mode model.slicingMode = mode; updateSlicingMode(mode); return true; } return false; }; publicAPI.getSliceIndex = function () { if ('XYZ'.indexOf(model.slicingMode) !== -1) { return model.mapper.getSliceAtPosition(model.mapper.getSlice()); } return model.mapper.getSlice(); }; publicAPI.getAnnotations = function () { var dynamicAddOn = {}; var sliceIndex = publicAPI.getSliceIndex(); var sliceBounds = model.mapper.getBoundsForSlice(); var sliceNormal = model.mapper.getSlicingModeNormal(); var _model$mapper$getClos2 = model.mapper.getClosestIJKAxis(), ijkMode = _model$mapper$getClos2.ijkMode; var sliceOrigin = [(sliceBounds[0] + sliceBounds[1]) * 0.5, (sliceBounds[2] + sliceBounds[3]) * 0.5, (sliceBounds[4] + sliceBounds[5]) * 0.5]; var slicePosition = 0; if (sliceBounds[1] - sliceBounds[0] < Number.EPSILON) { slicePosition = sliceBounds[0]; } if (sliceBounds[3] - sliceBounds[2] < Number.EPSILON) { slicePosition = sliceBounds[2]; } if (sliceBounds[5] - sliceBounds[4] < Number.EPSILON) { slicePosition = sliceBounds[4]; } var imageData = model.mapper.getInputData(); if (imageData) { dynamicAddOn.sliceSpacing = imageData.getSpacing()[ijkMode]; dynamicAddOn.dimensions = imageData.getDimensions(); dynamicAddOn.sliceCount = imageData.getDimensions()[ijkMode]; var ijkOrientation = []; for (var i = 0; i < 3; i++) { var extent = [0, 0, 0, 0, 0, 0]; extent[i * 2 + 1] = 1; var tmpBounds = imageData.extentToBounds(extent); if (tmpBounds[1] - tmpBounds[0] > Number.EPSILON) { ijkOrientation[0] = 'IJK'[i]; } if (tmpBounds[3] - tmpBounds[2] > Number.EPSILON) { ijkOrientation[1] = 'IJK'[i]; } if (tmpBounds[5] - tmpBounds[4] > Number.EPSILON) { ijkOrientation[2] = 'IJK'[i]; } } dynamicAddOn.ijkOrientation = ijkOrientation.join(''); } return _objectSpread({ ijkMode: ijkMode, sliceBounds: sliceBounds, sliceIndex: sliceIndex, sliceNormal: sliceNormal, sliceOrigin: sliceOrigin, slicePosition: slicePosition }, dynamicAddOn); }; var parentSetColorBy = publicAPI.setColorBy; publicAPI.setColorBy = function (arrayName, arrayLocation) { var componentIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; if (arrayName === null) { model.property.setRGBTransferFunction(null); model.property.setPiecewiseFunction(null); } else { parentSetColorBy(arrayName, arrayLocation, componentIndex); var lutProxy = publicAPI.getLookupTableProxy(arrayName); var pwfProxy = publicAPI.getPiecewiseFunctionProxy(arrayName); model.property.setRGBTransferFunction(lutProxy.getLookupTable()); model.property.setPiecewiseFunction(pwfProxy.getPiecewiseFunction()); } }; // Initialize slicing mode updateSlicingMode(model.slicingMode || 'X'); } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = {}; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Object methods vtkAbstractRepresentationProxy.extend(publicAPI, model, initialValues); macro.get(publicAPI, model, ['slicingMode']); // Object specific methods vtkSliceRepresentationProxy(publicAPI, model); // Proxyfy macro.proxyPropertyMapping(publicAPI, model, { visibility: { modelKey: 'actor', property: 'visibility' }, windowWidth: { modelKey: 'property', property: 'colorWindow' }, windowLevel: { modelKey: 'property', property: 'colorLevel' }, interpolationType: { modelKey: 'property', property: 'interpolationType' }, slice: { modelKey: 'mapper', property: 'slice' } }); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkSliceRepresentationProxy'); // ---------------------------------------------------------------------------- var vtkSliceRepresentationProxy$1 = { newInstance: newInstance, extend: extend }; export { vtkSliceRepresentationProxy$1 as default, extend, newInstance };