@kitware/vtk.js
Version:
Visualization Toolkit for the Web
572 lines (448 loc) • 19.1 kB
JavaScript
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 };