UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

572 lines (448 loc) 19.1 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import macro from '../../macros.js'; import vtkDataArray from './DataArray.js'; import vtkScalarsToColors$2 from './ScalarsToColors/Constants.js'; import Constants from '../../Rendering/Core/Mapper/Constants.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; } var ScalarMappingTarget = vtkScalarsToColors$2.ScalarMappingTarget, VectorMode = vtkScalarsToColors$2.VectorMode; var VtkDataTypes = vtkDataArray.VtkDataTypes; var ColorMode = Constants.ColorMode; var vtkErrorMacro = macro.vtkErrorMacro; // ---------------------------------------------------------------------------- // Global methods // ---------------------------------------------------------------------------- // Add module-level functions or api that you want to expose statically via // the next section... // ---------------------------------------------------------------------------- // Static API // ---------------------------------------------------------------------------- function intColorToUChar(c) { return c; } function floatColorToUChar(c) { return Math.floor(c * 255.0 + 0.5); } // ---------------------------------------------------------------------------- // vtkScalarsToColors methods // ---------------------------------------------------------------------------- function vtkScalarsToColors(publicAPI, model) { // Set our className model.classHierarchy.push('vtkScalarsToColors'); publicAPI.setVectorModeToMagnitude = function () { return publicAPI.setVectorMode(VectorMode.MAGNITUDE); }; publicAPI.setVectorModeToComponent = function () { return publicAPI.setVectorMode(VectorMode.COMPONENT); }; publicAPI.setVectorModeToRGBColors = function () { return publicAPI.setVectorMode(VectorMode.RGBCOLORS); }; publicAPI.build = function () {}; publicAPI.isOpaque = function () { return true; }; //---------------------------------------------------------------------------- publicAPI.setAnnotations = function (values, annotations) { if (values && !annotations || !values && annotations) { return; } if (values && annotations && values.length !== annotations.length) { vtkErrorMacro('Values and annotations do not have the same number of tuples so ignoring'); return; } model.annotationArray = []; if (annotations && values) { var num = annotations.length; for (var i = 0; i < num; i++) { model.annotationArray.push({ value: values[i], annotation: String(annotations[i]) }); } } publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); }; //---------------------------------------------------------------------------- publicAPI.setAnnotation = function (value, annotation) { var i = publicAPI.checkForAnnotatedValue(value); var modified = false; if (i >= 0) { if (model.annotationArray[i].annotation !== annotation) { model.annotationArray[i].annotation = annotation; modified = true; } } else { model.annotationArray.push({ value: value, annotation: annotation }); i = model.annotationArray.length - 1; modified = true; } if (modified) { publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); } return i; }; //---------------------------------------------------------------------------- publicAPI.getNumberOfAnnotatedValues = function () { return model.annotationArray.length; }; //---------------------------------------------------------------------------- publicAPI.getAnnotatedValue = function (idx) { if (idx < 0 || idx >= model.annotationArray.length) { return null; } return model.annotationArray[idx].value; }; //---------------------------------------------------------------------------- publicAPI.getAnnotation = function (idx) { if (model.annotationArray[idx] === undefined) { return null; } return model.annotationArray[idx].annotation; }; //---------------------------------------------------------------------------- publicAPI.getAnnotatedValueIndex = function (val) { return model.annotationArray.length ? publicAPI.checkForAnnotatedValue(val) : -1; }; //---------------------------------------------------------------------------- publicAPI.removeAnnotation = function (value) { var i = publicAPI.checkForAnnotatedValue(value); var needToRemove = i >= 0; if (needToRemove) { model.annotationArray.splice(i, 1); publicAPI.updateAnnotatedValueMap(); publicAPI.modified(); } return needToRemove; }; //---------------------------------------------------------------------------- publicAPI.resetAnnotations = function () { model.annotationArray = []; model.annotatedValueMap = []; publicAPI.modified(); }; //---------------------------------------------------------------------------- publicAPI.getAnnotationColor = function (val, rgba) { if (model.indexedLookup) { var i = publicAPI.getAnnotatedValueIndex(val); publicAPI.getIndexedColor(i, rgba); } else { publicAPI.getColor(parseFloat(val), rgba); rgba[3] = 1.0; } }; //---------------------------------------------------------------------------- publicAPI.checkForAnnotatedValue = function (value) { return publicAPI.getAnnotatedValueIndexInternal(value); }; //---------------------------------------------------------------------------- // An unsafe version of vtkScalarsToColors::CheckForAnnotatedValue for // internal use (no pointer checks performed) publicAPI.getAnnotatedValueIndexInternal = function (value) { if (model.annotatedValueMap[value] !== undefined) { var na = model.annotationArray.length; return model.annotatedValueMap[value] % na; } // Treat as a NaN return -1; }; //---------------------------------------------------------------------------- publicAPI.getIndexedColor = function (val, rgba) { rgba[0] = 0.0; rgba[1] = 0.0; rgba[2] = 0.0; rgba[3] = 0.0; }; //---------------------------------------------------------------------------- publicAPI.updateAnnotatedValueMap = function () { model.annotatedValueMap = []; var na = model.annotationArray.length; for (var i = 0; i < na; i++) { model.annotatedValueMap[model.annotationArray[i].value] = i; } }; // Description: // Internal methods that map a data array into a 4-component, // unsigned char RGBA array. The color mode determines the behavior // of mapping. If ColorMode.DEFAULT is set, then unsigned char // data arrays are treated as colors (and converted to RGBA if // necessary); If ColorMode.DIRECT_SCALARS is set, then all arrays // are treated as colors (integer types are clamped in the range 0-255, // floating point arrays are clamped in the range 0.0-1.0. Note 'char' does // not have enough values to represent a color so mapping this type is // considered an error); // otherwise, the data is mapped through this instance // of ScalarsToColors. The component argument is used for data // arrays with more than one component; it indicates which component // to use to do the blending. When the component argument is -1, // then the this object uses its own selected technique to change a // vector into a scalar to map. publicAPI.mapScalars = function (scalars, colorMode, componentIn) { var numberOfComponents = scalars.getNumberOfComponents(); var newColors = null; // map scalars through lookup table only if needed if (colorMode === ColorMode.DEFAULT && scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR || colorMode === ColorMode.DIRECT_SCALARS && scalars) { newColors = publicAPI.convertToRGBA(scalars, numberOfComponents, scalars.getNumberOfTuples()); } else { var newscalars = { type: 'vtkDataArray', name: 'temp', numberOfComponents: 4, dataType: VtkDataTypes.UNSIGNED_CHAR }; var s = macro.newTypedArray(newscalars.dataType, 4 * scalars.getNumberOfTuples()); newscalars.values = s; newscalars.size = s.length; newColors = vtkDataArray.newInstance(newscalars); var component = componentIn; // If mapper did not specify a component, use the VectorMode if (component < 0 && numberOfComponents > 1) { publicAPI.mapVectorsThroughTable(scalars, newColors, ScalarMappingTarget.RGBA, -1, -1); } else { if (component < 0) { component = 0; } if (component >= numberOfComponents) { component = numberOfComponents - 1; } // Map the scalars to colors publicAPI.mapScalarsThroughTable(scalars, newColors, ScalarMappingTarget.RGBA, component); } } return newColors; }; publicAPI.mapVectorsToMagnitude = function (input, output, compsToUse) { var length = input.getNumberOfTuples(); var inIncr = input.getNumberOfComponents(); var outputV = output.getData(); var inputV = input.getData(); for (var i = 0; i < length; i++) { var sum = 0.0; for (var j = 0; j < compsToUse; j++) { sum += inputV[i * inIncr + j] * inputV[i * inIncr + j]; } outputV[i] = Math.sqrt(sum); } }; //---------------------------------------------------------------------------- // Map a set of vector values through the table publicAPI.mapVectorsThroughTable = function (input, output, outputFormat, vectorComponentIn, vectorSizeIn) { var vectorMode = publicAPI.getVectorMode(); var vectorSize = vectorSizeIn; var vectorComponent = vectorComponentIn; var inComponents = input.getNumberOfComponents(); if (vectorMode === VectorMode.COMPONENT) { // make sure vectorComponent is within allowed range if (vectorComponent === -1) { // if set to -1, use default value provided by table vectorComponent = publicAPI.getVectorComponent(); } if (vectorComponent < 0) { vectorComponent = 0; } if (vectorComponent >= inComponents) { vectorComponent = inComponents - 1; } } else { // make sure vectorSize is within allowed range if (vectorSize === -1) { // if set to -1, use default value provided by table vectorSize = publicAPI.getVectorSize(); } if (vectorSize <= 0) { vectorComponent = 0; vectorSize = inComponents; } else { if (vectorComponent < 0) { vectorComponent = 0; } if (vectorComponent >= inComponents) { vectorComponent = inComponents - 1; } if (vectorComponent + vectorSize > inComponents) { vectorSize = inComponents - vectorComponent; } } if (vectorMode === VectorMode.MAGNITUDE && (inComponents === 1 || vectorSize === 1)) { vectorMode = VectorMode.COMPONENT; } } // increment input pointer to the first component to map var inputOffset = 0; if (vectorComponent > 0) { inputOffset = vectorComponent; } // map according to the current vector mode switch (vectorMode) { case VectorMode.COMPONENT: { publicAPI.mapScalarsThroughTable(input, output, outputFormat, inputOffset); break; } case VectorMode.RGBCOLORS: { // publicAPI.mapColorsToColors( // input, output, inComponents, vectorSize, // outputFormat); break; } // MAGNITUDE is considered default case VectorMode.MAGNITUDE: default: { var magValues = vtkDataArray.newInstance({ numberOfComponents: 1, values: new Float32Array(input.getNumberOfTuples()) }); publicAPI.mapVectorsToMagnitude(input, magValues, vectorSize); publicAPI.mapScalarsThroughTable(magValues, output, outputFormat, 0); break; } } }; publicAPI.luminanceToRGBA = function (newColors, colors, alpha, convtFun) { var a = convtFun(alpha); var values = colors.getData(); var newValues = newColors.getData(); var size = values.length; var component = 0; var tuple = 1; var count = 0; for (var i = component; i < size; i += tuple) { var l = convtFun(values[i]); newValues[count * 4] = l; newValues[count * 4 + 1] = l; newValues[count * 4 + 2] = l; newValues[count * 4 + 3] = a; count++; } }; publicAPI.luminanceAlphaToRGBA = function (newColors, colors, alpha, convtFun) { var values = colors.getData(); var newValues = newColors.getData(); var size = values.length; var component = 0; var tuple = 2; var count = 0; for (var i = component; i < size; i += tuple) { var l = convtFun(values[i]); newValues[count] = l; newValues[count + 1] = l; newValues[count + 2] = l; newValues[count + 3] = convtFun(values[i + 1]) * alpha; count += 4; } }; publicAPI.rGBToRGBA = function (newColors, colors, alpha, convtFun) { var a = floatColorToUChar(alpha); var values = colors.getData(); var newValues = newColors.getData(); var size = values.length; var component = 0; var tuple = 3; var count = 0; for (var i = component; i < size; i += tuple) { newValues[count * 4] = convtFun(values[i]); newValues[count * 4 + 1] = convtFun(values[i + 1]); newValues[count * 4 + 2] = convtFun(values[i + 2]); newValues[count * 4 + 3] = a; count++; } }; publicAPI.rGBAToRGBA = function (newColors, colors, alpha, convtFun) { var values = colors.getData(); var newValues = newColors.getData(); var size = values.length; var component = 0; var tuple = 4; var count = 0; for (var i = component; i < size; i += tuple) { newValues[count * 4] = convtFun(values[i]); newValues[count * 4 + 1] = convtFun(values[i + 1]); newValues[count * 4 + 2] = convtFun(values[i + 2]); newValues[count * 4 + 3] = convtFun(values[i + 3]) * alpha; count++; } }; //---------------------------------------------------------------------------- publicAPI.convertToRGBA = function (colors, numComp, numTuples) { var alpha = model.alpha; if (numComp === 4 && alpha >= 1.0 && colors.getDataType() === VtkDataTypes.UNSIGNED_CHAR) { return colors; } var newColors = vtkDataArray.newInstance({ numberOfComponents: 4, empty: true, size: 4 * numTuples, dataType: VtkDataTypes.UNSIGNED_CHAR }); if (numTuples <= 0) { return newColors; } alpha = alpha > 0 ? alpha : 0; alpha = alpha < 1 ? alpha : 1; var convtFun = intColorToUChar; if (colors.getDataType() === VtkDataTypes.FLOAT || colors.getDataType() === VtkDataTypes.DOUBLE) { convtFun = floatColorToUChar; } switch (numComp) { case 1: publicAPI.luminanceToRGBA(newColors, colors, alpha, convtFun); break; case 2: publicAPI.luminanceAlphaToRGBA(newColors, colors, convtFun); break; case 3: publicAPI.rGBToRGBA(newColors, colors, alpha, convtFun); break; case 4: publicAPI.rGBAToRGBA(newColors, colors, alpha, convtFun); break; default: vtkErrorMacro('Cannot convert colors'); return null; } return newColors; }; publicAPI.usingLogScale = function () { return false; }; publicAPI.getNumberOfAvailableColors = function () { return 256 * 256 * 256; }; publicAPI.setRange = function (min, max) { return publicAPI.setMappingRange(min, max); }; publicAPI.getRange = function () { return publicAPI.getMappingRange(); }; publicAPI.areScalarsOpaque = function (scalars, colorMode, componentIn) { if (!scalars) { return publicAPI.isOpaque(); } var numberOfComponents = scalars.getNumberOfComponents(); // map scalars through lookup table only if needed if (colorMode === ColorMode.DEFAULT && scalars.getDataType() === VtkDataTypes.UNSIGNED_CHAR || colorMode === ColorMode.DIRECT_SCALARS) { // we will be using the scalars directly, so look at the number of // components and the range if (numberOfComponents === 3 || numberOfComponents === 1) { return model.alpha >= 1.0; } // otherwise look at the range of the alpha channel var range = scalars.getRange(numberOfComponents - 1); return range[0] === 255; } return true; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- var DEFAULT_VALUES = { alpha: 1.0, vectorComponent: 0, vectorSize: -1, vectorMode: VectorMode.COMPONENT, mappingRange: null, annotationArray: null, annotatedValueMap: null, indexedLookup: false }; // ---------------------------------------------------------------------------- function extend(publicAPI, model) { var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; Object.assign(model, DEFAULT_VALUES, initialValues); // Object methods macro.obj(publicAPI, model); model.mappingRange = [0, 255]; model.annotationArray = []; model.annotatedValueMap = []; // Create get-set macros macro.setGet(publicAPI, model, ['vectorSize', 'vectorComponent', 'vectorMode', 'alpha', 'indexedLookup']); // Create set macros for array (needs to know size) macro.setArray(publicAPI, model, ['mappingRange'], 2); // Create get macros for array macro.getArray(publicAPI, model, ['mappingRange']); // For more macro methods, see "Sources/macros.js" // Object specific methods vtkScalarsToColors(publicAPI, model); } // ---------------------------------------------------------------------------- var newInstance = macro.newInstance(extend, 'vtkScalarsToColors'); // ---------------------------------------------------------------------------- var vtkScalarsToColors$1 = _objectSpread({ newInstance: newInstance, extend: extend }, vtkScalarsToColors$2); export { vtkScalarsToColors$1 as default, extend, newInstance };