@kitware/vtk.js
Version:
Visualization Toolkit for the Web
347 lines (277 loc) • 11.8 kB
JavaScript
import macro from '../../macros.js';
import { i as isNan, h as hsv2rgb } from './Math/index.js';
import vtkScalarsToColors from './ScalarsToColors.js';
import { ScalarMappingTarget } from './ScalarsToColors/Constants.js';
import { VtkDataTypes } from './DataArray/Constants.js';
var vtkErrorMacro = macro.vtkErrorMacro; // ----------------------------------------------------------------------------
// Global methods
// ----------------------------------------------------------------------------
// Add module-level functions or api that you want to expose statically via
// the next section...
// ----------------------------------------------------------------------------
// Static API
// ----------------------------------------------------------------------------
var BELOW_RANGE_COLOR_INDEX = 0;
var ABOVE_RANGE_COLOR_INDEX = 1;
var NAN_COLOR_INDEX = 2; // ----------------------------------------------------------------------------
// vtkMyClass methods
// ----------------------------------------------------------------------------
function vtkLookupTable(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkLookupTable'); //----------------------------------------------------------------------------
// Description:
// Return true if all of the values defining the mapping have an opacity
// equal to 1. Default implementation return true.
publicAPI.isOpaque = function () {
if (model.opaqueFlagBuildTime.getMTime() < publicAPI.getMTime()) {
var opaque = true;
if (model.nanColor[3] < 1.0) {
opaque = 0;
}
if (model.useBelowRangeColor && model.belowRangeColor[3] < 1.0) {
opaque = 0;
}
if (model.useAboveRangeColor && model.aboveRangeColor[3] < 1.0) {
opaque = 0;
}
for (var i = 3; i < model.table.length && opaque; i += 4) {
if (model.table[i] < 255) {
opaque = false;
}
}
model.opaqueFlag = opaque;
model.opaqueFlagBuildTime.modified();
}
return model.opaqueFlag;
};
publicAPI.usingLogScale = function () {
return false;
}; //----------------------------------------------------------------------------
publicAPI.getNumberOfAvailableColors = function () {
return model.table.length / 4;
}; //----------------------------------------------------------------------------
// Apply shift/scale to the scalar value v and return the index.
publicAPI.linearIndexLookup = function (v, p) {
var dIndex = 0;
if (v < p.range[0]) {
dIndex = p.maxIndex + BELOW_RANGE_COLOR_INDEX + 1.5;
} else if (v > p.range[1]) {
dIndex = p.maxIndex + ABOVE_RANGE_COLOR_INDEX + 1.5;
} else {
dIndex = (v + p.shift) * p.scale; // This conditional is needed because when v is very close to
// p.Range[1], it may map above p.MaxIndex in the linear mapping
// above.
dIndex = dIndex < p.maxIndex ? dIndex : p.maxIndex;
}
return Math.floor(dIndex);
};
publicAPI.linearLookup = function (v, table, p) {
var index = 0;
if (isNan(v)) {
index = Math.floor(p.maxIndex + 1.5 + NAN_COLOR_INDEX);
} else {
index = publicAPI.linearIndexLookup(v, p);
}
var offset = 4 * index;
return table.slice(offset, offset + 4);
};
publicAPI.indexedLookupFunction = function (v, table, p) {
var index = publicAPI.getAnnotatedValueIndexInternal(v);
if (index === -1) {
index = model.numberOfColors + NAN_COLOR_INDEX;
}
var offset = 4 * index;
return [table[offset], table[offset + 1], table[offset + 2], table[offset + 3]];
}; //----------------------------------------------------------------------------
publicAPI.lookupShiftAndScale = function (range, p) {
p.shift = -range[0];
p.scale = Number.MAX_VALUE;
if (range[1] > range[0]) {
p.scale = (p.maxIndex + 1) / (range[1] - range[0]);
}
}; // Public API methods
publicAPI.mapScalarsThroughTable = function (input, output, outFormat, inputOffset) {
var lookupFunc = publicAPI.linearLookup;
if (model.indexedLookup) {
lookupFunc = publicAPI.indexedLookupFunction;
}
var trange = publicAPI.getMappingRange();
var p = {
maxIndex: publicAPI.getNumberOfColors() - 1,
range: trange,
shift: 0.0,
scale: 0.0
};
publicAPI.lookupShiftAndScale(trange, p);
var alpha = publicAPI.getAlpha();
var length = input.getNumberOfTuples();
var inIncr = input.getNumberOfComponents();
var outputV = output.getData();
var inputV = input.getData();
if (alpha >= 1.0) {
if (outFormat === ScalarMappingTarget.RGBA) {
for (var i = 0; i < length; i++) {
var cptr = lookupFunc(inputV[i * inIncr + inputOffset], model.table, p);
outputV[i * 4] = cptr[0];
outputV[i * 4 + 1] = cptr[1];
outputV[i * 4 + 2] = cptr[2];
outputV[i * 4 + 3] = cptr[3];
}
}
} else {
/* eslint-disable no-lonely-if */
if (outFormat === ScalarMappingTarget.RGBA) {
for (var _i = 0; _i < length; _i++) {
var _cptr = lookupFunc(inputV[_i * inIncr + inputOffset], model.table, p);
outputV[_i * 4] = _cptr[0];
outputV[_i * 4 + 1] = _cptr[1];
outputV[_i * 4 + 2] = _cptr[2];
outputV[_i * 4 + 3] = Math.floor(_cptr[3] * alpha + 0.5);
}
}
} // alpha blending
};
publicAPI.forceBuild = function () {
var hinc = 0.0;
var sinc = 0.0;
var vinc = 0.0;
var ainc = 0.0;
var maxIndex = model.numberOfColors - 1;
if (maxIndex) {
hinc = (model.hueRange[1] - model.hueRange[0]) / maxIndex;
sinc = (model.saturationRange[1] - model.saturationRange[0]) / maxIndex;
vinc = (model.valueRange[1] - model.valueRange[0]) / maxIndex;
ainc = (model.alphaRange[1] - model.alphaRange[0]) / maxIndex;
}
model.table.length = 4 * maxIndex + 16;
var hsv = [];
var rgba = [];
for (var i = 0; i <= maxIndex; i++) {
hsv[0] = model.hueRange[0] + i * hinc;
hsv[1] = model.saturationRange[0] + i * sinc;
hsv[2] = model.valueRange[0] + i * vinc;
hsv2rgb(hsv, rgba);
rgba[3] = model.alphaRange[0] + i * ainc; // case VTK_RAMP_LINEAR:
model.table[i * 4] = rgba[0] * 255.0 + 0.5;
model.table[i * 4 + 1] = rgba[1] * 255.0 + 0.5;
model.table[i * 4 + 2] = rgba[2] * 255.0 + 0.5;
model.table[i * 4 + 3] = rgba[3] * 255.0 + 0.5;
}
publicAPI.buildSpecialColors();
model.buildTime.modified();
};
publicAPI.setTable = function (table) {
if (table.getNumberOfComponents() !== 4) {
vtkErrorMacro('Expected 4 components for RGBA colors');
return;
}
if (table.getDataType() !== VtkDataTypes.UNSIGNED_CHAR) {
vtkErrorMacro('Expected unsigned char values for RGBA colors');
return;
}
model.numberOfColors = table.getNumberOfTuples();
var data = table.getData();
model.table.length = data.length;
for (var i = 0; i < data.length; i++) {
model.table[i] = data[i];
}
publicAPI.buildSpecialColors();
model.insertTime.modified();
publicAPI.modified();
};
publicAPI.buildSpecialColors = function () {
// Add "special" colors (NaN, below range, above range) to table here.
var numberOfColors = model.numberOfColors;
var tptr = model.table;
var base = (numberOfColors + BELOW_RANGE_COLOR_INDEX) * 4; // Below range color
if (model.useBelowRangeColor || numberOfColors === 0) {
tptr[base] = model.belowRangeColor[0] * 255.0 + 0.5;
tptr[base + 1] = model.belowRangeColor[1] * 255.0 + 0.5;
tptr[base + 2] = model.belowRangeColor[2] * 255.0 + 0.5;
tptr[base + 3] = model.belowRangeColor[3] * 255.0 + 0.5;
} else {
// Duplicate the first color in the table.
tptr[base] = tptr[0];
tptr[base + 1] = tptr[1];
tptr[base + 2] = tptr[2];
tptr[base + 3] = tptr[3];
} // Above range color
base = (numberOfColors + ABOVE_RANGE_COLOR_INDEX) * 4;
if (model.useAboveRangeColor || numberOfColors === 0) {
tptr[base] = model.aboveRangeColor[0] * 255.0 + 0.5;
tptr[base + 1] = model.aboveRangeColor[1] * 255.0 + 0.5;
tptr[base + 2] = model.aboveRangeColor[2] * 255.0 + 0.5;
tptr[base + 3] = model.aboveRangeColor[3] * 255.0 + 0.5;
} else {
// Duplicate the last color in the table.
tptr[base] = tptr[4 * (numberOfColors - 1) + 0];
tptr[base + 1] = tptr[4 * (numberOfColors - 1) + 1];
tptr[base + 2] = tptr[4 * (numberOfColors - 1) + 2];
tptr[base + 3] = tptr[4 * (numberOfColors - 1) + 3];
} // Always use NanColor
base = (numberOfColors + NAN_COLOR_INDEX) * 4;
tptr[base] = model.nanColor[0] * 255.0 + 0.5;
tptr[base + 1] = model.nanColor[1] * 255.0 + 0.5;
tptr[base + 2] = model.nanColor[2] * 255.0 + 0.5;
tptr[base + 3] = model.nanColor[3] * 255.0 + 0.5;
};
publicAPI.build = function () {
if (model.table.length < 1 || publicAPI.getMTime() > model.buildTime.getMTime() && model.insertTime.getMTime() <= model.buildTime.getMTime()) {
publicAPI.forceBuild();
}
};
if (model.table.length > 0) {
// ensure insertTime is more recently modified than buildTime if
// a table is provided via the constructor
model.insertTime.modified();
}
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
numberOfColors: 256,
// table: null,
hueRange: [0.0, 0.66667],
saturationRange: [1.0, 1.0],
valueRange: [1.0, 1.0],
alphaRange: [1.0, 1.0],
nanColor: [0.5, 0.0, 0.0, 1.0],
belowRangeColor: [0.0, 0.0, 0.0, 1.0],
aboveRangeColor: [1.0, 1.0, 1.0, 1.0],
useAboveRangeColor: false,
useBelowRangeColor: false,
alpha: 1.0 // buildTime: null,
// opaqueFlagBuildTime: null,
// insertTime: null,
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
vtkScalarsToColors.extend(publicAPI, model, initialValues); // Internal objects initialization
if (!model.table) {
model.table = [];
}
model.buildTime = {};
macro.obj(model.buildTime);
model.opaqueFlagBuildTime = {};
macro.obj(model.opaqueFlagBuildTime, {
mtime: 0
});
model.insertTime = {};
macro.obj(model.insertTime, {
mtime: 0
}); // Create get-only macros
macro.get(publicAPI, model, ['buildTime']); // Create get-set macros
macro.setGet(publicAPI, model, ['numberOfColors', 'useAboveRangeColor', 'useBelowRangeColor']); // Create set macros for array (needs to know size)
macro.setArray(publicAPI, model, ['alphaRange', 'hueRange', 'saturationRange', 'valueRange'], 2);
macro.setArray(publicAPI, model, ['nanColor', 'belowRangeColor', 'aboveRangeColor'], 4); // Create get macros for array
macro.getArray(publicAPI, model, ['hueRange', 'saturationRange', 'valueRange', 'alphaRange', 'nanColor', 'belowRangeColor', 'aboveRangeColor']); // For more macro methods, see "Sources/macros.js"
// Object specific methods
vtkLookupTable(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkLookupTable'); // ----------------------------------------------------------------------------
var vtkLookupTable$1 = {
newInstance: newInstance,
extend: extend
};
export { vtkLookupTable$1 as default, extend, newInstance };